Changeset 247053 in webkit
- Timestamp:
- Jul 2, 2019 9:15:55 AM (5 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r247052 r247053 1 2019-07-02 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: DOM Debugger: descendant breakpoints should be able to be enabled/disabled/deleted from a collapsed parent 4 https://bugs.webkit.org/show_bug.cgi?id=199332 5 6 Reviewed by Matt Baker. 7 8 * UserInterface/Controllers/DOMDebuggerManager.js: 9 (WI.DOMDebuggerManager.prototype.get domBreakpoints): 10 (WI.DOMDebuggerManager.prototype.domBreakpointsForNode): 11 (WI.DOMDebuggerManager.prototype.domBreakpointsInSubtree): Added. 12 (WI.DOMDebuggerManager.prototype.removeDOMBreakpoint): 13 (WI.DOMDebuggerManager.prototype._detachDOMBreakpoint): 14 (WI.DOMDebuggerManager.prototype._detachBreakpointsForFrame): 15 (WI.DOMDebuggerManager.prototype._speculativelyResolveDOMBreakpointsForURL): 16 (WI.DOMDebuggerManager.prototype._resolveDOMBreakpoint): 17 Provide a way of getting a "summary" array of `DOMBreakpoint`s for all descendant nodes. 18 Rework the data structure for holding `DOMBreakpoint`s to use a `Multimap` so no duplicates 19 can be added (it uses a `Set` instead of an `Array`). 20 21 * UserInterface/Views/DOMTreeElement.js: 22 (WI.DOMTreeElement): 23 (WI.DOMTreeElement.prototype.get hasBreakpoint): 24 (WI.DOMTreeElement.prototype.set breakpointStatus): 25 (WI.DOMTreeElement.prototype.bindRevealDescendantBreakpointsMenuItemHandler): Added. 26 (WI.DOMTreeElement.prototype._subtreeBreakpointChanged): Added. 27 (WI.DOMTreeElement.prototype._updateBreakpointStatus): 28 (WI.DOMTreeElement.prototype._statusImageContextmenu): 29 (WI.DOMTreeElement.prototype.subtreeBreakpointCountDidChange): Deleted. 30 * UserInterface/Views/DOMTreeOutline.js: 31 (WI.DOMTreeOutline.prototype.populateContextMenu): 32 * UserInterface/Views/ContextMenuUtilities.js: 33 (WI.appendContextMenuItemsForDOMNode): 34 (WI.appendContextMenuItemsForDOMNodeBreakpoints): 35 Keep track of the actual descendant `DOMNodeTreeElement` that have breakpoints, rather than 36 just a count, so that the "Reveal Descendant Breakpoints" action is able to access them. 37 Change "Reveal Descendant Breakpoints" to reveal and select all descendant breakpoints 38 instead of just the first one. 39 Drive-by: don't remove specific (event) listener breakpoints when invoking the 40 "Delete Descendant Breakpoints" action, as that's not obvious from the UI. 41 42 * UserInterface/Controllers/BreakpointPopoverController.js: 43 (WI.BreakpointPopoverController.prototype.appendContextMenuItems): 44 * UserInterface/Views/DOMBreakpointTreeElement.js: 45 (WI.DOMBreakpointTreeElement.prototype.populateContextMenu): 46 * UserInterface/Views/DOMNodeTreeElement.js: 47 (WI.DOMNodeTreeElement.prototype.populateContextMenu): 48 * UserInterface/Views/EventBreakpointTreeElement.js: 49 (WI.EventBreakpointTreeElement.prototype.populateContextMenu): 50 * UserInterface/Views/URLBreakpointTreeElement.js: 51 (WI.URLBreakpointTreeElement.prototype.populateContextMenu): 52 Remove the separator before "Delete Breakpoint" so all breakpoint actions are in the same section. 53 54 * Localizations/en.lproj/localizedStrings.js: 55 * UserInterface/Base/Multimap.js: 56 (Multimap.prototype.get size): Added. 57 1 58 2019-07-02 Matt Baker <mattbaker@apple.com> 2 59 -
trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
r247042 r247053 325 325 localizedStrings["Delete Breakpoint"] = "Delete Breakpoint"; 326 326 localizedStrings["Delete Breakpoints"] = "Delete Breakpoints"; 327 localizedStrings["Delete Descendant Breakpoints"] = "Delete Descendant Breakpoints"; 327 328 localizedStrings["Demo Audit"] = "Demo Audit"; 328 329 localizedStrings["Detach into separate window"] = "Detach into separate window"; … … 334 335 localizedStrings["Disable Breakpoint"] = "Disable Breakpoint"; 335 336 localizedStrings["Disable Breakpoints"] = "Disable Breakpoints"; 337 localizedStrings["Disable Descendant Breakpoints"] = "Disable Descendant Breakpoints"; 336 338 localizedStrings["Disable Event Listener"] = "Disable Event Listener"; 337 339 localizedStrings["Disable ICE Candidate Restrictions"] = "Disable ICE Candidate Restrictions"; … … 405 407 localizedStrings["Enable Breakpoint"] = "Enable Breakpoint"; 406 408 localizedStrings["Enable Breakpoints"] = "Enable Breakpoints"; 409 localizedStrings["Enable Descendant Breakpoints"] = "Enable Descendant Breakpoints"; 407 410 localizedStrings["Enable Event Listener"] = "Enable Event Listener"; 408 411 localizedStrings["Enable Layers Tab"] = "Enable Layers Tab"; … … 883 886 localizedStrings["Return type for function: %s"] = "Return type for function: %s"; 884 887 localizedStrings["Return value is not an object, string, or boolean"] = "Return value is not an object, string, or boolean"; 885 localizedStrings["Reveal Breakpoint"] = "Reveal Breakpoint";888 localizedStrings["Reveal Descendant Breakpoints"] = "Reveal Descendant Breakpoints"; 886 889 /* Open Elements tab and select this node in DOM tree */ 887 890 localizedStrings["Reveal in DOM Tree"] = "Reveal in DOM Tree"; -
trunk/Source/WebInspectorUI/UserInterface/Base/Multimap.js
r243264 r247053 35 35 36 36 // Public 37 38 get size() 39 { 40 return this._map.size; 41 } 37 42 38 43 has(key, value) -
trunk/Source/WebInspectorUI/UserInterface/Controllers/BreakpointPopoverController.js
r243226 r247053 89 89 contextMenu.appendItem(WI.UIString("Set to Automatically Continue"), toggleAutoContinue); 90 90 91 if (WI.debuggerManager.isBreakpointRemovable(breakpoint)) { 92 contextMenu.appendSeparator(); 91 if (WI.debuggerManager.isBreakpointRemovable(breakpoint)) 93 92 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), removeBreakpoint); 94 }95 93 96 94 if (breakpoint._sourceCodeLocation.hasMappedLocation()) { -
trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js
r246523 r247053 147 147 let frame = frames.shift(); 148 148 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frame.id); 149 if (domBreakpointNodeIdentifierMap) { 150 for (let breakpoints of domBreakpointNodeIdentifierMap.values()) 151 resolvedBreakpoints = resolvedBreakpoints.concat(breakpoints); 152 } 149 if (domBreakpointNodeIdentifierMap) 150 resolvedBreakpoints = resolvedBreakpoints.concat(Array.from(domBreakpointNodeIdentifierMap.values())); 153 151 154 152 frames.push(...frame.childFrameCollection); … … 179 177 180 178 let breakpoints = domBreakpointNodeIdentifierMap.get(node.id); 181 return breakpoints ? breakpoints.slice() : []; 179 return breakpoints ? Array.from(breakpoints) : []; 180 } 181 182 domBreakpointsInSubtree(node) 183 { 184 console.assert(node instanceof WI.DOMNode); 185 186 let breakpoints = []; 187 188 if (node.children) { 189 let children = Array.from(node.children); 190 while (children.length) { 191 let child = children.pop(); 192 if (child.children) 193 children = children.concat(child.children); 194 breakpoints = breakpoints.concat(this.domBreakpointsForNode(child)); 195 } 196 } 197 198 return breakpoints; 182 199 } 183 200 … … 216 233 } 217 234 218 let nodeIdentifier = breakpoint.domNodeIdentifier;219 console.assert(nodeIdentifier, "Cannot remove unresolved DOM breakpoint.");220 if (!nodeIdentifier)221 return;222 223 235 this._detachDOMBreakpoint(breakpoint); 224 236 … … 228 240 // We should get the target associated with the nodeIdentifier of this breakpoint. 229 241 let target = WI.assumingMainTarget(); 230 target.DOMDebuggerAgent.removeDOMBreakpoint( nodeIdentifier, breakpoint.type);242 target.DOMDebuggerAgent.removeDOMBreakpoint(breakpoint.domNodeIdentifier, breakpoint.type); 231 243 } 232 244 … … 407 419 return; 408 420 409 let breakpoints = domBreakpointNodeIdentifierMap.get(nodeIdentifier); 410 console.assert(breakpoints, "Missing DOM breakpoints for node.", node); 411 if (!breakpoints) 412 return; 413 414 breakpoints.remove(breakpoint, true); 415 416 if (breakpoints.length) 417 return; 418 419 domBreakpointNodeIdentifierMap.delete(nodeIdentifier); 421 domBreakpointNodeIdentifierMap.delete(nodeIdentifier, breakpoint); 420 422 421 423 if (!domBreakpointNodeIdentifierMap.size) … … 431 433 this._domBreakpointFrameIdentifierMap.delete(frame.id); 432 434 433 for (let breakpoints of domBreakpointNodeIdentifierMap.values()) { 434 for (let breakpoint of breakpoints) 435 breakpoint.domNodeIdentifier = null; 436 } 435 for (let breakpoint of domBreakpointNodeIdentifierMap.values()) 436 breakpoint.domNodeIdentifier = null; 437 437 } 438 438 … … 448 448 449 449 WI.domManager.pushNodeByPathToFrontend(breakpoint.path, (nodeIdentifier) => { 450 if (breakpoint.domNodeIdentifier) { 451 // This breakpoint may have been resolved by a node being inserted before this 452 // callback is invoked. If so, the `nodeIdentifier` should match, so don't try 453 // to resolve it again as it would've already been resolved. 454 console.assert(breakpoint.domNodeIdentifier === nodeIdentifier); 455 return; 456 } 457 450 458 if (nodeIdentifier) 451 459 this._resolveDOMBreakpoint(breakpoint, nodeIdentifier); … … 464 472 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frameIdentifier); 465 473 if (!domBreakpointNodeIdentifierMap) { 466 domBreakpointNodeIdentifierMap = new M ap;474 domBreakpointNodeIdentifierMap = new Multimap; 467 475 this._domBreakpointFrameIdentifierMap.set(frameIdentifier, domBreakpointNodeIdentifierMap); 468 476 } 469 477 470 let breakpoints = domBreakpointNodeIdentifierMap.get(nodeIdentifier); 471 if (breakpoints) 472 breakpoints.push(breakpoint); 473 else 474 domBreakpointNodeIdentifierMap.set(nodeIdentifier, [breakpoint]); 478 domBreakpointNodeIdentifierMap.add(nodeIdentifier, breakpoint); 475 479 476 480 breakpoint.domNodeIdentifier = nodeIdentifier; -
trunk/Source/WebInspectorUI/UserInterface/Views/ContextMenuUtilities.js
r246532 r247053 225 225 contextMenu.appendSeparator(); 226 226 227 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, domNode );227 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, domNode, options); 228 228 } 229 229 … … 285 285 }; 286 286 287 WI.appendContextMenuItemsForDOMNodeBreakpoints = function(contextMenu, domNode, {allowEditing}= {})287 WI.appendContextMenuItemsForDOMNodeBreakpoints = function(contextMenu, domNode, options = {}) 288 288 { 289 289 if (contextMenu.__domBreakpointItemsAdded) … … 292 292 contextMenu.__domBreakpointItemsAdded = true; 293 293 294 let breakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode); 295 296 contextMenu.appendSeparator(); 297 294 298 let subMenu = contextMenu.appendSubMenuItem(WI.UIString("Break on")); 295 296 let breakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode);297 let keyValuePairs = breakpoints.map((breakpoint) => [breakpoint.type, breakpoint]);298 let breakpointsByType = new Map(keyValuePairs);299 299 300 300 for (let type of Object.values(WI.DOMBreakpoint.Type)) { 301 301 let label = WI.DOMBreakpointTreeElement.displayNameForType(type); 302 let breakpoint = breakpoints ByType.get(type);302 let breakpoint = breakpoints.find((breakpoint) => breakpoint.type === type); 303 303 304 304 subMenu.appendCheckboxItem(label, function() { … … 307 307 else 308 308 WI.domDebuggerManager.addDOMBreakpoint(new WI.DOMBreakpoint(domNode, type)); 309 }, !!breakpoint , false);310 } 311 312 if (allowEditing) {313 contextMenu.appendSeparator(); 314 309 }, !!breakpoint); 310 } 311 312 contextMenu.appendSeparator(); 313 314 if (breakpoints.length) { 315 315 let shouldEnable = breakpoints.some((breakpoint) => breakpoint.disabled); 316 let label = shouldEnable ? WI.UIString("Enable Breakpoints") : WI.UIString("Disable Breakpoints"); 317 contextMenu.appendItem(label, () => { 318 breakpoints.forEach((breakpoint) => breakpoint.disabled = !shouldEnable); 319 }); 320 321 contextMenu.appendItem(WI.UIString("Delete Breakpoints"), function() { 322 WI.domDebuggerManager.removeDOMBreakpointsForNode(domNode); 323 WI.domManager.removeEventListenerBreakpointsForNode(domNode); 324 }); 316 contextMenu.appendItem(shouldEnable ? WI.UIString("Enable Breakpoint") : WI.UIString("Disable Breakpoint"), () => { 317 for (let breakpoint of breakpoints) 318 breakpoint.disabled = !shouldEnable; 319 }); 320 321 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => { 322 for (let breakpoint of breakpoints) 323 WI.domDebuggerManager.removeDOMBreakpoint(breakpoint); 324 }); 325 326 contextMenu.appendSeparator(); 327 } 328 329 let subtreeBreakpoints = WI.domDebuggerManager.domBreakpointsInSubtree(domNode); 330 if (subtreeBreakpoints.length) { 331 if (options.revealDescendantBreakpointsMenuItemHandler) 332 contextMenu.appendItem(WI.UIString("Reveal Descendant Breakpoints"), options.revealDescendantBreakpointsMenuItemHandler); 333 334 let subtreeShouldEnable = subtreeBreakpoints.some((breakpoint) => breakpoint.disabled); 335 contextMenu.appendItem(subtreeShouldEnable ? WI.UIString("Enable Descendant Breakpoints") : WI.UIString("Disable Descendant Breakpoints"), () => { 336 for (let subtreeBreakpoint of subtreeBreakpoints) 337 subtreeBreakpoint.disabled = !subtreeShouldEnable; 338 }); 339 340 contextMenu.appendItem(WI.UIString("Delete Descendant Breakpoints"), () => { 341 for (let subtreeBreakpoint of subtreeBreakpoints) 342 WI.domDebuggerManager.removeDOMBreakpoint(subtreeBreakpoint); 343 }); 344 345 contextMenu.appendSeparator(); 325 346 } 326 347 }; -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMBreakpointTreeElement.js
r245827 r247053 127 127 contextMenu.appendItem(label, this._toggleBreakpoint.bind(this)); 128 128 129 contextMenu.appendSeparator();130 129 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), function() { 131 130 WI.domDebuggerManager.removeDOMBreakpoint(breakpoint); -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeTreeElement.js
r245827 r247053 56 56 contextMenu.appendSeparator(); 57 57 58 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, this.representedObject, { 59 allowEditing: true, 60 }); 58 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, this.representedObject); 61 59 62 60 contextMenu.appendSeparator(); -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js
r246855 r247053 46 46 this._shouldHighlightAfterReveal = false; 47 47 this._boundHighlightAnimationEnd = this._highlightAnimationEnd.bind(this); 48 this._subtreeBreakpoint Count = 0;48 this._subtreeBreakpointTreeElements = null; 49 49 50 50 this._showGoToArrow = false; … … 77 77 get hasBreakpoint() 78 78 { 79 return this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None || this._subtreeBreakpointCount > 0;79 return this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None || (this._subtreeBreakpointTreeElements && this._subtreeBreakpointTreeElements.size); 80 80 } 81 81 … … 104 104 let parentElement = this.parent; 105 105 while (parentElement && !parentElement.root) { 106 parentElement. subtreeBreakpointCountDidChange(increment);106 parentElement._subtreeBreakpointChanged(this); 107 107 parentElement = parentElement.parent; 108 108 } 109 } 110 111 bindRevealDescendantBreakpointsMenuItemHandler() 112 { 113 if (!this._subtreeBreakpointTreeElements || !this._subtreeBreakpointTreeElements.size) 114 return null; 115 116 let subtreeBreakpointTreeElements = Array.from(this._subtreeBreakpointTreeElements); 117 return () => { 118 for (let subtreeBreakpointTreeElement of subtreeBreakpointTreeElements) 119 subtreeBreakpointTreeElement.reveal(); 120 }; 109 121 } 110 122 … … 118 130 this._shouldHighlightAfterReveal = true; 119 131 this.reveal(); 120 }121 122 subtreeBreakpointCountDidChange(increment)123 {124 this._subtreeBreakpointCount += increment;125 this._updateBreakpointStatus();126 132 } 127 133 … … 1873 1879 } 1874 1880 1881 _subtreeBreakpointChanged(treeElement) 1882 { 1883 if (treeElement.hasBreakpoint) { 1884 if (!this._subtreeBreakpointTreeElements) 1885 this._subtreeBreakpointTreeElements = new Set; 1886 this._subtreeBreakpointTreeElements.add(treeElement); 1887 } else { 1888 this._subtreeBreakpointTreeElements.delete(treeElement); 1889 if (!this._subtreeBreakpointTreeElements.size) 1890 this._subtreeBreakpointTreeElements = null; 1891 } 1892 1893 this._updateBreakpointStatus(); 1894 } 1895 1875 1896 _updateBreakpointStatus() 1876 1897 { … … 1880 1901 1881 1902 let hasBreakpoint = this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None; 1882 let hasSubtreeBreakpoints = !!this._subtreeBreakpointCount;1903 let hasSubtreeBreakpoints = this._subtreeBreakpointTreeElements && this._subtreeBreakpointTreeElements.size; 1883 1904 1884 1905 if (!hasBreakpoint && !hasSubtreeBreakpoints) { … … 1922 1943 _statusImageContextmenu(event) 1923 1944 { 1924 let hasBreakpoint = this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None; 1925 let hasSubtreeBreakpoints = !!this._subtreeBreakpointCount; 1926 if (!hasBreakpoint && !hasSubtreeBreakpoints) 1945 if (!this.hasBreakpoint) 1927 1946 return; 1928 1947 1929 1948 let contextMenu = WI.ContextMenu.createFromEvent(event); 1930 if (hasBreakpoint) { 1931 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, this.representedObject, { 1932 allowEditing: true, 1933 }); 1934 return; 1935 } 1936 1937 contextMenu.appendItem(WI.UIString("Reveal Breakpoint"), () => { 1938 let breakpointTreeElement = this.selfOrDescendant((treeElement) => treeElement.breakpointStatus && treeElement.breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None); 1939 console.assert(breakpointTreeElement, "Missing breakpoint descendant.", this); 1940 if (!breakpointTreeElement) 1941 return; 1942 1943 breakpointTreeElement.revealAndHighlight(); 1949 1950 WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, this.representedObject, { 1951 revealDescendantBreakpointsMenuItemHandler: this.bindRevealDescendantBreakpointsMenuItemHandler(), 1944 1952 }); 1945 1953 } -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js
r245497 r247053 290 290 copySubMenu: subMenus.copy, 291 291 }; 292 293 if (treeElement.bindRevealDescendantBreakpointsMenuItemHandler) 294 options.revealDescendantBreakpointsMenuItemHandler = treeElement.bindRevealDescendantBreakpointsMenuItemHandler(); 295 292 296 WI.appendContextMenuItemsForDOMNode(contextMenu, treeElement.representedObject, options); 293 297 -
trunk/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js
r243722 r247053 115 115 contextMenu.appendItem(label, this._toggleBreakpoint.bind(this)); 116 116 117 contextMenu.appendSeparator();118 119 117 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => { 120 118 if (breakpoint.eventListener) -
trunk/Source/WebInspectorUI/UserInterface/Views/URLBreakpointTreeElement.js
r242318 r247053 115 115 contextMenu.appendItem(label, this._toggleBreakpoint.bind(this)); 116 116 117 contextMenu.appendSeparator();118 119 117 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => { 120 118 WI.domDebuggerManager.removeURLBreakpoint(breakpoint);
Note: See TracChangeset
for help on using the changeset viewer.