Files
sousa-gecko/testing/web-platform/tests/url/resources/setters_tests.json
T
Anne van Kesteren db42ec4364 Bug 2045918 [wpt PR 60476] - IDNA cannot fail ASCII domains, even if they start with xn--, a=testonly
Automatic update from web-platform-tests
IDNA cannot fail ASCII domains, even if they start with xn--

--

wpt-commits: b63305b743ed9ce2725d4ae09c5c8f0c40d8e6e1
wpt-pr: 60476
2026-07-06 08:45:21 +00:00

2600 lines
80 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"comment": [
"## Tests for setters of https://url.spec.whatwg.org/#urlutils-members",
"",
"This file contains a JSON object.",
"Other than 'comment', each key is an attribute of the `URL` interface",
"defined in WHATWG’s URL Standard.",
"The values are arrays of test case objects for that attribute.",
"",
"To run a test case for the attribute `attr`:",
"",
"* Create a new `URL` object with the value for the 'href' key",
" the constructor single parameter. (Without a base URL.)",
" This must not throw.",
"* Set the attribute `attr` to (invoke its setter with)",
" with the value of for 'new_value' key.",
"* The value for the 'expected' key is another object.",
" For each `key` / `value` pair of that object,",
" get the attribute `key` (invoke its getter).",
" The returned string must be equal to `value`.",
"",
"Note: the 'href' setter is already covered by urltestdata.json."
],
"protocol": [
{
"comment": "The empty string is not a valid scheme. Setter leaves the URL unchanged.",
"href": "a://example.net",
"new_value": "",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"href": "a://example.net",
"new_value": "b",
"expected": {
"href": "b://example.net",
"protocol": "b:"
}
},
{
"href": "javascript:alert(1)",
"new_value": "defuse",
"expected": {
"href": "defuse:alert(1)",
"protocol": "defuse:"
}
},
{
"comment": "Upper-case ASCII is lower-cased",
"href": "a://example.net",
"new_value": "B",
"expected": {
"href": "b://example.net",
"protocol": "b:"
}
},
{
"comment": "Non-ASCII is rejected",
"href": "a://example.net",
"new_value": "é",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"comment": "No leading digit",
"href": "a://example.net",
"new_value": "0b",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"comment": "No leading punctuation",
"href": "a://example.net",
"new_value": "+b",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"href": "a://example.net",
"new_value": "bC0+-.",
"expected": {
"href": "bc0+-.://example.net",
"protocol": "bc0+-.:"
}
},
{
"comment": "Only some punctuation is acceptable",
"href": "a://example.net",
"new_value": "b,c",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"comment": "Non-ASCII is rejected",
"href": "a://example.net",
"new_value": "bé",
"expected": {
"href": "a://example.net",
"protocol": "a:"
}
},
{
"comment": "Can’t switch from URL containing username/password/port to file",
"href": "http://test@example.net",
"new_value": "file",
"expected": {
"href": "http://test@example.net/",
"protocol": "http:"
}
},
{
"href": "https://example.net:1234",
"new_value": "file",
"expected": {
"href": "https://example.net:1234/",
"protocol": "https:"
}
},
{
"href": "wss://x:x@example.net:1234",
"new_value": "file",
"expected": {
"href": "wss://x:x@example.net:1234/",
"protocol": "wss:"
}
},
{
"comment": "Can’t switch from file URL with no host",
"href": "file://localhost/",
"new_value": "http",
"expected": {
"href": "file:///",
"protocol": "file:"
}
},
{
"href": "file:///test",
"new_value": "https",
"expected": {
"href": "file:///test",
"protocol": "file:"
}
},
{
"href": "file:",
"new_value": "wss",
"expected": {
"href": "file:///",
"protocol": "file:"
}
},
{
"comment": "Can’t switch from special scheme to non-special",
"href": "http://example.net",
"new_value": "b",
"expected": {
"href": "http://example.net/",
"protocol": "http:"
}
},
{
"href": "file://hi/path",
"new_value": "s",
"expected": {
"href": "file://hi/path",
"protocol": "file:"
}
},
{
"href": "https://example.net",
"new_value": "s",
"expected": {
"href": "https://example.net/",
"protocol": "https:"
}
},
{
"href": "ftp://example.net",
"new_value": "test",
"expected": {
"href": "ftp://example.net/",
"protocol": "ftp:"
}
},
{
"comment": "Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.",
"href": "mailto:me@example.net",
"new_value": "http",
"expected": {
"href": "mailto:me@example.net",
"protocol": "mailto:"
}
},
{
"comment": "Can’t switch from non-special scheme to special",
"href": "ssh://me@example.net",
"new_value": "http",
"expected": {
"href": "ssh://me@example.net",
"protocol": "ssh:"
}
},
{
"href": "ssh://me@example.net",
"new_value": "https",
"expected": {
"href": "ssh://me@example.net",
"protocol": "ssh:"
}
},
{
"href": "ssh://me@example.net",
"new_value": "file",
"expected": {
"href": "ssh://me@example.net",
"protocol": "ssh:"
}
},
{
"href": "ssh://example.net",
"new_value": "file",
"expected": {
"href": "ssh://example.net",
"protocol": "ssh:"
}
},
{
"href": "nonsense:///test",
"new_value": "https",
"expected": {
"href": "nonsense:///test",
"protocol": "nonsense:"
}
},
{
"comment": "Stuff after the first ':' is ignored",
"href": "http://example.net",
"new_value": "https:foo : bar",
"expected": {
"href": "https://example.net/",
"protocol": "https:"
}
},
{
"comment": "Stuff after the first ':' is ignored",
"href": "data:text/html,<p>Test",
"new_value": "view-source+data:foo : bar",
"expected": {
"href": "view-source+data:text/html,<p>Test",
"protocol": "view-source+data:"
}
},
{
"comment": "Port is set to null if it is the default for new scheme.",
"href": "http://foo.com:443/",
"new_value": "https",
"expected": {
"href": "https://foo.com/",
"protocol": "https:",
"port": ""
}
},
{
"comment": "Tab and newline are stripped",
"href": "http://test/",
"new_value": "h\u000D\u000Att\u0009ps",
"expected": {
"href": "https://test/",
"protocol": "https:",
"port": ""
}
},
{
"href": "http://test/",
"new_value": "https\u000D",
"expected": {
"href": "https://test/",
"protocol": "https:"
}
},
{
"comment": "Non-tab/newline C0 controls result in no-op",
"href": "http://test/",
"new_value": "https\u0000",
"expected": {
"href": "http://test/",
"protocol": "http:"
}
},
{
"href": "http://test/",
"new_value": "https\u000C",
"expected": {
"href": "http://test/",
"protocol": "http:"
}
},
{
"href": "http://test/",
"new_value": "https\u000E",
"expected": {
"href": "http://test/",
"protocol": "http:"
}
},
{
"href": "http://test/",
"new_value": "https\u0020",
"expected": {
"href": "http://test/",
"protocol": "http:"
}
}
],
"username": [
{
"comment": "No host means no username",
"href": "file:///home/you/index.html",
"new_value": "me",
"expected": {
"href": "file:///home/you/index.html",
"username": ""
}
},
{
"comment": "No host means no username",
"href": "unix:/run/foo.socket",
"new_value": "me",
"expected": {
"href": "unix:/run/foo.socket",
"username": ""
}
},
{
"comment": "Cannot-be-a-base means no username",
"href": "mailto:you@example.net",
"new_value": "me",
"expected": {
"href": "mailto:you@example.net",
"username": ""
}
},
{
"href": "javascript:alert(1)",
"new_value": "wario",
"expected": {
"href": "javascript:alert(1)",
"username": ""
}
},
{
"href": "http://example.net",
"new_value": "me",
"expected": {
"href": "http://me@example.net/",
"username": "me"
}
},
{
"href": "http://:secret@example.net",
"new_value": "me",
"expected": {
"href": "http://me:secret@example.net/",
"username": "me"
}
},
{
"href": "http://me@example.net",
"new_value": "",
"expected": {
"href": "http://example.net/",
"username": ""
}
},
{
"href": "http://me:secret@example.net",
"new_value": "",
"expected": {
"href": "http://:secret@example.net/",
"username": ""
}
},
{
"comment": "UTF-8 percent encoding with the userinfo encode set.",
"href": "http://example.net",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "http://%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9@example.net/",
"username": "%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Bytes already percent-encoded are left as-is.",
"href": "http://example.net",
"new_value": "%c3%89té",
"expected": {
"href": "http://%c3%89t%C3%A9@example.net/",
"username": "%c3%89t%C3%A9"
}
},
{
"href": "sc:///",
"new_value": "x",
"expected": {
"href": "sc:///",
"username": ""
}
},
{
"href": "javascript://x/",
"new_value": "wario",
"expected": {
"href": "javascript://wario@x/",
"username": "wario"
}
},
{
"href": "file://test/",
"new_value": "test",
"expected": {
"href": "file://test/",
"username": ""
}
}
],
"password": [
{
"comment": "No host means no password",
"href": "file:///home/me/index.html",
"new_value": "secret",
"expected": {
"href": "file:///home/me/index.html",
"password": ""
}
},
{
"comment": "No host means no password",
"href": "unix:/run/foo.socket",
"new_value": "secret",
"expected": {
"href": "unix:/run/foo.socket",
"password": ""
}
},
{
"comment": "Cannot-be-a-base means no password",
"href": "mailto:me@example.net",
"new_value": "secret",
"expected": {
"href": "mailto:me@example.net",
"password": ""
}
},
{
"href": "http://example.net",
"new_value": "secret",
"expected": {
"href": "http://:secret@example.net/",
"password": "secret"
}
},
{
"href": "http://me@example.net",
"new_value": "secret",
"expected": {
"href": "http://me:secret@example.net/",
"password": "secret"
}
},
{
"href": "http://:secret@example.net",
"new_value": "",
"expected": {
"href": "http://example.net/",
"password": ""
}
},
{
"href": "http://me:secret@example.net",
"new_value": "",
"expected": {
"href": "http://me@example.net/",
"password": ""
}
},
{
"comment": "UTF-8 percent encoding with the userinfo encode set.",
"href": "http://example.net",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "http://:%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9@example.net/",
"password": "%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Bytes already percent-encoded are left as-is.",
"href": "http://example.net",
"new_value": "%c3%89té",
"expected": {
"href": "http://:%c3%89t%C3%A9@example.net/",
"password": "%c3%89t%C3%A9"
}
},
{
"href": "sc:///",
"new_value": "x",
"expected": {
"href": "sc:///",
"password": ""
}
},
{
"href": "javascript://x/",
"new_value": "bowser",
"expected": {
"href": "javascript://:bowser@x/",
"password": "bowser"
}
},
{
"href": "file://test/",
"new_value": "test",
"expected": {
"href": "file://test/",
"password": ""
}
}
],
"host": [
{
"comment": "Non-special scheme",
"href": "sc://x/",
"new_value": "\u0000",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"href": "sc://x/",
"new_value": "\u0009",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "\u000A",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "\u000D",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": " ",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"href": "sc://x/",
"new_value": "#",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "/",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "?",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "@",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"href": "sc://x/",
"new_value": "ß",
"expected": {
"href": "sc://%C3%9F/",
"host": "%C3%9F",
"hostname": "%C3%9F"
}
},
{
"comment": "IDNA Nontransitional_Processing",
"href": "https://x/",
"new_value": "ß",
"expected": {
"href": "https://xn--zca/",
"host": "xn--zca",
"hostname": "xn--zca"
}
},
{
"comment": "Cannot-be-a-base means no host",
"href": "mailto:me@example.net",
"new_value": "example.com",
"expected": {
"href": "mailto:me@example.net",
"host": ""
}
},
{
"comment": "Cannot-be-a-base means no host",
"href": "data:text/plain,Stuff",
"new_value": "example.net",
"expected": {
"href": "data:text/plain,Stuff",
"host": ""
}
},
{
"href": "http://example.net",
"new_value": "example.com:8080",
"expected": {
"href": "http://example.com:8080/",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Port number is unchanged if not specified in the new value",
"href": "http://example.net:8080",
"new_value": "example.com",
"expected": {
"href": "http://example.com:8080/",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Port number is unchanged if not specified",
"href": "http://example.net:8080",
"new_value": "example.com:",
"expected": {
"href": "http://example.com:8080/",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "The empty host is not valid for special schemes",
"href": "http://example.net",
"new_value": "",
"expected": {
"href": "http://example.net/",
"host": "example.net"
}
},
{
"comment": "The empty host is OK for non-special schemes",
"href": "view-source+http://example.net/foo",
"new_value": "",
"expected": {
"href": "view-source+http:///foo",
"host": ""
}
},
{
"comment": "Path-only URLs can gain a host",
"href": "a:/foo",
"new_value": "example.net",
"expected": {
"href": "a://example.net/foo",
"host": "example.net"
}
},
{
"comment": "IPv4 address syntax is normalized",
"href": "http://example.net",
"new_value": "0x7F000001:8080",
"expected": {
"href": "http://127.0.0.1:8080/",
"host": "127.0.0.1:8080",
"hostname": "127.0.0.1",
"port": "8080"
}
},
{
"comment": "IPv6 address syntax is normalized",
"href": "http://example.net",
"new_value": "[::0:01]:2",
"expected": {
"href": "http://[::1]:2/",
"host": "[::1]:2",
"hostname": "[::1]",
"port": "2"
}
},
{
"comment": "IPv6 literal address with port, crbug.com/1012416",
"href": "http://example.net",
"new_value": "[2001:db8::2]:4002",
"expected": {
"href": "http://[2001:db8::2]:4002/",
"host": "[2001:db8::2]:4002",
"hostname": "[2001:db8::2]",
"port": "4002"
}
},
{
"comment": "Default port number is removed",
"href": "http://example.net",
"new_value": "example.com:80",
"expected": {
"href": "http://example.com/",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Default port number is removed",
"href": "https://example.net",
"new_value": "example.com:443",
"expected": {
"href": "https://example.com/",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Default port number is only removed for the relevant scheme",
"href": "https://example.net",
"new_value": "example.com:80",
"expected": {
"href": "https://example.com:80/",
"host": "example.com:80",
"hostname": "example.com",
"port": "80"
}
},
{
"comment": "Port number is removed if new port is scheme default and existing URL has a non-default port",
"href": "http://example.net:8080",
"new_value": "example.com:80",
"expected": {
"href": "http://example.com/",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a / delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com/stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a / delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com:8080/stuff",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Stuff after a ? delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com?stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a ? delimiter is ignored, trailing 'port'",
"href": "http://example.net/path",
"new_value": "example.com?stuff:8080",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a ? delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com:8080?stuff",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Stuff after a # delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com#stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a # delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com:8080#stuff",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Stuff after a \\ delimiter is ignored for special schemes",
"href": "http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a \\ delimiter is ignored for special schemes",
"href": "http://example.net/path",
"new_value": "example.com:8080\\stuff",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
"href": "view-source+http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
"href": "view-source+http://example.net/path",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "view-source+http://example.net/path",
"new_value": "example.com:8080stuff2",
"expected": {
"href": "view-source+http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net/path",
"new_value": "example.com:8080stuff2",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net/path",
"new_value": "example.com:8080+2",
"expected": {
"href": "http://example.com:8080/path",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net:8080",
"new_value": "example.com:invalid",
"expected": {
"href": "http://example.com:8080/",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net:8080/test",
"new_value": "[::1]:invalid",
"expected": {
"href": "http://[::1]:8080/test",
"host": "[::1]:8080",
"hostname": "[::1]",
"port": "8080"
}
},
{
"comment": "IPv6 without port",
"href": "http://example.net:8080/test",
"new_value": "[::1]",
"expected": {
"href": "http://[::1]:8080/test",
"host": "[::1]:8080",
"hostname": "[::1]",
"port": "8080"
}
},
{
"comment": "Port numbers are 16 bit integers",
"href": "http://example.net/path",
"new_value": "example.com:65535",
"expected": {
"href": "http://example.com:65535/path",
"host": "example.com:65535",
"hostname": "example.com",
"port": "65535"
}
},
{
"comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.",
"href": "http://example.net/path",
"new_value": "example.com:65536",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Broken IPv6",
"href": "http://example.net/",
"new_value": "[google.com]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.3.4x]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.3.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "file://y/",
"new_value": "x:123",
"expected": {
"href": "file://y/",
"host": "y",
"hostname": "y",
"port": ""
}
},
{
"href": "file://y/",
"new_value": "loc%41lhost",
"expected": {
"href": "file:///",
"host": "",
"hostname": "",
"port": ""
}
},
{
"href": "file://hi/x",
"new_value": "",
"expected": {
"href": "file:///x",
"host": "",
"hostname": "",
"port": ""
}
},
{
"href": "sc://test@test/",
"new_value": "",
"expected": {
"href": "sc://test@test/",
"host": "test",
"hostname": "test",
"username": "test"
}
},
{
"href": "sc://test:12/",
"new_value": "",
"expected": {
"href": "sc://test:12/",
"host": "test:12",
"hostname": "test",
"port": "12"
}
},
{
"comment": "Leading / is not stripped",
"href": "http://example.com/",
"new_value": "///bad.com",
"expected": {
"href": "http://example.com/",
"host": "example.com",
"hostname": "example.com"
}
},
{
"comment": "Leading / is not stripped",
"href": "sc://example.com/",
"new_value": "///bad.com",
"expected": {
"href": "sc:///",
"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://xn--/",
"host": "xn--",
"hostname": "xn--"
}
},
{
"href": "https://test.invalid/",
"new_value": "*",
"expected": {
"href": "https://*/",
"host": "*",
"hostname": "*"
}
},
{
"href": "https://test.invalid/",
"new_value": "x@x",
"expected": {
"href": "https://test.invalid/",
"host": "test.invalid",
"hostname": "test.invalid"
}
},
{
"href": "https://test.invalid/",
"new_value": "foo\t\r\nbar",
"expected": {
"href": "https://foobar/",
"host": "foobar",
"hostname": "foobar"
}
},
{
"href": "https://test.invalid/",
"new_value": "><",
"expected": {
"href": "https://test.invalid/",
"host": "test.invalid",
"hostname": "test.invalid"
}
},
{
"href": "https://test.invalid/",
"new_value": "test/@aaa",
"expected": {
"href": "https://test/",
"host": "test",
"hostname": "test"
}
},
{
"href": "https://test.invalid/",
"new_value": "test/:aaa",
"expected": {
"href": "https://test/",
"host": "test",
"hostname": "test"
}
},
{
"href": "foo://path/to",
"new_value": ":80",
"expected": {
"href": "foo://path/to",
"host": "path",
"port": ""
}
}
],
"hostname": [
{
"comment": "Non-special scheme",
"href": "sc://x/",
"new_value": "\u0000",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"href": "sc://x/",
"new_value": "\u0009",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "\u000A",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "\u000D",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": " ",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"href": "sc://x/",
"new_value": "#",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "/",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "?",
"expected": {
"href": "sc:///",
"host": "",
"hostname": ""
}
},
{
"href": "sc://x/",
"new_value": "@",
"expected": {
"href": "sc://x/",
"host": "x",
"hostname": "x"
}
},
{
"comment": "Cannot-be-a-base means no host",
"href": "mailto:me@example.net",
"new_value": "example.com",
"expected": {
"href": "mailto:me@example.net",
"host": ""
}
},
{
"comment": "Cannot-be-a-base means no host",
"href": "data:text/plain,Stuff",
"new_value": "example.net",
"expected": {
"href": "data:text/plain,Stuff",
"host": ""
}
},
{
"href": "http://example.net:8080",
"new_value": "example.com",
"expected": {
"href": "http://example.com:8080/",
"host": "example.com:8080",
"hostname": "example.com",
"port": "8080"
}
},
{
"comment": "The empty host is not valid for special schemes",
"href": "http://example.net",
"new_value": "",
"expected": {
"href": "http://example.net/",
"host": "example.net"
}
},
{
"comment": "The empty host is OK for non-special schemes",
"href": "view-source+http://example.net/foo",
"new_value": "",
"expected": {
"href": "view-source+http:///foo",
"host": ""
}
},
{
"comment": "Path-only URLs can gain a host",
"href": "a:/foo",
"new_value": "example.net",
"expected": {
"href": "a://example.net/foo",
"host": "example.net"
}
},
{
"comment": "IPv4 address syntax is normalized",
"href": "http://example.net:8080",
"new_value": "0x7F000001",
"expected": {
"href": "http://127.0.0.1:8080/",
"host": "127.0.0.1:8080",
"hostname": "127.0.0.1",
"port": "8080"
}
},
{
"comment": "IPv6 address syntax is normalized",
"href": "http://example.net",
"new_value": "[::0:01]",
"expected": {
"href": "http://[::1]/",
"host": "[::1]",
"hostname": "[::1]",
"port": ""
}
},
{
"comment": ": delimiter invalidates entire value",
"href": "http://example.net/path",
"new_value": "example.com:8080",
"expected": {
"href": "http://example.net/path",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": ": delimiter invalidates entire value",
"href": "http://example.net:8080/path",
"new_value": "example.com:",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Stuff after a / delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com/stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a ? delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com?stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a # delimiter is ignored",
"href": "http://example.net/path",
"new_value": "example.com#stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "Stuff after a \\ delimiter is ignored for special schemes",
"href": "http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
"href": "http://example.com/path",
"host": "example.com",
"hostname": "example.com",
"port": ""
}
},
{
"comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
"href": "view-source+http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
"href": "view-source+http://example.net/path",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": "Broken IPv6",
"href": "http://example.net/",
"new_value": "[google.com]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.3.4x]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.3.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.2.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "http://example.net/",
"new_value": "[::1.]",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net"
}
},
{
"href": "file://y/",
"new_value": "x:123",
"expected": {
"href": "file://y/",
"host": "y",
"hostname": "y",
"port": ""
}
},
{
"href": "file://y/",
"new_value": "loc%41lhost",
"expected": {
"href": "file:///",
"host": "",
"hostname": "",
"port": ""
}
},
{
"href": "file://hi/x",
"new_value": "",
"expected": {
"href": "file:///x",
"host": "",
"hostname": "",
"port": ""
}
},
{
"href": "sc://test@test/",
"new_value": "",
"expected": {
"href": "sc://test@test/",
"host": "test",
"hostname": "test",
"username": "test"
}
},
{
"href": "sc://test:12/",
"new_value": "",
"expected": {
"href": "sc://test:12/",
"host": "test:12",
"hostname": "test",
"port": "12"
}
},
{
"comment": "Drop /. from path",
"href": "non-spec:/.//p",
"new_value": "h",
"expected": {
"href": "non-spec://h//p",
"host": "h",
"hostname": "h",
"pathname": "//p"
}
},
{
"href": "non-spec:/.//p",
"new_value": "",
"expected": {
"href": "non-spec:////p",
"host": "",
"hostname": "",
"pathname": "//p"
}
},
{
"comment": "Leading / is not stripped",
"href": "http://example.com/",
"new_value": "///bad.com",
"expected": {
"href": "http://example.com/",
"host": "example.com",
"hostname": "example.com"
}
},
{
"comment": "Leading / is not stripped",
"href": "sc://example.com/",
"new_value": "///bad.com",
"expected": {
"href": "sc:///",
"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://xn--/",
"host": "xn--",
"hostname": "xn--"
}
},
{
"href": "https://test.invalid/",
"new_value": "*",
"expected": {
"href": "https://*/",
"host": "*",
"hostname": "*"
}
},
{
"href": "https://test.invalid/",
"new_value": "x@x",
"expected": {
"href": "https://test.invalid/",
"host": "test.invalid",
"hostname": "test.invalid"
}
},
{
"href": "https://test.invalid/",
"new_value": "foo\t\r\nbar",
"expected": {
"href": "https://foobar/",
"host": "foobar",
"hostname": "foobar"
}
},
{
"href": "https://test.invalid/",
"new_value": "><",
"expected": {
"href": "https://test.invalid/",
"host": "test.invalid",
"hostname": "test.invalid"
}
},
{
"href": "https://test.invalid/",
"new_value": "test/@aaa",
"expected": {
"href": "https://test/",
"host": "test",
"hostname": "test"
}
},
{
"href": "https://test.invalid/",
"new_value": "test/:aaa",
"expected": {
"href": "https://test/",
"host": "test",
"hostname": "test"
}
}
],
"port": [
{
"href": "http://example.net",
"new_value": "8080",
"expected": {
"href": "http://example.net:8080/",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Port number is removed if empty is the new value",
"href": "http://example.net:8080",
"new_value": "",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": "Default port number is removed",
"href": "http://example.net:8080",
"new_value": "80",
"expected": {
"href": "http://example.net/",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": "Default port number is removed",
"href": "https://example.net:4433",
"new_value": "443",
"expected": {
"href": "https://example.net/",
"host": "example.net",
"hostname": "example.net",
"port": ""
}
},
{
"comment": "Default port number is only removed for the relevant scheme",
"href": "https://example.net",
"new_value": "80",
"expected": {
"href": "https://example.net:80/",
"host": "example.net:80",
"hostname": "example.net",
"port": "80"
}
},
{
"comment": "Stuff after a / delimiter is ignored",
"href": "http://example.net/path",
"new_value": "8080/stuff",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Stuff after a ? delimiter is ignored",
"href": "http://example.net/path",
"new_value": "8080?stuff",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Stuff after a # delimiter is ignored",
"href": "http://example.net/path",
"new_value": "8080#stuff",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Stuff after a \\ delimiter is ignored for special schemes",
"href": "http://example.net/path",
"new_value": "8080\\stuff",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "view-source+http://example.net/path",
"new_value": "8080stuff2",
"expected": {
"href": "view-source+http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net/path",
"new_value": "8080stuff2",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
"href": "http://example.net/path",
"new_value": "8080+2",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Port numbers are 16 bit integers",
"href": "http://example.net/path",
"new_value": "65535",
"expected": {
"href": "http://example.net:65535/path",
"host": "example.net:65535",
"hostname": "example.net",
"port": "65535"
}
},
{
"comment": "Port numbers are 16 bit integers, overflowing is an error",
"href": "http://example.net:8080/path",
"new_value": "65536",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Setting port to a string that doesn't parse as a number",
"href": "http://example.net:8080/path",
"new_value": "randomstring",
"expected": {
"href": "http://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"comment": "Port numbers are 16 bit integers, overflowing is an error",
"href": "non-special://example.net:8080/path",
"new_value": "65536",
"expected": {
"href": "non-special://example.net:8080/path",
"host": "example.net:8080",
"hostname": "example.net",
"port": "8080"
}
},
{
"href": "file://test/",
"new_value": "12",
"expected": {
"href": "file://test/",
"port": ""
}
},
{
"href": "file://localhost/",
"new_value": "12",
"expected": {
"href": "file:///",
"port": ""
}
},
{
"href": "non-base:value",
"new_value": "12",
"expected": {
"href": "non-base:value",
"port": ""
}
},
{
"href": "sc:///",
"new_value": "12",
"expected": {
"href": "sc:///",
"port": ""
}
},
{
"href": "sc://x/",
"new_value": "12",
"expected": {
"href": "sc://x:12/",
"port": "12"
}
},
{
"href": "javascript://x/",
"new_value": "12",
"expected": {
"href": "javascript://x:12/",
"port": "12"
}
},
{
"comment": "Leading u0009 on special scheme",
"href": "https://domain.com:443",
"new_value": "\u00098080",
"expected": {
"port": "8080"
}
},
{
"comment": "Leading u0009 on non-special scheme",
"href": "wpt++://domain.com:443",
"new_value": "\u00098080",
"expected": {
"port": "8080"
}
},
{
"comment": "Should use all ascii prefixed characters as port",
"href": "https://www.google.com:4343",
"new_value": "4wpt",
"expected": {
"port": "4"
}
},
{
"href": "https://domain.com:3000",
"new_value": "\n\t80\n\t80\n\t",
"expected": {
"port": "8080"
}
},
{
"href": "https://domain.com:3000",
"new_value": "\n\n\t\t",
"expected": {
"port": "3000"
}
}
],
"pathname": [
{
"comment": "Opaque paths cannot be set",
"href": "mailto:me@example.net",
"new_value": "/foo",
"expected": {
"href": "mailto:me@example.net",
"pathname": "me@example.net"
}
},
{
"href": "data:original",
"new_value": "new value",
"expected": {
"href": "data:original",
"pathname": "original"
}
},
{
"href": "sc:original",
"new_value": "new value",
"expected": {
"href": "sc:original",
"pathname": "original"
}
},
{
"comment": "Special URLs cannot have their paths erased",
"href": "file:///some/path",
"new_value": "",
"expected": {
"href": "file:///",
"pathname": "/"
}
},
{
"comment": "Non-special URLs can have their paths erased",
"href": "foo://somehost/some/path",
"new_value": "",
"expected": {
"href": "foo://somehost",
"pathname": ""
}
},
{
"comment": "Non-special URLs with an empty host can have their paths erased",
"href": "foo:///some/path",
"new_value": "",
"expected": {
"href": "foo://",
"pathname": ""
}
},
{
"comment": "Path-only URLs cannot have their paths erased",
"href": "foo:/some/path",
"new_value": "",
"expected": {
"href": "foo:/",
"pathname": "/"
}
},
{
"comment": "Path-only URLs always have an initial slash",
"href": "foo:/some/path",
"new_value": "test",
"expected": {
"href": "foo:/test",
"pathname": "/test"
}
},
{
"href": "unix:/run/foo.socket?timeout=10",
"new_value": "/var/log/../run/bar.socket",
"expected": {
"href": "unix:/var/run/bar.socket?timeout=10",
"pathname": "/var/run/bar.socket"
}
},
{
"href": "https://example.net#nav",
"new_value": "home",
"expected": {
"href": "https://example.net/home#nav",
"pathname": "/home"
}
},
{
"href": "https://example.net#nav",
"new_value": "../home",
"expected": {
"href": "https://example.net/home#nav",
"pathname": "/home"
}
},
{
"comment": "\\ is a segment delimiter for 'special' URLs",
"href": "http://example.net/home?lang=fr#nav",
"new_value": "\\a\\%2E\\b\\%2e.\\c",
"expected": {
"href": "http://example.net/a/c?lang=fr#nav",
"pathname": "/a/c"
}
},
{
"comment": "\\ is *not* a segment delimiter for non-'special' URLs",
"href": "view-source+http://example.net/home?lang=fr#nav",
"new_value": "\\a\\%2E\\b\\%2e.\\c",
"expected": {
"href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav",
"pathname": "/\\a\\%2E\\b\\%2e.\\c"
}
},
{
"comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.",
"href": "a:/",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "a:/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]%5E_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9",
"pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]%5E_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.",
"href": "http://example.net",
"new_value": "%2e%2E%c3%89té",
"expected": {
"href": "http://example.net/%2e%2E%c3%89t%C3%A9",
"pathname": "/%2e%2E%c3%89t%C3%A9"
}
},
{
"comment": "? needs to be encoded",
"href": "http://example.net",
"new_value": "?",
"expected": {
"href": "http://example.net/%3F",
"pathname": "/%3F"
}
},
{
"comment": "# needs to be encoded",
"href": "http://example.net",
"new_value": "#",
"expected": {
"href": "http://example.net/%23",
"pathname": "/%23"
}
},
{
"comment": "? needs to be encoded, non-special scheme",
"href": "sc://example.net",
"new_value": "?",
"expected": {
"href": "sc://example.net/%3F",
"pathname": "/%3F"
}
},
{
"comment": "# needs to be encoded, non-special scheme",
"href": "sc://example.net",
"new_value": "#",
"expected": {
"href": "sc://example.net/%23",
"pathname": "/%23"
}
},
{
"comment": "? doesn't mess up encoding",
"href": "http://example.net",
"new_value": "/?é",
"expected": {
"href": "http://example.net/%3F%C3%A9",
"pathname": "/%3F%C3%A9"
}
},
{
"comment": "# doesn't mess up encoding",
"href": "http://example.net",
"new_value": "/#é",
"expected": {
"href": "http://example.net/%23%C3%A9",
"pathname": "/%23%C3%A9"
}
},
{
"comment": "File URLs and (back)slashes",
"href": "file://monkey/",
"new_value": "\\\\",
"expected": {
"href": "file://monkey//",
"pathname": "//"
}
},
{
"comment": "File URLs and (back)slashes",
"href": "file:///unicorn",
"new_value": "//\\/",
"expected": {
"href": "file://////",
"pathname": "////"
}
},
{
"comment": "File URLs and (back)slashes",
"href": "file:///unicorn",
"new_value": "//monkey/..//",
"expected": {
"href": "file://///",
"pathname": "///"
}
},
{
"comment": "Serialize /. in path",
"href": "non-spec:/",
"new_value": "/.//p",
"expected": {
"href": "non-spec:/.//p",
"pathname": "//p"
}
},
{
"href": "non-spec:/",
"new_value": "/..//p",
"expected": {
"href": "non-spec:/.//p",
"pathname": "//p"
}
},
{
"href": "non-spec:/",
"new_value": "//p",
"expected": {
"href": "non-spec:/.//p",
"pathname": "//p"
}
},
{
"comment": "Drop /. from path",
"href": "non-spec:/.//",
"new_value": "p",
"expected": {
"href": "non-spec:/p",
"pathname": "/p"
}
},
{
"comment": "Non-special URLs with non-opaque paths percent-encode U+0020",
"href": "data:/nospace",
"new_value": "space ",
"expected": {
"href": "data:/space%20",
"pathname": "/space%20"
}
},
{
"href": "sc:/nospace",
"new_value": "space ",
"expected": {
"href": "sc:/space%20",
"pathname": "/space%20"
}
},
{
"comment": "Trailing space should be encoded",
"href": "http://example.net",
"new_value": " ",
"expected": {
"href": "http://example.net/%20",
"pathname": "/%20"
}
},
{
"comment": "Trailing C0 control should be encoded",
"href": "http://example.net",
"new_value": "\u0000",
"expected": {
"href": "http://example.net/%00",
"pathname": "/%00"
}
},
{
"href": "foo://path/to",
"new_value": "/..",
"expected": {
"href": "foo://path/",
"pathname": "/"
}
}
],
"search": [
{
"href": "https://example.net#nav",
"new_value": "lang=fr",
"expected": {
"href": "https://example.net/?lang=fr#nav",
"search": "?lang=fr"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "lang=fr",
"expected": {
"href": "https://example.net/?lang=fr#nav",
"search": "?lang=fr"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "?lang=fr",
"expected": {
"href": "https://example.net/?lang=fr#nav",
"search": "?lang=fr"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "??lang=fr",
"expected": {
"href": "https://example.net/??lang=fr#nav",
"search": "??lang=fr"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "?",
"expected": {
"href": "https://example.net/?#nav",
"search": ""
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "",
"expected": {
"href": "https://example.net/#nav",
"search": ""
}
},
{
"href": "https://example.net?lang=en-US",
"new_value": "",
"expected": {
"href": "https://example.net/",
"search": ""
}
},
{
"href": "https://example.net",
"new_value": "",
"expected": {
"href": "https://example.net/",
"search": ""
}
},
{
"comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.",
"href": "a:/",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "a:/?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
"search": "?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Bytes already percent-encoded are left as-is",
"href": "http://example.net",
"new_value": "%c3%89té",
"expected": {
"href": "http://example.net/?%c3%89t%C3%A9",
"search": "?%c3%89t%C3%A9"
}
},
{
"comment": "Trailing spaces and opaque paths",
"href": "data:space ?query",
"new_value": "",
"expected": {
"href": "data:space%20",
"pathname": "space%20",
"search": ""
}
},
{
"href": "sc:space ?query",
"new_value": "",
"expected": {
"href": "sc:space%20",
"pathname": "space%20",
"search": ""
}
},
{
"comment": "Trailing spaces and opaque paths",
"href": "data:space ?query#fragment",
"new_value": "",
"expected": {
"href": "data:space %20#fragment",
"search": ""
}
},
{
"href": "sc:space ?query#fragment",
"new_value": "",
"expected": {
"href": "sc:space %20#fragment",
"search": ""
}
},
{
"comment": "Trailing space should be encoded",
"href": "http://example.net",
"new_value": " ",
"expected": {
"href": "http://example.net/?%20",
"search": "?%20"
}
},
{
"comment": "Trailing C0 control should be encoded",
"href": "http://example.net",
"new_value": "\u0000",
"expected": {
"href": "http://example.net/?%00",
"search": "?%00"
}
}
],
"hash": [
{
"href": "https://example.net",
"new_value": "main",
"expected": {
"href": "https://example.net/#main",
"hash": "#main"
}
},
{
"href": "https://example.net#nav",
"new_value": "main",
"expected": {
"href": "https://example.net/#main",
"hash": "#main"
}
},
{
"href": "https://example.net?lang=en-US",
"new_value": "##nav",
"expected": {
"href": "https://example.net/?lang=en-US##nav",
"hash": "##nav"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "#main",
"expected": {
"href": "https://example.net/?lang=en-US#main",
"hash": "#main"
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "#",
"expected": {
"href": "https://example.net/?lang=en-US#",
"hash": ""
}
},
{
"href": "https://example.net?lang=en-US#nav",
"new_value": "",
"expected": {
"href": "https://example.net/?lang=en-US",
"hash": ""
}
},
{
"href": "http://example.net",
"new_value": "#foo bar",
"expected": {
"href": "http://example.net/#foo%20bar",
"hash": "#foo%20bar"
}
},
{
"href": "http://example.net",
"new_value": "#foo\"bar",
"expected": {
"href": "http://example.net/#foo%22bar",
"hash": "#foo%22bar"
}
},
{
"href": "http://example.net",
"new_value": "#foo<bar",
"expected": {
"href": "http://example.net/#foo%3Cbar",
"hash": "#foo%3Cbar"
}
},
{
"href": "http://example.net",
"new_value": "#foo>bar",
"expected": {
"href": "http://example.net/#foo%3Ebar",
"hash": "#foo%3Ebar"
}
},
{
"href": "http://example.net",
"new_value": "#foo`bar",
"expected": {
"href": "http://example.net/#foo%60bar",
"hash": "#foo%60bar"
}
},
{
"comment": "Simple percent-encoding; tabs and newlines are removed",
"href": "a:/",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "a:/#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
"hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Percent-encode NULLs in fragment",
"href": "http://example.net",
"new_value": "a\u0000b",
"expected": {
"href": "http://example.net/#a%00b",
"hash": "#a%00b"
}
},
{
"comment": "Percent-encode NULLs in fragment",
"href": "non-spec:/",
"new_value": "a\u0000b",
"expected": {
"href": "non-spec:/#a%00b",
"hash": "#a%00b"
}
},
{
"comment": "Bytes already percent-encoded are left as-is",
"href": "http://example.net",
"new_value": "%c3%89té",
"expected": {
"href": "http://example.net/#%c3%89t%C3%A9",
"hash": "#%c3%89t%C3%A9"
}
},
{
"href": "javascript:alert(1)",
"new_value": "castle",
"expected": {
"href": "javascript:alert(1)#castle",
"hash": "#castle"
}
},
{
"comment": "Trailing spaces and opaque paths",
"href": "data:space #fragment",
"new_value": "",
"expected": {
"href": "data:space %20",
"pathname": "space %20",
"hash": ""
}
},
{
"href": "sc:space #fragment",
"new_value": "",
"expected": {
"href": "sc:space %20",
"pathname": "space %20",
"hash": ""
}
},
{
"comment": "Trailing spaces and opaque paths",
"href": "data:space ?query#fragment",
"new_value": "",
"expected": {
"href": "data:space %20?query",
"hash": ""
}
},
{
"href": "sc:space ?query#fragment",
"new_value": "",
"expected": {
"href": "sc:space %20?query",
"hash": ""
}
},
{
"comment": "Trailing space should be encoded",
"href": "http://example.net",
"new_value": " ",
"expected": {
"href": "http://example.net/#%20",
"hash": "#%20"
}
},
{
"comment": "Trailing C0 control should be encoded",
"href": "http://example.net",
"new_value": "\u0000",
"expected": {
"href": "http://example.net/#%00",
"hash": "#%00"
}
},
{
"comment": "Fragment with <> on data: URI",
"href": "data:text/plain,test",
"new_value": "#<foo> <bar>",
"expected": {
"href": "data:text/plain,test#%3Cfoo%3E%20%3Cbar%3E",
"hash": "#%3Cfoo%3E%20%3Cbar%3E"
}
},
{
"comment": "Fragment with <> on about:blank",
"href": "about:blank",
"new_value": "#<foo> <bar>",
"expected": {
"href": "about:blank#%3Cfoo%3E%20%3Cbar%3E",
"hash": "#%3Cfoo%3E%20%3Cbar%3E"
}
},
{
"comment": "Fragment percent-encode set on data: URI; tabs and newlines are removed",
"href": "data:text/plain,test",
"new_value": "#\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "data:text/plain,test#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
"hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
"comment": "Fragment percent-encode set on about:blank; tabs and newlines are removed",
"href": "about:blank",
"new_value": "#\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
"href": "about:blank#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
"hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
}
}
],
"href": [
{
"href": "file:///var/log/system.log",
"new_value": "http://0300.168.0xF0",
"expected": {
"href": "http://192.168.0.240/",
"protocol": "http:"
}
}
]
}