• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 without an opaque path",
24    "input": "javascript://host/1%0a//../0/;globalThis.shouldBeOne=1;/%0aglobalThis.shouldBeOne=2;/..///",
25    "property": "shouldBeOne",
26    "expected": 1
27  },
28  {
29    "description": "javascript: URL containing a JavaScript string split over path and query",
30    // Use ";undefined" to avoid returning a string.
31    "input": "javascript:globalThis.shouldBeAStringA = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined",
32    "property": "shouldBeAStringA",
33    "expected": "https://whatsoever.com/?a=b&c=5&x=y"
34  },
35  {
36    "description": "javascript: URL containing a JavaScript string split over path and query and has a U+000A in scheme",
37    // Use ";undefined" to avoid returning a string.
38    "input": "java\x0Ascript:globalThis.shouldBeAStringB = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined",
39    "property": "shouldBeAStringB",
40    "expected": "https://whatsoever.com/?a=b&c=5&x=y"
41  }
42].forEach(({ description, input, property, expected }) => {
43  // Use promise_test so the tests run in sequence. Needed for globalThis.verify below.
44  promise_test(t => {
45    const anchor = document.body.appendChild(document.createElement("a"));
46    t.add_cleanup(() => anchor.remove());
47    anchor.href = input;
48    assert_equals(globalThis[property], undefined, "Property is undefined before the click");
49    anchor.click();
50    assert_equals(globalThis[property], undefined, "Property is undefined immediately after the click");
51
52    // Since we cannot reliably queue a task to run after the task queued as a result of the click()
53    // above, we do another click() with a new URL.
54    return new Promise(resolve => {
55      globalThis.verify = t.step_func(() => {
56        assert_equals(globalThis[property], expected, `Property is ${expected} once the navigation happened`);
57        resolve();
58      });
59      anchor.href = "javascript:globalThis.verify()";
60      anchor.click();
61    });
62  }, description);
63});
64