Web Inspector: Implement snippets evaluation.
authorvsevik@chromium.org <vsevik@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2012 12:51:57 +0000 (12:51 +0000)
committervsevik@chromium.org <vsevik@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2012 12:51:57 +0000 (12:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88707

Reviewed by Pavel Feldman.

Source/WebCore:

Implemented snippet evaluation and adjusted breakpoints behavior when editing snippet.
Snippets are evaluated using separate compile and run.
Breakpoints are updated after compilation (once scriptId is available they can be set in debugger).
If separate compile and run is not supported by port or debugger is paused we fall back to evaluation in console.

* inspector/front-end/ConsoleView.js:
(WebInspector.ConsoleView.prototype.runScript.runCallback):
(WebInspector.ConsoleView.prototype.runScript):
(WebInspector.ConsoleView.prototype._printResult):
* inspector/front-end/JavaScriptSource.js:
(WebInspector.JavaScriptSource.prototype.supportsEnabledBreakpointsWhileEditing):
* inspector/front-end/JavaScriptSourceFrame.js:
(WebInspector.JavaScriptSourceFrame.prototype.afterTextChanged):
(WebInspector.JavaScriptSourceFrame.prototype.beforeTextChanged):
(WebInspector.JavaScriptSourceFrame.prototype._didEditContent):
(WebInspector.JavaScriptSourceFrame.prototype._removeBreakpointsBeforeEditing):
(WebInspector.JavaScriptSourceFrame.prototype._restoreBreakpointsAfterEditing):
(WebInspector.JavaScriptSourceFrame.prototype._addBreakpointDecoration):
(WebInspector.JavaScriptSourceFrame.prototype._onMouseDown):
* inspector/front-end/ScriptSnippetModel.js:
(WebInspector.ScriptSnippetModel.prototype.deleteScriptSnippet):
(WebInspector.ScriptSnippetModel.prototype._setScriptSnippetContent):
(WebInspector.ScriptSnippetModel.prototype.evaluateScriptSnippet.compileCallback):
(WebInspector.ScriptSnippetModel.prototype.evaluateScriptSnippet):
(WebInspector.ScriptSnippetModel.prototype._rawLocationToUILocation):
(WebInspector.ScriptSnippetModel.prototype._removeBreakpoints):
(WebInspector.ScriptSnippetModel.prototype._restoreBreakpoints):
(WebInspector.ScriptSnippetModel.prototype._evaluationSourceURL):
(WebInspector.SnippetJavaScriptSource.prototype.isDivergedFromVM):
(WebInspector.SnippetJavaScriptSource.prototype.workingCopyCommitted):
(WebInspector.SnippetJavaScriptSource.prototype.workingCopyChanged):
(WebInspector.SnippetJavaScriptSource.prototype.evaluate):
(WebInspector.SnippetJavaScriptSource.prototype.supportsEnabledBreakpointsWhileEditing):
(WebInspector.SnippetJavaScriptSource.prototype.breakpointStorageId):
* inspector/front-end/ScriptsNavigator.js:
(WebInspector.SnippetsNavigatorView.prototype._handleEvaluateSnippet):

LayoutTests:

* inspector/debugger/script-snippet-model-expected.txt:
* inspector/debugger/script-snippet-model.html:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121673 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/inspector/debugger/script-snippet-model-expected.txt
LayoutTests/inspector/debugger/script-snippet-model.html
Source/WebCore/ChangeLog
Source/WebCore/bindings/v8/ScriptDebugServer.cpp
Source/WebCore/inspector/front-end/ConsoleView.js
Source/WebCore/inspector/front-end/JavaScriptSource.js
Source/WebCore/inspector/front-end/JavaScriptSourceFrame.js
Source/WebCore/inspector/front-end/ScriptSnippetModel.js
Source/WebCore/inspector/front-end/ScriptsNavigator.js
Source/WebCore/inspector/front-end/externs.js

index 6a6a808..8d24e29 100644 (file)
@@ -1,3 +1,13 @@
+2012-06-22  Vsevolod Vlasov  <vsevik@chromium.org>
+
+        Web Inspector: Implement snippets evaluation.
+        https://bugs.webkit.org/show_bug.cgi?id=88707
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/debugger/script-snippet-model-expected.txt:
+        * inspector/debugger/script-snippet-model.html:
+
 2012-07-02  Christophe Dumez  <christophe.dumez@intel.com>
 
         [EFL] Rebaseline needed after r121296 and r121599
index 222b7a4..17cefc1 100644 (file)
@@ -3,11 +3,17 @@ Tests script snippet model.
 Debugger was enabled.
 
 Running: testEvaluate
-Last evaluation source url for snippet: snippets://1_1
-Snippet script added, sourceURL = snippets://1_1
-Last evaluation source url for snippet: snippets://2_2
-Snippet script added, sourceURL = snippets://2_2
-Last evaluation source url for snippet: snippets://1_3
-Snippet script added, sourceURL = snippets://1_3
+Last evaluation source url for snippet: snippets:///1_1
+Snippet script added, sourceURL = snippets:///1_1
+Snippet execution result: undefined
+Last evaluation source url for snippet: snippets:///2_2
+Snippet script added, sourceURL = snippets:///2_2
+Snippet execution result: function doesNothing()
+{
+    var  i = 2+2;
+}
+Last evaluation source url for snippet: snippets:///1_3
+Snippet script added, sourceURL = snippets:///1_3
+Snippet execution result: undefined
 Debugger was disabled.
 
index 52db124..767efb8 100644 (file)
@@ -26,29 +26,37 @@ function test()
             var content = "";
             content += "// This snippet does nothing.\n";
             content += "var i = 2+2;\n";
-            WebInspector.scriptSnippetModel.setScriptSnippetContent(snippetJavaScriptSource1, content);
+            WebInspector.scriptSnippetModel._setScriptSnippetContent(snippetJavaScriptSource1, content);
 
             var snippetJavaScriptSource2 = WebInspector.scriptSnippetModel.createScriptSnippet();
             WebInspector.scriptSnippetModel.renameScriptSnippet(snippetJavaScriptSource2, "Snippet2");
             content = "";
-            content += "// This snippet creates a function that does nothing.\n";
+            content += "// This snippet creates a function that does nothing and returns it.\n";
             content += "function doesNothing()\n";
             content += "{\n";
             content += "    var  i = 2+2;\n";
-            content += "}\n";
-            WebInspector.scriptSnippetModel.setScriptSnippetContent(snippetJavaScriptSource2, content);
+            content += "};\n";
+            content += "doesNothing;\n";
+            WebInspector.scriptSnippetModel._setScriptSnippetContent(snippetJavaScriptSource2, content);
 
             function evaluateSnippetAndDumpEvaluationDetails(snippetJavaScriptSource, callback)
             {
                 InspectorTest.addSniffer(WebInspector.SnippetScriptMapping.prototype, "addScript", dumpScript);
+                InspectorTest.addSniffer(WebInspector.ConsoleView.prototype, "_printResult", dumpResult);
                 WebInspector.scriptSnippetModel.evaluateScriptSnippet(snippetJavaScriptSource);
-                var snippet = WebInspector.scriptSnippetModel._snippetStorage.snippetForId(snippetJavaScriptSource.snippetId);
-                InspectorTest.addResult("Last evaluation source url for snippet: " + snippet._lastEvaluationSourceURL);
-                InspectorTest.assertEquals(snippet, WebInspector.scriptSnippetModel._snippetForSourceURL(snippet._lastEvaluationSourceURL), "Snippet can not be identified by its evaluation sourceURL.");
+                var evaluationSourceURL = WebInspector.scriptSnippetModel._evaluationSourceURL(snippetJavaScriptSource);
+                var snippetId = snippetJavaScriptSource.snippetId;
+                InspectorTest.addResult("Last evaluation source url for snippet: " + evaluationSourceURL);
+                InspectorTest.assertEquals(snippetId, WebInspector.scriptSnippetModel._snippetIdForSourceURL(evaluationSourceURL), "Snippet can not be identified by its evaluation sourceURL.");
 
                 function dumpScript(script)
                 {
                     InspectorTest.addResult("Snippet script added, sourceURL = " + script.sourceURL);
+                }
+
+                function dumpResult(result, wasThrown)
+                {
+                    InspectorTest.addResult("Snippet execution result: " + result.description);
                     callback();
                 }
             }
index c2e61bb..7948f8f 100644 (file)
@@ -1,3 +1,47 @@
+2012-06-22  Vsevolod Vlasov  <vsevik@chromium.org>
+
+        Web Inspector: Implement snippets evaluation.
+        https://bugs.webkit.org/show_bug.cgi?id=88707
+
+        Reviewed by Pavel Feldman.
+
+        Implemented snippet evaluation and adjusted breakpoints behavior when editing snippet.
+        Snippets are evaluated using separate compile and run.
+        Breakpoints are updated after compilation (once scriptId is available they can be set in debugger).
+        If separate compile and run is not supported by port or debugger is paused we fall back to evaluation in console.
+
+        * inspector/front-end/ConsoleView.js:
+        (WebInspector.ConsoleView.prototype.runScript.runCallback):
+        (WebInspector.ConsoleView.prototype.runScript):
+        (WebInspector.ConsoleView.prototype._printResult):
+        * inspector/front-end/JavaScriptSource.js:
+        (WebInspector.JavaScriptSource.prototype.supportsEnabledBreakpointsWhileEditing):
+        * inspector/front-end/JavaScriptSourceFrame.js:
+        (WebInspector.JavaScriptSourceFrame.prototype.afterTextChanged):
+        (WebInspector.JavaScriptSourceFrame.prototype.beforeTextChanged):
+        (WebInspector.JavaScriptSourceFrame.prototype._didEditContent):
+        (WebInspector.JavaScriptSourceFrame.prototype._removeBreakpointsBeforeEditing):
+        (WebInspector.JavaScriptSourceFrame.prototype._restoreBreakpointsAfterEditing):
+        (WebInspector.JavaScriptSourceFrame.prototype._addBreakpointDecoration):
+        (WebInspector.JavaScriptSourceFrame.prototype._onMouseDown):
+        * inspector/front-end/ScriptSnippetModel.js:
+        (WebInspector.ScriptSnippetModel.prototype.deleteScriptSnippet):
+        (WebInspector.ScriptSnippetModel.prototype._setScriptSnippetContent):
+        (WebInspector.ScriptSnippetModel.prototype.evaluateScriptSnippet.compileCallback):
+        (WebInspector.ScriptSnippetModel.prototype.evaluateScriptSnippet):
+        (WebInspector.ScriptSnippetModel.prototype._rawLocationToUILocation):
+        (WebInspector.ScriptSnippetModel.prototype._removeBreakpoints):
+        (WebInspector.ScriptSnippetModel.prototype._restoreBreakpoints):
+        (WebInspector.ScriptSnippetModel.prototype._evaluationSourceURL):
+        (WebInspector.SnippetJavaScriptSource.prototype.isDivergedFromVM):
+        (WebInspector.SnippetJavaScriptSource.prototype.workingCopyCommitted):
+        (WebInspector.SnippetJavaScriptSource.prototype.workingCopyChanged):
+        (WebInspector.SnippetJavaScriptSource.prototype.evaluate):
+        (WebInspector.SnippetJavaScriptSource.prototype.supportsEnabledBreakpointsWhileEditing):
+        (WebInspector.SnippetJavaScriptSource.prototype.breakpointStorageId):
+        * inspector/front-end/ScriptsNavigator.js:
+        (WebInspector.SnippetsNavigatorView.prototype._handleEvaluateSnippet):
+
 2012-06-26  Vsevolod Vlasov  <vsevik@chromium.org>
 
         Web Inspector: StyleSource should set content using CSSStyleModelResourceBinding directly.
index a3bede8..2c82510 100644 (file)
@@ -451,6 +451,8 @@ void ScriptDebugServer::clearCompiledScripts()
 
 void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage)
 {
+    if (!m_compiledScripts.contains(scriptId))
+        return;
     v8::HandleScope handleScope;
     OwnHandle<v8::Script>* scriptOwnHandle = m_compiledScripts.get(scriptId);
     v8::Local<v8::Script> script = v8::Local<v8::Script>::New(scriptOwnHandle->get());
index c06e947..4dfed1a 100644 (file)
@@ -712,6 +712,36 @@ WebInspector.ConsoleView.prototype = {
         this._appendCommand(str, "", true, false);
     },
 
+    runScript: function(scriptId)
+    {
+        var contextId = WebInspector.consoleView._currentEvaluationContextId();
+        DebuggerAgent.runScript(scriptId, contextId, "console", false, runCallback.bind(this));
+        WebInspector.userMetrics.ConsoleEvaluated.record();
+
+        /**
+         * @param {?string} error
+         * @param {?RuntimeAgent.RemoteObject} result
+         * @param {boolean=} wasThrown
+         */
+        function runCallback(error, result, wasThrown)
+        {
+            if (error) {
+                console.error(error);
+                return;
+            }
+            
+            this._printResult(result, wasThrown);
+        }
+    },
+
+    _printResult: function(result, wasThrown)
+    {
+        if (!result)
+            return;
+
+        this._appendConsoleMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, null, this._linkifier));
+    },
+
     _appendCommand: function(text, newPromptText, useCommandLineAPI, showResultOnly)
     {
         if (!showResultOnly) {
@@ -730,8 +760,8 @@ WebInspector.ConsoleView.prototype = {
                 this.prompt.pushHistoryItem(text);
                 WebInspector.settings.consoleHistory.set(this.prompt.historyData.slice(-30));
             }
-
-            this._appendConsoleMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, commandMessage, this._linkifier));
+            
+            this._printResult(result, wasThrown);
         }
         this.evalInInspectedWindow(text, "console", useCommandLineAPI, false, false, printResult.bind(this));
 
index 6487cbb..6e6c65b 100644 (file)
@@ -160,6 +160,14 @@ WebInspector.JavaScriptSource.prototype = {
     },
 
     /**
+     * @return {boolean}
+     */
+    supportsEnabledBreakpointsWhileEditing: function()
+    {
+        return false;
+    },
+
+    /**
      * @return {string}
      */
     breakpointStorageId: function()
@@ -188,7 +196,7 @@ WebInspector.JavaScriptSource.prototype = {
      * @param {function(?string)} callback
      */
     workingCopyCommitted: function(callback)
-    {  
+    {
         /**
          * @param {?string} error
          */
index 48c4b95..f59b09c 100644 (file)
@@ -149,14 +149,32 @@ WebInspector.JavaScriptSourceFrame.prototype = {
 
     afterTextChanged: function(oldRange, newRange)
     {
+        WebInspector.SourceFrame.prototype.afterTextChanged.call(this, oldRange, newRange);
         this._javaScriptSource.setWorkingCopy(this.textModel.text);
-        if (!this._javaScriptSource.isDirty())
-            this._didEditContent(null);
+        this._restoreBreakpointsAfterEditing();
     },
 
     beforeTextChanged: function()
     {
-        if (!this._javaScriptSource.isDirty()) {
+        WebInspector.SourceFrame.prototype.beforeTextChanged.call(this);
+        this._removeBreakpointsBeforeEditing();
+    },
+
+    _didEditContent: function(error)
+    {
+        delete this._isCommittingEditing;
+
+        if (error) {
+            WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true);
+            return;
+        }
+        if (!this._javaScriptSource.supportsEnabledBreakpointsWhileEditing())
+            this._restoreBreakpointsAfterEditing();
+    },
+
+    _removeBreakpointsBeforeEditing: function()
+    {
+        if (!this._javaScriptSource.isDirty() || this._javaScriptSource.supportsEnabledBreakpointsWhileEditing()) {
             // Disable all breakpoints in the model, store them as muted breakpoints.
             var breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._javaScriptSource);
             var lineNumbers = {};
@@ -168,27 +186,20 @@ WebInspector.JavaScriptSourceFrame.prototype = {
             }
             this.clearExecutionLine();
         }
-
-        WebInspector.SourceFrame.prototype.beforeTextChanged.call(this);
     },
 
-    _didEditContent: function(error)
+    _restoreBreakpointsAfterEditing: function()
     {
-        delete this._isCommittingEditing;
-
-        if (error) {
-            WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true);
-            return;
-        }
-
-        // Restore all muted breakpoints.
-        for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
-            var breakpointDecoration = this.textModel.getAttribute(lineNumber, "breakpoint");
-            if (breakpointDecoration) {
-                // Remove fake decoration
-                this._removeBreakpointDecoration(lineNumber);
-                // Set new breakpoint
-                this._setBreakpoint(lineNumber, breakpointDecoration.condition, breakpointDecoration.enabled);
+        if (!this._javaScriptSource.isDirty() || this._javaScriptSource.supportsEnabledBreakpointsWhileEditing()) {
+            // Restore all muted breakpoints.
+            for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
+                var breakpointDecoration = this.textModel.getAttribute(lineNumber, "breakpoint");
+                if (breakpointDecoration) {
+                    // Remove fake decoration
+                    this._removeBreakpointDecoration(lineNumber);
+                    // Set new breakpoint
+                    this._setBreakpoint(lineNumber, breakpointDecoration.condition, breakpointDecoration.enabled);
+                }
             }
         }
     },
@@ -326,7 +337,7 @@ WebInspector.JavaScriptSourceFrame.prototype = {
 
         this.textViewer.beginUpdates();
         this.textViewer.addDecoration(lineNumber, "webkit-breakpoint");
-        if (!enabled || mutedWhileEditing)
+        if (!enabled || (mutedWhileEditing && !this._javaScriptSource.supportsEnabledBreakpointsWhileEditing()))
             this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
         else
             this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled");
@@ -349,7 +360,7 @@ WebInspector.JavaScriptSourceFrame.prototype = {
 
     _onMouseDown: function(event)
     {
-        if (this._javaScriptSource.isDirty())
+        if (this._javaScriptSource.isDirty() && !this._javaScriptSource.supportsEnabledBreakpointsWhileEditing())
             return;
 
         if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey)
index 9593089..ede6352 100644 (file)
@@ -47,8 +47,7 @@ WebInspector.ScriptSnippetModel = function()
         this._addScriptSnippet(snippets[i]);
 }
 
-WebInspector.ScriptSnippetModel.evaluatedSnippetExtraLinesCount = 2;
-WebInspector.ScriptSnippetModel.snippetSourceURLPrefix = "snippets://";
+WebInspector.ScriptSnippetModel.snippetSourceURLPrefix = "snippets:///";
 
 WebInspector.ScriptSnippetModel.prototype = {
     /**
@@ -87,6 +86,7 @@ WebInspector.ScriptSnippetModel.prototype = {
     {
         var snippet = this._snippetStorage.snippetForId(snippetJavaScriptSource.snippetId);
         this._snippetStorage.deleteSnippet(snippet);
+        this._removeBreakpoints(snippetJavaScriptSource);
         this._releaseSnippetScript(snippetJavaScriptSource);
         delete this._snippetJavaScriptSourceForSnippetId[snippet.id];
         this._snippetScriptMapping._fireUISourceCodeRemoved(snippetJavaScriptSource);
@@ -107,9 +107,19 @@ WebInspector.ScriptSnippetModel.prototype = {
 
     /**
      * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
+     * @return {boolean}
+     */
+    _isDivergedFromVM: function(snippetJavaScriptSource)
+    {
+        var script = this._scriptForUISourceCode.get(snippetJavaScriptSource);
+        return !script;
+    },
+
+    /**
+     * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
      * @param {string} newContent
      */
-    setScriptSnippetContent: function(snippetJavaScriptSource, newContent)
+    _setScriptSnippetContent: function(snippetJavaScriptSource, newContent)
     {
         var snippet = this._snippetStorage.snippetForId(snippetJavaScriptSource.snippetId);
         snippet.content = newContent;
@@ -119,17 +129,86 @@ WebInspector.ScriptSnippetModel.prototype = {
     /**
      * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
      */
-    evaluateScriptSnippet: function(snippetJavaScriptSource)
+    _scriptSnippetEdited: function(snippetJavaScriptSource)
     {
+        var script = this._scriptForUISourceCode.get(snippetJavaScriptSource);
+        if (!script)
+            return;
+        
+        var breakpointLocations = this._removeBreakpoints(snippetJavaScriptSource);
         this._releaseSnippetScript(snippetJavaScriptSource);
+        this._restoreBreakpoints(snippetJavaScriptSource, breakpointLocations);
+    },
+
+    /**
+     * @param {string} snippetId
+     * @return {number}
+     */
+    _nextEvaluationIndex: function(snippetId)
+    {
         var evaluationIndex = this._lastSnippetEvaluationIndexSetting.get() + 1;
         this._lastSnippetEvaluationIndexSetting.set(evaluationIndex);
+        return evaluationIndex;
+    },
 
-        var snippet = this._snippetStorage.snippetForId(snippetJavaScriptSource.snippetId);
-        var sourceURL = this._sourceURLForSnippet(snippet, evaluationIndex);
-        snippet._lastEvaluationSourceURL = sourceURL;
-        var expression = "\n//@ sourceURL=" + sourceURL + "\n" + snippet.content;
-        WebInspector.evaluateInConsole(expression, true);
+    /**
+     * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
+     */
+    evaluateScriptSnippet: function(snippetJavaScriptSource)
+    {
+        var breakpointLocations = this._removeBreakpoints(snippetJavaScriptSource);
+        this._releaseSnippetScript(snippetJavaScriptSource);
+        this._restoreBreakpoints(snippetJavaScriptSource, breakpointLocations);
+        var evaluationIndex = this._nextEvaluationIndex(snippetJavaScriptSource.snippetId);
+        snippetJavaScriptSource._evaluationIndex = evaluationIndex;
+        var evaluationUrl = this._evaluationSourceURL(snippetJavaScriptSource);
+
+        var expression = snippetJavaScriptSource.workingCopy();
+        
+        // In order to stop on the breakpoints during the snippet evaluation we need to compile and run it separately.
+        // If separate compilation and execution is not supported by the port we fall back to evaluation in console.
+        // In case we don't need that since debugger is already paused.
+        // We do the same when we are stopped on the call frame  since debugger is already paused and can not stop on breakpoint anymore.
+        if (WebInspector.debuggerModel.selectedCallFrame() || !Capabilities.separateScriptCompilationAndExecutionEnabled) {
+            expression = snippetJavaScriptSource.workingCopy() + "\n//@ sourceURL=" + snippetJavaScriptSource.url + "\n";
+            WebInspector.evaluateInConsole(expression, true);
+            return;
+        }
+        
+        WebInspector.showConsole();
+        DebuggerAgent.compileScript(expression, evaluationUrl, compileCallback.bind(this));
+
+        /**
+         * @param {?string} error
+         * @param {string=} scriptId
+         * @param {string=} syntaxErrorMessage
+         */
+        function compileCallback(error, scriptId, syntaxErrorMessage)
+        {
+            if (!snippetJavaScriptSource || snippetJavaScriptSource._evaluationIndex !== evaluationIndex)
+                return;
+
+            if (error) {
+                console.error(error);
+                return;
+            }
+
+            if (!scriptId) {
+                var consoleMessage = WebInspector.ConsoleMessage.create(
+                        WebInspector.ConsoleMessage.MessageSource.JS,
+                        WebInspector.ConsoleMessage.MessageLevel.Error,
+                        syntaxErrorMessage || "",
+                        WebInspector.ConsoleMessage.MessageType.Log,
+                        "", 0, 1, null, null, null);
+                WebInspector.console.addMessage(consoleMessage);
+                return;
+            }
+
+            var breakpointLocations = this._removeBreakpoints(snippetJavaScriptSource);
+            this._restoreBreakpoints(snippetJavaScriptSource, breakpointLocations);
+
+            WebInspector.consoleView.runScript(scriptId);
+        }
     },
 
     /**
@@ -139,11 +218,6 @@ WebInspector.ScriptSnippetModel.prototype = {
     _rawLocationToUILocation: function(rawLocation)
     {
         var uiSourceCode = this._uiSourceCodeForScriptId[rawLocation.scriptId];
-        if (uiSourceCode.isSnippet) {
-            var uiLineNumber = rawLocation.lineNumber - WebInspector.ScriptSnippetModel.evaluatedSnippetExtraLinesCount;
-            return new WebInspector.UILocation(uiSourceCode, uiLineNumber, rawLocation.columnNumber || 0);
-        }
-
         return new WebInspector.UILocation(uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0);
     },
 
@@ -159,11 +233,6 @@ WebInspector.ScriptSnippetModel.prototype = {
         if (!script)
             return null;
 
-        if (uiSourceCode.isSnippet) {
-            var rawLineNumber = lineNumber + WebInspector.ScriptSnippetModel.evaluatedSnippetExtraLinesCount;
-            return WebInspector.debuggerModel.createRawLocation(script, rawLineNumber, columnNumber);
-        }
-
         return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber);
     },
 
@@ -199,7 +268,8 @@ WebInspector.ScriptSnippetModel.prototype = {
     {
         var snippetId = this._snippetIdForSourceURL(script.sourceURL);
         var snippetJavaScriptSource = this._snippetJavaScriptSourceForSnippetId[snippetId];
-        if (!snippetJavaScriptSource) {
+        
+        if (!snippetJavaScriptSource || this._evaluationSourceURL(snippetJavaScriptSource) !== script.sourceURL) {
             this._createUISourceCodeForScript(script);
             return;
         }
@@ -225,6 +295,31 @@ WebInspector.ScriptSnippetModel.prototype = {
 
     /**
      * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
+     * @return {Array.<Object>}
+     */
+    _removeBreakpoints: function(snippetJavaScriptSource)
+    {
+        var breakpointLocations = WebInspector.breakpointManager.breakpointLocationsForUISourceCode(snippetJavaScriptSource);
+        for (var i = 0; i < breakpointLocations.length; ++i)
+            breakpointLocations[i].breakpoint.remove();
+        return breakpointLocations;
+    },
+
+    /**
+     * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
+     * @param {Array.<Object>} breakpointLocations
+     */
+    _restoreBreakpoints: function(snippetJavaScriptSource, breakpointLocations)
+    {
+        for (var i = 0; i < breakpointLocations.length; ++i) {
+            var uiLocation = breakpointLocations[i].uiLocation;
+            var breakpoint = breakpointLocations[i].breakpoint;
+            WebInspector.breakpointManager.setBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber, breakpoint.condition(), breakpoint.enabled());
+        }
+    },
+
+    /**
+     * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
      */
     _releaseSnippetScript: function(snippetJavaScriptSource)
     {
@@ -234,20 +329,19 @@ WebInspector.ScriptSnippetModel.prototype = {
 
         delete this._uiSourceCodeForScriptId[script.scriptId];
         this._scriptForUISourceCode.remove(snippetJavaScriptSource);
-
+        delete snippetJavaScriptSource._evaluationIndex;
         this._createUISourceCodeForScript(script);
     },
 
     /**
-     * @param {WebInspector.Snippet} snippet
-     * @param {string} evaluationIndex
+     * @param {WebInspector.SnippetJavaScriptSource} snippetJavaScriptSource
      * @return {string}
      */
-    _sourceURLForSnippet: function(snippet, evaluationIndex)
+    _evaluationSourceURL: function(snippetJavaScriptSource)
     {
         var snippetPrefix = WebInspector.ScriptSnippetModel.snippetSourceURLPrefix;
-        var evaluationSuffix = evaluationIndex ? "_" + evaluationIndex : "";
-        return snippetPrefix + snippet.id + evaluationSuffix;
+        var evaluationSuffix = "_" + snippetJavaScriptSource._evaluationIndex;
+        return snippetPrefix + snippetJavaScriptSource.snippetId + evaluationSuffix;
     },
 
     /**
@@ -264,21 +358,6 @@ WebInspector.ScriptSnippetModel.prototype = {
         return snippetId;
     },
 
-    /**
-     * @param {string} sourceURL
-     * @return {WebInspector.Snippet|null}
-     */
-    _snippetForSourceURL: function(sourceURL)
-    {
-        var snippetId = this._snippetIdForSourceURL(sourceURL);
-        if (!snippetId)
-            return null;
-        var snippet = this._snippetStorage.snippetForId(snippetId);
-        if (!snippet || snippet._lastEvaluationSourceURL !== sourceURL)
-            return null;
-        return snippet;
-    },
-
     _reset: function()
     {
         var removedUISourceCodes = this._releasedUISourceCodes();
@@ -317,14 +396,48 @@ WebInspector.SnippetJavaScriptSource.prototype = {
     },
 
     /**
+     * @return {boolean}
+     */
+    isDivergedFromVM: function()
+    {
+        return this._scriptSnippetModel._isDivergedFromVM(this);
+    },
+
+    /**
      * @param {function(?string)} callback
      */
     workingCopyCommitted: function(callback)
     {  
-        this._scriptSnippetModel.setScriptSnippetContent(this, this.workingCopy());
+        this._scriptSnippetModel._setScriptSnippetContent(this, this.workingCopy());
         callback(null);
     },
 
+    workingCopyChanged: function()
+    {  
+        this._scriptSnippetModel._scriptSnippetEdited(this);
+    },
+
+    evaluate: function()
+    {
+        this._scriptSnippetModel.evaluateScriptSnippet(this);
+    },
+
+    /**
+     * @return {boolean}
+     */
+    supportsEnabledBreakpointsWhileEditing: function()
+    {
+        return true;
+    },
+
+    /**
+     * @return {string}
+     */
+    breakpointStorageId: function()
+    {
+        return WebInspector.ScriptSnippetModel.snippetSourceURLPrefix + this.snippetId;
+    },
+
     /**
      * @return {string}
      */
index a6dea59..fe52d43 100644 (file)
@@ -232,7 +232,10 @@ WebInspector.SnippetsNavigatorView.prototype = {
      */
     _handleEvaluateSnippet: function(uiSourceCode, event)
     {
-        // FIXME: To be implemented.
+        if (!uiSourceCode.isSnippet)
+            return;
+        var snippetJavaScriptSource = /** @type {WebInspector.SnippetJavaScriptSource} */ uiSourceCode;
+        snippetJavaScriptSource.evaluate();
     },
 
     /**
index cfc6ee6..cbc8271 100644 (file)
@@ -147,6 +147,8 @@ WebInspector.addMainEventListeners = function(doc) {}
 
 WebInspector.openResource = function(url, external) {}
 
+WebInspector.showConsole = function() {}
+
 /**
  * @param {string} expression
  * @param {boolean=} showResultOnly