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;