tor-browser

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

test_blockParsing.html (5437B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test for document.blockParsing</title>
      5  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css">
      7 </head>
      8 <body>
      9 <script>
     10 const {TestUtils} = ChromeUtils.importESModule(
     11  "resource://testing-common/TestUtils.sys.mjs"
     12 );
     13 
     14 async function runTest(url, initialHTML, finalHTML) {
     15  let iframe = document.createElement("iframe");
     16  iframe.src = url;
     17 
     18  let blockerPromise;
     19  let promise = TestUtils.topicObserved("document-element-inserted", document => {
     20    if (document !== iframe.contentDocument) {
     21      return false;
     22    }
     23 
     24    blockerPromise = new Promise(resolve => {
     25      setTimeout(resolve, 0);
     26    }).then(() => {
     27      return new Promise(resolve => setTimeout(resolve, 0));
     28    }).then(() => {
     29      return new Promise(resolve => setTimeout(resolve, 0));
     30    });
     31 
     32    is(document.documentElement.outerHTML, initialHTML,
     33       "Should have initial HTML during document-element-inserted");
     34    is(document.defaultView.wrappedJSObject.scriptRan, undefined,
     35       "Script node should not have run");
     36 
     37    document.blockParsing(blockerPromise);
     38 
     39    return true;
     40  }).then(([document]) => {
     41    return document;
     42  });
     43 
     44  document.body.appendChild(iframe);
     45 
     46  // Wait for document-element-inserted to fire.
     47  let doc = await promise;
     48  let win = doc.defaultView.wrappedJSObject;
     49  let root = doc.documentElement;
     50 
     51  // At this point, if the parser was successfully blocked, we should still
     52  // have the initial skeleton HTML for the page.
     53  is(root.outerHTML, initialHTML, "Should have initial HTML after document-element-inserted returns");
     54  is(win.scriptRan, undefined, "Script node should still not have run");
     55 
     56  await blockerPromise;
     57 
     58  // Just after the promise that's blocking the parser fires, we shouldn't have
     59  // returned to the main event loop, so we should still have the initial HTML.
     60  is(root.outerHTML, initialHTML, "Should still have initial HTML");
     61  is(win.scriptRan, undefined, "Script node should still not have run");
     62 
     63  await new Promise(resolve => win.addEventListener("DOMContentLoaded", resolve, {once: true}));
     64 
     65  // Parsing should have resumed, and we should have finished loading the document.
     66  is(root.outerHTML, finalHTML, "Should have final HTML");
     67  is(win.scriptRan, true, "Script node should have run");
     68 
     69  iframe.remove();
     70 }
     71 
     72 add_task(async function() {
     73  await runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_script.html",
     74                '<html lang="en"></html>',
     75                '<html lang="en"><head>\n  <script>window.scriptRan = true;<\/script>\n  <meta charset="utf-8">\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n\n\n</body></html>');
     76 
     77  await runTest("http://mochi.test:8888/chrome/dom/base/test/file_inline_script.xhtml",
     78                '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>',
     79                '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\n<head>\n  <script>window.scriptRan = true;<\/script>\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n</body>\n</html>');
     80 
     81  await runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.html",
     82                '<html lang="en"></html>',
     83                '<html lang="en"><head>\n  <script src="file_script.js"><\/script>\n  <meta charset="utf-8">\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n\n\n</body></html>');
     84 
     85  await runTest("http://mochi.test:8888/chrome/dom/base/test/file_external_script.xhtml",
     86                '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"></html>',
     87                '<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">\n<head>\n  <script src="file_script.js"><\/script>\n  <title></title>\n</head>\n<body>\n  <p>Hello Mochitest</p>\n</body>\n</html>');
     88 });
     89 
     90 add_task(async function test_cleanup() {
     91  const TOPIC = "blocking-promise-destroyed";
     92 
     93  const finalizationWitness = Cc["@mozilla.org/toolkit/finalizationwitness;1"]
     94      .getService(Ci.nsIFinalizationWitnessService);
     95 
     96  for (let url of ["http://mochi.test:8888/chrome/dom/base/test/file_inline_script.html",
     97                   "http://mochi.test:8888/chrome/dom/base/test/file_inline_script.xhtml"]) {
     98    let iframe = document.createElement("iframe");
     99    iframe.src = url;
    100 
    101    // Create a promise that never resolves.
    102    let blockerPromise = new Promise(() => {});
    103 
    104    // Create a finalization witness so we can be sure that the promises
    105    // have been collected before the end of the test.
    106    let destroyedPromise = TestUtils.topicObserved(TOPIC);
    107    let witness = finalizationWitness.make(TOPIC, url);
    108    blockerPromise.witness = witness;
    109 
    110    let insertedPromise = TestUtils.topicObserved("document-element-inserted", document => {
    111      document.blockParsing(blockerPromise).witness = witness;
    112 
    113      return true;
    114    });
    115 
    116    document.body.appendChild(iframe);
    117    await insertedPromise;
    118 
    119    // Clear the promise reference, destroy the document, and force GC/CC. This should
    120    // trigger any potential leaks or cleanup issues.
    121    blockerPromise = null;
    122    witness = null;
    123    iframe.remove();
    124 
    125    Cu.forceGC();
    126    Cu.forceCC();
    127    Cu.forceGC();
    128 
    129    // Make sure the blocker promise has been collected.
    130    let [, data] = await destroyedPromise;
    131    is(data, url, "Should have correct finalizer URL");
    132  }
    133 });
    134 </script>
    135 </body>
    136 </html>