Changeset 266669 in webkit
- Timestamp:
- Sep 5, 2020 1:06:22 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 11 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r266665 r266669 1 2020-09-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: allow DOM breakpoints to be configured 4 https://bugs.webkit.org/show_bug.cgi?id=215795 5 6 Reviewed by Brian Burg. 7 8 * inspector/debugger/resources/breakpoint-options-utilities.js: 9 (TestPage.registerInitializer.InspectorTest.BreakpointOptions.addTestCases): 10 11 * inspector/dom-debugger/resources/dom-breakpoint-utilities.js: Added. 12 (TestPage.registerInitializer.InspectorTest.DOMBreakpoint.teardown): 13 (TestPage.registerInitializer.InspectorTest.DOMBreakpoint.createBreakpoint): 14 (TestPage.registerInitializer.InspectorTest.DOMBreakpoint.addBreakpoint): 15 (TestPage.registerInitializer.InspectorTest.DOMBreakpoint.awaitQuerySelector): 16 17 * inspector/dom-debugger/attribute-modified-style.html: 18 * inspector/dom-debugger/attribute-modified-style-expected.txt: 19 * inspector/dom-debugger/dom-breakpoints.html: 20 * inspector/dom-debugger/dom-breakpoints-expected.txt: 21 * inspector/dom-debugger/dom-breakpoint-attribute-modified.html: Added. 22 * inspector/dom-debugger/dom-breakpoint-attribute-modified-expected.txt: Added. 23 * inspector/dom-debugger/dom-breakpoint-node-removed-ancestor.html: Added. 24 * inspector/dom-debugger/dom-breakpoint-node-removed-ancestor-expected.txt: Added. 25 * inspector/dom-debugger/dom-breakpoint-node-removed-direct.html: Added. 26 * inspector/dom-debugger/dom-breakpoint-node-removed-direct-expected.txt: Added. 27 * inspector/dom-debugger/dom-breakpoint-subtree-modified-add.html: Added. 28 * inspector/dom-debugger/dom-breakpoint-subtree-modified-remove-expected.txt: Added. 29 * inspector/dom-debugger/dom-breakpoint-subtree-modified-remove.html: Added. 30 * inspector/dom-debugger/dom-breakpoint-subtree-modified-add-expected.txt: Added. 31 1 32 2020-09-05 Myles C. Maxfield <mmaxfield@apple.com> 2 33 -
trunk/LayoutTests/inspector/debugger/resources/breakpoint-options-utilities.js
r266538 r266669 2 2 InspectorTest.BreakpointOptions = {}; 3 3 4 InspectorTest.BreakpointOptions.addTestCases = function(suite, {testCaseNamePrefix, createBreakpoint, triggerBreakpoint }) {4 InspectorTest.BreakpointOptions.addTestCases = function(suite, {testCaseNamePrefix, createBreakpoint, triggerBreakpoint, skip}) { 5 5 testCaseNamePrefix ??= ""; 6 6 … … 43 43 44 44 InspectorTest.log("Triggering breakpoint..."); 45 await triggerBreakpoint( );45 await triggerBreakpoint(breakpoint); 46 46 47 47 if (i <= 2) … … 57 57 }); 58 58 59 suite.addTestCase({ 60 name: suite.name + "." + testCaseNamePrefix + "Options.IgnoreCount", 61 description: "Check that the debugger will not pause unless the breakpoint is hit at least as many times as it's `ignoreCount`.", 62 async test() { 63 let pauseCount = 0; 64 65 let pausedListener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { 66 ++pauseCount; 67 WI.debuggerManager.resume(); 68 }); 69 70 let breakpoint = await createBreakpoint(); 71 72 InspectorTest.newline(); 73 74 InspectorTest.log("Setting ignoreCount to '2'..."); 75 breakpoint.ignoreCount = 2; 76 77 for (let i = 1; i <=4; ++i) { 78 InspectorTest.newline(); 79 80 InspectorTest.log("Triggering breakpoint..."); 81 await triggerBreakpoint(); 82 83 if (i <= 2) 84 InspectorTest.expectEqual(pauseCount, 0, "Should not pause."); 85 else 86 InspectorTest.expectEqual(pauseCount, i - 2, "Should pause."); 87 } 88 89 removeBreakpoint(breakpoint); 90 91 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, pausedListener); 92 }, 93 }); 59 if (!skip?.ignoreCount) { 60 suite.addTestCase({ 61 name: suite.name + "." + testCaseNamePrefix + "Options.IgnoreCount", 62 description: "Check that the debugger will not pause unless the breakpoint is hit at least as many times as it's `ignoreCount`.", 63 async test() { 64 let pauseCount = 0; 65 66 let pausedListener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { 67 ++pauseCount; 68 WI.debuggerManager.resume(); 69 }); 70 71 let breakpoint = await createBreakpoint(); 72 73 InspectorTest.newline(); 74 75 InspectorTest.log("Setting ignoreCount to '2'..."); 76 breakpoint.ignoreCount = 2; 77 78 for (let i = 1; i <=4; ++i) { 79 InspectorTest.newline(); 80 81 InspectorTest.log("Triggering breakpoint..."); 82 await triggerBreakpoint(breakpoint); 83 84 if (i <= 2) 85 InspectorTest.expectEqual(pauseCount, 0, "Should not pause."); 86 else 87 InspectorTest.expectEqual(pauseCount, i - 2, "Should pause."); 88 } 89 90 removeBreakpoint(breakpoint); 91 92 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, pausedListener); 93 }, 94 }); 95 } 94 96 95 97 suite.addTestCase({ … … 134 136 135 137 InspectorTest.log("Triggering breakpoint..."); 136 await triggerBreakpoint( );138 await triggerBreakpoint(breakpoint); 137 139 138 140 WI.consoleManager.removeEventListener(WI.ConsoleManager.Event.MessageAdded, messageAddedListener); … … 187 189 188 190 InspectorTest.log("Triggering breakpoint..."); 189 await triggerBreakpoint( );191 await triggerBreakpoint(breakpoint); 190 192 191 193 let breakpointActionEvaluateResult = await InspectorTest.evaluateInPage(`window.BREAKPOINT_ACTION_EVALUATE`); -
trunk/LayoutTests/inspector/dom-debugger/attribute-modified-style-expected.txt
r244269 r266669 1 CONSOLE MESSAGE: BREAKPOINT ACTION LOG 1 2 CONSOLE MESSAGE: BREAKPOINT ACTION LOG 2 3 CONSOLE MESSAGE: BREAKPOINT ACTION LOG 3 4 CONSOLE MESSAGE: BREAKPOINT ACTION LOG 4 1 5 Tests functionality of attribute modified DOM breakpoints when modifying the inline style attribute. 2 6 3 Adding attribute modified breakpoint to #test...4 PASS: Added attribute modified breakpoint to #test.5 7 6 == Running test suite: DOMBreakpoints.AttributeModified.Style 7 -- Running test case: DOMBreakpoints.AttributeModified.Style.Add 8 == Running test suite: DOMBreakpoint.AttributeModified 9 -- Running test case: DOMBreakpoint.AttributeModified.Style.Add 10 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 8 11 Getting 'display'... 9 12 PASS: 'display' should have the value ''. … … 15 18 Getting 'display'... 16 19 PASS: 'display' should have the value 'none'. 20 -- Running test teardown. 17 21 18 -- Running test case: DOMBreakpoints.AttributeModified.Style.ReplaceSame 22 -- Running test case: DOMBreakpoint.AttributeModified.Style.ReplaceSame 23 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 19 24 Getting 'display'... 20 25 PASS: 'display' should have the value 'none'. … … 26 31 Getting 'display'... 27 32 PASS: 'display' should have the value 'none'. 33 -- Running test teardown. 28 34 29 -- Running test case: DOMBreakpoints.AttributeModified.Style.ReplaceDifferent 35 -- Running test case: DOMBreakpoint.AttributeModified.Style.ReplaceDifferent 36 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 30 37 Getting 'display'... 31 38 PASS: 'display' should have the value 'none'. … … 37 44 Getting 'display'... 38 45 PASS: 'display' should have the value 'block'. 46 -- Running test teardown. 39 47 40 -- Running test case: DOMBreakpoints.AttributeModified.Style.Remove 48 -- Running test case: DOMBreakpoint.AttributeModified.Style.Remove 49 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 41 50 Getting 'display'... 42 51 PASS: 'display' should have the value 'block'. … … 48 57 Getting 'display'... 49 58 PASS: 'display' should have the value ''. 59 -- Running test teardown. 50 60 51 -- Running test case: DOMBreakpoints.AttributeModified.Style.Text 61 -- Running test case: DOMBreakpoint.AttributeModified.Style.Text 62 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 52 63 Getting 'display'... 53 64 PASS: 'display' should have the value ''. … … 59 70 Getting 'display'... 60 71 PASS: 'display' should have the value 'none'. 72 -- Running test teardown. 61 73 74 -- Running test case: DOMBreakpoint.AttributeModified.Style.Options.Condition 75 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 76 77 Setting condition to 'false'... 78 79 Triggering breakpoint... 80 PASS: Should not pause. 81 82 Triggering breakpoint... 83 PASS: Should not pause. 84 85 Setting condition to 'true'... 86 87 Triggering breakpoint... 88 PASS: Should pause. 89 90 Triggering breakpoint... 91 PASS: Should pause. 92 93 -- Running test case: DOMBreakpoint.AttributeModified.Style.Options.IgnoreCount 94 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 95 96 Setting ignoreCount to '2'... 97 98 Triggering breakpoint... 99 PASS: Should not pause. 100 101 Triggering breakpoint... 102 PASS: Should not pause. 103 104 Triggering breakpoint... 105 PASS: Should pause. 106 107 Triggering breakpoint... 108 PASS: Should pause. 109 110 -- Running test case: DOMBreakpoint.AttributeModified.Style.Options.Action.Log 111 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 112 113 Adding log action... 114 115 Triggering breakpoint... 116 PASS: Should execute breakpoint action. 117 PASS: Should pause. 118 119 Editing log action... 120 121 Triggering breakpoint... 122 PASS: Should execute breakpoint action. 123 PASS: Should pause. 124 125 Editing log action... 126 Enabling auto-continue... 127 128 Triggering breakpoint... 129 PASS: Should execute breakpoint action. 130 PASS: Should not pause. 131 132 Editing log action... 133 134 Triggering breakpoint... 135 PASS: Should execute breakpoint action. 136 PASS: Should not pause. 137 138 -- Running test case: DOMBreakpoint.AttributeModified.Style.Options.Actions.Evaluate 139 Adding "attribute-modified:1,HTML,1,BODY,1,DIV" DOM Breakpoint... 140 141 Adding evaluate action... 142 143 Triggering breakpoint... 144 PASS: Should execute breakpoint action. 145 PASS: Should pause. 146 147 Editing evaluate action... 148 149 Triggering breakpoint... 150 PASS: Should execute breakpoint action. 151 PASS: Should pause. 152 153 Editing evaluate action... 154 Enabling auto-continue... 155 156 Triggering breakpoint... 157 PASS: Should execute breakpoint action. 158 PASS: Should not pause. 159 160 Editing evaluate action... 161 162 Triggering breakpoint... 163 PASS: Should execute breakpoint action. 164 PASS: Should not pause. 165 -
trunk/LayoutTests/inspector/dom-debugger/attribute-modified-style.html
r253242 r266669 3 3 <head> 4 4 <script src="../../http/tests/inspector/resources/inspector-test.js"></script> 5 <script src="../debugger/resources/breakpoint-options-utilities.js"></script> 5 6 <script src="../debugger/resources/log-active-stack-trace.js"></script> 7 <script src="resources/dom-breakpoint-utilities.js"></script> 6 8 <script> 7 9 … … 21 23 function test() 22 24 { 23 InspectorTest.debug(); 24 25 let suite = InspectorTest.createAsyncSuite("DOMBreakpoints.AttributeModified.Style"); 25 let suite = InspectorTest.createAsyncSuite("DOMBreakpoint.AttributeModified"); 26 26 27 27 async function checkPropertyValue(name, expectedValue) { … … 35 35 name, 36 36 async test() { 37 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("#test"); 38 await InspectorTest.DOMBreakpoint.createBreakpoint(node, WI.DOMBreakpoint.Type.AttributeModified); 39 37 40 await checkPropertyValue(propertyName, propertyValueBefore); 38 41 … … 57 60 await checkPropertyValue(propertyName, propertyValueAfter); 58 61 }, 62 teardown: InspectorTest.DOMBreakpoint.teardown, 59 63 }); 60 64 } 61 65 62 66 addTestCase({ 63 name: "DOMBreakpoint s.AttributeModified.Style.Add",67 name: "DOMBreakpoint.AttributeModified.Style.Add", 64 68 propertyName: "display", 65 69 propertyValueBefore: "", … … 67 71 }); 68 72 addTestCase({ 69 name: "DOMBreakpoint s.AttributeModified.Style.ReplaceSame",73 name: "DOMBreakpoint.AttributeModified.Style.ReplaceSame", 70 74 propertyName: "display", 71 75 propertyValueBefore: "none", … … 73 77 }); 74 78 addTestCase({ 75 name: "DOMBreakpoint s.AttributeModified.Style.ReplaceDifferent",79 name: "DOMBreakpoint.AttributeModified.Style.ReplaceDifferent", 76 80 propertyName: "display", 77 81 propertyValueBefore: "none", … … 79 83 }); 80 84 addTestCase({ 81 name: "DOMBreakpoint s.AttributeModified.Style.Remove",85 name: "DOMBreakpoint.AttributeModified.Style.Remove", 82 86 propertyName: "display", 83 87 propertyValueBefore: "block", … … 86 90 87 91 suite.addTestCase({ 88 name: "DOMBreakpoint s.AttributeModified.Style.Text",92 name: "DOMBreakpoint.AttributeModified.Style.Text", 89 93 async test() { 94 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("#test"); 95 await InspectorTest.DOMBreakpoint.createBreakpoint(node, WI.DOMBreakpoint.Type.AttributeModified); 96 90 97 await checkPropertyValue("display", ""); 91 98 … … 107 114 await checkPropertyValue("display", "none"); 108 115 }, 116 teardown: InspectorTest.DOMBreakpoint.teardown, 109 117 }); 110 118 111 WI.domManager.requestDocument((documentNode) => { 112 if (!documentNode) { 113 InspectorTest.fail("Missing document node"); 114 InspectorTest.completeTest(); 115 return; 116 } 119 InspectorTest.BreakpointOptions.addTestCases(suite, { 120 testCaseNamePrefix: "Style.", 121 async createBreakpoint() { 122 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("#test"); 123 return InspectorTest.DOMBreakpoint.createBreakpoint(node, WI.DOMBreakpoint.Type.AttributeModified); 124 }, 125 async triggerBreakpoint(breakpoint) { 126 return InspectorTest.evaluateInPage(`setProperty("--test", Math.random())`); 127 }, 128 }); 117 129 118 documentNode.querySelector("#test", async (nodeId) => { 119 let testNode = WI.domManager.nodeForId(nodeId); 120 if (!testNode) { 121 InspectorTest.fail("Missing #test node"); 122 InspectorTest.completeTest(); 123 return; 124 } 125 126 let promise = WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.DOMBreakpointAdded) 127 .then((event) => { 128 InspectorTest.pass("Added attribute modified breakpoint to #test."); 129 }); 130 131 InspectorTest.log("Adding attribute modified breakpoint to #test..."); 132 WI.domDebuggerManager.addDOMBreakpoint(new WI.DOMBreakpoint(testNode, WI.DOMBreakpoint.Type.AttributeModified)); 133 await promise; 134 135 InspectorTest.assert(!WI.debuggerManager.paused, "Should not be paused."); 136 137 suite.runTestCasesAndFinish(); 138 }); 139 }); 130 suite.runTestCasesAndFinish(); 140 131 } 141 132 </script> -
trunk/LayoutTests/inspector/dom-debugger/dom-breakpoints-expected.txt
r251871 r266669 2 2 3 3 4 == Running test suite: DOMBreakpoint s5 -- Running test case: BasicBreakpoint6 PASS: Added 'subtree-modified' breakpoint.4 == Running test suite: DOMBreakpoint 5 -- Running test case: DOMBreakpoint.Basic 6 Adding "subtree-modified:1,HTML,1,BODY,1,DIV,0,DIV" DOM Breakpoint... 7 7 PASS: Breakpoint should not be disabled. 8 8 PASS: Breakpoint should have node identifier. … … 10 10 -- Running test teardown. 11 11 12 -- Running test case: DOMBreakpoints.SubtreeModified.BreakpointEnabled 13 PASS: Added 'subtree-modified' breakpoint. 14 PASS: Breakpoint should have expected type. 15 Call DOM operation. 16 PAUSED: 17 PASS: Pause reason should be DOM. 18 PASS: Pause type should be 'subtree-modified'. 19 PASS: Pause nodeId should be expected value. 20 PASS: Pause insertion should be 'true'. 21 PASS: Pause targetNodeId should match nodeId. 22 CALL STACK: 23 0: [F] subtreeModifiedTest 24 1: [P] Global Code 12 -- Running test case: DOMBreakpoint.RemoveAllBreakpointsForNode 13 Adding "subtree-modified:1,HTML,1,BODY,1,DIV,1,DIV" DOM Breakpoint... 14 Adding "attribute-modified:1,HTML,1,BODY,1,DIV,1,DIV" DOM Breakpoint... 15 Adding "node-removed:1,HTML,1,BODY,1,DIV,1,DIV" DOM Breakpoint... 16 PASS: Should have 3 breakpoints. 17 Removing all breakpoints for #multiple-breakpoints-test... 18 PASS: Should remove all breakpoints. 25 19 -- Running test teardown. 26 20 27 -- Running test case: DOMBreakpoints.SubtreeModified.BreakpointDisabled 28 PASS: Added 'subtree-modified' breakpoint. 29 Wait for evaluate in page to return. 30 PASS: Should not pause for disabled breakpoint. 31 -- Running test teardown. 21 -- Running test case: DOMBreakpoint.SetBreakpointWithInvalidNodeId 22 Setting breakpoint... 23 PASS: Should produce an exception. 24 Error: Missing node for given nodeId 32 25 33 -- Running test case: DOMBreakpoints.SubtreeModified.DebuggerDisabled 34 PASS: Added 'subtree-modified' breakpoint. 35 Wait for evaluate in page to return. 36 PASS: Should not pause for disabled breakpoint. 37 -- Running test teardown. 26 -- Running test case: DOMBreakpoint.SetBreakpointWithInvalidType 27 Setting breakpoint... 28 PASS: Should produce an exception. 29 Error: Unknown type: custom-breakpoint-type 38 30 39 -- Running test case: DOMBreakpoints.SubtreeModified.RemoveBreakpoint 40 PASS: Added 'subtree-modified' breakpoint. 41 Remove breakpoint. 42 Wait for evaluate in page to return. 43 PASS: Should not pause for removed breakpoint. 44 -- Running test teardown. 31 -- Running test case: DOMBreakpoint.RemoveBreakpointWithInvalidNodeId 32 Removing breakpoint... 33 PASS: Should produce an exception. 34 Error: Missing node for given nodeId 45 35 46 -- Running test case: DOMBreakpoints.AttributeModified.BreakpointEnabled 47 PASS: Added 'attribute-modified' breakpoint. 48 PASS: Breakpoint should have expected type. 49 Call DOM operation. 50 PAUSED: 51 PASS: Pause reason should be DOM. 52 PASS: Pause type should be 'attribute-modified'. 53 PASS: Pause nodeId should be expected value. 54 CALL STACK: 55 0: [F] attributeModifiedTest 56 1: [P] Global Code 57 -- Running test teardown. 36 -- Running test case: DOMBreakpoint.RemoveBreakpointWithInvalidType 37 Removing breakpoint... 38 PASS: Should produce an exception. 39 Error: Unknown type: custom-breakpoint-type 58 40 59 -- Running test case: DOMBreakpoints.AttributeModified.BreakpointDisabled60 PASS: Added 'attribute-modified' breakpoint.61 Wait for evaluate in page to return.62 PASS: Should not pause for disabled breakpoint.63 -- Running test teardown.64 65 -- Running test case: DOMBreakpoints.AttributeModified.DebuggerDisabled66 PASS: Added 'attribute-modified' breakpoint.67 Wait for evaluate in page to return.68 PASS: Should not pause for disabled breakpoint.69 -- Running test teardown.70 71 -- Running test case: DOMBreakpoints.AttributeModified.RemoveBreakpoint72 PASS: Added 'attribute-modified' breakpoint.73 Remove breakpoint.74 Wait for evaluate in page to return.75 PASS: Should not pause for removed breakpoint.76 -- Running test teardown.77 78 -- Running test case: DOMBreakpoints.NodeRemovedSelf.BreakpointEnabled79 PASS: Added 'node-removed' breakpoint.80 PASS: Breakpoint should have expected type.81 Call DOM operation.82 PAUSED:83 PASS: Pause reason should be DOM.84 PASS: Pause type should be 'node-removed'.85 PASS: Pause nodeId should be expected value.86 CALL STACK:87 0: [F] nodeRemovedDirectTest88 1: [P] Global Code89 -- Running test teardown.90 91 -- Running test case: DOMBreakpoints.NodeRemovedSelf.BreakpointDisabled92 PASS: Added 'node-removed' breakpoint.93 Wait for evaluate in page to return.94 PASS: Should not pause for disabled breakpoint.95 -- Running test teardown.96 97 -- Running test case: DOMBreakpoints.NodeRemovedSelf.DebuggerDisabled98 PASS: Added 'node-removed' breakpoint.99 Wait for evaluate in page to return.100 PASS: Should not pause for disabled breakpoint.101 -- Running test teardown.102 103 -- Running test case: DOMBreakpoints.NodeRemovedSelf.RemoveBreakpoint104 PASS: Added 'node-removed' breakpoint.105 Remove breakpoint.106 Wait for evaluate in page to return.107 PASS: Should not pause for removed breakpoint.108 -- Running test teardown.109 110 -- Running test case: DOMBreakpoints.NodeRemovedAncestor.BreakpointEnabled111 PASS: Added 'node-removed' breakpoint.112 PASS: Breakpoint should have expected type.113 Call DOM operation.114 PAUSED:115 PASS: Pause reason should be DOM.116 PASS: Pause type should be 'node-removed'.117 PASS: Pause nodeId should be expected value.118 PASS: Pause targetNodeId should not match nodeId.119 CALL STACK:120 0: [F] nodeRemovedAncestorTest121 1: [P] Global Code122 -- Running test teardown.123 124 -- Running test case: DOMBreakpoints.NodeRemovedAncestor.BreakpointDisabled125 PASS: Added 'node-removed' breakpoint.126 Wait for evaluate in page to return.127 PASS: Should not pause for disabled breakpoint.128 -- Running test teardown.129 130 -- Running test case: DOMBreakpoints.NodeRemovedAncestor.DebuggerDisabled131 PASS: Added 'node-removed' breakpoint.132 Wait for evaluate in page to return.133 PASS: Should not pause for disabled breakpoint.134 -- Running test teardown.135 136 -- Running test case: DOMBreakpoints.NodeRemovedAncestor.RemoveBreakpoint137 PASS: Added 'node-removed' breakpoint.138 Remove breakpoint.139 Wait for evaluate in page to return.140 PASS: Should not pause for removed breakpoint.141 -- Running test teardown.142 143 -- Running test case: RemoveAllBreakpointsForNode144 PASS: Added 'subtree-modified' breakpoint.145 PASS: Added 'attribute-modified' breakpoint.146 PASS: Added 'node-removed' breakpoint.147 PASS: Removed 3 breakpoints.148 PASS: DOM node should have no breakpoints.149 -- Running test teardown.150 151 -- Running test case: SetBreakpointWithInvalidNodeId152 Attempting to set breakpoint.153 Protocol result: Missing node for given nodeId154 PASS: Protocol should return an error.155 -- Running test teardown.156 157 -- Running test case: SetBreakpointWithInvalidType158 Attempting to set breakpoint.159 Protocol result: Unknown DOM breakpoint type: custom-breakpoint-type160 PASS: Protocol should return an error.161 -- Running test teardown.162 163 -- Running test case: RemoveBreakpointWithInvalidNodeId164 Attempting to remove breakpoint.165 Protocol result: Missing node for given nodeId166 PASS: Protocol should return an error.167 -- Running test teardown.168 169 -- Running test case: RemoveBreakpointWithInvalidType170 Attempting to remove breakpoint.171 Protocol result: Unknown DOM breakpoint type: custom-breakpoint-type172 PASS: Protocol should return an error.173 -- Running test teardown.174 -
trunk/LayoutTests/inspector/dom-debugger/dom-breakpoints.html
r253242 r266669 4 4 <script src="../../http/tests/inspector/resources/inspector-test.js"></script> 5 5 <script src="../debugger/resources/log-active-stack-trace.js"></script> 6 <script src="resources/dom-breakpoint-utilities.js"></script> 6 7 <script> 7 function subtreeModifiedTest() {8 document.getElementById("subtree-modified-test").append(document.createElement("p"));9 }10 11 function attributeModifiedTest() {12 document.getElementById("attribute-modified-test").setAttribute("display", "none");13 }14 15 function nodeRemovedDirectTest() {16 let node = document.getElementById("node-removed-direct-test");17 let parent = node.parentNode;18 node.remove();19 parent.append(node);20 }21 22 function nodeRemovedAncestorTest() {23 let node = document.getElementById("node-removed-ancestor-test");24 let parent = node.parentNode;25 let grandparent = parent.parentNode;26 parent.remove(node);27 grandparent.append(parent);28 }29 30 8 function test() 31 9 { 32 const subtreeModifiedTestId = "subtree-modified-test"; 33 const attributeModifiedTestId = "attribute-modified-test"; 34 const nodeRemovedDirectTestId = "node-removed-direct-test"; 35 const nodeRemovedAncestorTestId = "node-removed-ancestor-test"; 36 const multipleBreakpointsTestId = "multiple-breakpoints-test"; 37 38 let debuggerPausedListener = null; 39 40 let suite = InspectorTest.createAsyncSuite("DOMBreakpoints"); 41 42 function teardown(resolve) { 43 let breakpoints = WI.domDebuggerManager.domBreakpoints; 44 for (let breakpoint of breakpoints) 45 WI.domDebuggerManager.removeDOMBreakpoint(breakpoint); 46 InspectorTest.assert(!WI.domDebuggerManager.domBreakpoints.length); 47 48 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, debuggerPausedListener); 49 debuggerPausedListener = null; 50 51 resolve(); 52 } 53 54 function rejectOnPause() { 55 return new Promise((resolve, reject) => { 56 InspectorTest.assert(!debuggerPausedListener); 57 debuggerPausedListener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { 58 WI.debuggerManager.resume(); 59 InspectorTest.fail("Should not pause."); 60 reject(); 61 }); 62 }); 63 } 64 65 function awaitEvaluateInPage(expression) { 66 return new Promise((resolve, reject) => { 67 InspectorTest.log("Wait for evaluate in page to return."); 68 InspectorTest.evaluateInPage(expression, (error) => { 69 if (error) 70 reject(error); 71 72 resolve(); 73 }); 74 }); 75 } 76 77 function awaitQuerySelector(selector) { 78 return new Promise((resolve, reject) => { 79 WI.domManager.requestDocument((documentNode) => { 80 if (!documentNode) { 81 reject(); 82 return; 83 } 84 85 documentNode.querySelector(selector, (nodeId) => { 86 if (!nodeId) { 87 InspectorTest.fail("Selector returned no nodes.", selector); 88 reject(); 89 return; 90 } 91 92 let node = WI.domManager.nodeForId(nodeId); 93 InspectorTest.assert(node, "Missing node for id.", nodeId); 94 if (!node) { 95 reject(); 96 return; 97 } 98 99 resolve(node); 100 }); 101 }); 102 }); 103 } 104 105 function addBreakpointForElementIdentifier(elementIdentifier, type, disabled) { 106 return new Promise((resolve, reject) => { 107 awaitQuerySelector("#" + elementIdentifier) 108 .then((node) => { 109 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.DOMBreakpointAdded) 110 .then((event) => { 111 let breakpoint = event.data.breakpoint; 112 InspectorTest.pass(`Added '${type}' breakpoint.`); 113 resolve(event); 114 }); 115 116 WI.domDebuggerManager.addDOMBreakpoint(new WI.DOMBreakpoint(node, type, {disabled})); 117 }); 118 }); 119 } 120 121 function addTestsForBreakpointType({name, elementIdentifier, type, expression, insertion, shouldMatch}) { 122 suite.addTestCase({ 123 name: `DOMBreakpoints.${name}.BreakpointEnabled`, 124 description: "Check that debugger pauses for breakpoint type.", 125 teardown, 126 test(resolve, reject) { 127 addBreakpointForElementIdentifier(elementIdentifier, type) 128 .then((event) => { 129 let breakpoint = event.data.breakpoint; 130 InspectorTest.expectEqual(breakpoint.type, type, "Breakpoint should have expected type."); 131 132 InspectorTest.log("Call DOM operation."); 133 InspectorTest.evaluateInPage(expression); 134 return WI.debuggerManager.awaitEvent(WI.DebuggerManager.Event.Paused); 135 }) 136 .then(() => { 137 let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); 138 InspectorTest.log("PAUSED:"); 139 InspectorTest.expectEqual(targetData.pauseReason, WI.DebuggerManager.PauseReason.DOM, "Pause reason should be DOM."); 140 141 let pauseData = targetData.pauseData; 142 InspectorTest.expectEqual(pauseData.type, type, `Pause type should be '${type}'.`); 143 InspectorTest.expectEqual(pauseData.nodeId, domNodeIdentifier, `Pause nodeId should be expected value.`); 144 145 if (insertion !== undefined) 146 InspectorTest.expectEqual(insertion, target.pauseData.insertion, `Pause insertion should be '${insertion}'.`); 147 148 if (pauseData.targetNodeId) { 149 if (shouldMatch) 150 InspectorTest.expectEqual(pauseData.targetNodeId, pauseData.nodeId, "Pause targetNodeId should match nodeId."); 151 else 152 InspectorTest.expectNotEqual(pauseData.targetNodeId, pauseData.nodeId, "Pause targetNodeId should not match nodeId."); 153 } 154 155 logActiveStackTrace(); 156 return WI.debuggerManager.resume(); 157 }) 158 .then(resolve, reject); 159 } 160 }); 161 162 suite.addTestCase({ 163 name: `DOMBreakpoints.${name}.BreakpointDisabled`, 164 description: "Check that debugger does not pause for disabled breakpoint.", 165 teardown, 166 test(resolve, reject) { 167 const disabled = true; 168 addBreakpointForElementIdentifier(elementIdentifier, type, disabled) 169 .then(() => Promise.race([awaitEvaluateInPage(expression), rejectOnPause()])) 170 .then(() => { 171 InspectorTest.pass("Should not pause for disabled breakpoint."); 172 resolve(); 173 }) 174 .catch(reject); 175 } 176 }); 177 178 suite.addTestCase({ 179 name: `DOMBreakpoints.${name}.DebuggerDisabled`, 180 description: "Check that debugger does not pause when the debugger is disabled.", 181 teardown, 182 test(resolve, reject) { 183 addBreakpointForElementIdentifier(elementIdentifier, type) 184 .then(() => DebuggerAgent.setBreakpointsActive(false)) 185 .then(() => Promise.race([awaitEvaluateInPage(expression), rejectOnPause()])) 186 .then(() => DebuggerAgent.setBreakpointsActive(true)) 187 .then(() => { 188 InspectorTest.pass("Should not pause for disabled breakpoint."); 189 resolve(); 190 }) 191 .catch(reject); 192 } 193 }); 194 195 suite.addTestCase({ 196 name: `DOMBreakpoints.${name}.RemoveBreakpoint`, 197 description: "Check that debugger does not pause for removed breakpoint.", 198 teardown, 199 test(resolve, reject) { 200 addBreakpointForElementIdentifier(elementIdentifier, type) 201 .then((event) => { 202 let promise = WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved); 203 let breakpoint = event.data.breakpoint; 204 205 InspectorTest.log("Remove breakpoint."); 206 WI.domDebuggerManager.removeDOMBreakpoint(breakpoint); 207 return promise; 208 }) 209 .then(() => Promise.race([awaitEvaluateInPage(expression), rejectOnPause()])) 210 .then(() => { 211 InspectorTest.pass("Should not pause for removed breakpoint."); 212 resolve(); 213 }) 214 .catch(reject); 215 } 216 }); 217 } 10 let suite = InspectorTest.createAsyncSuite("DOMBreakpoint"); 218 11 219 12 suite.addTestCase({ 220 name: " BasicBreakpoint",13 name: "DOMBreakpoint.Basic", 221 14 description: "Check that breakpoint is in a valid initial state.", 222 teardown, 223 test(resolve, reject) { 224 addBreakpointForElementIdentifier(subtreeModifiedTestId, WI.DOMBreakpoint.Type.SubtreeModified) 225 .then((event) => { 226 let breakpoint = event.data.breakpoint; 227 InspectorTest.expectFalse(breakpoint.disabled, "Breakpoint should not be disabled."); 228 InspectorTest.expectThat(breakpoint.domNodeIdentifier, "Breakpoint should have node identifier."); 15 async test() { 16 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("#basic-test"); 229 17 230 InspectorTest.assert(WI.networkManager.mainFrame, "Missing main frame."); 231 let documentURL = WI.networkManager.mainFrame.url; 232 InspectorTest.expectEqual(breakpoint.url, documentURL, "Breakpoint URL should match document URL."); 233 }) 234 .then(resolve, reject); 235 } 236 }); 237 238 addTestsForBreakpointType({ 239 name: "SubtreeModified", 240 elementIdentifier: subtreeModifiedTestId, 241 type: WI.DOMBreakpoint.Type.SubtreeModified, 242 expression: "subtreeModifiedTest()", 243 insertion: true, 244 shouldMatch: true, 245 }); 246 247 addTestsForBreakpointType({ 248 name: "AttributeModified", 249 elementIdentifier: attributeModifiedTestId, 250 type: WI.DOMBreakpoint.Type.AttributeModified, 251 expression: "attributeModifiedTest()", 252 }); 253 254 addTestsForBreakpointType({ 255 name: "NodeRemovedSelf", 256 elementIdentifier: nodeRemovedDirectTestId, 257 type: WI.DOMBreakpoint.Type.NodeRemoved, 258 expression: "nodeRemovedDirectTest()", 259 }); 260 261 addTestsForBreakpointType({ 262 name: "NodeRemovedAncestor", 263 elementIdentifier: nodeRemovedAncestorTestId, 264 type: WI.DOMBreakpoint.Type.NodeRemoved, 265 expression: "nodeRemovedAncestorTest()", 266 shouldMatch: true, 18 let breakpoint = await InspectorTest.DOMBreakpoint.createBreakpoint(node, WI.DOMBreakpoint.Type.SubtreeModified); 19 InspectorTest.expectFalse(breakpoint.disabled, "Breakpoint should not be disabled."); 20 InspectorTest.expectEqual(breakpoint.domNode, node, "Breakpoint should have node identifier."); 21 InspectorTest.expectEqual(breakpoint.url, WI.networkManager.mainFrame.url, "Breakpoint URL should match document URL."); 22 }, 23 teardown: InspectorTest.DOMBreakpoint.teardown, 267 24 }); 268 25 269 26 suite.addTestCase({ 270 name: " RemoveAllBreakpointsForNode",27 name: "DOMBreakpoint.RemoveAllBreakpointsForNode", 271 28 description: "Check that debugger does not pause for removed breakpoints on node.", 272 teardown, 273 test(resolve, reject) { 274 let breakpointTypes = Object.values(WI.DOMBreakpoint.Type); 275 let breakpointPromises = breakpointTypes.map(type => addBreakpointForElementIdentifier(multipleBreakpointsTestId, type)); 29 async test() { 30 const types = Object.values(WI.DOMBreakpoint.Type); 276 31 277 Promise.all(breakpointPromises) 278 .then((values) => { 279 let breakpoints = values.map(event => event.data.breakpoint); 280 if (!breakpoints.length) { 281 InspectorTest.fail("No breakpoints added."); 282 reject(); 283 return; 284 } 32 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("#remove-all-breakpoints-for-node-test"); 285 33 286 let node = WI.domManager.nodeForId(breakpoints[0].domNodeIdentifier); 287 if (!node) { 288 InspectorTest.fail("No DOM node associated with breakpoint."); 289 reject(); 290 return; 291 } 34 let breakpointsBefore = await Promise.all(types.map((type) => InspectorTest.DOMBreakpoint.createBreakpoint(node, type))); 35 InspectorTest.expectEqual(breakpointsBefore.length, types.length, `Should have ${types.length} breakpoints.`); 292 36 293 let breakpointsRemoved = 0; 37 InspectorTest.log("Removing all breakpoints for #multiple-breakpoints-test..."); 38 WI.domDebuggerManager.removeDOMBreakpointsForNode(node); 294 39 295 function breakpointRemoved() { 296 if (++breakpointsRemoved === breakpoints.length) { 297 InspectorTest.pass(`Removed ${breakpointsRemoved} breakpoints.`); 298 299 let nodeBreakpoints = WI.domDebuggerManager.domBreakpointsForNode(node); 300 InspectorTest.expectThat(!nodeBreakpoints.length, "DOM node should have no breakpoints."); 301 302 WI.domDebuggerManager.removeEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, breakpointRemoved); 303 resolve(); 304 } 305 } 306 307 WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, breakpointRemoved); 308 WI.domDebuggerManager.removeDOMBreakpointsForNode(node); 309 }) 310 .then(resolve, reject); 311 } 40 let breakpointsAfter = WI.domDebuggerManager.domBreakpointsForNode(node); 41 InspectorTest.expectEqual(breakpointsAfter.length, 0, "Should remove all breakpoints."); 42 }, 43 teardown: InspectorTest.DOMBreakpoint.teardown, 312 44 }); 313 45 314 46 suite.addTestCase({ 315 name: " SetBreakpointWithInvalidNodeId",47 name: "DOMBreakpoint.SetBreakpointWithInvalidNodeId", 316 48 description: "Check that setting a breakpoint for a nonexistant node returns an error.", 317 teardown, 318 test(resolve, reject) { 319 InspectorTest.log("Attempting to set breakpoint."); 320 321 DOMDebuggerAgent.setDOMBreakpoint(0, WI.DOMBreakpoint.Type.SubtreeModified, (error) => { 322 InspectorTest.log("Protocol result: " + error); 323 InspectorTest.expectThat(error, "Protocol should return an error.") 324 resolve(); 49 async test() { 50 InspectorTest.log("Setting breakpoint..."); 51 await InspectorTest.expectException(async () => { 52 await DOMDebuggerAgent.setDOMBreakpoint(0, WI.DOMBreakpoint.Type.SubtreeModified); 325 53 }); 326 } 54 }, 327 55 }); 328 56 329 57 suite.addTestCase({ 330 name: " SetBreakpointWithInvalidType",58 name: "DOMBreakpoint.SetBreakpointWithInvalidType", 331 59 description: "Check that setting a breakpoint with an invalid type returns an error.", 332 teardown, 333 test(resolve, reject) { 334 awaitQuerySelector("body") 335 .then((node) => { 336 InspectorTest.log("Attempting to set breakpoint."); 60 async test() { 61 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("body"); 337 62 338 DOMDebuggerAgent.setDOMBreakpoint(node.id, "custom-breakpoint-type", (error) => { 339 InspectorTest.log("Protocol result: " + error); 340 InspectorTest.expectThat(error, "Protocol should return an error.") 341 resolve(); 342 }); 63 InspectorTest.log("Setting breakpoint..."); 64 await InspectorTest.expectException(async () => { 65 await DOMDebuggerAgent.setDOMBreakpoint(node.id, "custom-breakpoint-type"); 343 66 }); 344 } 67 }, 345 68 }); 346 69 347 70 suite.addTestCase({ 348 name: " RemoveBreakpointWithInvalidNodeId",71 name: "DOMBreakpoint.RemoveBreakpointWithInvalidNodeId", 349 72 description: "Check that removing a breakpoint for a nonexistant node returns an error.", 350 teardown, 351 test(resolve, reject) { 352 InspectorTest.log("Attempting to remove breakpoint."); 353 354 DOMDebuggerAgent.removeDOMBreakpoint(0, WI.DOMBreakpoint.Type.SubtreeModified, (error) => { 355 InspectorTest.log("Protocol result: " + error); 356 InspectorTest.expectThat(error, "Protocol should return an error.") 357 resolve(); 73 async test() { 74 InspectorTest.log("Removing breakpoint..."); 75 await InspectorTest.expectException(async () => { 76 await DOMDebuggerAgent.removeDOMBreakpoint(0, WI.DOMBreakpoint.Type.SubtreeModified); 358 77 }); 359 } 78 }, 360 79 }); 361 80 362 81 suite.addTestCase({ 363 name: " RemoveBreakpointWithInvalidType",82 name: "DOMBreakpoint.RemoveBreakpointWithInvalidType", 364 83 description: "Check that removing a breakpoint with an invalid type returns an error.", 365 teardown, 366 test(resolve, reject) { 367 awaitQuerySelector("body") 368 .then((node) => { 369 InspectorTest.log("Attempting to remove breakpoint."); 84 async test() { 85 let node = await InspectorTest.DOMBreakpoint.awaitQuerySelector("body"); 370 86 371 DOMDebuggerAgent.removeDOMBreakpoint(node.id, "custom-breakpoint-type", (error) => { 372 InspectorTest.log("Protocol result: " + error); 373 InspectorTest.expectThat(error, "Protocol should return an error.") 374 resolve(); 375 }); 87 InspectorTest.log("Removing breakpoint..."); 88 await InspectorTest.expectException(async () => { 89 await DOMDebuggerAgent.removeDOMBreakpoint(node.id, "custom-breakpoint-type"); 376 90 }); 377 } 91 }, 378 92 }); 379 93 … … 385 99 <p>Tests for DOM breakpoints.</p> 386 100 <div id="test-container" style="display: none"> 387 <div id="subtree-modified-test"></div> 388 <div id="attribute-modified-test"></div> 389 <div id="node-removed-direct-test"></div> 390 <div><div id="node-removed-ancestor-test"></div></div> 391 <div id="multiple-breakpoints-test"></div> 101 <div id="basic-test"></div> 102 <div id="remove-all-breakpoints-for-node-test"></div> 392 103 </div> 393 104 </body> -
trunk/Source/JavaScriptCore/ChangeLog
r266655 r266669 1 2020-09-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: allow DOM breakpoints to be configured 4 https://bugs.webkit.org/show_bug.cgi?id=215795 5 6 Reviewed by Brian Burg. 7 8 * inspector/protocol/DOMDebugger.json: 9 Add an `options` parameter to `DOMDebugger.setDOMBreakpoint` to allow configuration. 10 1 11 2020-09-04 Yusuke Suzuki <ysuzuki@apple.com> 2 12 -
trunk/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json
r266538 r266669 24 24 "parameters": [ 25 25 { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Identifier of the node to set breakpoint on." }, 26 { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the operation to stop upon." } 26 { "name": "type", "$ref": "DOMBreakpointType", "description": "Type of the operation to stop upon." }, 27 { "name": "options", "$ref": "Debugger.BreakpointOptions", "optional": true, "description": "Options to apply to this breakpoint to modify its behavior." } 27 28 ] 28 29 }, -
trunk/Source/WebCore/ChangeLog
r266668 r266669 1 2020-09-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: allow DOM breakpoints to be configured 4 https://bugs.webkit.org/show_bug.cgi?id=215795 5 6 Reviewed by Brian Burg. 7 8 Tests: inspector/dom-debugger/attribute-modified-style.html 9 inspector/dom-debugger/dom-breakpoints.html 10 inspector/dom-debugger/dom-breakpoint-attribute-modified.html 11 inspector/dom-debugger/dom-breakpoint-node-removed-ancestor.html 12 inspector/dom-debugger/dom-breakpoint-node-removed-direct.html 13 inspector/dom-debugger/dom-breakpoint-subtree-modified-add.html 14 inspector/dom-debugger/dom-breakpoint-subtree-modified-remove.html 15 16 * inspector/agents/page/PageDOMDebuggerAgent.h: 17 * inspector/agents/page/PageDOMDebuggerAgent.cpp: 18 (WebCore::PageDOMDebuggerAgent::disable): 19 (WebCore::PageDOMDebuggerAgent::setDOMBreakpoint): 20 (WebCore::PageDOMDebuggerAgent::removeDOMBreakpoint): 21 (WebCore::PageDOMDebuggerAgent::frameDocumentUpdated): 22 (WebCore::calculateDistance): Added. 23 (WebCore::PageDOMDebuggerAgent::willInsertDOMNode): 24 (WebCore::PageDOMDebuggerAgent::willRemoveDOMNode): 25 (WebCore::PageDOMDebuggerAgent::didRemoveDOMNode): 26 (WebCore::PageDOMDebuggerAgent::willModifyDOMAttr): 27 (WebCore::PageDOMDebuggerAgent::willInvalidateStyleAttr): 28 (WebCore::PageDOMDebuggerAgent::buildPauseDataForDOMBreakpoint): Added. 29 (WebCore::domTypeForName): Deleted. 30 (WebCore::domTypeName): Deleted. 31 (WebCore::PageDOMDebuggerAgent::didInsertDOMNode): Deleted. 32 (WebCore::PageDOMDebuggerAgent::descriptionForDOMEvent): Deleted. 33 (WebCore::PageDOMDebuggerAgent::updateSubtreeBreakpoints): Deleted. 34 (WebCore::PageDOMDebuggerAgent::hasBreakpoint): Deleted. 35 Replace the bitmask with separate `HashMap` for each type of DOM breakpoint. Instead of 36 propagating the `SubtreeModified` bit to the entire subtree when new nodes are added (which 37 means there's an entry in the `HashMap` for every descendant) and removing them all when 38 that node is removed, only keep nodes in each `HashMap` if it directly has a DOM breakpoint. 39 Walk up the ancestor chain when nodes are added/removed to determine if there is a nearby 40 breakpoint to pause. When a node is removed, remove any existing DOM breakpoint if it's 41 owner is part of the removed subtree. 42 43 * inspector/agents/worker/WorkerDOMDebuggerAgent.h: 44 * inspector/agents/worker/WorkerDOMDebuggerAgent.cpp: 45 (WebCore::WorkerDOMDebuggerAgent::setDOMBreakpoint): 46 47 * inspector/InspectorInstrumentation.cpp: 48 (WebCore::InspectorInstrumentation::didInsertDOMNodeImpl): 49 1 50 2020-09-05 Alex Christensen <achristensen@webkit.org> 2 51 -
trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp
r266074 r266669 161 161 if (auto* domAgent = instrumentingAgents.persistentDOMAgent()) 162 162 domAgent->didInsertDOMNode(node); 163 if (auto* pageDOMDebuggerAgent = instrumentingAgents.enabledPageDOMDebuggerAgent())164 pageDOMDebuggerAgent->didInsertDOMNode(node);165 163 } 166 164 -
trunk/Source/WebCore/inspector/agents/page/PageDOMDebuggerAgent.cpp
r266074 r266669 32 32 #include "InstrumentingAgents.h" 33 33 #include "Node.h" 34 #include <wtf/Optional.h> 34 35 35 36 namespace WebCore { 36 37 37 38 using namespace Inspector; 38 39 enum DOMBreakpointType {40 SubtreeModified,41 AttributeModified,42 NodeRemoved,43 };44 45 const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);46 const int domBreakpointDerivedTypeShift = 16;47 48 static int domTypeForName(ErrorString& errorString, const String& typeString)49 {50 if (typeString == "subtree-modified")51 return SubtreeModified;52 if (typeString == "attribute-modified")53 return AttributeModified;54 if (typeString == "node-removed")55 return NodeRemoved;56 errorString = makeString("Unknown DOM breakpoint type: ", typeString);57 return -1;58 }59 60 static String domTypeName(int type)61 {62 switch (type) {63 case SubtreeModified:64 return "subtree-modified"_s;65 case AttributeModified:66 return "attribute-modified"_s;67 case NodeRemoved:68 return "node-removed"_s;69 }70 return emptyString();71 }72 39 73 40 PageDOMDebuggerAgent::PageDOMDebuggerAgent(PageAgentContext& context, InspectorDebuggerAgent* debuggerAgent) … … 94 61 m_instrumentingAgents.setEnabledPageDOMDebuggerAgent(nullptr); 95 62 96 m_domBreakpoints.clear(); 63 m_domSubtreeModifiedBreakpoints.clear(); 64 m_domAttributeModifiedBreakpoints.clear(); 65 m_domNodeRemovedBreakpoints.clear(); 97 66 98 67 m_pauseOnAllAnimationFramesBreakpoint = nullptr; … … 101 70 } 102 71 103 void PageDOMDebuggerAgent::setDOMBreakpoint(ErrorString& errorString, int nodeId, const String& typeString )72 void PageDOMDebuggerAgent::setDOMBreakpoint(ErrorString& errorString, int nodeId, const String& typeString, const JSON::Object* optionsPayload) 104 73 { 105 74 auto* domAgent = m_instrumentingAgents.persistentDOMAgent(); … … 113 82 return; 114 83 115 int type = domTypeForName(errorString, typeString); 116 if (type == -1) 117 return; 118 119 uint32_t rootBit = 1 << type; 120 m_domBreakpoints.set(node, m_domBreakpoints.get(node) | rootBit); 121 if (rootBit & inheritableDOMBreakpointTypesMask) { 122 for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child)) 123 updateSubtreeBreakpoints(child, rootBit, true); 124 } 84 auto type = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::DOMBreakpointType>(typeString); 85 if (!type) { 86 errorString = makeString("Unknown type: "_s, typeString); 87 return; 88 } 89 90 auto breakpoint = InspectorDebuggerAgent::debuggerBreakpointFromPayload(errorString, optionsPayload); 91 if (!breakpoint) 92 return; 93 94 switch (*type) { 95 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::SubtreeModified: 96 if (!m_domSubtreeModifiedBreakpoints.add(node, breakpoint.releaseNonNull())) 97 errorString = "Breakpoint for given node and given type already exists"_s; 98 return; 99 100 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::AttributeModified: 101 if (!m_domAttributeModifiedBreakpoints.add(node, breakpoint.releaseNonNull())) 102 errorString = "Breakpoint for given node and given type already exists"_s; 103 return; 104 105 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::NodeRemoved: 106 if (!m_domNodeRemovedBreakpoints.add(node, breakpoint.releaseNonNull())) 107 errorString = "Breakpoint for given node and given type already exists"_s; 108 return; 109 } 110 111 ASSERT_NOT_REACHED(); 125 112 } 126 113 … … 137 124 return; 138 125 139 int type = domTypeForName(errorString, typeString); 140 if (type == -1) 141 return; 142 143 uint32_t rootBit = 1 << type; 144 uint32_t mask = m_domBreakpoints.get(node) & ~rootBit; 145 if (mask) 146 m_domBreakpoints.set(node, mask); 147 else 148 m_domBreakpoints.remove(node); 149 150 if ((rootBit & inheritableDOMBreakpointTypesMask) && !(mask & (rootBit << domBreakpointDerivedTypeShift))) { 151 for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child)) 152 updateSubtreeBreakpoints(child, rootBit, false); 153 } 126 auto type = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::DOMBreakpointType>(typeString); 127 if (!type) { 128 errorString = makeString("Unknown type: "_s, typeString); 129 return; 130 } 131 132 switch (*type) { 133 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::SubtreeModified: 134 if (!m_domSubtreeModifiedBreakpoints.remove(node)) 135 errorString = "Breakpoint for given node and given type missing"_s; 136 return; 137 138 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::AttributeModified: 139 if (!m_domAttributeModifiedBreakpoints.remove(node)) 140 errorString = "Breakpoint for given node and given type missing"_s; 141 return; 142 143 case Inspector::Protocol::DOMDebugger::DOMBreakpointType::NodeRemoved: 144 if (!m_domNodeRemovedBreakpoints.remove(node)) 145 errorString = "Breakpoint for given node and given type missing"_s; 146 return; 147 } 148 149 ASSERT_NOT_REACHED(); 154 150 } 155 151 … … 167 163 return; 168 164 169 m_domBreakpoints.clear(); 165 m_domSubtreeModifiedBreakpoints.clear(); 166 m_domAttributeModifiedBreakpoints.clear(); 167 m_domNodeRemovedBreakpoints.clear(); 168 } 169 170 171 static Optional<size_t> calculateDistance(Node& child, Node& ancestor) 172 { 173 size_t distance = 0; 174 175 auto* current = &child; 176 while (current != &ancestor) { 177 ++distance; 178 179 current = InspectorDOMAgent::innerParentNode(current); 180 if (!current) 181 return WTF::nullopt; 182 } 183 184 return distance; 170 185 } 171 186 … … 175 190 return; 176 191 177 if (hasBreakpoint(&parent, SubtreeModified)) { 178 Ref<JSON::Object> eventData = JSON::Object::create(); 179 descriptionForDOMEvent(parent, SubtreeModified, true, eventData.get()); 180 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData)); 181 } 182 } 183 184 void PageDOMDebuggerAgent::didInsertDOMNode(Node& node) 185 { 186 if (m_domBreakpoints.size()) { 187 uint32_t mask = m_domBreakpoints.get(InspectorDOMAgent::innerParentNode(&node)); 188 uint32_t inheritableTypesMask = (mask | (mask >> domBreakpointDerivedTypeShift)) & inheritableDOMBreakpointTypesMask; 189 if (inheritableTypesMask) 190 updateSubtreeBreakpoints(&node, inheritableTypesMask, true); 191 } 192 if (m_domSubtreeModifiedBreakpoints.isEmpty()) 193 return; 194 195 Optional<size_t> closestDistance; 196 RefPtr<JSC::Breakpoint> closestBreakpoint; 197 Node* closestBreakpointOwner = nullptr; 198 199 for (auto [breakpointOwner, breakpoint] : m_domSubtreeModifiedBreakpoints) { 200 auto distance = calculateDistance(parent, *breakpointOwner); 201 if (!distance) 202 continue; 203 204 if (!closestDistance || distance < closestDistance) { 205 closestDistance = distance; 206 closestBreakpoint = breakpoint.copyRef(); 207 closestBreakpointOwner = breakpointOwner; 208 } 209 } 210 211 if (!closestBreakpoint) 212 return; 213 214 ASSERT(closestBreakpointOwner); 215 216 auto pauseData = buildPauseDataForDOMBreakpoint(Inspector::Protocol::DOMDebugger::DOMBreakpointType::SubtreeModified, *closestBreakpointOwner); 217 pauseData->setBoolean("insertion", true); 218 // FIXME: <https://webkit.org/b/213499> Web Inspector: allow DOM nodes to be instrumented at any point, regardless of whether the main document has also been instrumented 219 // Include the new child node ID so the frontend can show the node that's about to be inserted. 220 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(pauseData), WTFMove(closestBreakpoint)); 192 221 } 193 222 … … 197 226 return; 198 227 199 if ( hasBreakpoint(&node, NodeRemoved)) {200 auto eventData = JSON::Object::create();201 descriptionForDOMEvent(node, NodeRemoved, false, eventData.get()); 202 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData));203 return;204 }205 206 uint32_t rootBit = 1 << NodeRemoved; 207 uint32_t derivedBit = rootBit << domBreakpointDerivedTypeShift;208 uint32_t matchBit = rootBit | derivedBit;209 for (auto& [nodeWithBreakpoint, breakpointTypes] : m_domBreakpoints) {210 if (node.contains(nodeWithBreakpoint) && (breakpointTypes & matchBit)) {211 auto eventData = JSON::Object::create(); 212 descriptionForDOMEvent(*nodeWithBreakpoint, NodeRemoved, false, eventData.get());213 if (auto* domAgent = m_instrumentingAgents.persistentDOMAgent())214 eventData->setInteger("targetNodeId"_s, domAgent->pushNodeToFrontend(&node));215 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData));216 return;228 if (m_domNodeRemovedBreakpoints.isEmpty() && m_domSubtreeModifiedBreakpoints.isEmpty()) 229 return; 230 231 Optional<size_t> closestDistance; 232 RefPtr<JSC::Breakpoint> closestBreakpoint; 233 Optional<Inspector::Protocol::DOMDebugger::DOMBreakpointType> closestBreakpointType; 234 Node* closestBreakpointOwner = nullptr; 235 236 for (auto [breakpointOwner, breakpoint] : m_domNodeRemovedBreakpoints) { 237 auto distance = calculateDistance(*breakpointOwner, node); 238 if (!distance) 239 continue; 240 241 if (!closestDistance || distance < closestDistance) { 242 closestDistance = distance; 243 closestBreakpoint = breakpoint.copyRef(); 244 closestBreakpointType = Inspector::Protocol::DOMDebugger::DOMBreakpointType::NodeRemoved; 245 closestBreakpointOwner = breakpointOwner; 217 246 } 218 247 } 219 248 220 auto* parentNode = InspectorDOMAgent::innerParentNode(&node); 221 if (parentNode && hasBreakpoint(parentNode, SubtreeModified)) { 222 auto eventData = JSON::Object::create(); 223 descriptionForDOMEvent(node, SubtreeModified, false, eventData.get()); 224 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData)); 225 return; 226 } 249 if (!closestBreakpoint) { 250 for (auto [breakpointOwner, breakpoint] : m_domSubtreeModifiedBreakpoints) { 251 auto distance = calculateDistance(node, *breakpointOwner); 252 if (!distance) 253 continue; 254 255 if (!closestDistance || distance < closestDistance) { 256 closestDistance = distance; 257 closestBreakpoint = breakpoint.copyRef(); 258 closestBreakpointType = Inspector::Protocol::DOMDebugger::DOMBreakpointType::SubtreeModified; 259 closestBreakpointOwner = breakpointOwner; 260 } 261 } 262 } 263 264 if (!closestBreakpoint) 265 return; 266 267 ASSERT(closestBreakpointType); 268 ASSERT(closestBreakpointOwner); 269 270 auto pauseData = buildPauseDataForDOMBreakpoint(*closestBreakpointType, *closestBreakpointOwner); 271 if (auto* domAgent = m_instrumentingAgents.persistentDOMAgent()) { 272 if (&node != closestBreakpointOwner) { 273 if (auto targetNodeId = domAgent->pushNodeToFrontend(&node)) 274 pauseData->setInteger("targetNodeId", targetNodeId); 275 } 276 } 277 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(pauseData), WTFMove(closestBreakpoint)); 227 278 } 228 279 229 280 void PageDOMDebuggerAgent::didRemoveDOMNode(Node& node) 230 281 { 231 if (m_domBreakpoints.size()) { 232 // Remove subtree breakpoints. 233 m_domBreakpoints.remove(&node); 234 Vector<Node*> stack(1, InspectorDOMAgent::innerFirstChild(&node)); 235 do { 236 Node* node = stack.last(); 237 stack.removeLast(); 238 if (!node) 239 continue; 240 m_domBreakpoints.remove(node); 241 stack.append(InspectorDOMAgent::innerFirstChild(node)); 242 stack.append(InspectorDOMAgent::innerNextSibling(node)); 243 } while (!stack.isEmpty()); 244 } 282 auto nodeContainsBreakpointOwner = [&] (auto& entry) { 283 return node.contains(entry.key); 284 }; 285 m_domSubtreeModifiedBreakpoints.removeIf(nodeContainsBreakpointOwner); 286 m_domAttributeModifiedBreakpoints.removeIf(nodeContainsBreakpointOwner); 287 m_domNodeRemovedBreakpoints.removeIf(nodeContainsBreakpointOwner); 245 288 } 246 289 … … 250 293 return; 251 294 252 if (hasBreakpoint(&element, AttributeModified)) { 253 Ref<JSON::Object> eventData = JSON::Object::create(); 254 descriptionForDOMEvent(element, AttributeModified, false, eventData.get()); 255 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData)); 256 } 295 auto it = m_domAttributeModifiedBreakpoints.find(&element); 296 if (it == m_domAttributeModifiedBreakpoints.end()) 297 return; 298 299 auto pauseData = buildPauseDataForDOMBreakpoint(Inspector::Protocol::DOMDebugger::DOMBreakpointType::AttributeModified, element); 300 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(pauseData), it->value.copyRef()); 257 301 } 258 302 … … 286 330 return; 287 331 288 if (hasBreakpoint(&element, AttributeModified)) { 289 Ref<JSON::Object> eventData = JSON::Object::create(); 290 descriptionForDOMEvent(element, AttributeModified, false, eventData.get()); 291 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(eventData)); 292 } 332 auto it = m_domAttributeModifiedBreakpoints.find(&element); 333 if (it == m_domAttributeModifiedBreakpoints.end()) 334 return; 335 336 auto pauseData = buildPauseDataForDOMBreakpoint(Inspector::Protocol::DOMDebugger::DOMBreakpointType::AttributeModified, element); 337 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::DOM, WTFMove(pauseData), it->value.copyRef()); 293 338 } 294 339 … … 303 348 } 304 349 305 void PageDOMDebuggerAgent::descriptionForDOMEvent(Node& target, int breakpointType, bool insertion, JSON::Object& description)350 Ref<JSON::Object> PageDOMDebuggerAgent::buildPauseDataForDOMBreakpoint(Inspector::Protocol::DOMDebugger::DOMBreakpointType breakpointType, Node& breakpointOwner) 306 351 { 307 352 ASSERT(m_debuggerAgent->breakpointsActive()); 308 ASSERT(hasBreakpoint(&target, breakpointType)); 309 310 auto* domAgent = m_instrumentingAgents.persistentDOMAgent(); 311 312 Node* breakpointOwner = ⌖ 313 if ((1 << breakpointType) & inheritableDOMBreakpointTypesMask) { 314 if (domAgent) { 315 // For inheritable breakpoint types, target node isn't always the same as the node that owns a breakpoint. 316 // Target node may be unknown to frontend, so we need to push it first. 317 description.setInteger("targetNodeId"_s, domAgent->pushNodeToFrontend(&target)); 318 } 319 320 // Find breakpoint owner node. 321 if (!insertion) 322 breakpointOwner = InspectorDOMAgent::innerParentNode(&target); 323 ASSERT(breakpointOwner); 324 while (!(m_domBreakpoints.get(breakpointOwner) & (1 << breakpointType))) { 325 Node* parentNode = InspectorDOMAgent::innerParentNode(breakpointOwner); 326 if (!parentNode) 327 break; 328 breakpointOwner = parentNode; 329 } 330 331 if (breakpointType == SubtreeModified) 332 description.setBoolean("insertion", insertion); 333 } 334 335 if (domAgent) { 336 int breakpointOwnerNodeId = domAgent->boundNodeId(breakpointOwner); 337 ASSERT(breakpointOwnerNodeId); 338 description.setInteger("nodeId", breakpointOwnerNodeId); 339 } 340 341 description.setString("type", domTypeName(breakpointType)); 342 } 343 344 void PageDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_t rootMask, bool set) 345 { 346 uint32_t oldMask = m_domBreakpoints.get(node); 347 uint32_t derivedMask = rootMask << domBreakpointDerivedTypeShift; 348 uint32_t newMask = set ? oldMask | derivedMask : oldMask & ~derivedMask; 349 if (newMask) 350 m_domBreakpoints.set(node, newMask); 351 else 352 m_domBreakpoints.remove(node); 353 354 uint32_t newRootMask = rootMask & ~newMask; 355 if (!newRootMask) 356 return; 357 358 for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child)) 359 updateSubtreeBreakpoints(child, newRootMask, set); 360 } 361 362 bool PageDOMDebuggerAgent::hasBreakpoint(Node* node, int type) 363 { 364 uint32_t rootBit = 1 << type; 365 uint32_t derivedBit = rootBit << domBreakpointDerivedTypeShift; 366 return m_domBreakpoints.get(node) & (rootBit | derivedBit); 353 ASSERT(m_domSubtreeModifiedBreakpoints.contains(&breakpointOwner) || m_domAttributeModifiedBreakpoints.contains(&breakpointOwner) || m_domNodeRemovedBreakpoints.contains(&breakpointOwner)); 354 355 auto pauseData = JSON::Object::create(); 356 pauseData->setString("type", Inspector::Protocol::InspectorHelpers::getEnumConstantValue(breakpointType)); 357 if (auto* domAgent = m_instrumentingAgents.persistentDOMAgent()) { 358 if (auto breakpointOwnerNodeId = domAgent->pushNodeToFrontend(&breakpointOwner)) 359 pauseData->setInteger("nodeId", breakpointOwnerNodeId); 360 } 361 return pauseData; 367 362 } 368 363 -
trunk/Source/WebCore/inspector/agents/page/PageDOMDebuggerAgent.h
r266074 r266669 28 28 #include "InspectorDOMDebuggerAgent.h" 29 29 #include <JavaScriptCore/Breakpoint.h> 30 #include <JavaScriptCore/InspectorProtocolObjects.h> 30 31 #include <wtf/RefPtr.h> 31 32 … … 46 47 47 48 // DOMDebuggerBackendDispatcherHandler 48 void setDOMBreakpoint(ErrorString&, int nodeId, const String& type ) override;49 void setDOMBreakpoint(ErrorString&, int nodeId, const String& type, const JSON::Object* options) override; 49 50 void removeDOMBreakpoint(ErrorString&, int nodeId, const String& type) override; 50 51 … … 53 54 void frameDocumentUpdated(Frame&); 54 55 void willInsertDOMNode(Node& parent); 55 void didInsertDOMNode(Node&);56 56 void willRemoveDOMNode(Node&); 57 57 void didRemoveDOMNode(Node&); … … 67 67 void setAnimationFrameBreakpoint(ErrorString&, RefPtr<JSC::Breakpoint>&&) override; 68 68 69 void descriptionForDOMEvent(Node&, int breakpointType, bool insertion, JSON::Object& description); 70 void updateSubtreeBreakpoints(Node*, uint32_t rootMask, bool set); 71 bool checkSubtreeForNodeRemoved(Node*); 72 bool hasBreakpoint(Node*, int type); 69 Ref<JSON::Object> buildPauseDataForDOMBreakpoint(Inspector::Protocol::DOMDebugger::DOMBreakpointType, Node& breakpointOwner); 73 70 74 HashMap<Node*, uint32_t> m_domBreakpoints; 71 HashMap<Node*, Ref<JSC::Breakpoint>> m_domSubtreeModifiedBreakpoints; 72 HashMap<Node*, Ref<JSC::Breakpoint>> m_domAttributeModifiedBreakpoints; 73 HashMap<Node*, Ref<JSC::Breakpoint>> m_domNodeRemovedBreakpoints; 75 74 76 75 RefPtr<JSC::Breakpoint> m_pauseOnAllAnimationFramesBreakpoint; -
trunk/Source/WebCore/inspector/agents/worker/WorkerDOMDebuggerAgent.cpp
r266074 r266669 38 38 WorkerDOMDebuggerAgent::~WorkerDOMDebuggerAgent() = default; 39 39 40 void WorkerDOMDebuggerAgent::setDOMBreakpoint(ErrorString& errorString, int /* nodeId */, const String& /* typeString */ )40 void WorkerDOMDebuggerAgent::setDOMBreakpoint(ErrorString& errorString, int /* nodeId */, const String& /* typeString */, const JSON::Object* /* optionsPayload */) 41 41 { 42 42 errorString = "Not supported"_s; -
trunk/Source/WebCore/inspector/agents/worker/WorkerDOMDebuggerAgent.h
r266074 r266669 40 40 41 41 // DOMDebuggerBackendDispatcherHandler 42 void setDOMBreakpoint(ErrorString&, int nodeId, const String& type ) override;42 void setDOMBreakpoint(ErrorString&, int nodeId, const String& type, const JSON::Object* options) override; 43 43 void removeDOMBreakpoint(ErrorString&, int nodeId, const String& type) override; 44 44 -
trunk/Source/WebInspectorUI/ChangeLog
r266624 r266669 1 2020-09-05 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: allow DOM breakpoints to be configured 4 https://bugs.webkit.org/show_bug.cgi?id=215795 5 6 Reviewed by Brian Burg. 7 8 * UserInterface/Controllers/DOMManager.js: 9 (WI.DOMManager.prototype._setChildNodes): 10 Dispatch events for each new child node added and each existing child node removed so that 11 any listeners can also know when new nodes are added via a full children payload update. 12 13 * UserInterface/Controllers/DOMDebuggerManager.js: 14 (WI.DOMDebuggerManager): 15 (WI.DOMDebuggerManager.prototype.addDOMBreakpoint): 16 (WI.DOMDebuggerManager.prototype.removeDOMBreakpoint): 17 (WI.DOMDebuggerManager.prototype._detachDOMBreakpointsForFrame): Added. 18 (WI.DOMDebuggerManager.prototype._speculativelyResolveDOMBreakpointsForURL): 19 (WI.DOMDebuggerManager.prototype._speculativelyResolveDOMBreakpoint): Added. 20 (WI.DOMDebuggerManager.prototype._resolveDOMBreakpoint): 21 (WI.DOMDebuggerManager.prototype._setDOMBreakpoint): Added. 22 (WI.DOMDebuggerManager.prototype._removeDOMBreakpoint): Added. 23 (WI.DOMDebuggerManager.prototype._handleDOMBreakpointDisabledStateChanged): 24 (WI.DOMDebuggerManager.prototype._handleDOMBreakpointEditablePropertyChanged): Added. 25 (WI.DOMDebuggerManager.prototype._handleDOMBreakpointActionsChanged): Added. 26 (WI.DOMDebuggerManager.prototype._handleDOMBreakpointDOMNodeWillChange): Added. 27 (WI.DOMDebuggerManager.prototype._handleDOMBreakpointDOMNodeDidChange): Added. 28 (WI.DOMDebuggerManager.prototype._childFrameWasRemoved): 29 (WI.DOMDebuggerManager.prototype._mainResourceDidChange): 30 (WI.DOMDebuggerManager.prototype._nodeInserted): 31 (WI.DOMDebuggerManager.prototype._nodeRemoved): 32 (WI.DOMDebuggerManager.prototype._detachDOMBreakpoint): Deleted. 33 (WI.DOMDebuggerManager.prototype._detachBreakpointsForFrame): Deleted. 34 (WI.DOMDebuggerManager.prototype._updateDOMBreakpoint): Deleted. 35 Recursively walk any added node's subtree to resolve and set any matching DOM breakpoints. 36 Iterate all existing DOM breakpoints to see if the owner node is part of the subtree of any 37 removed nodes and remove ot if so. 38 39 * UserInterface/Models/DOMBreakpoint.js: 40 (WI.DOMBreakpoint): 41 (WI.DOMBreakpoint.displayNameForType): 42 (WI.DOMBreakpoint.fromJSON): 43 (WI.DOMBreakpoint.prototype.get editable): Added. 44 (WI.DOMBreakpoint.prototype.get domNode): Added. 45 (WI.DOMBreakpoint.prototype.set domNode): Added. 46 (WI.DOMBreakpoint.prototype.get domNodeIdentifier): Deleted. 47 (WI.DOMBreakpoint.prototype.set domNodeIdentifier): Deleted. 48 * UserInterface/Views/DOMTreeContentView.js: 49 (WI.DOMTreeContentView): 50 (WI.DOMTreeContentView.prototype.closed): 51 (WI.DOMTreeContentView.prototype._domTreeElementAdded): 52 (WI.DOMTreeContentView.prototype._domBreakpointAddedOrRemoved): 53 (WI.DOMTreeContentView.prototype._handleDOMBreakpointDisabledStateChanged): 54 (WI.DOMTreeContentView.prototype._handleDOMBreakpointDOMNodeWillChange): Added. 55 (WI.DOMTreeContentView.prototype._handleDOMBreakpointDOMNodeDidChange): Added. 56 (WI.DOMTreeContentView.prototype._updateBreakpointStatus): 57 (WI.DOMTreeContentView.prototype._restoreBreakpointsAfterUpdate): 58 (WI.DOMTreeContentView.prototype._handleDOMBreakpointDOMNodeChanged): Deleted. 59 * UserInterface/Views/SourcesNavigationSidebarPanel.js: 60 (WI.SourcesNavigationSidebarPanel): 61 (WI.SourcesNavigationSidebarPanel.prototype._updatePauseReasonSection): 62 (WI.SourcesNavigationSidebarPanel.prototype._handleDOMBreakpointDOMNodeWillChange): Added. 63 (WI.SourcesNavigationSidebarPanel.prototype._handleDOMBreakpointDOMNodeDidChange): Added. 64 (WI.SourcesNavigationSidebarPanel.prototype._handleDOMBreakpointDOMNodeChanged): Deleted. 65 Use a `WI.DOMNode` instead of an identifier instead of fetching the node for the identifier 66 each time and checking if is valid. 67 1 68 2020-09-04 Patrick Angle <pangle@apple.com> 2 69 -
trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js
r266538 r266669 32 32 this._domBreakpointURLMap = new Multimap; 33 33 this._domBreakpointFrameIdentifierMap = new Map; 34 this._clearingDOMBreakpointsForRemovedDOMNode = false; 34 35 35 36 this._listenerBreakpoints = []; … … 43 44 44 45 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.DisabledStateDidChange, this._handleDOMBreakpointDisabledStateChanged, this); 46 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.ConditionDidChange, this._handleDOMBreakpointEditablePropertyChanged, this); 47 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.IgnoreCountDidChange, this._handleDOMBreakpointEditablePropertyChanged, this); 48 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.AutoContinueDidChange, this._handleDOMBreakpointEditablePropertyChanged, this); 49 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.ActionsDidChange, this._handleDOMBreakpointActionsChanged, this); 50 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeWillChange, this._handleDOMBreakpointDOMNodeWillChange, this); 51 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeDidChange, this._handleDOMBreakpointDOMNodeDidChange, this); 45 52 46 53 WI.EventBreakpoint.addEventListener(WI.Breakpoint.Event.DisabledStateDidChange, this._handleEventBreakpointDisabledStateChanged, this); … … 231 238 let frame = frames.shift(); 232 239 233 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frame .id);240 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frame); 234 241 if (domBreakpointNodeIdentifierMap) 235 242 resolvedBreakpoints.pushAll(domBreakpointNodeIdentifierMap.values()); … … 251 258 return []; 252 259 253 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(node.frame .id);260 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(node.frame); 254 261 if (!domBreakpointNodeIdentifierMap) 255 262 return []; 256 263 257 let breakpoints = domBreakpointNodeIdentifierMap.get(node .id);264 let breakpoints = domBreakpointNodeIdentifierMap.get(node); 258 265 return breakpoints ? Array.from(breakpoints) : []; 259 266 } … … 280 287 addDOMBreakpoint(breakpoint) 281 288 { 282 console.assert(breakpoint instanceof WI.DOMBreakpoint); 289 console.assert(breakpoint instanceof WI.DOMBreakpoint, breakpoint); 290 console.assert(breakpoint.url, breakpoint); 283 291 if (!breakpoint || !breakpoint.url) 284 292 return; 285 293 286 if (breakpoint.special) { 294 console.assert(!breakpoint.special, breakpoint); 295 296 this._domBreakpointURLMap.add(breakpoint.url, breakpoint); 297 298 if (breakpoint.domNode) { 299 this._resolveDOMBreakpoint(breakpoint, breakpoint.domNode); 300 301 if (!breakpoint.disabled) { 302 // We should get the target associated with the nodeIdentifier of this breakpoint. 303 let target = WI.assumingMainTarget(); 304 if (target) 305 this._setDOMBreakpoint(breakpoint, target); 306 } 307 287 308 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, {breakpoint}); 288 return; 289 } 290 291 this._domBreakpointURLMap.add(breakpoint.url, breakpoint); 292 293 if (breakpoint.domNodeIdentifier) 294 this._resolveDOMBreakpoint(breakpoint, breakpoint.domNodeIdentifier); 295 296 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, {breakpoint}); 309 310 WI.debuggerManager.addProbesForBreakpoint(breakpoint); 311 } else 312 this._speculativelyResolveDOMBreakpoint(breakpoint); 297 313 298 314 if (!this._restoringBreakpoints) … … 302 318 removeDOMBreakpoint(breakpoint) 303 319 { 304 console.assert(breakpoint instanceof WI.DOMBreakpoint); 305 if (!breakpoint) 306 return; 307 308 if (breakpoint.special) { 309 breakpoint.disabled = true; 320 console.assert(breakpoint instanceof WI.DOMBreakpoint, breakpoint); 321 console.assert(breakpoint.url, breakpoint); 322 if (!breakpoint || !breakpoint.url) 323 return; 324 325 console.assert(!breakpoint.special, breakpoint); 326 327 // Disable the breakpoint first, so removing actions doesn't re-add the breakpoint. 328 breakpoint.disabled = true; 329 breakpoint.clearActions(); 330 331 this._domBreakpointURLMap.delete(breakpoint.url); 332 333 if (breakpoint.domNode) { 334 if (breakpoint.domNode.frame) { 335 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(breakpoint.domNode.frame); 336 domBreakpointNodeIdentifierMap.delete(breakpoint.domNode, breakpoint); 337 if (!domBreakpointNodeIdentifierMap.size) 338 this._domBreakpointFrameIdentifierMap.delete(breakpoint.domNode.frame); 339 } 340 310 341 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, {breakpoint}); 311 return; 312 } 313 314 this._detachDOMBreakpoint(breakpoint); 315 316 this._domBreakpointURLMap.delete(breakpoint.url); 317 318 if (!breakpoint.disabled) { 319 // We should get the target associated with the nodeIdentifier of this breakpoint. 320 let target = WI.assumingMainTarget(); 321 target.DOMDebuggerAgent.removeDOMBreakpoint(breakpoint.domNodeIdentifier, breakpoint.type); 322 } 323 324 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, {breakpoint}); 325 326 breakpoint.domNodeIdentifier = null; 342 343 breakpoint.domNode = null; 344 } 327 345 328 346 if (!this._restoringBreakpoints) … … 510 528 // Private 511 529 512 _detachDOMBreakpoint(breakpoint) 513 { 514 let nodeIdentifier = breakpoint.domNodeIdentifier; 515 let node = WI.domManager.nodeForId(nodeIdentifier); 516 console.assert(node, "Missing DOM node for breakpoint.", breakpoint); 517 if (!node || !node.frame) 518 return; 519 520 let frameIdentifier = node.frame.id; 521 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frameIdentifier); 522 console.assert(domBreakpointNodeIdentifierMap, "Missing DOM breakpoints for node parent frame.", node); 523 if (!domBreakpointNodeIdentifierMap) 524 return; 525 526 domBreakpointNodeIdentifierMap.delete(nodeIdentifier, breakpoint); 527 528 if (!domBreakpointNodeIdentifierMap.size) 529 this._domBreakpointFrameIdentifierMap.delete(frameIdentifier); 530 } 531 532 _detachBreakpointsForFrame(frame) 533 { 534 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frame.id); 535 if (!domBreakpointNodeIdentifierMap) 536 return; 537 538 this._domBreakpointFrameIdentifierMap.delete(frame.id); 539 540 for (let breakpoint of domBreakpointNodeIdentifierMap.values()) 541 breakpoint.domNodeIdentifier = null; 530 _detachDOMBreakpointsForFrame(frame) 531 { 532 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frame); 533 if (domBreakpointNodeIdentifierMap) { 534 this._domBreakpointFrameIdentifierMap.delete(frame); 535 536 this._clearingDOMBreakpointsForRemovedDOMNode = true; 537 for (let breakpoint of domBreakpointNodeIdentifierMap.values()) 538 breakpoint.domNode = null; 539 this._clearingDOMBreakpointsForRemovedDOMNode = false; 540 } 541 542 for (let childFrame of frame.childFrameCollection) 543 this._detachDOMBreakpointsForFrame(childFrame); 542 544 } 543 545 … … 548 550 return; 549 551 550 for (let breakpoint of domBreakpoints) { 551 if (breakpoint.domNodeIdentifier) 552 continue; 553 554 WI.domManager.pushNodeByPathToFrontend(breakpoint.path, (nodeIdentifier) => { 555 if (breakpoint.domNodeIdentifier) { 556 // This breakpoint may have been resolved by a node being inserted before this 557 // callback is invoked. If so, the `nodeIdentifier` should match, so don't try 558 // to resolve it again as it would've already been resolved. 559 console.assert(breakpoint.domNodeIdentifier === nodeIdentifier); 560 return; 561 } 562 563 if (!nodeIdentifier) 564 return; 565 566 this._restoringBreakpoints = true; 567 this._resolveDOMBreakpoint(breakpoint, nodeIdentifier); 568 this._restoringBreakpoints = false; 569 }); 570 } 571 } 572 573 _resolveDOMBreakpoint(breakpoint, nodeIdentifier) 574 { 575 let node = WI.domManager.nodeForId(nodeIdentifier); 576 console.assert(node, "Missing DOM node for nodeIdentifier.", nodeIdentifier); 577 if (!node || !node.frame) 578 return; 579 580 let frameIdentifier = node.frame.id; 581 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(frameIdentifier); 552 for (let breakpoint of domBreakpoints) 553 this._speculativelyResolveDOMBreakpoint(breakpoint); 554 } 555 556 _speculativelyResolveDOMBreakpoint(breakpoint) 557 { 558 if (breakpoint.domNode) 559 return; 560 561 WI.domManager.pushNodeByPathToFrontend(breakpoint.path, (nodeIdentifier) => { 562 if (!nodeIdentifier) 563 return; 564 565 if (breakpoint.domNode) { 566 // This breakpoint may have been resolved by a node being inserted before this 567 // callback is invoked. If so, the `nodeIdentifier` should match, so don't try 568 // to resolve it again as it would've already been resolved. 569 console.assert(breakpoint.domNode.id === nodeIdentifier); 570 return; 571 } 572 573 this._restoringBreakpoints = true; 574 this._resolveDOMBreakpoint(breakpoint, WI.domManager.nodeForId(nodeIdentifier)); 575 this._restoringBreakpoints = false; 576 }); 577 } 578 579 _resolveDOMBreakpoint(breakpoint, node) 580 { 581 console.assert(node instanceof WI.DOMNode, node); 582 583 if (!node.frame) 584 return; 585 586 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(node.frame); 582 587 if (!domBreakpointNodeIdentifierMap) { 583 588 domBreakpointNodeIdentifierMap = new Multimap; 584 this._domBreakpointFrameIdentifierMap.set(frameIdentifier, domBreakpointNodeIdentifierMap); 585 } 586 587 domBreakpointNodeIdentifierMap.add(nodeIdentifier, breakpoint); 588 589 breakpoint.domNodeIdentifier = nodeIdentifier; 590 591 if (!breakpoint.disabled) { 592 // We should get the target associated with the nodeIdentifier of this breakpoint. 593 let target = WI.assumingMainTarget(); 594 if (target) 595 this._updateDOMBreakpoint(breakpoint, target); 596 } 597 } 598 599 _updateDOMBreakpoint(breakpoint, target) 600 { 601 console.assert(target.type !== WI.TargetType.Worker, "Worker targets do not support DOM breakpoints"); 602 if (target.type === WI.TargetType.Worker) 603 return; 604 605 if (!target.hasCommand("DOMDebugger.setDOMBreakpoint") || !target.hasCommand("DOMDebugger.removeDOMBreakpoint")) 606 return; 607 608 if (!breakpoint.domNodeIdentifier) 609 return; 610 611 if (breakpoint.disabled) 612 target.DOMDebuggerAgent.removeDOMBreakpoint(breakpoint.domNodeIdentifier, breakpoint.type); 613 else { 614 if (!this._restoringBreakpoints && !WI.debuggerManager.breakpointsDisabledTemporarily) 615 WI.debuggerManager.breakpointsEnabled = true; 616 617 target.DOMDebuggerAgent.setDOMBreakpoint(breakpoint.domNodeIdentifier, breakpoint.type); 618 } 589 this._domBreakpointFrameIdentifierMap.set(node.frame, domBreakpointNodeIdentifierMap); 590 } 591 592 domBreakpointNodeIdentifierMap.add(node, breakpoint); 593 594 breakpoint.domNode = node; 595 } 596 597 _setDOMBreakpoint(breakpoint, target) 598 { 599 console.assert(!breakpoint.disabled, breakpoint); 600 console.assert(breakpoint.domNode instanceof WI.DOMNode, breakpoint); 601 console.assert(target.type !== WI.TargetType.Worker, "Worker targets do not support DOM breakpoints", target); 602 603 // COMPATIBILITY (iOS 10.3): DOMDebugger.setDOMBreakpoint did not exist yet. 604 if (!target.hasCommand("DOMDebugger.setDOMBreakpoint")) 605 return; 606 607 if (!this._restoringBreakpoints && !WI.debuggerManager.breakpointsDisabledTemporarily) 608 WI.debuggerManager.breakpointsEnabled = true; 609 610 target.DOMDebuggerAgent.setDOMBreakpoint.invoke({ 611 nodeId: breakpoint.domNode.id, 612 type: breakpoint.type, 613 options: breakpoint.optionsToProtocol(), 614 }); 615 } 616 617 _removeDOMBreakpoint(breakpoint, target) 618 { 619 console.assert(breakpoint.domNode instanceof WI.DOMNode, breakpoint); 620 console.assert(target.type !== WI.TargetType.Worker, "Worker targets do not support DOM breakpoints", target); 621 622 // COMPATIBILITY (iOS 10.3): DOMDebugger.removeDOMBreakpoint did not exist yet. 623 if (!target.hasCommand("DOMDebugger.removeDOMBreakpoint")) 624 return; 625 626 target.DOMDebuggerAgent.removeDOMBreakpoint(breakpoint.domNode.id, breakpoint.type); 619 627 } 620 628 … … 773 781 { 774 782 let breakpoint = event.target; 783 784 if (!this._restoringBreakpoints) 785 WI.objectStores.domBreakpoints.putObject(breakpoint); 786 787 if (!breakpoint.domNode) 788 return; 789 790 // We should get the target associated with the nodeIdentifier of this breakpoint. 775 791 let target = WI.assumingMainTarget(); 776 if (target) 777 this._updateDOMBreakpoint(breakpoint, target); 792 if (target) { 793 if (breakpoint.disabled) 794 this._removeDOMBreakpoint(breakpoint, target); 795 else 796 this._setDOMBreakpoint(breakpoint, target); 797 } 798 } 799 800 _handleDOMBreakpointEditablePropertyChanged(event) 801 { 802 let breakpoint = event.target; 778 803 779 804 if (!this._restoringBreakpoints) 780 805 WI.objectStores.domBreakpoints.putObject(breakpoint); 806 807 if (!breakpoint.domNode) 808 return; 809 810 if (breakpoint.disabled) 811 return; 812 813 this._restoringBreakpoints = true; 814 // We should get the target associated with the nodeIdentifier of this breakpoint. 815 let target = WI.assumingMainTarget(); 816 if (target) { 817 // Clear the old breakpoint from the backend before setting the new one. 818 this._removeDOMBreakpoint(breakpoint, target); 819 this._setDOMBreakpoint(breakpoint, target); 820 } 821 this._restoringBreakpoints = false; 822 } 823 824 _handleDOMBreakpointActionsChanged(event) 825 { 826 let breakpoint = event.target; 827 828 this._handleDOMBreakpointEditablePropertyChanged(event); 829 830 if (!breakpoint.domNode) 831 return; 832 833 WI.debuggerManager.updateProbesForBreakpoint(breakpoint); 834 } 835 836 _handleDOMBreakpointDOMNodeWillChange(event) 837 { 838 if (this._clearingDOMBreakpointsForRemovedDOMNode) 839 return; 840 841 let breakpoint = event.target; 842 843 if (!breakpoint.domNode) 844 return; 845 846 if (!breakpoint.disabled) { 847 // We should get the target associated with the nodeIdentifier of this breakpoint. 848 let target = WI.assumingMainTarget(); 849 if (target) 850 this._removeDOMBreakpoint(breakpoint, target); 851 } 852 853 WI.debuggerManager.removeProbesForBreakpoint(breakpoint); 854 } 855 856 _handleDOMBreakpointDOMNodeDidChange(event) 857 { 858 let breakpoint = event.target; 859 860 if (!breakpoint.domNode) 861 return; 862 863 if (!breakpoint.disabled) { 864 // We should get the target associated with the nodeIdentifier of this breakpoint. 865 let target = WI.assumingMainTarget(); 866 if (target) 867 this._setDOMBreakpoint(breakpoint, target); 868 } 869 870 WI.debuggerManager.addProbesForBreakpoint(breakpoint); 781 871 } 782 872 … … 882 972 { 883 973 let frame = event.data.childFrame; 884 this._detach BreakpointsForFrame(frame);974 this._detachDOMBreakpointsForFrame(frame); 885 975 } 886 976 … … 894 984 let frame = event.target; 895 985 if (frame.isMainFrame()) { 986 this._clearingDOMBreakpointsForRemovedDOMNode = true; 896 987 for (let breakpoint of this._domBreakpointURLMap.values()) 897 breakpoint.domNodeIdentifier = null; 988 breakpoint.domNode = null; 989 this._clearingDOMBreakpointsForRemovedDOMNode = false; 898 990 899 991 this._domBreakpointFrameIdentifierMap.clear(); 900 992 } else 901 this._detach BreakpointsForFrame(frame);993 this._detachDOMBreakpointsForFrame(frame); 902 994 903 995 this._speculativelyResolveDOMBreakpointsForURL(frame.url); … … 915 1007 return; 916 1008 1009 let resolvableBreakpoints = []; 917 1010 for (let breakpoint of breakpoints) { 918 if (breakpoint.domNodeIdentifier) 919 continue; 920 921 if (breakpoint.path !== node.path()) 922 continue; 923 924 this._restoringBreakpoints = true; 925 this._resolveDOMBreakpoint(breakpoint, node.id); 926 this._restoringBreakpoints = false; 1011 if (!breakpoint.domNode) 1012 resolvableBreakpoints.push(breakpoint); 1013 } 1014 if (!resolvableBreakpoints.length) 1015 return; 1016 1017 // This is not very expensive because `WI.DOMNode` children are lazily populated, so it's 1018 // unlikely that there will be a deep subtree to walk. 1019 let stack = [node]; 1020 while (stack.length) { 1021 let child = stack.pop(); 1022 let path = child.path(); 1023 1024 for (let i = resolvableBreakpoints.length - 1; i >= 0; --i) { 1025 if (resolvableBreakpoints[i].path === path) { 1026 this._restoringBreakpoints = true; 1027 this._resolveDOMBreakpoint(resolvableBreakpoints[i], child); 1028 this._restoringBreakpoints = false; 1029 1030 resolvableBreakpoints.splice(i, 1); 1031 } 1032 } 1033 if (!resolvableBreakpoints.length) 1034 break; 1035 1036 if (child.children?.length) 1037 stack.pushAll(child.children); 927 1038 } 928 1039 } … … 934 1045 return; 935 1046 936 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(node.frame .id);1047 let domBreakpointNodeIdentifierMap = this._domBreakpointFrameIdentifierMap.get(node.frame); 937 1048 if (!domBreakpointNodeIdentifierMap) 938 1049 return; 939 1050 940 let breakpoints = domBreakpointNodeIdentifierMap.get(node.id); 941 if (!breakpoints) 942 return; 943 944 domBreakpointNodeIdentifierMap.delete(node.id); 945 946 if (!domBreakpointNodeIdentifierMap.size) 947 this._domBreakpointFrameIdentifierMap.delete(node.frame.id); 948 949 for (let breakpoint of breakpoints) 950 breakpoint.domNodeIdentifier = null; 1051 for (let [breakpointOwner, breakpoints] of domBreakpointNodeIdentifierMap.sets()) { 1052 if (breakpointOwner == node || node.isAncestor(breakpointOwner)) { 1053 this._clearingDOMBreakpointsForRemovedDOMNode = true; 1054 for (let breakpoint of breakpoints) 1055 breakpoint.domNode = null; 1056 this._clearingDOMBreakpointsForRemovedDOMNode = false; 1057 1058 domBreakpointNodeIdentifierMap.delete(breakpointOwner); 1059 if (!domBreakpointNodeIdentifierMap.size) { 1060 this._domBreakpointFrameIdentifierMap.delete(node.frame); 1061 break; 1062 } 1063 } 1064 } 951 1065 } 952 1066 }; -
trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js
r266074 r266669 381 381 382 382 var parent = this._idToDOMNode[parentId]; 383 384 if (parent.children) { 385 for (let node of parent.children) 386 this.dispatchEventToListeners(WI.DOMManager.Event.NodeRemoved, {node, parent}); 387 } 388 383 389 parent._setChildrenPayload(payloads); 390 391 for (let node of parent.children) 392 this.dispatchEventToListeners(WI.DOMManager.Event.NodeInserted, {node, parent}); 384 393 } 385 394 -
trunk/Source/WebInspectorUI/UserInterface/Models/DOMBreakpoint.js
r266480 r266669 26 26 WI.DOMBreakpoint = class DOMBreakpoint extends WI.Breakpoint 27 27 { 28 constructor(domNodeOrInfo, type, {disabled } = {})28 constructor(domNodeOrInfo, type, {disabled, actions, condition, ignoreCount, autoContinue} = {}) 29 29 { 30 30 console.assert(domNodeOrInfo instanceof WI.DOMNode || typeof domNodeOrInfo === "object", domNodeOrInfo); 31 31 console.assert(Object.values(WI.DOMBreakpoint.Type).includes(type), type); 32 32 33 super({disabled });33 super({disabled, actions, condition, ignoreCount, autoContinue}); 34 34 35 35 if (domNodeOrInfo instanceof WI.DOMNode) { 36 this._domNode Identifier = domNodeOrInfo.id;36 this._domNode = domNodeOrInfo; 37 37 this._path = domNodeOrInfo.path(); 38 38 console.assert(WI.networkManager.mainFrame); 39 39 this._url = WI.networkManager.mainFrame.url; 40 40 } else if (domNodeOrInfo && typeof domNodeOrInfo === "object") { 41 this._domNode Identifier= null;41 this._domNode = null; 42 42 this._path = domNodeOrInfo.path; 43 43 this._url = domNodeOrInfo.url; … … 64 64 } 65 65 66 console. error();66 console.assert(false, "Unknown DOM breakpoint type", type); 67 67 return WI.UIString("DOM"); 68 68 } … … 72 72 return new WI.DOMBreakpoint(json, json.type, { 73 73 disabled: json.disabled, 74 condition: json.condition, 75 actions: json.actions?.map((actionJSON) => WI.BreakpointAction.fromJSON(actionJSON)) || [], 76 ignoreCount: json.ignoreCount, 77 autoContinue: json.autoContinue, 74 78 }); 75 79 } … … 86 90 } 87 91 88 get domNodeIdentifier()92 get editable() 89 93 { 90 return this._domNodeIdentifier; 94 // COMPATIBILITY (iOS 14): DOMDebugger.setDOMBreakpoint did not have an "options" parameter yet. 95 return InspectorBackend.hasCommand("DOMDebugger.setDOMBreakpoint", "options"); 91 96 } 92 97 93 set domNodeIdentifier(nodeIdentifier)98 get domNode() 94 99 { 95 if (this._domNodeIdentifier === nodeIdentifier) 100 return this._domNode; 101 } 102 103 set domNode(domNode) 104 { 105 console.assert(domNode instanceof WI.DOMNode, domNode); 106 console.assert(!this._domNode !== !domNode, "domNode should not change once set"); 107 if (!this._domNode === !domNode) 96 108 return; 97 109 98 let data = {}; 99 if (!nodeIdentifier) 100 data.oldNodeIdentifier = this._domNodeIdentifier; 101 102 this._domNodeIdentifier = nodeIdentifier; 103 104 this.dispatchEventToListeners(WI.DOMBreakpoint.Event.DOMNodeChanged, data); 110 this.dispatchEventToListeners(WI.DOMBreakpoint.Event.DOMNodeWillChange); 111 this._domNode = domNode; 112 this.dispatchEventToListeners(WI.DOMBreakpoint.Event.DOMNodeDidChange); 105 113 } 106 114 … … 138 146 139 147 WI.DOMBreakpoint.Event = { 140 DOMNodeChanged: "dom-breakpoint-dom-node-changed", 148 DOMNodeDidChange: "dom-breakpoint-dom-node-did-change", 149 DOMNodeWillChange: "dom-breakpoint-dom-node-will-change", 141 150 }; 142 151 -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js
r266074 r266669 86 86 87 87 this._breakpointGutterEnabled = false; 88 this._pendingBreakpointNode Identifiers = new Set;88 this._pendingBreakpointNodes = new Set; 89 89 90 90 this._defaultAppearanceDidChange(); … … 97 97 98 98 WI.DOMBreakpoint.addEventListener(WI.Breakpoint.Event.DisabledStateDidChange, this._handleDOMBreakpointDisabledStateChanged, this); 99 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeChanged, this._handleDOMBreakpointDOMNodeChanged, this); 99 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeWillChange, this._handleDOMBreakpointDOMNodeWillChange, this); 100 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeDidChange, this._handleDOMBreakpointDOMNodeDidChange, this); 100 101 101 102 this._breakpointsEnabledDidChange(); … … 171 172 172 173 this._domTreeOutline.close(); 173 this._pendingBreakpointNode Identifiers.clear();174 this._pendingBreakpointNodes.clear(); 174 175 } 175 176 … … 488 489 _domTreeElementAdded(event) 489 490 { 490 if (!this._pendingBreakpointNode Identifiers.size)491 if (!this._pendingBreakpointNodes.size) 491 492 return; 492 493 … … 497 498 return; 498 499 499 if (!this._pendingBreakpointNode Identifiers.delete(node.id))500 if (!this._pendingBreakpointNodes.delete(node)) 500 501 return; 501 502 … … 754 755 { 755 756 let breakpoint = event.data.breakpoint; 756 this._updateBreakpointStatus(breakpoint.domNode Identifier);757 this._updateBreakpointStatus(breakpoint.domNode); 757 758 } 758 759 … … 760 761 { 761 762 let breakpoint = event.target; 762 this._updateBreakpointStatus(breakpoint.domNode Identifier);763 } 764 765 _handleDOMBreakpointDOMNode Changed(event)763 this._updateBreakpointStatus(breakpoint.domNode); 764 } 765 766 _handleDOMBreakpointDOMNodeWillChange(event) 766 767 { 767 768 let breakpoint = event.target; 768 let nodeIdentifier = breakpoint.domNodeIdentifier || event.data.oldNodeIdentifier; 769 this._updateBreakpointStatus(nodeIdentifier); 770 } 771 772 _updateBreakpointStatus(nodeIdentifier) 773 { 774 let domNode = WI.domManager.nodeForId(nodeIdentifier); 769 this._updateBreakpointStatus(breakpoint.domNode); 770 } 771 772 _handleDOMBreakpointDOMNodeDidChange(event) 773 { 774 let breakpoint = event.target; 775 this._updateBreakpointStatus(breakpoint.domNode); 776 } 777 778 _updateBreakpointStatus(domNode) 779 { 775 780 if (!domNode) 776 781 return; … … 778 783 let treeElement = this._domTreeOutline.findTreeElement(domNode); 779 784 if (!treeElement) { 780 this._pendingBreakpointNode Identifiers.add(nodeIdentifier);785 this._pendingBreakpointNodes.add(domNode); 781 786 return; 782 787 } … … 796 801 _restoreBreakpointsAfterUpdate() 797 802 { 798 this._pendingBreakpointNode Identifiers.clear();803 this._pendingBreakpointNodes.clear(); 799 804 800 805 this.breakpointGutterEnabled = false; … … 802 807 let updatedNodes = new Set; 803 808 for (let breakpoint of WI.domDebuggerManager.domBreakpoints) { 804 if (updatedNodes.has(breakpoint.domNode Identifier))809 if (updatedNodes.has(breakpoint.domNode)) 805 810 continue; 806 811 807 this._updateBreakpointStatus(breakpoint.domNode Identifier);812 this._updateBreakpointStatus(breakpoint.domNode); 808 813 } 809 814 } -
trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js
r266538 r266669 329 329 WI.IssueMessage.addEventListener(WI.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this); 330 330 331 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeChanged, this._handleDOMBreakpointDOMNodeChanged, this); 331 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeWillChange, this._handleDOMBreakpointDOMNodeWillChange, this); 332 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeDidChange, this._handleDOMBreakpointDOMNodeDidChange, this); 332 333 333 334 WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._handleConsoleIssueAdded, this); … … 1258 1259 1259 1260 let getDOMNodeTreeElement = (domNode) => { 1260 console.assert(domNode, "Missing DOMNode for identifier", breakpoint.domNodeIdentifier);1261 if (!domNode)1262 return null;1263 1264 1261 let domNodeTreeElement = this._breakpointsTreeOutline.findTreeElement(domNode); 1265 1262 if (!domNodeTreeElement) { … … 1281 1278 options.classNames = ["microtask"]; 1282 1279 else if (breakpoint instanceof WI.DOMBreakpoint) { 1283 if (!breakpoint.domNode Identifier)1280 if (!breakpoint.domNode) 1284 1281 return null; 1285 1282 1286 1283 constructor = WI.DOMBreakpointTreeElement; 1287 1284 1288 let domNode = WI.domManager.nodeForId(breakpoint.domNodeIdentifier); 1289 parentTreeElement = getDOMNodeTreeElement(domNode); 1285 parentTreeElement = getDOMNodeTreeElement(breakpoint.domNode); 1290 1286 } else if (breakpoint instanceof WI.EventBreakpoint) { 1291 1287 constructor = WI.EventBreakpointTreeElement; … … 1672 1668 if (pauseData.targetNodeId) { 1673 1669 console.assert(domBreakpoint.type === WI.DOMBreakpoint.Type.SubtreeModified || domBreakpoint.type === WI.DOMBreakpoint.Type.NodeRemoved); 1670 console.assert(pauseData.targetNodeId !== domBreakpoint.domNode.id, pauseData.targetNodeId, domBreakpoint); 1674 1671 updateTargetDescription(pauseData.targetNodeId); 1675 1672 } else if (pauseData.targetNode) { // COMPATIBILITY (iOS 13): `targetNode` was renamed to `targetNodeId` and was changed from a `Runtime.RemoteObject` to a `DOM.NodeId`. … … 2382 2379 } 2383 2380 2384 _handleDOMBreakpointDOMNode Changed(event)2381 _handleDOMBreakpointDOMNodeWillChange(event) 2385 2382 { 2386 2383 let breakpoint = event.target; 2387 if (breakpoint.domNodeIdentifier) 2388 this._addBreakpoint(breakpoint); 2389 else 2390 this._removeBreakpoint(breakpoint); 2384 this._removeBreakpoint(breakpoint); 2385 } 2386 2387 _handleDOMBreakpointDOMNodeDidChange(event) 2388 { 2389 let breakpoint = event.target; 2390 this._addBreakpoint(breakpoint); 2391 2391 } 2392 2392
Note: See TracChangeset
for help on using the changeset viewer.