Commit e77c8b3a authored by aandrey@chromium.org's avatar aandrey@chromium.org

DevTools: Add context menu option for objects to save to temp variable.

Adding ability to access objects from printed ObjectPropertySections (console, scopes pane and etc.).

BUG=306120
R=pfeldman

Review URL: https://codereview.chromium.org/201613004

git-svn-id: svn://svn.chromium.org/blink/trunk@169649 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent df86b335
...@@ -156,4 +156,16 @@ InspectorTest.waitUntilMessageReceived = function(callback) ...@@ -156,4 +156,16 @@ InspectorTest.waitUntilMessageReceived = function(callback)
InspectorTest.addSniffer(WebInspector.console, "addMessage", callback, false); InspectorTest.addSniffer(WebInspector.console, "addMessage", callback, false);
} }
InspectorTest.waitUntilNthMessageReceived = function(count, callback)
{
function override()
{
if (--count === 0)
InspectorTest.safeWrap(callback)();
else
InspectorTest.addSniffer(WebInspector.console, "addMessage", override, false);
}
InspectorTest.addSniffer(WebInspector.console, "addMessage", override, false);
}
} }
Tests saving objects to temporary variables.
Number of expressions: 11
Names [temp3..temp7] are reserved
temp1
42
temp2
"foo string"
temp8
NaN
temp9
Infinity
temp10
-Infinity
temp11
-0
temp12
[1, 2, NaN, -0, null, undefined]
temp13
Object {foo: "bar"}
temp14
[1, 2, 3, 4]
temp15
function func() {}
temp16
Error {stack: (...), message: "errr"}
<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="../../http/tests/inspector/console-test.js"></script>
<script>
function onload()
{
for (var i = 3; i < 8; ++i)
window["temp" + i] = "Reserved";
runTest();
}
function test()
{
WebInspector.inspectorView.showPanel("sources");
var expressions = [
"42",
"'foo string'",
"NaN",
"Infinity",
"-Infinity",
"-0",
"[1, 2, NaN, -0, null, undefined]",
"({ foo: 'bar' })",
"(function(){ return arguments; })(1,2,3,4)",
"(function func() {})",
"new Error('errr')"
];
InspectorTest.addResult("Number of expressions: " + expressions.length);
InspectorTest.addResult("Names [temp3..temp7] are reserved\n");
function evaluateNext()
{
var expression = expressions.shift();
if (!expression) {
dumpConsoleMessages();
return;
}
function didEvaluate(result, wasThrown)
{
InspectorTest.assertTrue(!wasThrown, "FAIL: was thrown. Expression: " + expression);
WebInspector.panels.sources._saveToTempVariable(result);
InspectorTest.waitUntilNthMessageReceived(2, evaluateNext);
}
WebInspector.runtimeModel.evaluate(expression, "console", true, undefined, undefined, undefined, didEvaluate);
}
function dumpConsoleMessages()
{
InspectorTest.dumpConsoleMessages();
InspectorTest.completeTest();
}
evaluateNext();
}
</script>
</head>
<body onload="onload()">
<p>
Tests saving objects to temporary variables.
</p>
</body>
</html>
...@@ -178,6 +178,34 @@ WebInspector.RemoteObject.type = function(remoteObject) ...@@ -178,6 +178,34 @@ WebInspector.RemoteObject.type = function(remoteObject)
return remoteObject.type; return remoteObject.type;
} }
/**
* @param {!RuntimeAgent.RemoteObject|!WebInspector.RemoteObject} remoteObject
* @return {!RuntimeAgent.CallArgument}
*/
WebInspector.RemoteObject.toCallArgument = function(remoteObject)
{
var type = /** @type {!RuntimeAgent.CallArgumentType.<string>} */ (remoteObject.type);
var value = remoteObject.value;
// Handle special numbers: NaN, Infinity, -Infinity, -0.
if (type === "number") {
switch (remoteObject.description) {
case "NaN":
case "Infinity":
case "-Infinity":
case "-0":
value = remoteObject.description;
break;
}
}
return {
value: value,
objectId: remoteObject.objectId,
type: type
};
}
/** /**
* @constructor * @constructor
* @extends {WebInspector.RemoteObject} * @extends {WebInspector.RemoteObject}
...@@ -390,7 +418,7 @@ WebInspector.RemoteObjectImpl.prototype = { ...@@ -390,7 +418,7 @@ WebInspector.RemoteObjectImpl.prototype = {
// where property was defined; so do we. // where property was defined; so do we.
var setPropertyValueFunction = "function(a, b) { this[a] = b; }"; var setPropertyValueFunction = "function(a, b) { this[a] = b; }";
var argv = [{ value: name }, this._toCallArgument(result)] var argv = [{ value: name }, WebInspector.RemoteObject.toCallArgument(result)]
this._runtimeAgent.callFunctionOn(this._objectId, setPropertyValueFunction, argv, true, undefined, undefined, propertySetCallback); this._runtimeAgent.callFunctionOn(this._objectId, setPropertyValueFunction, argv, true, undefined, undefined, propertySetCallback);
/** /**
...@@ -408,15 +436,6 @@ WebInspector.RemoteObjectImpl.prototype = { ...@@ -408,15 +436,6 @@ WebInspector.RemoteObjectImpl.prototype = {
} }
}, },
/**
* @param {!RuntimeAgent.RemoteObject} object
* @return {!RuntimeAgent.CallArgument}
*/
_toCallArgument: function(object)
{
return { value: object.value, objectId: object.objectId, type: /** @type {!RuntimeAgent.CallArgumentType.<string>} */ (object.type) };
},
/** /**
* @param {function(?DOMAgent.NodeId)} callback * @param {function(?DOMAgent.NodeId)} callback
*/ */
...@@ -655,7 +674,7 @@ WebInspector.ScopeRemoteObject.prototype = { ...@@ -655,7 +674,7 @@ WebInspector.ScopeRemoteObject.prototype = {
*/ */
doSetObjectPropertyValue: function(result, name, callback) doSetObjectPropertyValue: function(result, name, callback)
{ {
this._debuggerAgent.setVariableValue(this._scopeRef.number, name, this._toCallArgument(result), this._scopeRef.callFrameId, this._scopeRef.functionId, setVariableValueCallback.bind(this)); this._debuggerAgent.setVariableValue(this._scopeRef.number, name, WebInspector.RemoteObject.toCallArgument(result), this._scopeRef.callFrameId, this._scopeRef.functionId, setVariableValueCallback.bind(this));
/** /**
* @param {?Protocol.Error} error * @param {?Protocol.Error} error
......
...@@ -1267,7 +1267,7 @@ WebInspector.SourcesPanel.prototype = { ...@@ -1267,7 +1267,7 @@ WebInspector.SourcesPanel.prototype = {
appendApplicableItems: function(event, contextMenu, target) appendApplicableItems: function(event, contextMenu, target)
{ {
this._appendUISourceCodeItems(event, contextMenu, target); this._appendUISourceCodeItems(event, contextMenu, target);
this._appendFunctionItems(contextMenu, target); this._appendRemoteObjectItems(contextMenu, target);
}, },
_suggestReload: function() _suggestReload: function()
...@@ -1385,20 +1385,89 @@ WebInspector.SourcesPanel.prototype = { ...@@ -1385,20 +1385,89 @@ WebInspector.SourcesPanel.prototype = {
* @param {!WebInspector.ContextMenu} contextMenu * @param {!WebInspector.ContextMenu} contextMenu
* @param {!Object} target * @param {!Object} target
*/ */
_appendFunctionItems: function(contextMenu, target) _appendRemoteObjectItems: function(contextMenu, target)
{ {
if (!(target instanceof WebInspector.RemoteObject)) if (!(target instanceof WebInspector.RemoteObject))
return; return;
var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target); var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target);
if (remoteObject.type !== "function") contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Store as global variable" : "Store as Global Variable"), this._saveToTempVariable.bind(this, remoteObject));
return; if (remoteObject.type === "function")
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), this._showFunctionDefinition.bind(this, remoteObject));
},
/**
* @param {!WebInspector.RemoteObject} remoteObject
*/
_saveToTempVariable: function(remoteObject)
{
WebInspector.runtimeModel.evaluate("window", "", false, true, false, false, didGetGlobalObject);
/**
* @param {?WebInspector.RemoteObject} global
* @param {boolean=} wasThrown
*/
function didGetGlobalObject(global, wasThrown)
{
/**
* @suppressReceiverCheck
* @this {Window}
*/
function remoteFunction(value)
{
var prefix = "temp";
var index = 1;
while ((prefix + index) in this)
++index;
var name = prefix + index;
this[name] = value;
return name;
}
if (wasThrown || !global)
failedToSave(global);
else
global.callFunction(remoteFunction, [WebInspector.RemoteObject.toCallArgument(remoteObject)], didSave.bind(null, global));
}
/**
* @param {!WebInspector.RemoteObject} global
* @param {?WebInspector.RemoteObject} result
* @param {boolean=} wasThrown
*/
function didSave(global, result, wasThrown)
{
global.release();
if (wasThrown || !result || result.type !== "string")
failedToSave(result);
else
WebInspector.console.evaluate(result.value);
}
/**
* @param {?WebInspector.RemoteObject} result
*/
function failedToSave(result)
{
var message = WebInspector.UIString("Failed to save to temp variable.");
if (result) {
message += " " + result.description;
result.release();
}
WebInspector.console.showErrorMessage(message)
}
},
/**
* @param {!WebInspector.RemoteObject} remoteObject
*/
_showFunctionDefinition: function(remoteObject)
{
/** /**
* @param {?Protocol.Error} error * @param {?Protocol.Error} error
* @param {!DebuggerAgent.FunctionDetails} response * @param {!DebuggerAgent.FunctionDetails} response
* @this {WebInspector.SourcesPanel} * @this {WebInspector.SourcesPanel}
*/ */
function didGetDetails(error, response) function didGetFunctionDetails(error, response)
{ {
if (error) { if (error) {
console.error(error); console.error(error);
...@@ -1411,16 +1480,7 @@ WebInspector.SourcesPanel.prototype = { ...@@ -1411,16 +1480,7 @@ WebInspector.SourcesPanel.prototype = {
this.showUILocation(uiLocation, true); this.showUILocation(uiLocation, true);
} }
DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetFunctionDetails.bind(this));
/**
* @this {WebInspector.SourcesPanel}
*/
function revealFunction()
{
DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), revealFunction.bind(this));
}, },
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment