summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);