tor-browser

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

javascript-urls.window.js (3108B)


      1 // The results of this test are all over the map due to browsers behaving very differently for
      2 // javascript: URLs.
      3 //
      4 // Chromium is pretty close execution-wise, but it parses javascript: URLs incorrectly.
      5 // Gecko navigates to non-string return values of the result of executing a javascript: URL.
      6 // WebKit executes javascript: URLs too early and has a harness error due to URL parsing.
      7 //
      8 // The expectations below should match the HTML and URL standards.
      9 [
     10  {
     11    "description": "javascript: URL that fails to parse due to invalid host",
     12    "input": "javascript://test:test/%0aglobalThis.shouldNotExistA=1",
     13    "property": "shouldNotExistA",
     14    "expected": undefined
     15  },
     16  {
     17    "description": "javascript: URL that fails to parse due to invalid host and has a U+0009 in scheme",
     18    "input": "java\x09script://test:test/%0aglobalThis.shouldNotExistB=1",
     19    "property": "shouldNotExistB",
     20    "expected": undefined
     21  },
     22  {
     23    "description": "javascript: URL with extra slashes at the start",
     24    "input": "javascript:///globalThis.shouldNotExistC=1",
     25    "property": "shouldNotExistC",
     26    "expected": undefined
     27  },
     28  {
     29    "description": "javascript: URL without an opaque path",
     30    "input": "javascript://host/1%0a//../0/;globalThis.shouldBeOne=1;/%0aglobalThis.shouldBeOne=2;/..///",
     31    "property": "shouldBeOne",
     32    "expected": 1
     33  },
     34  {
     35    "description": "javascript: URL containing a JavaScript string split over path and query",
     36    // Use ";undefined" to avoid returning a string.
     37    "input": "javascript:globalThis.shouldBeAStringA = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined",
     38    "property": "shouldBeAStringA",
     39    "expected": "https://whatsoever.com/?a=b&c=5&x=y"
     40  },
     41  {
     42    "description": "javascript: URL containing a JavaScript string split over path and query and has a U+000A in scheme",
     43    // Use ";undefined" to avoid returning a string.
     44    "input": "java\x0Ascript:globalThis.shouldBeAStringB = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined",
     45    "property": "shouldBeAStringB",
     46    "expected": "https://whatsoever.com/?a=b&c=5&x=y"
     47  }
     48 ].forEach(({ description, input, property, expected }) => {
     49  // Use promise_test so the tests run in sequence. Needed for globalThis.verify below.
     50  promise_test(t => {
     51    const anchor = document.body.appendChild(document.createElement("a"));
     52    t.add_cleanup(() => anchor.remove());
     53    anchor.href = input;
     54    assert_equals(globalThis[property], undefined, "Property is undefined before the click");
     55    anchor.click();
     56    assert_equals(globalThis[property], undefined, "Property is undefined immediately after the click");
     57 
     58    // Since we cannot reliably queue a task to run after the task queued as a result of the click()
     59    // above, we do another click() with a new URL.
     60    return new Promise(resolve => {
     61      globalThis.verify = t.step_func(() => {
     62        assert_equals(globalThis[property], expected, `Property is ${expected} once the navigation happened`);
     63        resolve();
     64      });
     65      anchor.href = "javascript:globalThis.verify()";
     66      anchor.click();
     67    });
     68  }, description);
     69 });