browser_dbg-event-breakpoints.js (11705B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 "use strict"; 6 7 add_task(async function () { 8 await pushPref("dom.element.commandfor.enabled", true); 9 await pushPref("dom.events.textevent.enabled", true); 10 await pushPref("dom.closewatcher.enabled", true); 11 12 const dbg = await initDebugger( 13 "doc-event-breakpoints.html", 14 "event-breakpoints.js" 15 ); 16 await selectSource(dbg, "event-breakpoints.js"); 17 await waitForSelectedSource(dbg, "event-breakpoints.js"); 18 const eventBreakpointsSource = findSource(dbg, "event-breakpoints.js"); 19 20 // We want to set each breakpoint individually to test adding/removing breakpoints, see Bug 1748589. 21 await toggleEventBreakpoint(dbg, "Mouse", "event.mouse.click"); 22 23 invokeInTab("clickHandler"); 24 await waitForPaused(dbg); 25 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 12); 26 27 const whyPaused = await waitFor( 28 () => dbg.win.document.querySelector(".why-paused")?.innerText 29 ); 30 is( 31 whyPaused, 32 `Paused on event breakpoint\nclickTargetClicked - event-breakpoints.js:12:2\nDOM 'click' event`, 33 "whyPaused does state that the debugger is paused as a result of a click event breakpoint" 34 ); 35 await resume(dbg); 36 37 await toggleEventBreakpoint(dbg, "XHR", "event.xhr.load"); 38 invokeInTab("xhrHandler"); 39 await waitForPaused(dbg); 40 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 24); 41 await resume(dbg); 42 43 await toggleEventBreakpoint(dbg, "Timer", "timer.timeout.set"); 44 await toggleEventBreakpoint(dbg, "Timer", "timer.timeout.fire"); 45 invokeInTab("timerHandler"); 46 await waitForPaused(dbg); 47 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 31); 48 await resume(dbg); 49 50 await waitForPaused(dbg); 51 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 32); 52 await resume(dbg); 53 54 await toggleEventBreakpoint(dbg, "Script", "script.source.firstStatement"); 55 invokeInTab("evalHandler"); 56 await waitForPaused(dbg); 57 await assertPausedAtSourceAndLine(dbg, findSource(dbg, "eval-test.js").id, 2); 58 await resume(dbg); 59 await toggleEventBreakpoint(dbg, "Script", "script.source.firstStatement"); 60 61 await toggleEventBreakpoint(dbg, "Control", "event.control.focusin"); 62 await toggleEventBreakpoint(dbg, "Control", "event.control.focusout"); 63 invokeOnElement("#focus-text", "focus"); 64 await waitForPaused(dbg); 65 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 47); 66 await resume(dbg); 67 68 // wait for focus-out event to fire 69 await waitForPaused(dbg); 70 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 52); 71 await resume(dbg); 72 73 info("Deselect focus events"); 74 // We need to give the input focus to test composition, but we don't want the 75 // focus breakpoints to fire. 76 await toggleEventBreakpoint(dbg, "Control", "event.control.focusin"); 77 await toggleEventBreakpoint(dbg, "Control", "event.control.focusout"); 78 79 await toggleEventBreakpoint(dbg, "Control", "event.control.command"); 80 invokeOnElement("#invoker", "click"); 81 await waitForPaused(dbg); 82 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 77); 83 await resume(dbg); 84 85 info("Enable closewatcher cancel and close events"); 86 await toggleEventBreakpoint(dbg, "CloseWatcher", "event.closewatcher.cancel"); 87 await toggleEventBreakpoint(dbg, "CloseWatcher", "event.closewatcher.close"); 88 invokeInTab("closeWatcherRequestClose"); 89 info("Wait for pause in cancel event listener"); 90 await waitForPaused(dbg); 91 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 116); 92 await resume(dbg); 93 info("And wait for pause in close event listener after resuming"); 94 await waitForPaused(dbg); 95 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 120); 96 await resume(dbg); 97 98 info("Enable beforetoggle and toggle events"); 99 await toggleEventBreakpoint(dbg, "Control", "event.control.beforetoggle"); 100 await toggleEventBreakpoint(dbg, "Control", "event.control.toggle"); 101 invokeOnElement("#popover-toggle", "click"); 102 info("Wait for pause in beforetoggle event listener"); 103 await waitForPaused(dbg); 104 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 93); 105 await resume(dbg); 106 info("And wait for pause in toggle event listener after resuming"); 107 await waitForPaused(dbg); 108 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 97); 109 await resume(dbg); 110 111 await toggleEventBreakpoint( 112 dbg, 113 "Keyboard", 114 "event.keyboard.compositionstart" 115 ); 116 invokeOnElement("#focus-text", "focus"); 117 118 info("Type some characters during composition"); 119 invokeComposition(); 120 121 await waitForPaused(dbg); 122 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 57); 123 await resume(dbg); 124 125 info("Deselect compositionstart and select compositionupdate"); 126 await toggleEventBreakpoint( 127 dbg, 128 "Keyboard", 129 "event.keyboard.compositionstart" 130 ); 131 await toggleEventBreakpoint( 132 dbg, 133 "Keyboard", 134 "event.keyboard.compositionupdate" 135 ); 136 137 invokeOnElement("#focus-text", "focus"); 138 139 info("Type some characters during composition"); 140 invokeComposition(); 141 142 await waitForPaused(dbg); 143 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 62); 144 await resume(dbg); 145 146 info("Deselect compositionupdate and select compositionend"); 147 await toggleEventBreakpoint( 148 dbg, 149 "Keyboard", 150 "event.keyboard.compositionupdate" 151 ); 152 await toggleEventBreakpoint(dbg, "Keyboard", "event.keyboard.compositionend"); 153 invokeOnElement("#focus-text", "focus"); 154 155 info("Type some characters during composition"); 156 invokeComposition(); 157 158 info("Commit the composition"); 159 EventUtils.synthesizeComposition({ 160 type: "compositioncommitasis", 161 key: { key: "KEY_Enter" }, 162 }); 163 164 await waitForPaused(dbg); 165 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 67); 166 await resume(dbg); 167 168 info("Test textInput"); 169 await toggleEventBreakpoint(dbg, "Keyboard", "event.keyboard.textInput"); 170 invokeOnElement("#focus-text", "focus"); 171 EventUtils.sendChar("N"); 172 await waitForPaused(dbg); 173 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 102); 174 await resume(dbg); 175 await toggleEventBreakpoint(dbg, "Keyboard", "event.keyboard.textInput"); 176 177 info(`Check that breakpoint can be set on "scrollend"`); 178 await toggleEventBreakpoint(dbg, "Control", "event.control.scrollend"); 179 180 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { 181 content.scrollTo({ top: 20, behavior: "smooth" }); 182 }); 183 184 await waitForPaused(dbg); 185 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 72); 186 await resume(dbg); 187 188 info(`Check that breakpoint can be set on "pointerrawupdate"`); 189 await toggleEventBreakpoint(dbg, "Pointer", "event.pointer.pointerrawupdate"); 190 191 SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { 192 // EventUtils.synthesize throws when dispatching a pointerrawupdate for some reason, 193 // let's build and dispatch the event directly 194 content.document 195 .getElementById("pointer-target") 196 .dispatchEvent( 197 new content.wrappedJSObject.PointerEvent("pointerrawupdate", {}) 198 ); 199 }); 200 201 await waitForPaused(dbg); 202 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 107); 203 await resume(dbg); 204 await toggleEventBreakpoint(dbg, "Pointer", "event.pointer.pointerrawupdate"); 205 206 info("Check that the click event breakpoint is still enabled"); 207 invokeInTab("clickHandler"); 208 await waitForPaused(dbg); 209 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 12); 210 await resume(dbg); 211 212 info("Check that disabling an event breakpoint works"); 213 await toggleEventBreakpoint(dbg, "Mouse", "event.mouse.click"); 214 invokeInTab("clickHandler"); 215 // wait for a bit to make sure the debugger do not pause 216 await wait(100); 217 assertNotPaused(dbg); 218 219 info("Check that we can re-enable event breakpoints"); 220 await toggleEventBreakpoint(dbg, "Mouse", "event.mouse.click"); 221 invokeInTab("clickHandler"); 222 await waitForPaused(dbg); 223 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 12); 224 await resume(dbg); 225 226 info( 227 "Test that we don't pause on event breakpoints when source is blackboxed." 228 ); 229 await clickElement(dbg, "blackbox"); 230 await waitForDispatch(dbg.store, "BLACKBOX_WHOLE_SOURCES"); 231 232 invokeInTab("clickHandler"); 233 // wait for a bit to make sure the debugger do not pause 234 await wait(100); 235 assertNotPaused(dbg); 236 237 invokeInTab("xhrHandler"); 238 // wait for a bit to make sure the debugger do not pause 239 await wait(100); 240 assertNotPaused(dbg); 241 242 invokeInTab("timerHandler"); 243 // wait for a bit to make sure the debugger do not pause 244 await wait(100); 245 assertNotPaused(dbg); 246 247 // Cleanup - unblackbox the source 248 await clickElement(dbg, "blackbox"); 249 await waitForDispatch(dbg.store, "UNBLACKBOX_WHOLE_SOURCES"); 250 251 info(`Check that breakpoint can be set on "beforeUnload" event`); 252 await toggleEventBreakpoint(dbg, "Load", "event.load.beforeunload"); 253 let onReload = reload(dbg); 254 await waitForPaused(dbg); 255 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 82); 256 await resume(dbg); 257 await onReload; 258 await toggleEventBreakpoint(dbg, "Load", "event.load.beforeunload"); 259 260 info(`Check that breakpoint can be set on "unload" event`); 261 await toggleEventBreakpoint(dbg, "Load", "event.load.unload"); 262 onReload = reload(dbg); 263 await waitForPaused(dbg); 264 await assertPausedAtSourceAndLine(dbg, eventBreakpointsSource.id, 87); 265 await resume(dbg); 266 await onReload; 267 await toggleEventBreakpoint(dbg, "Load", "event.load.unload"); 268 }); 269 270 // Cover CmdOrCtrl+click on event breakpoints 271 add_task(async function () { 272 const dbg = await initDebugger( 273 "doc-event-breakpoints.html", 274 "event-breakpoints.js" 275 ); 276 277 // Toggle two distinct categories 278 await toggleEventBreakpoint(dbg, "Load", "event.load.unload"); 279 await toggleEventBreakpoint(dbg, "Mouse", "event.mouse.click"); 280 281 info("CmdOrCtrl + click on the Timer category"); 282 const loadGroupCheckbox = findElementWithSelector(dbg, `input[value="Load"]`); 283 const mouseGroupCheckbox = findElementWithSelector( 284 dbg, 285 `input[value="Mouse"]` 286 ); 287 const timerGroupCheckbox = findElementWithSelector( 288 dbg, 289 `input[value="Timer"]` 290 ); 291 is(loadGroupCheckbox.indeterminate, true); 292 is(mouseGroupCheckbox.indeterminate, true); 293 is(timerGroupCheckbox.checked, false); 294 timerGroupCheckbox.scrollIntoView(); 295 EventUtils.synthesizeMouseAtCenter( 296 timerGroupCheckbox, 297 { [Services.appinfo.OS === "Darwin" ? "metaKey" : "ctrlKey"]: true }, 298 dbg.win 299 ); 300 info("Wait for the checkboxes to update"); 301 await waitFor( 302 () => 303 timerGroupCheckbox.checked === true && 304 loadGroupCheckbox.indeterminate === false 305 ); 306 is(loadGroupCheckbox.indeterminate, false); 307 is(mouseGroupCheckbox.indeterminate, false); 308 is(timerGroupCheckbox.checked, true); 309 }); 310 311 async function invokeOnElement(selector, action) { 312 await SpecialPowers.focus(gBrowser.selectedBrowser); 313 await SpecialPowers.spawn( 314 gBrowser.selectedBrowser, 315 [selector, action], 316 (_selector, _action) => { 317 content.document.querySelector(_selector)[_action](); 318 } 319 ); 320 } 321 322 function invokeComposition() { 323 const string = "ex"; 324 EventUtils.synthesizeCompositionChange({ 325 composition: { 326 string, 327 clauses: [ 328 { 329 length: string.length, 330 attr: Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE, 331 }, 332 ], 333 }, 334 caret: { start: string.length, length: 0 }, 335 key: { key: string[string.length - 1] }, 336 }); 337 }