tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_dbg-windowless-workers.js (5421B)


      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 // Test basic worker functionality: the main thread and worker can be
      6 // separately controlled from the same debugger.
      7 
      8 "use strict";
      9 
     10 add_task(async function () {
     11  await pushPref("devtools.debugger.threads-visible", true);
     12 
     13  const dbg = await initDebugger(
     14    "doc-windowless-workers.html",
     15    "simple-worker.js"
     16  );
     17  const mainThread = dbg.toolbox.threadFront.actor;
     18 
     19  await waitForThreadCount(dbg, 2);
     20  const workers = dbg.selectors.getThreads();
     21  Assert.equal(workers.length, 2, "Got two workers");
     22  const thread1 = workers[0].actor;
     23  const thread2 = workers[1].actor;
     24 
     25  const mainThreadSource = findSource(dbg, "doc-windowless-workers.html");
     26 
     27  info("Pause in the main thread");
     28  assertNotPaused(dbg);
     29  await dbg.actions.breakOnNext();
     30  await waitForPaused(dbg, "doc-windowless-workers.html");
     31  await assertPausedAtSourceAndLine(dbg, mainThreadSource.id, 10);
     32  threadIsSelected(dbg, 1);
     33 
     34  info("Pause in the first worker");
     35  await dbg.actions.selectThread(thread1);
     36  assertNotPaused(dbg);
     37  await dbg.actions.breakOnNext();
     38  await waitForPaused(dbg, "simple-worker.js");
     39  threadIsSelected(dbg, 2);
     40  const workerSource2 = dbg.selectors.getSelectedSource();
     41  await assertPausedAtSourceAndLine(dbg, workerSource2.id, 3);
     42 
     43  info("Add a watch expression and view the value");
     44  await addExpression(dbg, "count");
     45  is(getWatchExpressionLabel(dbg, 1), "count");
     46  const v = getWatchExpressionValue(dbg, 1);
     47  Assert.equal(v, `${+v}`, "Value of count should be a number");
     48 
     49  info("StepOver in the first worker");
     50  await stepOver(dbg);
     51  await assertPausedAtSourceAndLine(dbg, workerSource2.id, 4);
     52 
     53  info("Ensure that the watch expression has updated");
     54  await waitUntil(() => {
     55    const v2 = getWatchExpressionValue(dbg, 1);
     56    return +v2 == +v + 1;
     57  });
     58 
     59  info("Resume in the first worker");
     60  await resume(dbg);
     61  assertNotPaused(dbg);
     62 
     63  info("StepOver in the main thread");
     64  dbg.actions.selectThread(mainThread);
     65  await stepOver(dbg);
     66  await assertPausedAtSourceAndLine(dbg, mainThreadSource.id, 11);
     67 
     68  info("Resume in the mainThread");
     69  await resume(dbg);
     70  assertNotPaused(dbg);
     71 
     72  info("Pause in both workers");
     73  await addBreakpoint(dbg, "simple-worker.js", 10);
     74  invokeInTab("sayHello");
     75 
     76  info("Wait for both workers to pause");
     77  // When a thread pauses the current thread changes,
     78  // and we don't want to get confused.
     79  await waitForPausedThread(dbg, thread1);
     80  await waitForPausedThread(dbg, thread2);
     81  threadIsPaused(dbg, 2);
     82  threadIsPaused(dbg, 3);
     83 
     84  info("View the first paused thread");
     85  dbg.actions.selectThread(thread1);
     86  await waitForPaused(dbg);
     87  await assertPausedAtSourceAndLine(dbg, workerSource2.id, 10);
     88 
     89  info("View the second paused thread");
     90  await dbg.actions.selectThread(thread2);
     91  threadIsSelected(dbg, 3);
     92  await waitForPaused(dbg);
     93  const workerSource3 = dbg.selectors.getSelectedSource();
     94  is(
     95    workerSource2,
     96    workerSource3,
     97    "The selected source is the same as we have one source per URL"
     98  );
     99  await assertPausedAtSourceAndLine(dbg, workerSource3.id, 10);
    100 
    101  info("StepOver in second worker and not the first");
    102  await stepOver(dbg);
    103  await assertPausedAtSourceAndLine(dbg, workerSource3.id, 11);
    104  await dbg.actions.selectThread(thread1);
    105  await assertPausedAtSourceAndLine(dbg, workerSource2.id, 10);
    106 
    107  info("Resume both worker execution");
    108  await resume(dbg);
    109  assertNotPaused(dbg);
    110  await dbg.actions.selectThread(thread2);
    111  await resume(dbg);
    112  assertNotPaused(dbg);
    113 
    114  let sourceActors = dbg.selectors.getSourceActorsForSource(workerSource3.id);
    115  is(
    116    sourceActors.length,
    117    2,
    118    "There is one source actor per thread for the worker source"
    119  );
    120  info(
    121    "Terminate the first worker and wait for having only the second worker in threads list"
    122  );
    123  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
    124    content.wrappedJSObject.worker1.terminate();
    125  });
    126  await waitForThreadCount(dbg, 1);
    127  sourceActors = dbg.selectors.getSourceActorsForSource(workerSource3.id);
    128  is(
    129    sourceActors.length,
    130    1,
    131    "After the first worker is destroyed, we only have one source actor for the worker source"
    132  );
    133  ok(
    134    sourceExists(dbg, "simple-worker.js"),
    135    "But we still have the worker source object"
    136  );
    137 
    138  info("Terminate the second worker and wait for no more additional threads");
    139  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
    140    content.wrappedJSObject.worker2.terminate();
    141  });
    142  await waitForThreadCount(dbg, 0);
    143  sourceActors = dbg.selectors.getSourceActorsForSource(workerSource3.id);
    144  is(
    145    sourceActors.length,
    146    0,
    147    "After all workers are destroyed, we no longer have any source actor"
    148  );
    149  ok(
    150    !sourceExists(dbg, "simple-worker.js"),
    151    "And we no longer have the worker source"
    152  );
    153 });
    154 
    155 function assertClass(dbg, selector, className, ...args) {
    156  ok(
    157    findElement(dbg, selector, ...args).classList.contains(className),
    158    `${className} class exists`
    159  );
    160 }
    161 
    162 function threadIsPaused(dbg, index) {
    163  return ok(
    164    findElement(dbg, "threadsPaneItemPause", index),
    165    `Thread ${index} is paused`
    166  );
    167 }
    168 
    169 function threadIsSelected(dbg, index) {
    170  return assertClass(dbg, "threadsPaneItem", "selected", index);
    171 }