tor-browser

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

tasks.window.js (4481B)


      1 // An older version of the HTML Standard mandated that document.open() remove
      2 // all tasks associated with the document on which open() is called. This step
      3 // has been proposed to be removed. This series of tests ensures that this step
      4 // is no longer executed.
      5 //
      6 // This file comprehensively (but not exhaustively) tests for many queued tasks
      7 // that may be observable. Each taskTest() call in fact runs two tests: the
      8 // first one "tasks without document.open()" does not actually run
      9 // document.open(), just to test that the tested task works ordinarily; the
     10 // second actually calls document.open() to test if the method call removes
     11 // that specific task from the queue.
     12 
     13 // This is necessary to allow the promise rejection test below.
     14 setup({
     15  allow_uncaught_exception: true
     16 });
     17 
     18 function taskTest(description, testBody) {
     19  async_test(t => {
     20    const frame = document.body.appendChild(document.createElement("iframe"));
     21    // The empty HTML seems to be necessary to cajole Chrome and Safari into
     22    // firing a load event asynchronously, which is necessary to make sure the
     23    // frame's document doesn't have a parser associated with it.
     24    // See: https://crbug.com/569511
     25    frame.src = "/common/blank.html";
     26    t.add_cleanup(() => frame.remove());
     27    frame.onload = t.step_func(() => {
     28      // Make sure there is no parser. Firefox seems to have an additional
     29      // non-spec-compliant readiness state "uninitialized", so test for the
     30      // two known valid readiness states instead.
     31      // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1191683
     32      assert_in_array(frame.contentDocument.readyState, ["interactive", "complete"]);
     33      testBody(t, frame, doc => {});
     34    });
     35  }, `tasks without document.open() (${description})`);
     36 
     37  async_test(t => {
     38    const frame = document.body.appendChild(document.createElement("iframe"));
     39    // The empty HTML seems to be necessary to cajole Chrome into firing a load
     40    // event, which is necessary to make sure the frame's document doesn't have
     41    // a parser associated with it.
     42    // See: https://crbug.com/569511
     43    frame.src = "/common/blank.html";
     44    t.add_cleanup(() => frame.remove());
     45    frame.onload = t.step_func(() => {
     46      // Make sure there is no parser. Firefox seems to have an additional
     47      // non-spec-compliant readiness state "uninitialized", so test for the
     48      // two known valid readiness states instead.
     49      // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1191683
     50      assert_in_array(frame.contentDocument.readyState, ["interactive", "complete"]);
     51      testBody(t, frame, doc => doc.open());
     52    });
     53  }, `document.open() and tasks (${description})`);
     54 }
     55 
     56 taskTest("timeout", (t, frame, open) => {
     57  frame.contentWindow.setTimeout(t.step_func_done(), 100);
     58  open(frame.contentDocument);
     59 });
     60 
     61 taskTest("window message", (t, frame, open) => {
     62  let counter = 0;
     63  frame.contentWindow.postMessage(undefined, "*");
     64  open(frame.contentDocument);
     65  frame.contentWindow.postMessage(undefined, "*");
     66  frame.contentWindow.onmessage = t.step_func(e => {
     67    assert_equals(e.data, undefined);
     68    counter++;
     69    assert_less_than_equal(counter, 2);
     70    if (counter == 2) {
     71      t.done();
     72    }
     73  });
     74 });
     75 
     76 taskTest("canvas.toBlob()", (t, frame, open) => {
     77  const canvas = frame.contentDocument.body.appendChild(frame.contentDocument.createElement("canvas"));
     78  canvas.toBlob(t.step_func_done());
     79  open(frame.contentDocument);
     80 });
     81 
     82 taskTest("MessagePort", (t, frame, open) => {
     83  frame.contentWindow.eval(`({ port1, port2 } = new MessageChannel());`);
     84  frame.contentWindow.port2.onmessage = t.step_func_done(ev => {
     85    assert_equals(ev.data, "Hello world");
     86  });
     87  frame.contentWindow.port1.postMessage("Hello world");
     88  open(frame.contentDocument);
     89 });
     90 
     91 taskTest("Promise rejection", (t, frame, open) => {
     92  // There is currently some ambiguity on which Window object the
     93  // unhandledrejection event should be fired on. Here, let's account for that
     94  // ambiguity and allow event fired on _any_ global to pass this test.
     95  // See:
     96  // - https://github.com/whatwg/html/issues/958,
     97  // - https://bugs.webkit.org/show_bug.cgi?id=187822
     98  const promise = frame.contentWindow.eval("Promise.reject(42);");
     99  open(frame.contentDocument);
    100  const listener = t.step_func_done(ev => {
    101    assert_equals(ev.promise, promise);
    102    assert_equals(ev.reason, 42);
    103  });
    104  frame.contentWindow.onunhandledrejection = listener;
    105  window.onunhandledrejection = listener;
    106 });