Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// Test that the debugger pauses and is automatically highlighted and selected,
// even when it hasn't been opened.
"use strict";
const IFRAME_TEST_COM_URI = `https://example.com/document-builder.sjs?html=${encodeURI(
`<script>const a=2;\ndebugger;\nconsole.log(a);</script>`
)}`;
// Embed the example.com test page in an example.org iframe.
const IFRAME_TEST_URI = `https://example.org/document-builder.sjs?html=${encodeURI(
`<script>function breakDebugger() {const b=3;\ndebugger;\nconsole.log(b);}</script><iframe src="${IFRAME_TEST_COM_URI}"></iframe><body>`
)}`;
add_task(async function () {
info("Test a debugger statement from the top level document");
// Make sure the toolbox opens with the webconsole initially selected.
const toolbox = await initPane("doc-debugger-statements.html", "webconsole");
info("Execute a debugger statement");
const pausedRun = SpecialPowers.spawn(
gBrowser.selectedBrowser,
[],
function () {
content.wrappedJSObject.test();
}
);
const dbg = await assertDebuggerIsHighlightedAndPaused(toolbox);
const source = findSource(dbg, "doc-debugger-statements.html");
await assertPausedAtSourceAndLine(dbg, source.id, 16);
await resume(dbg);
info("Wait for the paused code to complete after resume");
await pausedRun;
ok(
!toolbox.isHighlighted("jsdebugger"),
"Debugger is no longer highlighted after resume"
);
});
add_task(async function () {
info("Test a debugger statement from an iframe");
// Make sure the toolbox opens with the webconsole initially selected.
const toolbox = await openNewTabAndToolbox(IFRAME_TEST_URI, "webconsole");
info(
"Reload the test page, which will trigger the debugger statement in the iframe"
);
const pausedReload = reloadBrowser();
const dbg = await assertDebuggerIsHighlightedAndPaused(toolbox);
const source = findSource(dbg, IFRAME_TEST_COM_URI);
await assertPausedAtSourceAndLine(dbg, source.id, 2);
await resume(dbg);
info("Wait for the paused code to complete after resume");
await pausedReload;
ok(
!toolbox.isHighlighted("jsdebugger"),
"Debugger is no longer highlighted after resume"
);
});
add_task(async function () {
info("Test pausing from two distinct targets");
// Make sure the toolbox opens with the webconsole initially selected.
const toolbox = await openNewTabAndToolbox(IFRAME_TEST_URI, "webconsole");
info(
"Reload the test page, which will trigger the debugger statement in the iframe"
);
const pausedReload = reloadBrowser();
const dbg = await assertDebuggerIsHighlightedAndPaused(toolbox);
const topLevelThread =
toolbox.commands.targetCommand.targetFront.threadFront.actorID;
const iframeThread = dbg.selectors.getCurrentThread();
if (isFissionEnabled() || isEveryFrameTargetEnabled()) {
isnot(
topLevelThread,
iframeThread,
"With fission/EFT, we get two distinct threads and could pause two times"
);
ok(
!dbg.selectors.getIsPaused(topLevelThread),
"The top level document thread is not paused"
);
ok(
dbg.selectors.getIsPaused(iframeThread),
"Only the iframe thread is paused"
);
} else {
is(
topLevelThread,
iframeThread,
"Without fission/EFT, we get a unique thread and we won't pause when calling top document code"
);
}
const source = findSource(dbg, IFRAME_TEST_COM_URI);
await assertPausedAtSourceAndLine(dbg, source.id, 2);
info("Step over to the next line");
await stepOver(dbg);
await assertPausedAtSourceAndLine(dbg, source.id, 3);
info("Now execute a debugger statement in the top level target");
const onPaused = waitForPausedThread(dbg, topLevelThread);
const pausedTopTarget = SpecialPowers.spawn(
gBrowser.selectedBrowser,
[],
function () {
content.wrappedJSObject.breakDebugger();
}
);
if (isFissionEnabled() || isEveryFrameTargetEnabled()) {
info("Wait for the top level target to be paused");
await onPaused;
// also use waitForPause to wait for UI updates
await waitForPaused(dbg);
ok(
dbg.selectors.getIsPaused(topLevelThread),
"The top level document thread is paused"
);
ok(dbg.selectors.getIsPaused(iframeThread), "The iframe thread is paused");
ok(
toolbox.isHighlighted("jsdebugger"),
"Debugger stays highlighted when pausing on another thread"
);
info(
"The new paused state refers to the latest breakpoint being hit, on the top level target"
);
const source2 = findSource(dbg, IFRAME_TEST_URI);
await assertPausedAtSourceAndLine(dbg, source2.id, 2);
info("Resume the top level target");
await resume(dbg);
info("Wait for top level target paused code to complete after resume");
await pausedTopTarget;
info(
"By default we stay on the last selected thread on resume and so the current thread is no longer paused"
);
assertNotPaused(dbg);
ok(
toolbox.isHighlighted("jsdebugger"),
"Debugger stays highlighted when resuming only the top level target"
);
info(
"Re-select the iframe thread, which is still paused on the original breakpoint"
);
dbg.actions.selectThread(iframeThread);
await waitForPausedThread(dbg, iframeThread);
await waitForSelectedSource(dbg, source);
await assertPausedAtSourceAndLine(dbg, source.id, 3);
info("Resume the iframe target");
await resume(dbg);
assertNotPaused(dbg);
info("Wait for the paused code in the iframe to complete after resume");
await pausedReload;
await waitUntil(() => !toolbox.isHighlighted("jsdebugger"));
ok(
true,
"Debugger is no longer highlighted after resuming all the paused targets"
);
} else {
info(
"Without fission/EFT, the iframe thread is the same as top document and doesn't pause. So wait for its resolution."
);
await pausedTopTarget;
}
info("Resume the last paused thread");
await resume(dbg);
assertNotPaused(dbg);
info("Wait for the paused code in the iframe to complete after resume");
await pausedReload;
await waitUntil(() => !toolbox.isHighlighted("jsdebugger"));
ok(
true,
"Debugger is no longer highlighted after resuming all the paused targets"
);
});