summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
authoryurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-03 12:05:54 +0000
committeryurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-03 12:05:54 +0000
commit31b488cb0b502b551f28cc0a7038b996faa49739 (patch)
tree12d330efe987b4db7e0e1f0e0bf689a57a7188af /webkit/glue
parent9994b662152d6fc3519e12aeda574a3960c576dd (diff)
downloadchromium_src-31b488cb0b502b551f28cc0a7038b996faa49739.zip
chromium_src-31b488cb0b502b551f28cc0a7038b996faa49739.tar.gz
chromium_src-31b488cb0b502b551f28cc0a7038b996faa49739.tar.bz2
1. Scope pane is populated with local variables, arguments and 'this' object for each call frame. These are only data we can extract from 'backtrace' response for now. It will be improved once we extend the debugger protocol.
2. Created descendants of ObjectPropertiesSection and ObjectPropertyTreeElement for Elements panel. This way we avoid conflicts with Scripts panel which uses same classes but with data represented in a different format. Review URL: http://codereview.chromium.org/62003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13081 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r--webkit/glue/devtools/js/debugger_agent.js194
-rw-r--r--webkit/glue/devtools/js/devtools.js85
-rw-r--r--webkit/glue/devtools/js/dom_agent.js4
3 files changed, 231 insertions, 52 deletions
diff --git a/webkit/glue/devtools/js/debugger_agent.js b/webkit/glue/devtools/js/debugger_agent.js
index 6dcb83d..647a84b 100644
--- a/webkit/glue/devtools/js/debugger_agent.js
+++ b/webkit/glue/devtools/js/debugger_agent.js
@@ -20,16 +20,16 @@ devtools.DebuggerAgent = function() {
* Mapping from script id to script info.
* @type {Object}
*/
- this.parsedScripts_ = {};
+ this.parsedScripts_ = null;
/**
* Mapping from the request id to the devtools.BreakpointInfo for the
* breakpoints whose v8 ids are not set yet. These breakpoints are waiting for
* 'setbreakpoint' responses to learn their ids in the v8 debugger.
* @see #handleSetBreakpointResponse_
- * @type {!Object}
+ * @type {Object}
*/
- this.requestNumberToBreakpointInfo_ = {};
+ this.requestNumberToBreakpointInfo_ = null;
/**
* Information on current stack top frame.
@@ -41,6 +41,16 @@ devtools.DebuggerAgent = function() {
/**
+ * Resets debugger agent to its initial state.
+ */
+ devtools.DebuggerAgent.prototype.reset = function() {
+ this.parsedScripts_ = {};
+ this.requestNumberToBreakpointInfo_ = {};
+ this.currentCallFrame_ = null;
+ };
+
+
+/**
* Asynchronously requests for all parsed script sources. Response will be
* processed in handleScriptsResponse_.
*/
@@ -50,7 +60,7 @@ devtools.DebuggerAgent.prototype.requestScripts = function() {
});
devtools.DebuggerAgent.sendCommand_(cmd);
// Force v8 execution so that it gets to processing the requested command.
- devtools.tools.evaluateJavaScript("javascript:void(0)");
+ devtools.tools.evaluateJavaScript('javascript:void(0)');
};
@@ -223,8 +233,8 @@ devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) {
if (msg.getType() == 'event') {
if (msg.getEvent() == 'break') {
this.handleBreakEvent_(msg);
- } else if (msg.getEvent() == 'exception') {
- this.handleExceptionEvent_(msg);
+ } else if (msg.getEvent() == 'exception') {
+ this.handleExceptionEvent_(msg);
}
} else if (msg.getType() == 'response') {
if (msg.getCommand() == 'scripts') {
@@ -261,11 +271,11 @@ devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) {
/**
* @param {devtools.DebuggerMessage} msg
*/
-devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) {
- var body = msg.getBody();
- debugPrint('Uncaught exception in ' + body.script.name + ':' +
- body.sourceLine + '\n' + body.sourceLineText);
- this.resumeExecution();
+devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) {
+ var body = msg.getBody();
+ debugPrint('Uncaught exception in ' + body.script.name + ':' +
+ body.sourceLine + '\n' + body.sourceLineText);
+ this.resumeExecution();
};
@@ -340,42 +350,14 @@ devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) {
var script = this.currentCallFrame_.script;
- var caller = null;
+ var callerFrame = null;
var f = null;
var frames = msg.getBody().frames;
for (var i = frames.length - 1; i>=0; i--) {
var nextFrame = frames[i];
- var func = msg.lookup(nextFrame.func.ref);
-
- // Format arguments.
- var argv = [];
- for (var j = 0; j < nextFrame.arguments.length; j++) {
- var arg = nextFrame.arguments[j];
- var val = msg.lookup(arg.value.ref);
- if (val) {
- if (val.value) {
- argv.push(arg.name + " = " + val.value);
- } else {
- argv.push(arg.name + " = [" + val.type + "]");
- }
-
- } else {
- argv.push(arg.name + " = {ref:" + arg.value.ref + "} ");
- }
- }
-
- var funcName = func.name + "(" + argv.join(", ") + ")";
-
- var f = {
- 'sourceID': script.id,
- 'line': nextFrame.line - script.lineOffset +1,
- 'type': 'function',
- 'functionName': funcName, //nextFrame.text,
- 'caller': caller,
- 'scopeChain': [],
- 'thisObject': {}
- };
- caller = f;
+ var f = devtools.DebuggerAgent.formatCallFrame_(nextFrame, script, msg);
+ f.caller = callerFrame;
+ callerFrame = f;
}
this.currentCallFrame_ = f;
@@ -385,6 +367,132 @@ devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) {
/**
+ * @param {Object} stackFrame Frame json object from 'backtrace' response.
+ * @param {Object} script Script json object from 'break' event.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ * @return {!Object} Object containing information related to the call frame in
+ * the format expected by ScriptsPanel and its panes.
+ */
+devtools.DebuggerAgent.formatCallFrame_ = function(stackFrame, script, msg) {
+ var funcName = devtools.DebuggerAgent.formatFunction_(stackFrame, msg);
+
+ var scope = {};
+
+ // Add arguments.
+ devtools.DebuggerAgent.valuesArrayToMap_(stackFrame.arguments, scope, msg);
+
+ // Add local variables.
+ devtools.DebuggerAgent.valuesArrayToMap_(stackFrame.locals, scope, msg);
+
+ var thisObject = msg.lookup(stackFrame.receiver.ref);
+ // Add variable with name 'this' to the scope.
+ scope['this'] = devtools.DebuggerAgent.formatObject_(thisObject, msg);
+
+ return {
+ 'sourceID': script.id,
+ 'line': stackFrame.line - script.lineOffset +1,
+ 'type': 'function',
+ 'functionName': funcName, //stackFrame.text,
+ 'caller': null,
+ 'localScope': scope,
+ 'scopeChain': [scope],
+ 'thisObject': thisObject,
+ };
+};
+
+
+/**
+ * Returns user-friendly representation of the function call from the stack
+ * frame.
+ * @param {Object} stackFrame Frame json object from 'backtrace' response.
+ * @return {!string} Function name with argument values.
+ */
+devtools.DebuggerAgent.formatFunction_ = function(stackFrame, msg) {
+ var func = msg.lookup(stackFrame.func.ref);
+ var argv = [];
+ for (var j = 0; j < stackFrame.arguments.length; j++) {
+ var arg = stackFrame.arguments[j];
+ var val = devtools.DebuggerAgent.formatObjectReference_(arg.value, msg);
+ argv.push(arg.name + ' = ' + val);
+ }
+ return func.name + '(' + argv.join(', ') + ')';
+};
+
+
+/**
+ * @param {Object} thisObject Receiver json object from 'backtrace' response.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ * @return {!Object} Object describing 'this' in the format expected by
+ * ScriptsPanel and its panes.
+ */
+devtools.DebuggerAgent.formatObject_ = function(thisObject, msg) {
+ var result = {};
+ devtools.DebuggerAgent.propertiesToMap_(thisObject.properties, result, msg);
+ result.protoObject = devtools.DebuggerAgent.formatObjectReference_(
+ thisObject.protoObject, msg);
+ result.prototypeObject = devtools.DebuggerAgent.formatObjectReference_(
+ thisObject.prototypeObject, msg);
+ return result;
+};
+
+
+/**
+ * For each property in 'properties' puts its name and user-friendly value into
+ * 'map'.
+ * @param {Array.<Object>} properties Receiver properties array from 'backtrace'
+ * response.
+ * @param {Object} map Result holder.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ */
+devtools.DebuggerAgent.propertiesToMap_ = function(properties, map, msg) {
+ for (var j = 0; j < properties.length; j++) {
+ var nextValue = properties[j];
+ map[nextValue.name] =devtools.DebuggerAgent.formatObjectReference_(
+ nextValue, msg);
+ }
+};
+
+
+/**
+ * For each property in 'array' puts its name and user-friendly value into
+ * 'map'.
+ * @param {Array.<Object>} array Arguments or locals array from 'backtrace'
+ * response.
+ * @param {Object} map Result holder.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ */
+devtools.DebuggerAgent.valuesArrayToMap_ = function(array, map, msg) {
+ for (var j = 0; j < array.length; j++) {
+ var nextValue = array[j];
+ map[nextValue.name] = devtools.DebuggerAgent.formatObjectReference_(
+ nextValue.value, msg);
+ }
+};
+
+
+/**
+ * @param {Object} objectRef Object reference from the debugger protocol.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ * @return {string} User-friendly representation of the reference.
+ */
+devtools.DebuggerAgent.formatObjectReference_ = function(objectRef, msg) {
+ if (!objectRef.ref) {
+ return 'illegal ref';
+ }
+
+ var object = msg.lookup(objectRef.ref);
+ if (!object) {
+ return '{ref: ' + objectRef.ref + '}';
+ }
+
+ if ('value' in object) {
+ return object.value;
+ }
+ return '[' + object.type + ']';
+};
+
+
+/**
* @param {number} scriptId Id of the script.
* @param {number} lineOffset First line 0-based offset in the containing
* document.
diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js
index 1cc682d..b3b6266 100644
--- a/webkit/glue/devtools/js/devtools.js
+++ b/webkit/glue/devtools/js/devtools.js
@@ -24,17 +24,19 @@ devtools.ToolsAgent = function() {
this.debuggerAgent_ = new devtools.DebuggerAgent();
this.domAgent_ = new devtools.DomAgent();
this.netAgent_ = new devtools.NetAgent();
- this.reset();
};
/**
- * Rests tools agent to its initial state.
+ * Resets tools agent to its initial state.
*/
devtools.ToolsAgent.prototype.reset = function() {
this.domAgent_.reset();
this.netAgent_.reset();
+ this.debuggerAgent_.reset();
+
this.domAgent_.getDocumentElementAsync();
+ this.debuggerAgent_.requestScripts();
};
@@ -168,12 +170,12 @@ var context = {}; // Used by WebCore's inspector routines.
var oldLoaded = WebInspector.loaded;
WebInspector.loaded = function() {
devtools.tools = new devtools.ToolsAgent();
+ devtools.tools.reset();
Preferences.ignoreWhitespace = false;
oldLoaded.call(this);
DevToolsHost.loaded();
- devtools.tools.getDebuggerAgent().requestScripts();
};
@@ -285,12 +287,13 @@ WebInspector.PropertiesSidebarPane.prototype.update = function(object) {
var self = this;
devtools.tools.getNodePrototypesAsync(object.id_, function(json) {
+ // Get array of prototype user-friendly names.
var prototypes = goog.json.parse(json);
for (var i = 0; i < prototypes.length; ++i) {
var prototype = {};
prototype.id_ = object.id_;
prototype.protoDepth_ = i;
- var section = new WebInspector.ObjectPropertiesSection(prototype,
+ var section = new WebInspector.SidebarObjectPropertiesSection(prototype,
prototypes[i]);
self.sections.push(section);
body.appendChild(section.element);
@@ -300,9 +303,24 @@ WebInspector.PropertiesSidebarPane.prototype.update = function(object) {
/**
+ * Our implementation of ObjectPropertiesSection for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertiesSection = function(object, title) {
+ WebInspector.ObjectPropertiesSection.call(this, object, title,
+ null /* subtitle */, null /* emptyPlaceholder */,
+ null /* ignoreHasOwnProperty */, null /* extraProperties */,
+ WebInspector.SidebarObjectPropertyTreeElement /* treeElementConstructor */
+ );
+};
+goog.inherits(WebInspector.SidebarObjectPropertiesSection,
+ WebInspector.ObjectPropertiesSection);
+
+
+/**
* @override
*/
-WebInspector.ObjectPropertiesSection.prototype.onpopulate = function() {
+WebInspector.SidebarObjectPropertiesSection.prototype.onpopulate = function() {
var nodeId = this.object.id_;
var protoDepth = this.object.protoDepth_;
var path = [];
@@ -316,9 +334,22 @@ WebInspector.ObjectPropertiesSection.prototype.onpopulate = function() {
/**
+ * Our implementation of ObjectPropertyTreeElement for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertyTreeElement = function(parentObject,
+ propertyName) {
+ WebInspector.ObjectPropertyTreeElement.call(this, parentObject, propertyName);
+};
+goog.inherits(WebInspector.SidebarObjectPropertyTreeElement,
+ WebInspector.ObjectPropertyTreeElement);
+
+
+/**
* @override
*/
-WebInspector.ObjectPropertyTreeElement.prototype.onpopulate = function() {
+WebInspector.SidebarObjectPropertyTreeElement.prototype.onpopulate =
+ function() {
var nodeId = this.parentObject.devtools$$nodeId_;
var path = this.parentObject.devtools$$path_.slice(0);
path.push(this.propertyName);
@@ -413,3 +444,45 @@ WebInspector.didGetNodePropertiesAsync_ = function(treeOutline, constructor,
treeOutline.appendChild(new constructor(obj, propertyName));
}
};
+
+
+/**
+ * Replace WebKit method with our own implementation to use our call stack
+ * representation. Original method uses Object.prototype.toString.call to
+ * learn if scope object is a JSActivation which doesn't work in Chrome.
+ */
+WebInspector.ScopeChainSidebarPane.prototype.update = function(callFrame) {
+ this.bodyElement.removeChildren();
+
+ this.sections = [];
+ this.callFrame = callFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ if (!callFrame._expandedProperties) {
+ callFrame._expandedProperties = {};
+ }
+
+ var scopeObject = callFrame.localScope;
+ var title = WebInspector.UIString("Local");
+ var subtitle = Object.describe(scopeObject, true);
+ var emptyPlaceholder = null;
+ var extraProperties = null;
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title,
+ subtitle, emptyPlaceholder, true, extraProperties,
+ WebInspector.ScopeVariableTreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ section.expanded = true;
+
+ this.sections.push(section);
+ this.bodyElement.appendChild(section.element);
+};
diff --git a/webkit/glue/devtools/js/dom_agent.js b/webkit/glue/devtools/js/dom_agent.js
index 12330b2..31d13a7 100644
--- a/webkit/glue/devtools/js/dom_agent.js
+++ b/webkit/glue/devtools/js/dom_agent.js
@@ -540,13 +540,11 @@ devtools.DomAgent = function() {
* @private
*/
this.searchResults_ = null;
-
- this.reset();
};
/**
- * Rests dom agent to its initial state.
+ * Resets dom agent to its initial state.
*/
devtools.DomAgent.prototype.reset = function() {
this.window_ = new devtools.DomWindow(this);