diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 0a19086a73c220..d767e533ec3e67 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -27,7 +27,7 @@ Last update: - resource-timing: https://github.com/web-platform-tests/wpt/tree/22d38586d0/resource-timing - resources: https://github.com/web-platform-tests/wpt/tree/919874f84f/resources - streams: https://github.com/web-platform-tests/wpt/tree/51750bc8d7/streams -- url: https://github.com/web-platform-tests/wpt/tree/1eaeb0e178/url +- url: https://github.com/web-platform-tests/wpt/tree/84caeb6fbd/url - user-timing: https://github.com/web-platform-tests/wpt/tree/df24fb604e/user-timing - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/d8dbe6990b/wasm/jsapi - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi diff --git a/test/fixtures/wpt/url/javascript-urls.window.js b/test/fixtures/wpt/url/javascript-urls.window.js new file mode 100644 index 00000000000000..4f617beca17082 --- /dev/null +++ b/test/fixtures/wpt/url/javascript-urls.window.js @@ -0,0 +1,63 @@ +// The results of this test are all over the map due to browsers behaving very differently for +// javascript: URLs. +// +// Chromium is pretty close execution-wise, but it parses javascript: URLs incorrectly. +// Gecko navigates to non-string return values of the result of executing a javascript: URL. +// WebKit executes javascript: URLs too early and has a harness error due to URL parsing. +// +// The expectations below should match the HTML and URL standards. +[ + { + "description": "javascript: URL that fails to parse due to invalid host", + "input": "javascript://test:test/%0aglobalThis.shouldNotExistA=1", + "property": "shouldNotExistA", + "expected": undefined + }, + { + "description": "javascript: URL that fails to parse due to invalid host and has a U+0009 in scheme", + "input": "java\x09script://test:test/%0aglobalThis.shouldNotExistB=1", + "property": "shouldNotExistB", + "expected": undefined + }, + { + "description": "javascript: URL without an opaque path", + "input": "javascript://host/1%0a//../0/;globalThis.shouldBeOne=1;/%0aglobalThis.shouldBeOne=2;/..///", + "property": "shouldBeOne", + "expected": 1 + }, + { + "description": "javascript: URL containing a JavaScript string split over path and query", + // Use ";undefined" to avoid returning a string. + "input": "javascript:globalThis.shouldBeAStringA = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined", + "property": "shouldBeAStringA", + "expected": "https://whatsoever.com/?a=b&c=5&x=y" + }, + { + "description": "javascript: URL containing a JavaScript string split over path and query and has a U+000A in scheme", + // Use ";undefined" to avoid returning a string. + "input": "java\x0Ascript:globalThis.shouldBeAStringB = \"https://whatsoever.com/?a=b&c=5&x=y\";undefined", + "property": "shouldBeAStringB", + "expected": "https://whatsoever.com/?a=b&c=5&x=y" + } +].forEach(({ description, input, property, expected }) => { + // Use promise_test so the tests run in sequence. Needed for globalThis.verify below. + promise_test(t => { + const anchor = document.body.appendChild(document.createElement("a")); + t.add_cleanup(() => anchor.remove()); + anchor.href = input; + assert_equals(globalThis[property], undefined, "Property is undefined before the click"); + anchor.click(); + assert_equals(globalThis[property], undefined, "Property is undefined immediately after the click"); + + // Since we cannot reliably queue a task to run after the task queued as a result of the click() + // above, we do another click() with a new URL. + return new Promise(resolve => { + globalThis.verify = t.step_func(() => { + assert_equals(globalThis[property], expected, `Property is ${expected} once the navigation happened`); + resolve(); + }); + anchor.href = "javascript:globalThis.verify()"; + anchor.click(); + }); + }, description); +}); diff --git a/test/fixtures/wpt/url/resources/setters_tests.json b/test/fixtures/wpt/url/resources/setters_tests.json index d040d081c6d467..347caf49ab0520 100644 --- a/test/fixtures/wpt/url/resources/setters_tests.json +++ b/test/fixtures/wpt/url/resources/setters_tests.json @@ -1061,6 +1061,42 @@ "host": "", "hostname": "" } + }, + { + "href": "https://example.com/", + "new_value": "a%C2%ADb", + "expected": { + "href": "https://ab/", + "host": "ab", + "hostname": "ab" + } + }, + { + "href": "https://example.com/", + "new_value": "\u00AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "%C2%AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "xn--", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } } ], "hostname": [ @@ -1436,6 +1472,42 @@ "host": "", "hostname": "" } + }, + { + "href": "https://example.com/", + "new_value": "a%C2%ADb", + "expected": { + "href": "https://ab/", + "host": "ab", + "hostname": "ab" + } + }, + { + "href": "https://example.com/", + "new_value": "\u00AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "%C2%AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "xn--", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } } ], "port": [ diff --git a/test/fixtures/wpt/url/resources/toascii.json b/test/fixtures/wpt/url/resources/toascii.json index 4cb41e94cd4a0f..bca28b4a1e454a 100644 --- a/test/fixtures/wpt/url/resources/toascii.json +++ b/test/fixtures/wpt/url/resources/toascii.json @@ -160,23 +160,6 @@ "input": "a\u00ADb", "output": "ab" }, - { - "input": "a%C2%ADb", - "output": "ab" - }, - { - "comment": "Empty host after domain to ASCII", - "input": "\u00AD", - "output": null - }, - { - "input": "%C2%AD", - "output": null - }, - { - "input": "xn--", - "output": null - }, { "comment": "Interesting UseSTD3ASCIIRules=false cases", "input": "≠", diff --git a/test/fixtures/wpt/url/resources/urltestdata.json b/test/fixtures/wpt/url/resources/urltestdata.json index 19f9ecddbee187..a3cf976534cce6 100644 --- a/test/fixtures/wpt/url/resources/urltestdata.json +++ b/test/fixtures/wpt/url/resources/urltestdata.json @@ -8892,5 +8892,457 @@ "protocol": "https:", "search": "", "username": "" + }, + { + "input": "https://a%C2%ADb/", + "base": "about:blank", + "hash": "", + "host": "ab", + "hostname": "ab", + "href": "https://ab/", + "origin": "https://ab", + "password": "", + "pathname": "/", + "port": "", + "protocol": "https:", + "search": "", + "username": "" + }, + { + "comment": "Empty host after domain to ASCII", + "input": "https://\u00AD/", + "base": "about:blank", + "failure": true + }, + { + "input": "https://%C2%AD/", + "base": "about:blank", + "failure": true + }, + { + "input": "https://xn--/", + "base": "about:blank", + "failure": true + }, + "Non-special schemes that some implementations might incorrectly treat as special", + { + "input": "data://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "data://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "data:///test", + "base": "about:blank", + "href": "data:///test", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "data://test/a/../b", + "base": "about:blank", + "href": "data://test/b", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "data://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "data://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "data://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "javascript://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "javascript://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "javascript:///test", + "base": "about:blank", + "href": "javascript:///test", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "javascript://test/a/../b", + "base": "about:blank", + "href": "javascript://test/b", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "javascript://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "javascript://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "javascript://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "mailto://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "mailto://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "mailto:///test", + "base": "about:blank", + "href": "mailto:///test", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "mailto://test/a/../b", + "base": "about:blank", + "href": "mailto://test/b", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "mailto://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "mailto://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "mailto://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "intent://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "intent://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "intent:///test", + "base": "about:blank", + "href": "intent:///test", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "intent://test/a/../b", + "base": "about:blank", + "href": "intent://test/b", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "intent://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "intent://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "intent://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "urn://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "urn://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "urn:///test", + "base": "about:blank", + "href": "urn:///test", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "urn://test/a/../b", + "base": "about:blank", + "href": "urn://test/b", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "urn://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "urn://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "urn://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "turn://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "turn://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "turn:///test", + "base": "about:blank", + "href": "turn:///test", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "turn://test/a/../b", + "base": "about:blank", + "href": "turn://test/b", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "turn://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "turn://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "turn://[:1]", + "base": "about:blank", + "failure": true + }, + { + "input": "stun://example.com:8080/pathname?search#hash", + "base": "about:blank", + "href": "stun://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "stun:///test", + "base": "about:blank", + "href": "stun:///test", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "stun://test/a/../b", + "base": "about:blank", + "href": "stun://test/b", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "stun://:443", + "base": "about:blank", + "failure": true + }, + { + "input": "stun://test:test", + "base": "about:blank", + "failure": true + }, + { + "input": "stun://[:1]", + "base": "about:blank", + "failure": true } ] diff --git a/test/fixtures/wpt/url/urlencoded-parser.any.js b/test/fixtures/wpt/url/urlencoded-parser.any.js index 46b932bb014364..847465cb9214e1 100644 --- a/test/fixtures/wpt/url/urlencoded-parser.any.js +++ b/test/fixtures/wpt/url/urlencoded-parser.any.js @@ -2,6 +2,7 @@ { "input": "test", "output": [["test", ""]] }, { "input": "\uFEFFtest=\uFEFF", "output": [["\uFEFFtest", "\uFEFF"]] }, { "input": "%EF%BB%BFtest=%EF%BB%BF", "output": [["\uFEFFtest", "\uFEFF"]] }, + { "input": "%EF%BF%BF=%EF%BF%BF", "output": [["\uFFFF", "\uFFFF"]] }, { "input": "%FE%FF", "output": [["\uFFFD\uFFFD", ""]] }, { "input": "%FF%FE", "output": [["\uFFFD\uFFFD", ""]] }, { "input": "†&†=x", "output": [["†", ""], ["†", "x"]] }, diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 8699b783b1423f..03f6b716210f4b 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -68,7 +68,7 @@ "path": "streams" }, "url": { - "commit": "1eaeb0e178b14078bd730ffecd62cb7569315523", + "commit": "84caeb6fbdf45129f57c67448e6113ee1ced9fb3", "path": "url" }, "user-timing": { diff --git a/test/wpt/status/url.json b/test/wpt/status/url.json index c333559537f6a9..257c1961b97604 100644 --- a/test/wpt/status/url.json +++ b/test/wpt/status/url.json @@ -34,5 +34,9 @@ }, "IdnaTestV2.window.js": { "requires": ["small-icu"] + }, + "javascript-urls.window.js": { + "required": ["small-icu"], + "skip": "requires document.body reference" } }