summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/front-end/BreakpointManager.js
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-10-22 13:02:20 +0100
committerBen Murdoch <benm@google.com>2010-10-26 15:21:41 +0100
commita94275402997c11dd2e778633dacf4b7e630a35d (patch)
treee66f56c67e3b01f22c9c23cd932271ee9ac558ed /WebCore/inspector/front-end/BreakpointManager.js
parent09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff)
downloadexternal_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip
external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz
external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'WebCore/inspector/front-end/BreakpointManager.js')
-rw-r--r--WebCore/inspector/front-end/BreakpointManager.js387
1 files changed, 334 insertions, 53 deletions
diff --git a/WebCore/inspector/front-end/BreakpointManager.js b/WebCore/inspector/front-end/BreakpointManager.js
index ec4e7cf..77ba89d 100644
--- a/WebCore/inspector/front-end/BreakpointManager.js
+++ b/WebCore/inspector/front-end/BreakpointManager.js
@@ -27,7 +27,8 @@
WebInspector.BreakpointManager = function()
{
this._breakpoints = {};
- this._xhrBreakpoints = {};
+ this._nativeBreakpoints = {};
+ this._domBreakpoints = {};
}
WebInspector.BreakpointManager.prototype = {
@@ -87,6 +88,7 @@ WebInspector.BreakpointManager.prototype = {
{
this._breakpoints = {};
delete this._oneTimeBreakpoint;
+ this._nativeBreakpoints = {};
},
_setBreakpoint: function(sourceID, url, line, enabled, condition)
@@ -127,20 +129,144 @@ WebInspector.BreakpointManager.prototype = {
InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition, didSetBreakpoint.bind(this));
},
- createXHRBreakpoint: function(url)
+ createDOMBreakpoint: function(nodeId, domEventType, disabled)
{
- if (url in this._xhrBreakpoints)
+ var frontendId = "dom:" + nodeId + ":" + domEventType;
+ if (frontendId in this._nativeBreakpoints)
return;
- this._xhrBreakpoints[url] = true;
- var breakpoint = new WebInspector.XHRBreakpoint(url);
- breakpoint.addEventListener("removed", this._xhrBreakpointRemoved.bind(this));
+ var breakpoint = new WebInspector.DOMBreakpoint(this, frontendId, nodeId, domEventType);
+ this._nativeBreakpoints[frontendId] = breakpoint;
+ this._domBreakpoints[frontendId] = breakpoint;
+ this.dispatchEventToListeners("dom-breakpoint-added", breakpoint);
+ breakpoint.enabled = !disabled;
+ return breakpoint;
+ },
+
+ createEventListenerBreakpoint: function(eventName, disabled)
+ {
+ var frontendId = eventName;
+ if (frontendId in this._nativeBreakpoints)
+ return;
+
+ var breakpoint = new WebInspector.EventListenerBreakpoint(this, frontendId, eventName);
+ this._nativeBreakpoints[frontendId] = breakpoint;
+ breakpoint.enabled = !disabled;
+ return breakpoint;
+ },
+
+ createXHRBreakpoint: function(url, disabled)
+ {
+ var frontendId = url;
+ if (frontendId in this._nativeBreakpoints)
+ return;
+
+ var breakpoint = new WebInspector.XHRBreakpoint(this, frontendId, url);
+ this._nativeBreakpoints[frontendId] = breakpoint;
this.dispatchEventToListeners("xhr-breakpoint-added", breakpoint);
+ breakpoint.enabled = !disabled
+ return breakpoint;
},
- _xhrBreakpointRemoved: function(event)
+ _removeNativeBreakpoint: function(breakpoint)
{
- delete this._xhrBreakpoints[event.target.url];
+ if (breakpoint._beingSetOnBackend)
+ return;
+ if (breakpoint.enabled)
+ this._removeNativeBreakpointFromBackend(breakpoint);
+ delete this._nativeBreakpoints[breakpoint._frontendId];
+ if (breakpoint._type === "DOM")
+ delete this._domBreakpoints[breakpoint._frontendId];
+ breakpoint.dispatchEventToListeners("removed");
+ },
+
+ _setNativeBreakpointEnabled: function(breakpoint, enabled)
+ {
+ if (breakpoint._beingSetOnBackend)
+ return;
+ if (breakpoint.enabled === enabled)
+ return;
+ if (enabled)
+ this._setNativeBreakpointOnBackend(breakpoint);
+ else
+ this._removeNativeBreakpointFromBackend(breakpoint);
+ },
+
+ _setNativeBreakpointOnBackend: function(breakpoint)
+ {
+ breakpoint._beingSetOnBackend = true;
+ var data = { type: breakpoint._type, condition: breakpoint._condition() };
+ InspectorBackend.setNativeBreakpoint(data, didSetNativeBreakpoint.bind(this));
+
+ function didSetNativeBreakpoint(backendBreakpointId)
+ {
+ breakpoint._beingSetOnBackend = false;
+ if (backendBreakpointId !== "") {
+ breakpoint._backendId = backendBreakpointId;
+ this._breakpoints[backendBreakpointId] = breakpoint;
+ }
+ breakpoint.dispatchEventToListeners("enable-changed");
+ }
+ },
+
+ _removeNativeBreakpointFromBackend: function(breakpoint)
+ {
+ InspectorBackend.removeNativeBreakpoint(breakpoint._backendId);
+ delete this._breakpoints[breakpoint._backendId]
+ delete breakpoint._backendId;
+ breakpoint.dispatchEventToListeners("enable-changed");
+ },
+
+ debuggerPaused: function(details)
+ {
+ if (details.eventType !== WebInspector.DebuggerEventTypes.NativeBreakpoint)
+ return;
+
+ var breakpoint = this._breakpoints[details.eventData.breakpointId];
+ if (!breakpoint)
+ return;
+
+ breakpoint.hit = true;
+ breakpoint.dispatchEventToListeners("hit-state-changed");
+ this._lastHitBreakpoint = breakpoint;
+
+ this.dispatchEventToListeners("breakpoint-hit", { breakpoint: breakpoint, eventData: details.eventData });
+ },
+
+ debuggerResumed: function()
+ {
+ if (!this._lastHitBreakpoint)
+ return;
+ this._lastHitBreakpoint.hit = false;
+ this._lastHitBreakpoint.dispatchEventToListeners("hit-state-changed");
+ delete this._lastHitBreakpoint;
+ },
+
+ restoreDOMBreakpoints: function()
+ {
+ var domBreakpoints = this._domBreakpoints;
+ this._domBreakpoints = {};
+
+ var breakpointsToRestore = {};
+ for (var frontendId in domBreakpoints) {
+ var breakpoint = domBreakpoints[frontendId];
+ var path = breakpoint._path;
+ if (!path)
+ continue;
+ if (!breakpointsToRestore[path]) {
+ breakpointsToRestore[path] = [];
+ InspectorBackend.pushNodeByPathToFrontend(path, restoreBreakpointsForNode.bind(this, breakpointsToRestore[path]));
+ }
+ breakpointsToRestore[path].push(breakpoint);
+ }
+
+ function restoreBreakpointsForNode(breakpoints, nodeId)
+ {
+ if (!nodeId)
+ return;
+ for (var i = 0; i < breakpoints.length; ++i)
+ this.createDOMBreakpoint(nodeId, breakpoints[i]._domEventType, !breakpoints[i].enabled);
+ }
}
}
@@ -226,82 +352,237 @@ WebInspector.Breakpoint.prototype = {
WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype;
-WebInspector.XHRBreakpoint = function(url)
+WebInspector.NativeBreakpoint = function(manager, frontendId, type)
{
- this._url = url;
- this._locked = false;
- this.enabled = true;
+ this._manager = manager;
+ this.__frontendId = frontendId;
+ this.__type = type;
}
-WebInspector.XHRBreakpoint.prototype = {
+WebInspector.NativeBreakpoint.prototype = {
get enabled()
{
- return "_id" in this;
+ return "_backendId" in this;
},
set enabled(enabled)
{
- if (this._locked)
- return;
- if (this.enabled === enabled)
- return;
- if (enabled)
- this._setOnBackend();
- else
- this._removeFromBackend();
+ this._manager._setNativeBreakpointEnabled(this, enabled);
},
- get url()
+ remove: function()
{
- return this._url;
+ this._manager._removeNativeBreakpoint(this);
+ this._onRemove();
},
- formatLabel: function()
+ get _frontendId()
{
- var label = "";
- if (!this.url.length)
- label = WebInspector.UIString("Any XHR");
- else
- label = WebInspector.UIString("URL contains \"%s\"", this.url);
- return label;
+ return this.__frontendId;
},
- compareTo: function(other)
+ get _type()
{
- if (this.url != other.url)
- return this.url < other.url ? -1 : 1;
+ return this.__type;
+ },
+
+ _compare: function(x, y)
+ {
+ if (x !== y)
+ return x < y ? -1 : 1;
return 0;
},
- remove: function()
+ _onRemove: function()
{
- if (this._locked)
- return;
- if (this.enabled)
- this._removeFromBackend();
- this.dispatchEventToListeners("removed");
+ }
+}
+
+WebInspector.NativeBreakpoint.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DOMBreakpoint = function(manager, frontendId, nodeId, domEventType)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "DOM");
+ this._nodeId = nodeId;
+ this._domEventType = domEventType;
+
+ var node = WebInspector.domAgent.nodeForId(this._nodeId);
+ if (node) {
+ node.breakpoints[this._domEventType] = this;
+ this._path = node.path();
+ }
+}
+
+WebInspector.DOMBreakpoint.prototype = {
+ click: function()
+ {
+ WebInspector.updateFocusedNode(this._nodeId);
},
- _setOnBackend: function()
+ compareTo: function(other)
{
- this._locked = true;
- var data = { type: "XHR", condition: { url: this.url } };
- InspectorBackend.setNativeBreakpoint(data, didSet.bind(this));
+ return this._compare(this._domEventType, other._domEventType);
+ },
- function didSet(breakpointId)
+ populateLabelElement: function(element)
+ {
+ element.appendChild(WebInspector.panels.elements.linkifyNodeById(this._nodeId));
+ element.appendChild(document.createTextNode(" - "));
+ element.appendChild(document.createTextNode(WebInspector.domBreakpointTypeLabel(this._domEventType)));
+ },
+
+ populateStatusMessageElement: function(element, eventData)
+ {
+ var substitutions = [WebInspector.domBreakpointTypeLabel(this._domEventType), WebInspector.panels.elements.linkifyNodeById(this._nodeId)];
+ var formatters = {
+ s: function(substitution)
+ {
+ return substitution;
+ }
+ };
+ function append(a, b)
{
- this._locked = false;
- this._id = breakpointId;
- this.dispatchEventToListeners("enable-changed");
+ if (typeof b === "string")
+ b = document.createTextNode(b);
+ element.appendChild(b);
}
+ if (this._domEventType === WebInspector.DOMBreakpointTypes.SubtreeModified) {
+ var targetNode = WebInspector.panels.elements.linkifyNodeById(eventData.targetNodeId);
+ if (eventData.insertion) {
+ if (eventData.targetNodeId !== this._nodeId)
+ WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", substitutions.concat(targetNode), formatters, "", append);
+ else
+ WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.", substitutions, formatters, "", append);
+ } else
+ WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", substitutions.concat(targetNode), formatters, "", append);
+ } else
+ WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s.", substitutions, formatters, "", append);
},
- _removeFromBackend: function()
+ _condition: function()
{
- InspectorBackend.removeNativeBreakpoint(this._id);
- delete this._id;
- this.dispatchEventToListeners("enable-changed");
+ return { nodeId: this._nodeId, type: this._domEventType };
+ },
+
+ _onRemove: function()
+ {
+ var node = WebInspector.domAgent.nodeForId(this._nodeId);
+ if (node)
+ delete node.breakpoints[this._domEventType];
}
}
-WebInspector.XHRBreakpoint.prototype.__proto__ = WebInspector.Object.prototype;
+WebInspector.DOMBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.EventListenerBreakpoint = function(manager, frontendId, eventName)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "EventListener");
+ this._eventName = eventName;
+}
+
+WebInspector.EventListenerBreakpoint.prototype = {
+ compareTo: function(other)
+ {
+ return this._compare(this._eventName, other._eventName);
+ },
+
+ populateLabelElement: function(element)
+ {
+ element.appendChild(document.createTextNode(this._uiEventName()));
+ },
+
+ populateStatusMessageElement: function(element, eventData)
+ {
+ var status = WebInspector.UIString("Paused on a \"%s\" Event Listener.", this._uiEventName());
+ element.appendChild(document.createTextNode(status));
+ },
+
+ _condition: function()
+ {
+ return { eventName: this._eventName };
+ },
+
+ _uiEventName: function()
+ {
+ if (!WebInspector.EventListenerBreakpoint._uiEventNames) {
+ WebInspector.EventListenerBreakpoint._uiEventNames = {
+ "instrumentation:setTimer": WebInspector.UIString("Set Timer"),
+ "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
+ "instrumentation:timerFired": WebInspector.UIString("Timer Fired")
+ };
+ }
+ return WebInspector.EventListenerBreakpoint._uiEventNames[this._eventName] || this._eventName.substring(this._eventName.indexOf(":") + 1);
+ }
+}
+
+WebInspector.EventListenerBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.XHRBreakpoint = function(manager, frontendId, url)
+{
+ WebInspector.NativeBreakpoint.call(this, manager, frontendId, "XHR");
+ this._url = url;
+}
+
+WebInspector.XHRBreakpoint.prototype = {
+ compareTo: function(other)
+ {
+ return this._compare(this._url, other._url);
+ },
+
+ populateLabelElement: function(element)
+ {
+ var label;
+ if (!this._url.length)
+ label = WebInspector.UIString("Any XHR");
+ else
+ label = WebInspector.UIString("URL contains \"%s\"", this._url);
+ element.appendChild(document.createTextNode(label));
+ },
+
+ populateStatusMessageElement: function(element)
+ {
+ var status = WebInspector.UIString("Paused on a XMLHttpRequest.");
+ element.appendChild(document.createTextNode(status));
+ },
+
+ _condition: function()
+ {
+ return { url: this._url };
+ }
+}
+
+WebInspector.XHRBreakpoint.prototype.__proto__ = WebInspector.NativeBreakpoint.prototype;
+
+WebInspector.DebuggerEventTypes = {
+ JavaScriptPause: 0,
+ JavaScriptBreakpoint: 1,
+ NativeBreakpoint: 2
+};
+
+WebInspector.DOMBreakpointTypes = {
+ SubtreeModified: 0,
+ AttributeModified: 1,
+ NodeRemoved: 2
+};
+
+WebInspector.domBreakpointTypeLabel = function(type)
+{
+ if (!WebInspector._DOMBreakpointTypeLabels) {
+ WebInspector._DOMBreakpointTypeLabels = {};
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified");
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified");
+ WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed");
+ }
+ return WebInspector._DOMBreakpointTypeLabels[type];
+}
+
+WebInspector.domBreakpointTypeContextMenuLabel = function(type)
+{
+ if (!WebInspector._DOMBreakpointTypeContextMenuLabels) {
+ WebInspector._DOMBreakpointTypeContextMenuLabels = {};
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications");
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications");
+ WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Break on Node Removal");
+ }
+ return WebInspector._DOMBreakpointTypeContextMenuLabels[type];
+}