Index: third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js |
index 083ffbd255fef71fda729ee57b4a470f036bbf29..6d0bf4ea57d1106055091e23d7e75f15a62435b5 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js |
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js |
@@ -27,20 +27,31 @@ |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
+ |
/** |
* @implements {UI.ContextFlavorListener} |
- * @unrestricted |
*/ |
Components.DOMBreakpointsSidebarPane = class extends Components.BreakpointsSidebarPaneBase { |
constructor() { |
super(); |
- this._domBreakpointsSetting = Common.settings.createLocalSetting('domBreakpoints', []); |
+ this.registerRequiredCSS('components/breakpointsList.css'); |
this.listElement.classList.add('dom-breakpoints-list'); |
- /** @type {!Map<string, !Element>} */ |
- this._breakpointElements = new Map(); |
+ /** @type {!Map<!SDK.DOMDebuggerModel.DOMBreakpoint, !Components.DOMBreakpointsSidebarPane.Item>} */ |
+ this._items = new Map(); |
+ SDK.targetManager.addModelListener( |
+ SDK.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, this._breakpointAdded, this); |
+ SDK.targetManager.addModelListener( |
+ SDK.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointToggled, this._breakpointToggled, this); |
+ SDK.targetManager.addModelListener( |
+ SDK.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved, this._breakpointsRemoved, this); |
+ |
+ for (var domDebuggerModel of SDK.targetManager.models(SDK.DOMDebuggerModel)) { |
+ for (var breakpoint of domDebuggerModel.domBreakpoints()) |
+ this._addBreakpoint(breakpoint); |
+ } |
- SDK.targetManager.addModelListener(SDK.DOMModel, SDK.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); |
+ this._highlightedElement = null; |
this._update(); |
} |
@@ -50,225 +61,126 @@ Components.DOMBreakpointsSidebarPane = class extends Components.BreakpointsSideb |
*/ |
static createBreakpointHitMessage(details) { |
var messageWrapper = createElement('span'); |
+ var domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel); |
+ if (!details.auxData || !domDebuggerModel) |
+ return messageWrapper; |
+ var data = domDebuggerModel.resolveDOMBreakpointData(/** @type {!Object} */ (details.auxData)); |
+ if (!data) |
+ return messageWrapper; |
+ |
var mainElement = messageWrapper.createChild('div', 'status-main'); |
mainElement.appendChild(UI.Icon.create('smallicon-info', 'status-icon')); |
- var auxData = /** @type {!Object} */ (details.auxData); |
mainElement.appendChild(createTextNode( |
- String.sprintf('Paused on %s', Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns[auxData['type']]))); |
+ String.sprintf('Paused on %s', Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns.get(data.type)))); |
- var domModel = details.debuggerModel.target().model(SDK.DOMModel); |
- if (domModel) { |
- var subElement = messageWrapper.createChild('div', 'status-sub monospace'); |
- var node = domModel.nodeForId(auxData['nodeId']); |
- var linkifiedNode = Components.DOMPresentationUtils.linkifyNodeReference(node); |
- subElement.appendChild(linkifiedNode); |
+ var subElement = messageWrapper.createChild('div', 'status-sub monospace'); |
+ var linkifiedNode = Components.DOMPresentationUtils.linkifyNodeReference(data.node); |
+ subElement.appendChild(linkifiedNode); |
- var targetNode = auxData['targetNodeId'] ? domModel.nodeForId(auxData['targetNodeId']) : null; |
- var targetNodeLink = targetNode ? Components.DOMPresentationUtils.linkifyNodeReference(targetNode) : ''; |
+ if (data.targetNode) { |
+ var targetNodeLink = Components.DOMPresentationUtils.linkifyNodeReference(data.targetNode); |
var message; |
- if (auxData.type === Components.DOMBreakpointsSidebarPane.BreakpointTypes.SubtreeModified) { |
- if (auxData['insertion']) |
- message = targetNode === node ? 'Child %s added' : 'Descendant %s added'; |
- else |
- message = 'Descendant %s removed'; |
- subElement.appendChild(createElement('br')); |
- subElement.appendChild(UI.formatLocalized(message, [targetNodeLink])); |
- } |
- } |
- return messageWrapper; |
- } |
- |
- /** |
- * @param {!SDK.DOMNode} node |
- * @param {!UI.ContextMenu} contextMenu |
- * @param {boolean} createSubMenu |
- */ |
- populateNodeContextMenu(node, contextMenu, createSubMenu) { |
- if (node.pseudoType()) |
- return; |
- |
- var nodeBreakpoints = this._nodeBreakpoints(node); |
- |
- /** |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- * @this {Components.DOMBreakpointsSidebarPane} |
- */ |
- function toggleBreakpoint(type) { |
- if (!nodeBreakpoints.has(type)) |
- this._setBreakpoint(node, type, true); |
+ if (data.insertion) |
+ message = data.targetNode === data.node ? 'Child %s added' : 'Descendant %s added'; |
else |
- this._removeBreakpoint(node, type); |
- this._saveBreakpoints(); |
+ message = 'Descendant %s removed'; |
+ subElement.appendChild(createElement('br')); |
+ subElement.appendChild(UI.formatLocalized(message, [targetNodeLink])); |
} |
- |
- var breakpointsMenu = createSubMenu ? contextMenu.appendSubMenuItem(Common.UIString('Break on...')) : contextMenu; |
- for (var key in Components.DOMBreakpointsSidebarPane.BreakpointTypes) { |
- var type = Components.DOMBreakpointsSidebarPane.BreakpointTypes[key]; |
- var label = Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns[type]; |
- breakpointsMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints.has(type)); |
- } |
- } |
- |
- /** |
- * @param {!SDK.DOMNode} node |
- * @return {!Set<!Protocol.DOMDebugger.DOMBreakpointType>} |
- */ |
- _nodeBreakpoints(node) { |
- /** @type {!Set<!Protocol.DOMDebugger.DOMBreakpointType>} */ |
- var nodeBreakpoints = new Set(); |
- for (var element of this._breakpointElements.values()) { |
- if (element._node === node && element._checkboxElement.checked) |
- nodeBreakpoints.add(element._type); |
- } |
- return nodeBreakpoints; |
+ return messageWrapper; |
} |
/** |
- * @param {!SDK.DOMNode} node |
- * @return {boolean} |
+ * @param {!Common.Event} event |
*/ |
- hasBreakpoints(node) { |
- for (var element of this._breakpointElements.values()) { |
- if (element._node === node && element._checkboxElement.checked) |
- return true; |
- } |
- return false; |
- } |
- |
- _nodeRemoved(event) { |
- var node = event.data.node; |
- this._removeBreakpointsForNode(event.data.node); |
- var children = node.children(); |
- if (!children) |
- return; |
- for (var i = 0; i < children.length; ++i) |
- this._removeBreakpointsForNode(children[i]); |
- this._saveBreakpoints(); |
+ _breakpointAdded(event) { |
+ this._addBreakpoint(/** @type {!SDK.DOMDebuggerModel.DOMBreakpoint} */ (event.data)); |
} |
/** |
- * @param {!SDK.DOMNode} node |
+ * @param {!Common.Event} event |
*/ |
- _removeBreakpointsForNode(node) { |
- for (var element of this._breakpointElements.values()) { |
- if (element._node === node) |
- this._removeBreakpoint(element._node, element._type); |
- } |
+ _breakpointToggled(event) { |
+ var breakpoint = /** @type {!SDK.DOMDebuggerModel.DOMBreakpoint} */ (event.data); |
+ var item = this._items.get(breakpoint); |
+ if (item) |
+ item.checkbox.checked = breakpoint.enabled(); |
} |
/** |
- * @param {!SDK.DOMNode} node |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- * @param {boolean} enabled |
+ * @param {!Common.Event} event |
*/ |
- _setBreakpoint(node, type, enabled) { |
- var breakpointId = this._createBreakpointId(node.id, type); |
- var breakpointElement = this._breakpointElements.get(breakpointId); |
- if (!breakpointElement) { |
- breakpointElement = this._createBreakpointElement(node, type, enabled); |
- this._breakpointElements.set(breakpointId, breakpointElement); |
- } else { |
- breakpointElement._checkboxElement.checked = enabled; |
+ _breakpointsRemoved(event) { |
+ var breakpoints = /** @type {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>} */ (event.data); |
+ for (var breakpoint of breakpoints) { |
+ var item = this._items.get(breakpoint); |
+ if (item) { |
+ this._items.delete(breakpoint); |
+ this.removeListElement(item.element); |
+ } |
} |
- if (enabled) |
- node.domModel().target().domdebuggerAgent().setDOMBreakpoint(node.id, type); |
- node.setMarker(Components.DOMBreakpointsSidebarPane.Marker, true); |
} |
/** |
- * @param {!SDK.DOMNode} node |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- * @param {boolean} enabled |
+ * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint |
*/ |
- _createBreakpointElement(node, type, enabled) { |
+ _addBreakpoint(breakpoint) { |
var element = createElement('li'); |
- element._node = node; |
- element._type = type; |
- element.addEventListener('contextmenu', this._contextMenu.bind(this, node, type), true); |
+ element.addEventListener('contextmenu', this._contextMenu.bind(this, breakpoint), true); |
- var checkboxLabel = UI.CheckboxLabel.create('', enabled); |
+ var checkboxLabel = UI.CheckboxLabel.create('', breakpoint.enabled()); |
var checkboxElement = checkboxLabel.checkboxElement; |
- checkboxElement.addEventListener('click', this._checkboxClicked.bind(this, node, type), false); |
- element._checkboxElement = checkboxElement; |
+ checkboxElement.addEventListener('click', this._checkboxClicked.bind(this, breakpoint), false); |
element.appendChild(checkboxLabel); |
var labelElement = createElementWithClass('div', 'dom-breakpoint'); |
element.appendChild(labelElement); |
- var linkifiedNode = Components.DOMPresentationUtils.linkifyNodeReference(node); |
+ var linkifiedNode = Components.DOMPresentationUtils.linkifyNodeReference(breakpoint.node()); |
linkifiedNode.classList.add('monospace'); |
linkifiedNode.style.display = 'block'; |
labelElement.appendChild(linkifiedNode); |
var description = createElement('div'); |
- description.textContent = Components.DOMBreakpointsSidebarPane.BreakpointTypeLabels[type]; |
+ description.textContent = Components.DOMBreakpointsSidebarPane.BreakpointTypeLabels.get(breakpoint.type()); |
labelElement.appendChild(description); |
+ var item = {breakpoint: breakpoint, element: element, checkbox: checkboxElement}; |
+ element._item = item; |
+ this._items.set(breakpoint, item); |
+ |
var currentElement = this.listElement.firstChild; |
while (currentElement) { |
- if (currentElement._type && currentElement._type < element._type) |
+ if (currentElement._item && currentElement._item.breakpoint.type() < breakpoint.type()) |
break; |
currentElement = currentElement.nextSibling; |
} |
this.addListElement(element, currentElement); |
- return element; |
- } |
- |
- _removeAllBreakpoints() { |
- for (var element of this._breakpointElements.values()) |
- this._removeBreakpoint(element._node, element._type); |
- this._saveBreakpoints(); |
- } |
- |
- /** |
- * @param {!SDK.DOMNode} node |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- */ |
- _removeBreakpoint(node, type) { |
- var breakpointId = this._createBreakpointId(node.id, type); |
- var element = this._breakpointElements.get(breakpointId); |
- if (!element) |
- return; |
- |
- this.removeListElement(element); |
- this._breakpointElements.delete(breakpointId); |
- if (element._checkboxElement.checked) |
- node.domModel().target().domdebuggerAgent().removeDOMBreakpoint(node.id, type); |
- node.setMarker(Components.DOMBreakpointsSidebarPane.Marker, this.hasBreakpoints(node) ? true : null); |
} |
/** |
- * @param {!SDK.DOMNode} node |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
+ * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint |
* @param {!Event} event |
*/ |
- _contextMenu(node, type, event) { |
+ _contextMenu(breakpoint, event) { |
var contextMenu = new UI.ContextMenu(event); |
- |
- /** |
- * @this {Components.DOMBreakpointsSidebarPane} |
- */ |
- function removeBreakpoint() { |
- this._removeBreakpoint(node, type); |
- this._saveBreakpoints(); |
- } |
- contextMenu.appendItem(Common.UIString.capitalize('Remove ^breakpoint'), removeBreakpoint.bind(this)); |
- contextMenu.appendItem( |
- Common.UIString.capitalize('Remove ^all DOM breakpoints'), this._removeAllBreakpoints.bind(this)); |
+ contextMenu.appendItem(Common.UIString.capitalize('Remove ^breakpoint'), () => { |
+ breakpoint.domDebuggerModel().removeDOMBreakpoint(breakpoint.node(), breakpoint.type()); |
+ }); |
+ contextMenu.appendItem(Common.UIString.capitalize('Remove ^all DOM breakpoints'), () => { |
+ breakpoint.domDebuggerModel().removeAllDOMBreakpoints(); |
+ }); |
contextMenu.show(); |
} |
/** |
- * @param {!SDK.DOMNode} node |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- * @param {!Event} event |
+ * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint |
*/ |
- _checkboxClicked(node, type, event) { |
- if (event.target.checked) |
- node.domModel().target().domdebuggerAgent().setDOMBreakpoint(node.id, type); |
- else |
- node.domModel().target().domdebuggerAgent().removeDOMBreakpoint(node.id, type); |
- this._saveBreakpoints(); |
+ _checkboxClicked(breakpoint) { |
+ var item = this._items.get(breakpoint); |
+ if (!item) |
+ return; |
+ breakpoint.setEnabled(item.checkbox.checked); |
} |
/** |
@@ -281,133 +193,82 @@ Components.DOMBreakpointsSidebarPane = class extends Components.BreakpointsSideb |
_update() { |
var details = UI.context.flavor(SDK.DebuggerPausedDetails); |
- if (!details || details.reason !== SDK.DebuggerModel.BreakReason.DOM) { |
+ if (!details || !details.auxData || details.reason !== SDK.DebuggerModel.BreakReason.DOM) { |
if (this._highlightedElement) { |
this._highlightedElement.classList.remove('breakpoint-hit'); |
delete this._highlightedElement; |
} |
return; |
} |
- var auxData = details.auxData; |
- var breakpointId = this._createBreakpointId(auxData.nodeId, auxData.type); |
- var element = this._breakpointElements.get(breakpointId); |
+ var domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel); |
+ if (!domDebuggerModel) |
+ return; |
+ var data = domDebuggerModel.resolveDOMBreakpointData(/** @type {!Object} */ (details.auxData)); |
+ if (!data) |
+ return; |
+ |
+ var element = null; |
+ for (var item of this._items.values()) { |
+ if (item.breakpoint.node() === data.node && item.breakpoint.type() === data.type) |
+ element = item.element; |
+ } |
if (!element) |
return; |
UI.viewManager.showView('sources.domBreakpoints'); |
element.classList.add('breakpoint-hit'); |
this._highlightedElement = element; |
} |
+}; |
- /** |
- * @param {number} nodeId |
- * @param {!Protocol.DOMDebugger.DOMBreakpointType} type |
- */ |
- _createBreakpointId(nodeId, type) { |
- return nodeId + ':' + type; |
- } |
+/** @typedef {!{element: !Element, checkbox: !Element, breakpoint: !SDK.DOMDebuggerModel.DOMBreakpoint}} */ |
+Components.DOMBreakpointsSidebarPane.Item; |
- _saveBreakpoints() { |
- var breakpoints = []; |
- var storedBreakpoints = this._domBreakpointsSetting.get(); |
- for (var i = 0; i < storedBreakpoints.length; ++i) { |
- var breakpoint = storedBreakpoints[i]; |
- if (breakpoint.url !== this._inspectedURL) |
- breakpoints.push(breakpoint); |
- } |
- for (var element of this._breakpointElements.values()) { |
- breakpoints.push({ |
- url: this._inspectedURL, |
- path: element._node.path(), |
- type: element._type, |
- enabled: element._checkboxElement.checked |
- }); |
- } |
- this._domBreakpointsSetting.set(breakpoints); |
- } |
+Components.DOMBreakpointsSidebarPane.BreakpointTypeLabels = new Map([ |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.SubtreeModified, Common.UIString('Subtree Modified')], |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.AttributeModified, Common.UIString('Attribute Modified')], |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.NodeRemoved, Common.UIString('Node Removed')], |
+]); |
+ |
+Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns = new Map([ |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.SubtreeModified, Common.UIString('subtree modifications')], |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.AttributeModified, Common.UIString('attribute modifications')], |
+ [SDK.DOMDebuggerModel.DOMBreakpoint.Type.NodeRemoved, Common.UIString('node removal')], |
+]); |
+/** |
+ * @implements {UI.ContextMenu.Provider} |
+ */ |
+Components.DOMBreakpointsSidebarPane.ContextMenuProvider = class { |
/** |
- * @param {!SDK.DOMDocument} domDocument |
+ * @override |
+ * @param {!Event} event |
+ * @param {!UI.ContextMenu} contextMenu |
+ * @param {!Object} object |
*/ |
- restoreBreakpoints(domDocument) { |
- this._breakpointElements.clear(); |
- this.reset(); |
- this._inspectedURL = domDocument.documentURL; |
- var domModel = domDocument.domModel(); |
- /** @type {!Map<string, !Array<!Object>>} */ |
- var pathToBreakpoints = new Map(); |
+ appendApplicableItems(event, contextMenu, object) { |
+ var node = /** @type {!SDK.DOMNode} */ (object); |
+ if (node.pseudoType()) |
+ return; |
+ var domDebuggerModel = node.domModel().target().model(SDK.DOMDebuggerModel); |
+ if (!domDebuggerModel) |
+ return; |
/** |
- * @param {string} path |
- * @param {?Protocol.DOM.NodeId} nodeId |
- * @this {Components.DOMBreakpointsSidebarPane} |
+ * @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type |
*/ |
- function didPushNodeByPathToFrontend(path, nodeId) { |
- var node = nodeId ? domModel.nodeForId(nodeId) : null; |
- if (!node) |
- return; |
- |
- var breakpoints = pathToBreakpoints.get(path); |
- for (var i = 0; i < breakpoints.length; ++i) |
- this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled); |
+ function toggleBreakpoint(type) { |
+ if (domDebuggerModel.hasDOMBreakpoint(node, type)) |
+ domDebuggerModel.removeDOMBreakpoint(node, type); |
+ else |
+ domDebuggerModel.setDOMBreakpoint(node, type); |
} |
- var breakpoints = this._domBreakpointsSetting.get(); |
- for (var i = 0; i < breakpoints.length; ++i) { |
- var breakpoint = breakpoints[i]; |
- if (breakpoint.url !== this._inspectedURL) |
- continue; |
- var path = breakpoint.path; |
- if (!pathToBreakpoints.has(path)) { |
- pathToBreakpoints.set(path, []); |
- domModel.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); |
- } |
- pathToBreakpoints.get(path).push(breakpoint); |
+ var breakpointsMenu = contextMenu.appendSubMenuItem(Common.UIString('Break on...')); |
+ for (var key in SDK.DOMDebuggerModel.DOMBreakpoint.Type) { |
+ var type = SDK.DOMDebuggerModel.DOMBreakpoint.Type[key]; |
+ var label = Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns.get(type); |
+ breakpointsMenu.appendCheckboxItem( |
+ label, toggleBreakpoint.bind(null, type), domDebuggerModel.hasDOMBreakpoint(node, type)); |
} |
} |
}; |
- |
-Components.DOMBreakpointsSidebarPane.BreakpointTypes = { |
- SubtreeModified: 'subtree-modified', |
- AttributeModified: 'attribute-modified', |
- NodeRemoved: 'node-removed' |
-}; |
- |
-Components.DOMBreakpointsSidebarPane.BreakpointTypeLabels = { |
- 'subtree-modified': Common.UIString('Subtree Modified'), |
- 'attribute-modified': Common.UIString('Attribute Modified'), |
- 'node-removed': Common.UIString('Node Removed') |
-}; |
- |
-Components.DOMBreakpointsSidebarPane.BreakpointTypeNouns = { |
- 'subtree-modified': Common.UIString('subtree modifications'), |
- 'attribute-modified': Common.UIString('attribute modifications'), |
- 'node-removed': Common.UIString('node removal') |
-}; |
- |
-Components.DOMBreakpointsSidebarPane.Marker = 'breakpoint-marker'; |
- |
- |
-/** |
- * @unrestricted |
- */ |
-Components.DOMBreakpointsSidebarPane.Proxy = class extends UI.VBox { |
- constructor() { |
- super(); |
- this.registerRequiredCSS('components/breakpointsList.css'); |
- } |
- |
- /** |
- * @override |
- */ |
- wasShown() { |
- super.wasShown(); |
- var pane = Components.domBreakpointsSidebarPane; |
- if (pane.element.parentNode !== this.element) |
- pane.show(this.element); |
- } |
-}; |
- |
-/** |
- * @type {!Components.DOMBreakpointsSidebarPane} |
- */ |
-Components.domBreakpointsSidebarPane; |