Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1025)

Unified Diff: Source/core/inspector/InjectedScriptSource.js

Issue 136333007: DevTools: Implement evaluation on async call frames. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/inspector/InjectedScriptSource.js
diff --git a/Source/core/inspector/InjectedScriptSource.js b/Source/core/inspector/InjectedScriptSource.js
index 022f48c7ef07551db8550e64ccb369deb775f787..3c7da7faf4d844777ee7dde6bb3754e8dd823b20 100644
--- a/Source/core/inspector/InjectedScriptSource.js
+++ b/Source/core/inspector/InjectedScriptSource.js
@@ -78,20 +78,21 @@ function toStringDescription(obj)
* Please use this bind, not the one from Function.prototype
* @param {function(...)} func
* @param {Object} thisObject
- * @param {...number} var_args
+ * @param {...} var_args
*/
function bind(func, thisObject, var_args)
{
var args = slice(arguments, 2);
/**
- * @param {...number} var_args
+ * @param {...} var_args
*/
function bound(var_args)
{
return func.apply(thisObject, args.concat(slice(arguments)));
}
- bound.toString = function() {
+ bound.toString = function()
+ {
return "bound: " + func;
};
return bound;
@@ -538,7 +539,8 @@ InjectedScript.prototype = {
* @return {*} resolved value
* @throws {string} error message
*/
- _resolveCallArgument: function(callArgumentJson) {
+ _resolveCallArgument: function(callArgumentJson)
+ {
var objectId = callArgumentJson.objectId;
if (objectId) {
var parsedArgId = this._parseObjectId(objectId);
@@ -564,13 +566,14 @@ InjectedScript.prototype = {
* @param {boolean} injectCommandLineAPI
* @param {boolean} returnByValue
* @param {boolean} generatePreview
+ * @param {!Object=} contextExtension
* @return {*}
*/
- _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI, returnByValue, generatePreview)
+ _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI, returnByValue, generatePreview, contextExtension)
{
try {
return { wasThrown: false,
- result: this._wrapObject(this._evaluateOn(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI), objectGroup, returnByValue, generatePreview) };
+ result: this._wrapObject(this._evaluateOn(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI, contextExtension), objectGroup, returnByValue, generatePreview) };
} catch (e) {
return this._createThrownValue(e, objectGroup);
}
@@ -597,9 +600,10 @@ InjectedScript.prototype = {
* @param {string} expression
* @param {boolean} isEvalOnCallFrame
* @param {boolean} injectCommandLineAPI
+ * @param {!Object=} contextExtension
* @return {*}
*/
- _evaluateOn: function(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI)
+ _evaluateOn: function(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI, contextExtension)
{
// Only install command line api object for the time of evaluation.
// Surround the expression in with statements to inject our command line API so that
@@ -610,7 +614,7 @@ InjectedScript.prototype = {
inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
expression = "with ((console && console._commandLineAPI) || { __proto__: null }) {\n" + expression + "\n}";
}
- var result = evalFunction.call(object, expression);
+ var result = evalFunction.call(object, expression, contextExtension);
if (objectGroup === "console")
this._lastResult = result;
return result;
@@ -621,10 +625,11 @@ InjectedScript.prototype = {
},
/**
- * @param {Object} callFrame
- * @return {!Array.<InjectedScript.CallFrameProxy>|boolean}
+ * @param {?Object} callFrame
+ * @param {number} asyncOrdinal
+ * @return {!Array.<!InjectedScript.CallFrameProxy>|boolean}
*/
- wrapCallFrames: function(callFrame)
+ wrapCallFrames: function(callFrame, asyncOrdinal)
{
if (!callFrame)
return false;
@@ -632,14 +637,15 @@ InjectedScript.prototype = {
var result = [];
var depth = 0;
do {
- result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
+ result.push(new InjectedScript.CallFrameProxy(depth++, callFrame, asyncOrdinal));
callFrame = callFrame.caller;
} while (callFrame);
return result;
},
/**
- * @param {Object} topCallFrame
+ * @param {!Object} topCallFrame
+ * @param {!Array.<!Object>} asyncCallStacks
* @param {string} callFrameId
* @param {string} expression
* @param {string} objectGroup
@@ -648,16 +654,19 @@ InjectedScript.prototype = {
* @param {boolean} generatePreview
* @return {*}
*/
- evaluateOnCallFrame: function(topCallFrame, callFrameId, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
+ evaluateOnCallFrame: function(topCallFrame, asyncCallStacks, callFrameId, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
{
- var callFrame = this.callFrameForId(topCallFrame, callFrameId);
+ var parsedCallFrameId = InjectedScriptHost.evaluate("(" + callFrameId + ")");
+ var callFrame = this._callFrameForParsedId(topCallFrame, parsedCallFrameId, asyncCallStacks);
if (!callFrame)
return "Could not find call frame with given id";
+ if (parsedCallFrameId["asyncOrdinal"])
+ return this._evaluateAndWrap(topCallFrame.evaluateGlobal, topCallFrame, expression, objectGroup, true, injectCommandLineAPI, returnByValue, generatePreview, InjectedScript.CallFrameProxy._toProtoChainedScope(callFrame));
yurys 2014/01/21 11:56:52 Why do we use topCallFrame as object argument but
aandrey 2014/01/21 13:30:22 We can evaluate only on the call frames of the cur
yurys 2014/01/21 13:54:43 Sound like we should have a version of evaluateGlo
return this._evaluateAndWrap(callFrame.evaluate, callFrame, expression, objectGroup, true, injectCommandLineAPI, returnByValue, generatePreview);
},
/**
- * @param {Object} topCallFrame
+ * @param {!Object} topCallFrame
* @param {string} callFrameId
* @return {*}
*/
@@ -673,7 +682,7 @@ InjectedScript.prototype = {
},
/**
- * @param {Object} topCallFrame
+ * @param {!Object} topCallFrame
* @param {string} callFrameId
* @return {*} a stepIn position array ready for protocol JSON or a string error
*/
@@ -690,7 +699,7 @@ InjectedScript.prototype = {
/**
* Either callFrameId or functionObjectId must be specified.
- * @param {Object} topCallFrame
+ * @param {!Object} topCallFrame
* @param {string|boolean} callFrameId or false
* @param {string|boolean} functionObjectId or false
* @param {number} scopeNumber
@@ -734,15 +743,29 @@ InjectedScript.prototype = {
},
/**
- * @param {Object} topCallFrame
+ * @param {!Object} topCallFrame
* @param {string} callFrameId
- * @return {Object}
+ * @return {?Object}
*/
callFrameForId: function(topCallFrame, callFrameId)
{
var parsedCallFrameId = InjectedScriptHost.evaluate("(" + callFrameId + ")");
- var ordinal = parsedCallFrameId["ordinal"];
+ return this._callFrameForParsedId(topCallFrame, parsedCallFrameId, []);
+ },
+
+ /**
+ * @param {!Object} topCallFrame
+ * @param {!Object} parsedCallFrameId
+ * @param {!Array.<!Object>} asyncCallStacks
+ * @return {?Object}
+ */
+ _callFrameForParsedId: function(topCallFrame, parsedCallFrameId, asyncCallStacks)
+ {
+ var asyncOrdinal = parsedCallFrameId["asyncOrdinal"] || 0; // 1-based index
yurys 2014/01/21 11:56:52 You don't really need "|| 0" part.
aandrey 2014/01/21 13:30:22 Done.
+ if (asyncOrdinal)
+ topCallFrame = asyncCallStacks[asyncOrdinal - 1];
var callFrame = topCallFrame;
+ var ordinal = parsedCallFrameId["ordinal"];
while (--ordinal >= 0 && callFrame)
callFrame = callFrame.caller;
return callFrame;
@@ -1114,10 +1137,11 @@ InjectedScript.RemoteObject.prototype = {
* @constructor
* @param {number} ordinal
* @param {!Object} callFrame
+ * @param {number} asyncOrdinal
*/
-InjectedScript.CallFrameProxy = function(ordinal, callFrame)
+InjectedScript.CallFrameProxy = function(ordinal, callFrame, asyncOrdinal)
{
- this.callFrameId = "{\"ordinal\":" + ordinal + ",\"injectedScriptId\":" + injectedScriptId + "}";
+ this.callFrameId = "{\"ordinal\":" + ordinal + ",\"injectedScriptId\":" + injectedScriptId + (asyncOrdinal ? ",\"asyncOrdinal\":" + asyncOrdinal : "") + "}";
this.functionName = (callFrame.type === "function" ? callFrame.functionName : "");
this.location = { scriptId: toString(callFrame.sourceID), lineNumber: callFrame.line, columnNumber: callFrame.column };
this.scopeChain = this._wrapScopeChain(callFrame);
@@ -1135,7 +1159,7 @@ InjectedScript.CallFrameProxy.prototype = {
{
var scopeChain = callFrame.scopeChain;
var scopeChainProxy = [];
- for (var i = 0; i < scopeChain.length; i++) {
+ for (var i = 0; i < scopeChain.length; ++i) {
var scope = InjectedScript.CallFrameProxy._createScopeJson(callFrame.scopeType(i), scopeChain[i], "backtrace");
scopeChainProxy.push(scope);
}
@@ -1149,7 +1173,8 @@ InjectedScript.CallFrameProxy.prototype = {
* @param {string} groupId
* @return {!DebuggerAgent.Scope}
*/
-InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId) {
+InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId)
+{
const GLOBAL_SCOPE = 0;
const LOCAL_SCOPE = 1;
const WITH_SCOPE = 2;
@@ -1171,6 +1196,43 @@ InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeOb
}
/**
+ * @param {!Object} callFrame
+ * @return {!Object}
+ */
+InjectedScript.CallFrameProxy._toProtoChainedScope = function(callFrame)
+{
+ /**
+ * @this {Object}
+ */
+ function getter(name)
+ {
+ return this[name];
+ }
+
+ function addProperties(object)
+ {
+ for (var o = object; injectedScript._isDefined(o); o = o.__proto__) {
+ var names = Object.getOwnPropertyNames(/** @type {!Object} */ (o));
+ for (var i = 0, n = names.length; i < n; ++i) {
+ var name = names[i];
+ if (name in proxy || name === "__proto__")
+ continue;
+ Object.prototype.__defineGetter__.call(proxy, name, bind(getter, object, name));
yurys 2014/01/21 11:56:52 Why not simply copy the value: proxy[name] = o[nam
aandrey 2014/01/21 13:30:22 To avoid side effects. For example, accessing wind
yurys 2014/01/21 13:54:43 I'm concerned about the performance here. We may e
+ }
+ }
+ return proxy;
+ }
+
+ var proxy = { __proto__: null };
+
+ var scopeChain = callFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i)
+ addProperties(scopeChain[i]);
+
+ return proxy;
+}
+
+/**
* @constructor
* @param {CommandLineAPIImpl} commandLineAPIImpl
* @param {Object} callFrame
@@ -1448,7 +1510,8 @@ CommandLineAPIImpl.prototype = {
InjectedScriptHost.monitorFunction(fn);
},
- unmonitor: function(fn) {
+ unmonitor: function(fn)
+ {
InjectedScriptHost.unmonitorFunction(fn);
},

Powered by Google App Engine
This is Rietveld 408576698