Title: [146759] trunk
Revision
146759
Author
commit-qu...@webkit.org
Date
2013-03-25 05:38:46 -0700 (Mon, 25 Mar 2013)

Log Message

Web Inspector: support changing local variables in frontend
https://bugs.webkit.org/show_bug.cgi?id=112470

Patch by Peter Rybin <pry...@chromium.org> on 2013-03-25
Reviewed by Yury Semikhatsky.

Source/WebCore:

ScopeRef type is added to RemoteObject and setPropertyValue is patched accordingly.

Test: inspector/debugger/debugger-change-variable.html

* inspector/front-end/DebuggerModel.js:
(WebInspector.DebuggerModel.CallFrame.prototype.get id):
* inspector/front-end/ObjectPropertiesSection.js:
(WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate.didGetDetails):
(WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate):
* inspector/front-end/RemoteObject.js:
(WebInspector.RemoteObject):
(WebInspector.RemoteObject.fromScopePayload):
(WebInspector.RemoteObject.prototype.):
(WebInspector.RemoteObject.prototype.setPropertyValue):
(WebInspector.RemoteObject.prototype.setVariableValueCallback):
(WebInspector.RemoteObject.prototype._setDeclarativeVariableValue):
(WebInspector.ScopeRef):
* inspector/front-end/ScopeChainSidebarPane.js:
(WebInspector.ScopeChainSidebarPane.prototype.update):

LayoutTests:

* inspector/debugger/debugger-change-variable-expected.txt: Added.
* inspector/debugger/debugger-change-variable.html: Added.
* platform/chromium/inspector/debugger/debugger-change-variable-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (146758 => 146759)


--- trunk/LayoutTests/ChangeLog	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/LayoutTests/ChangeLog	2013-03-25 12:38:46 UTC (rev 146759)
@@ -1,3 +1,14 @@
+2013-03-25  Peter Rybin  <pry...@chromium.org>
+
+        Web Inspector: support changing local variables in frontend
+        https://bugs.webkit.org/show_bug.cgi?id=112470
+
+        Reviewed by Yury Semikhatsky.
+
+        * inspector/debugger/debugger-change-variable-expected.txt: Added.
+        * inspector/debugger/debugger-change-variable.html: Added.
+        * platform/chromium/inspector/debugger/debugger-change-variable-expected.txt: Added.
+
 2013-03-25  Mike West  <mk...@chromium.org>
 
         CSP 1.1: Strip URLs in SecurityPolicyViolationEvents, just as we do for POSTed violation reports.

Added: trunk/LayoutTests/inspector/debugger/debugger-change-variable-expected.txt (0 => 146759)


--- trunk/LayoutTests/inspector/debugger/debugger-change-variable-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/debugger/debugger-change-variable-expected.txt	2013-03-25 12:38:46 UTC (rev 146759)
@@ -0,0 +1,11 @@
+Tests that modifying local variables works fine.
+
+Debugger was enabled.
+Set timer for test function.
+Script execution paused.
+Evaluated script on the calling frame: 310
+Set property value error: Failed to change variable value: TypeError: Variable value mutation is not supported
+Evaluated script on the calling frame (after value modification): 310
+Script execution resumed.
+Debugger was disabled.
+

Added: trunk/LayoutTests/inspector/debugger/debugger-change-variable.html (0 => 146759)


--- trunk/LayoutTests/inspector/debugger/debugger-change-variable.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/debugger/debugger-change-variable.html	2013-03-25 12:38:46 UTC (rev 146759)
@@ -0,0 +1,73 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+
+function slave(x)
+{
+    var y = 20;
+    debugger;
+}
+
+function testFunction()
+{
+    var localObject = { a: 310 };
+    slave(4000);
+}
+
+var test = function()
+{
+    InspectorTest.startDebuggerTest(step1);
+
+    function step1()
+    {
+        InspectorTest.runTestFunctionAndWaitUntilPaused(step2);
+    }
+
+    function step2(callFrames)
+    {
+        var pane = WebInspector.panels.scripts.sidebarPanes.callstack;
+        pane._placardSelected(pane.placards[1]);
+        InspectorTest.runAfterPendingDispatches(step3);
+    }
+
+    function step3()
+    {
+        InspectorTest.evaluateInConsole("localObject.a", step4);
+    }
+
+    function step4(result)
+    {
+        InspectorTest.addResult("Evaluated script on the calling frame: " + result);
+
+        var pane = WebInspector.panels.scripts.sidebarPanes.scopechain;
+        var localsSection = pane._sections[0];
+        localsSection.object.setPropertyValue("localObject", "({ a: -290})", step5);
+    }
+
+    function step5(error)
+    {
+        if (error)
+            InspectorTest.addResult("Set property value error: " + error);
+
+        InspectorTest.evaluateInConsole("localObject.a", step6);
+    }
+
+    function step6(result)
+    {
+        InspectorTest.addResult("Evaluated script on the calling frame (after value modification): " + result);
+        InspectorTest.completeDebuggerTest();
+    }
+}
+
+</script>
+</head>
+
+<body _onload_="runTest()">
+<p>
+Tests that modifying local variables works fine.
+</p>
+
+</body>
+</html>

Added: trunk/LayoutTests/platform/chromium/inspector/debugger/debugger-change-variable-expected.txt (0 => 146759)


--- trunk/LayoutTests/platform/chromium/inspector/debugger/debugger-change-variable-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/chromium/inspector/debugger/debugger-change-variable-expected.txt	2013-03-25 12:38:46 UTC (rev 146759)
@@ -0,0 +1,10 @@
+Tests that modifying local variables works fine.
+
+Debugger was enabled.
+Set timer for test function.
+Script execution paused.
+Evaluated script on the calling frame: 310
+Evaluated script on the calling frame (after value modification): -290
+Script execution resumed.
+Debugger was disabled.
+

Modified: trunk/Source/WebCore/ChangeLog (146758 => 146759)


--- trunk/Source/WebCore/ChangeLog	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/Source/WebCore/ChangeLog	2013-03-25 12:38:46 UTC (rev 146759)
@@ -1,3 +1,30 @@
+2013-03-25  Peter Rybin  <pry...@chromium.org>
+
+        Web Inspector: support changing local variables in frontend
+        https://bugs.webkit.org/show_bug.cgi?id=112470
+
+        Reviewed by Yury Semikhatsky.
+
+        ScopeRef type is added to RemoteObject and setPropertyValue is patched accordingly.
+
+        Test: inspector/debugger/debugger-change-variable.html
+
+        * inspector/front-end/DebuggerModel.js:
+        (WebInspector.DebuggerModel.CallFrame.prototype.get id):
+        * inspector/front-end/ObjectPropertiesSection.js:
+        (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate.didGetDetails):
+        (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate):
+        * inspector/front-end/RemoteObject.js:
+        (WebInspector.RemoteObject):
+        (WebInspector.RemoteObject.fromScopePayload):
+        (WebInspector.RemoteObject.prototype.):
+        (WebInspector.RemoteObject.prototype.setPropertyValue):
+        (WebInspector.RemoteObject.prototype.setVariableValueCallback):
+        (WebInspector.RemoteObject.prototype._setDeclarativeVariableValue):
+        (WebInspector.ScopeRef):
+        * inspector/front-end/ScopeChainSidebarPane.js:
+        (WebInspector.ScopeChainSidebarPane.prototype.update):
+
 2013-03-25  Mike West  <mk...@chromium.org>
 
         CSP 1.1: Strip URLs in SecurityPolicyViolationEvents, just as we do for POSTed violation reports.

Modified: trunk/Source/WebCore/inspector/front-end/DebuggerModel.js (146758 => 146759)


--- trunk/Source/WebCore/inspector/front-end/DebuggerModel.js	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/Source/WebCore/inspector/front-end/DebuggerModel.js	2013-03-25 12:38:46 UTC (rev 146759)
@@ -706,6 +706,14 @@
     },
 
     /**
+     * @return {string}
+     */
+    get id()
+    {
+        return this._payload.callFrameId;
+    },
+
+    /**
      * @return {Array.<DebuggerAgent.Scope>}
      */
     get scopeChain()

Modified: trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js (146758 => 146759)


--- trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js	2013-03-25 12:38:46 UTC (rev 146759)
@@ -554,8 +554,14 @@
                         console.error("Unknown scope type: " + scope.type);
                         continue;
                 }
+                
+                var scopeRef;
+                if (isTrueObject)
+                    scopeRef = undefined;
+                else 
+                    scopeRef = new WebInspector.ScopeRef(i, undefined, this._remoteObject.objectId);
 
-                var remoteObject = WebInspector.RemoteObject.fromPayload(scope.object);
+                var remoteObject = WebInspector.RemoteObject.fromScopePayload(scope.object, scopeRef);
                 if (isTrueObject) {
                     var property = WebInspector.RemoteObjectProperty.fromScopeValue(title, remoteObject);
                     property.parentObject = null;

Modified: trunk/Source/WebCore/inspector/front-end/RemoteObject.js (146758 => 146759)


--- trunk/Source/WebCore/inspector/front-end/RemoteObject.js	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/Source/WebCore/inspector/front-end/RemoteObject.js	2013-03-25 12:38:46 UTC (rev 146759)
@@ -36,8 +36,9 @@
  * @param {*} value
  * @param {string=} description
  * @param {RuntimeAgent.ObjectPreview=} preview
+ * @param {WebInspector.ScopeRef=} scopeRef
  */
-WebInspector.RemoteObject = function(objectId, type, subtype, value, description, preview)
+WebInspector.RemoteObject = function(objectId, type, subtype, value, description, preview, scopeRef)
 {
     this._type = type;
     this._subtype = subtype;
@@ -54,6 +55,7 @@
         this._hasChildren = false;
         this.value = value;
     }
+    this._scopeRef = scopeRef;
 }
 
 /**
@@ -110,6 +112,16 @@
 }
 
 /**
+ * @param {RuntimeAgent.RemoteObject} payload
+ * @param {WebInspector.ScopeRef=} scopeRef
+ * @return {WebInspector.RemoteObject}
+ */
+WebInspector.RemoteObject.fromScopePayload = function(payload, scopeRef)
+{
+    return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description, payload.preview, scopeRef);
+}
+
+/**
  * @param {WebInspector.RemoteObject} remoteObject
  * @return {string}
  */
@@ -249,19 +261,35 @@
                 callback(error || result.description);
                 return;
             }
+            
+            if (this._scopeRef)
+                this._setDeclarativeVariableValue(result, name, callback);
+            else
+                this._setObjectPropertyValue(result, name, callback);
 
-            var setPropertyValueFunction = "function(a, b) { this[a] = b; }";
-
-            // Special case for NaN, Infinity and -Infinity
-            if (result.type === "number" && typeof result.value !== "number")
-                setPropertyValueFunction = "function(a) { this[a] = " + result.description + "; }";
-
-            delete result.description; // Optimize on traffic.
-            RuntimeAgent.callFunctionOn(this._objectId, setPropertyValueFunction, [{ value:name }, result], true, undefined, undefined, propertySetCallback.bind(this));
             if (result._objectId)
                 RuntimeAgent.releaseObject(result._objectId);
         }
+    },
+    
+    /**
+     * @param {WebInspector.RemoteObject} result
+     * @param {string} name
+     * @param {function(string=)} callback
+     */
+    _setObjectPropertyValue: function(result, name, callback)
+    {
+        // Note that it is not that simple with accessor properties. The proto object may contain the property,
+        // however not the proto object must be 'this', but the main object. 
+        var setPropertyValueFunction = "function(a, b) { this[a] = b; }";
 
+        // Special case for NaN, Infinity and -Infinity
+        if (result.type === "number" && typeof result.value !== "number")
+            setPropertyValueFunction = "function(a) { this[a] = " + result.description + "; }";
+
+        delete result.description; // Optimize on traffic.
+        RuntimeAgent.callFunctionOn(this._objectId, setPropertyValueFunction, [{ value:name }, result], true, undefined, undefined, propertySetCallback.bind(this));
+
         /**
          * @param {?Protocol.Error} error
          * @param {RuntimeAgent.RemoteObject} result
@@ -278,6 +306,42 @@
     },
 
     /**
+     * @param {WebInspector.RemoteObject} result
+     * @param {string} name
+     * @param {function(string=)} callback
+     */
+    _setDeclarativeVariableValue: function(result, name, callback)
+    {
+        var newValue;
+        
+        switch (result.type) {
+            case "undefined":
+                newValue = {};
+                break;
+            case "object":
+            case "function":
+                newValue = { objectId: result.objectId };
+                break;
+            default:
+                newValue = { value: result.value };
+        }
+        
+        DebuggerAgent.setVariableValue(this._scopeRef.number, name, newValue, this._scopeRef.callFrameId, this._scopeRef.functionId, setVariableValueCallback.bind(this));
+
+        /**
+         * @param {?Protocol.Error} error
+         */
+        function setVariableValueCallback(error)
+        {
+            if (error) {
+                callback(error);
+                return;
+            }
+            callback();
+        }
+    },
+
+    /**
      * @param {function(?DOMAgent.NodeId)} callback
      */
     pushNodeToFrontend: function(callback)
@@ -364,7 +428,21 @@
 }
 
 /**
+ * Either callFrameId or functionId (exactly one) must be defined.
  * @constructor
+ * @param {number} number
+ * @param {string=} callFrameId
+ * @param {string=} functionId
+ */
+WebInspector.ScopeRef = function(number, callFrameId, functionId)
+{
+    this.number = number;
+    this.callFrameId = callFrameId;
+    this.functionId = functionId;
+}
+
+/**
+ * @constructor
  * @param {string} name
  * @param {WebInspector.RemoteObject} value
  * @param {Object=} descriptor

Modified: trunk/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js (146758 => 146759)


--- trunk/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js	2013-03-25 12:20:23 UTC (rev 146758)
+++ trunk/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js	2013-03-25 12:38:46 UTC (rev 146759)
@@ -69,7 +69,8 @@
             var subtitle = scope.object.description;
             var emptyPlaceholder = null;
             var extraProperties = null;
-
+            var declarativeScope;
+            
             switch (scope.type) {
                 case "local":
                     foundLocalScope = true;
@@ -87,28 +88,40 @@
                             extraProperties.push(new WebInspector.RemoteObjectProperty("<exception>", WebInspector.RemoteObject.fromPayload(exceptionObject)));
                         }
                     }
+                    declarativeScope = true;
                     break;
                 case "closure":
                     title = WebInspector.UIString("Closure");
                     emptyPlaceholder = WebInspector.UIString("No Variables");
                     subtitle = null;
+                    declarativeScope = true;
                     break;
                 case "catch":
                     title = WebInspector.UIString("Catch");
                     subtitle = null;
+                    declarativeScope = true;
                     break;
                 case "with":
                     title = WebInspector.UIString("With Block");
+                    declarativeScope = false;
                     break;
                 case "global":
                     title = WebInspector.UIString("Global");
+                    declarativeScope = false;
                     break;
             }
 
             if (!title || title === subtitle)
                 subtitle = null;
+            
+            var scopeRef;
+            if (declarativeScope)
+                scopeRef = new WebInspector.ScopeRef(i, callFrame.id, undefined);
+            else
+                scopeRef = undefined;
+            
 
-            var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scope.object), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+            var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromScopePayload(scope.object, scopeRef), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
             section.editInSelectedCallFrameWhenPaused = true;
             section.pane = this;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to