tor-browser

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

browser_webconsole_stubs_page_error.js (4100B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const {
      7  STUBS_UPDATE_ENV,
      8  createCommandsForTab,
      9  getCleanedPacket,
     10  getSerializedPacket,
     11  getStubFile,
     12  writeStubsToFile,
     13 } = require(`${CHROME_URL_ROOT}stub-generator-helpers`);
     14 
     15 const TEST_URI =
     16  "https://example.com/browser/devtools/client/webconsole/test/browser/test-console-api.html";
     17 const STUB_FILE = "pageError.js";
     18 
     19 add_task(async function () {
     20  await pushPref("javascript.options.asyncstack_capture_debuggee_only", false);
     21 
     22  const isStubsUpdate = Services.env.get(STUBS_UPDATE_ENV) == "true";
     23  info(`${isStubsUpdate ? "Update" : "Check"} ${STUB_FILE}`);
     24 
     25  const generatedStubs = await generatePageErrorStubs();
     26 
     27  if (isStubsUpdate) {
     28    await writeStubsToFile(STUB_FILE, generatedStubs);
     29    ok(true, `${STUB_FILE} was updated`);
     30    return;
     31  }
     32 
     33  const existingStubs = getStubFile(STUB_FILE);
     34  const FAILURE_MSG =
     35    "The pageError stubs file needs to be updated by running `" +
     36    `mach test ${getCurrentTestFilePath()} --headless --setenv WEBCONSOLE_STUBS_UPDATE=true` +
     37    "`";
     38 
     39  if (generatedStubs.size !== existingStubs.rawPackets.size) {
     40    ok(false, FAILURE_MSG);
     41    return;
     42  }
     43 
     44  let failed = false;
     45  for (const [key, packet] of generatedStubs) {
     46    const packetStr = getSerializedPacket(packet, {
     47      sortKeys: true,
     48      replaceActorIds: true,
     49    });
     50    const existingPacketStr = getSerializedPacket(
     51      existingStubs.rawPackets.get(key),
     52      { sortKeys: true, replaceActorIds: true }
     53    );
     54    is(packetStr, existingPacketStr, `"${key}" packet has expected value`);
     55    failed = failed || packetStr !== existingPacketStr;
     56  }
     57 
     58  if (failed) {
     59    ok(false, FAILURE_MSG);
     60  } else {
     61    ok(true, "Stubs are up to date");
     62  }
     63 });
     64 
     65 async function generatePageErrorStubs() {
     66  const stubs = new Map();
     67 
     68  const tab = await addTab(TEST_URI);
     69  const commands = await createCommandsForTab(tab);
     70  await commands.targetCommand.startListening();
     71  const resourceCommand = commands.resourceCommand;
     72 
     73  // Ensure waiting for sources in order to populate message.sourceId correctly.
     74  await resourceCommand.watchResources([resourceCommand.TYPES.SOURCE], {
     75    onAvailable() {},
     76  });
     77 
     78  // The resource-watcher only supports a single call to watch/unwatch per
     79  // instance, so we attach a unique watch callback, which will forward the
     80  // resource to `handleErrorMessage`, dynamically updated for each command.
     81  let handleErrorMessage = function () {};
     82 
     83  const onErrorMessageAvailable = resources => {
     84    for (const resource of resources) {
     85      handleErrorMessage(resource);
     86    }
     87  };
     88  await resourceCommand.watchResources([resourceCommand.TYPES.ERROR_MESSAGE], {
     89    onAvailable: onErrorMessageAvailable,
     90  });
     91 
     92  for (const [key, code] of getCommands()) {
     93    const onPageError = new Promise(resolve => {
     94      handleErrorMessage = packet => resolve(packet);
     95    });
     96 
     97    // On e10s, the exception is triggered in child process
     98    // and is ignored by test harness
     99    // expectUncaughtException should be called for each uncaught exception.
    100    if (!Services.appinfo.browserTabsRemoteAutostart) {
    101      expectUncaughtException();
    102    }
    103 
    104    // Note: This needs to use ContentTask rather than SpecialPowers.spawn
    105    // because the latter includes cross-process stack information.
    106    await ContentTask.spawn(gBrowser.selectedBrowser, code, function (subCode) {
    107      const script = content.document.createElement("script");
    108      script.append(content.document.createTextNode(subCode));
    109      content.document.body.append(script);
    110      script.remove();
    111    });
    112 
    113    const packet = await onPageError;
    114    stubs.set(key, getCleanedPacket(key, packet));
    115  }
    116 
    117  return stubs;
    118 }
    119 
    120 function getCommands() {
    121  const pageError = new Map();
    122 
    123  pageError.set(
    124    "ReferenceError: asdf is not defined",
    125    `
    126  function bar() {
    127    asdf()
    128  }
    129  function foo() {
    130    bar()
    131  }
    132 
    133  foo()
    134 `
    135  );
    136 
    137  pageError.set(
    138    "TypeError longString message",
    139    `throw new Error("Long error ".repeat(10000))`
    140  );
    141  return pageError;
    142 }