summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/test/mochitest/browser_dbg-unselected-pause.js
blob: f93859eb054167062bd07d97431ce34e7fbaf1f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/* 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");
  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);
  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);
  assertPausedAtSourceAndLine(dbg, source.id, 2);

  info("Step over to the next line");
  await stepOver(dbg);
  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);
    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);
    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"
  );
});