Import w3c URL tests
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Aug 2016 01:22:33 +0000 (01:22 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Aug 2016 01:22:33 +0000 (01:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161177

Reviewed by Tim Horton.

LayoutTests/imported/w3c:

* web-platform-tests/url: Added.
* web-platform-tests/url/OWNERS: Added.
* web-platform-tests/url/README.md: Added.
* web-platform-tests/url/a-element-expected.txt: Added.
* web-platform-tests/url/a-element-xhtml-expected.txt: Added.
* web-platform-tests/url/a-element-xhtml.xhtml: Added.
* web-platform-tests/url/a-element.html: Added.
* web-platform-tests/url/a-element.js: Added.
(setup.async_test.string_appeared_here.setup.step):
(setBase):
(bURL):
(runURLTests):
* web-platform-tests/url/historical-expected.txt: Added.
* web-platform-tests/url/historical.html: Added.
* web-platform-tests/url/historical.worker.js: Added.
(test):
* web-platform-tests/url/interfaces-expected.txt: Added.
* web-platform-tests/url/interfaces.html: Added.
* web-platform-tests/url/setters_tests.json: Added.
* web-platform-tests/url/url-constructor-expected.txt: Added.
* web-platform-tests/url/url-constructor.html: Added.
* web-platform-tests/url/url-domainToUnicode-expected.txt: Added.
* web-platform-tests/url/url-domainToUnicode.html: Added.
* web-platform-tests/url/url-setters-expected.txt: Added.
* web-platform-tests/url/url-setters.html: Added.
* web-platform-tests/url/urlsearchparams-append-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-append.html: Added.
* web-platform-tests/url/urlsearchparams-constructor-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-constructor.html: Added.
* web-platform-tests/url/urlsearchparams-delete-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-delete.html: Added.
* web-platform-tests/url/urlsearchparams-get-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-get.html: Added.
* web-platform-tests/url/urlsearchparams-getall-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-getall.html: Added.
* web-platform-tests/url/urlsearchparams-has-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-has.html: Added.
* web-platform-tests/url/urlsearchparams-set-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-set.html: Added.
* web-platform-tests/url/urlsearchparams-stringifier-expected.txt: Added.
* web-platform-tests/url/urlsearchparams-stringifier.html: Added.
* web-platform-tests/url/urltestdata.json: Added.

Source/WebCore:

Tests: imported/w3c/web-platform-tests/url/a-element-xhtml.xhtml
       imported/w3c/web-platform-tests/url/a-element.html
       imported/w3c/web-platform-tests/url/historical.html
       imported/w3c/web-platform-tests/url/interfaces.html
       imported/w3c/web-platform-tests/url/url-constructor.html
       imported/w3c/web-platform-tests/url/url-domainToUnicode.html
       imported/w3c/web-platform-tests/url/url-setters.html
       imported/w3c/web-platform-tests/url/urlsearchparams-append.html
       imported/w3c/web-platform-tests/url/urlsearchparams-constructor.html
       imported/w3c/web-platform-tests/url/urlsearchparams-delete.html
       imported/w3c/web-platform-tests/url/urlsearchparams-get.html
       imported/w3c/web-platform-tests/url/urlsearchparams-getall.html
       imported/w3c/web-platform-tests/url/urlsearchparams-has.html
       imported/w3c/web-platform-tests/url/urlsearchparams-set.html
       imported/w3c/web-platform-tests/url/urlsearchparams-stringifier.html

* platform/URL.cpp:
(WebCore::URL::setQuery):

LayoutTests:

* TestExpectations:
Skip asserting test.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@204948 268f45cc-cd09-0410-ab3c-d52691b4dbfc

41 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/url/OWNERS [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/README.md [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/a-element-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml.xhtml [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/a-element.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/a-element.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/historical-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/historical.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/historical.worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/interfaces-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/interfaces.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/setters_tests.json [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-constructor-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-constructor.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-setters-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/url-setters.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/url/urltestdata.json [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/URL.cpp

index 418d6873b1f39a64775f1d017e9f841a2819a34f..705638ef3db0da33ff9c96a790f6e2d2e159d1a2 100644 (file)
@@ -1,3 +1,13 @@
+2016-08-24  Alex Christensen  <achristensen@webkit.org>
+
+        Import w3c URL tests
+        https://bugs.webkit.org/show_bug.cgi?id=161177
+
+        Reviewed by Tim Horton.
+
+        * TestExpectations:
+        Skip asserting test.
+
 2016-08-24  Simon Fraser  <simon.fraser@apple.com>
 
         [iOS DRT] Hook up uiController.zoomToScale() for DRT
index d173007f5ee365e6f83f678c9943cd0c2a9f5739..ae700204ce21ae68ece236414957dc61ecaebe33 100644 (file)
@@ -500,6 +500,8 @@ imported/w3c/web-platform-tests/XMLHttpRequest/responsexml-document-properties.h
 
 imported/w3c/web-platform-tests/fetch/api/request/request-cache.html [ Skip ]
 
+webkit.org/b/161176 [ Debug ] imported/w3c/web-platform-tests/url/url-setters.html [ Skip ]
+
 [ Debug ] imported/w3c/web-platform-tests/fetch/api/cors/cors-basic-worker.html [ Skip ]
 [ Debug ] imported/w3c/web-platform-tests/fetch/api/cors/cors-cookies-worker.html [ Skip ]
 [ Debug ] imported/w3c/web-platform-tests/fetch/api/cors/cors-filtering-worker.html [ Skip ]
index f8534a459a8a96184252bda47e0ee7319bf66f0e..4a35b682ecc79863c476fead3ffad0a72ddd73ee 100644 (file)
@@ -1,3 +1,53 @@
+2016-08-24  Alex Christensen  <achristensen@webkit.org>
+
+        Import w3c URL tests
+        https://bugs.webkit.org/show_bug.cgi?id=161177
+
+        Reviewed by Tim Horton.
+
+        * web-platform-tests/url: Added.
+        * web-platform-tests/url/OWNERS: Added.
+        * web-platform-tests/url/README.md: Added.
+        * web-platform-tests/url/a-element-expected.txt: Added.
+        * web-platform-tests/url/a-element-xhtml-expected.txt: Added.
+        * web-platform-tests/url/a-element-xhtml.xhtml: Added.
+        * web-platform-tests/url/a-element.html: Added.
+        * web-platform-tests/url/a-element.js: Added.
+        (setup.async_test.string_appeared_here.setup.step):
+        (setBase):
+        (bURL):
+        (runURLTests):
+        * web-platform-tests/url/historical-expected.txt: Added.
+        * web-platform-tests/url/historical.html: Added.
+        * web-platform-tests/url/historical.worker.js: Added.
+        (test):
+        * web-platform-tests/url/interfaces-expected.txt: Added.
+        * web-platform-tests/url/interfaces.html: Added.
+        * web-platform-tests/url/setters_tests.json: Added.
+        * web-platform-tests/url/url-constructor-expected.txt: Added.
+        * web-platform-tests/url/url-constructor.html: Added.
+        * web-platform-tests/url/url-domainToUnicode-expected.txt: Added.
+        * web-platform-tests/url/url-domainToUnicode.html: Added.
+        * web-platform-tests/url/url-setters-expected.txt: Added.
+        * web-platform-tests/url/url-setters.html: Added.
+        * web-platform-tests/url/urlsearchparams-append-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-append.html: Added.
+        * web-platform-tests/url/urlsearchparams-constructor-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-constructor.html: Added.
+        * web-platform-tests/url/urlsearchparams-delete-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-delete.html: Added.
+        * web-platform-tests/url/urlsearchparams-get-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-get.html: Added.
+        * web-platform-tests/url/urlsearchparams-getall-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-getall.html: Added.
+        * web-platform-tests/url/urlsearchparams-has-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-has.html: Added.
+        * web-platform-tests/url/urlsearchparams-set-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-set.html: Added.
+        * web-platform-tests/url/urlsearchparams-stringifier-expected.txt: Added.
+        * web-platform-tests/url/urlsearchparams-stringifier.html: Added.
+        * web-platform-tests/url/urltestdata.json: Added.
+
 2016-08-23  Chris Dumez  <cdumez@apple.com>
 
         Add support for CanvasRenderingContext2D.resetTransform()
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/OWNERS b/LayoutTests/imported/w3c/web-platform-tests/url/OWNERS
new file mode 100644 (file)
index 0000000..562d1cc
--- /dev/null
@@ -0,0 +1,10 @@
+@mikewest
+@frewsxcv
+@tomalec
+@rubys
+@sideshowbarker
+@zcorpan
+@xiaojunwu
+@smola
+@domenic
+@Sebmaster
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/README.md b/LayoutTests/imported/w3c/web-platform-tests/url/README.md
new file mode 100644 (file)
index 0000000..77965cc
--- /dev/null
@@ -0,0 +1,35 @@
+These tests are for browsers, but the data for
+`a-element.html`, `url-constructor.html`, and `a-element-xhtml.xhtml`
+is in `urltestdata.json` and can be re-used by non-browser implementations.
+This file contains a JSON array of comments as strings and test cases as objects.
+The keys for each test case are:
+
+* `base`: an absolute URL as a string whose [parsing] without a base of its own should succeed.
+  This key is always present,
+  and may have a value like `"about:blank"` when `input` is an absolute URL.
+* `input`: an URL as a string to be [parsed][parsing] with `base` as its base URL.
+* Either:
+  * `failure` with the value `true`, indicating that parsing `input` should return failure,
+  * or `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`,
+    `pathname`, `search`, and `hash` with string values;
+    indicating that parsing `input` should return an URL record
+    and that the getters of each corresponding attribute in that URL’s [API]
+    should return the corresponding value.
+
+    The `origin` key may be missing.
+    In that case, the API’s `origin` attribute is not tested.
+
+[parsing]: https://url.spec.whatwg.org/#concept-basic-url-parser
+[API]: https://url.spec.whatwg.org/#api
+
+[`annevk/url`](https://github.com/annevk/url) hosts some other files that might be of
+interest if you want to create additional tests.
+
+Similar to `a-element.html` it would be trivial to add more tests for other objects that
+expose links (e.g. URL and `<area>`). There's also room for enhancement and bits that
+require independent tests:
+
+* The encoding part of the URL parser
+* The state override part of the URL parser (setting individual properties of a URL)
+* Origin serialization
+* `application/x-www-form-urlencoded`
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/a-element-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/a-element-expected.txt
new file mode 100644 (file)
index 0000000..e006a2f
--- /dev/null
@@ -0,0 +1,340 @@
+
+PASS Loading data… 
+PASS Parsing: <http://example  .
+org> against <http://example.org/foo/bar> 
+PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> 
+PASS Parsing: <http:foo.com> against <http://example.org/foo/bar> 
+PASS Parsing: <           :foo.com   
+> against <http://example.org/foo/bar> 
+PASS Parsing: < foo.com  > against <http://example.org/foo/bar> 
+FAIL Parsing: <a:       foo.com> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "a://"
+PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:0/c> against <http://example.org/foo/bar> assert_equals: origin expected "http://f:0" but got "http://f"
+FAIL Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f:0/c" but got "http://f:00000000000000/c"
+FAIL Parsing: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f/c" but got "http://f:00000000000000000000080/c"
+PASS Parsing: <http://f:b/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f: /c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:
+/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:999999/c> against <http://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: 21 / b ? d # e " but got "http://f: 21 / b ? d # e"
+PASS Parsing: <> against <http://example.org/foo/bar> 
+PASS Parsing: <        > against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <:> against <http://example.org/foo/bar> 
+PASS Parsing: <:a> against <http://example.org/foo/bar> 
+PASS Parsing: <:/> against <http://example.org/foo/bar> 
+PASS Parsing: <:\> against <http://example.org/foo/bar> 
+PASS Parsing: <:#> against <http://example.org/foo/bar> 
+PASS Parsing: <#> against <http://example.org/foo/bar> 
+PASS Parsing: <#/> against <http://example.org/foo/bar> 
+PASS Parsing: <#\> against <http://example.org/foo/bar> 
+PASS Parsing: <#;?> against <http://example.org/foo/bar> 
+PASS Parsing: <?> against <http://example.org/foo/bar> 
+PASS Parsing: </> against <http://example.org/foo/bar> 
+PASS Parsing: <:23> against <http://example.org/foo/bar> 
+PASS Parsing: </:23> against <http://example.org/foo/bar> 
+PASS Parsing: <::> against <http://example.org/foo/bar> 
+PASS Parsing: <::23> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo://> against <http://example.org/foo/bar> assert_equals: href expected "foo:///" but got "foo://"
+PASS Parsing: <http://a:b@c:29/d> against <http://example.org/foo/bar> 
+PASS Parsing: <http::@c:29> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> assert_equals: href expected "http://&a:foo(b%5Dc@d:2/" but got "http://&a:foo(b]c@d:2/"
+FAIL Parsing: <http://::@c@d:2> against <http://example.org/foo/bar> assert_equals: href expected "http://:%3A%40c@d:2/" but got "http://::@c@d:2"
+PASS Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo.com/\@> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo:/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:/bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:////://///> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <c:/foo> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "c://"
+PASS Parsing: <//foo/bar> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> 
+PASS Parsing: <[61:24:74]:98> against <http://example.org/foo/bar> 
+PASS Parsing: <http:[61:27]/:foo> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[1::2]:3:4> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]:80> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar> 
+FAIL Parsing: <http:/example.com/> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/example.com/" but got "http://example.com/"
+PASS Parsing: <ftp:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <ftps:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ftp:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: </a/b/c> against <http://example.org/foo/bar> 
+PASS Parsing: </a/ /c> against <http://example.org/foo/bar> 
+PASS Parsing: </a%2fc> against <http://example.org/foo/bar> 
+PASS Parsing: </a/%2f/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <#β> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/foo/bar#β" but got "http://example.org/foo/bar#%CE%B2"
+PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar> 
+FAIL Parsing: <tel:1234567890> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "tel://"
+FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
+FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c|////foo/bar.html"
+FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C|/foo/bar"
+FAIL Parsing: </C|\foo\bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///C|/foo/bar"
+FAIL Parsing: <//C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "//C|/foo/bar"
+PASS Parsing: <//server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <\\server\file> against <file:///tmp/mock/path> 
+PASS Parsing: </\server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///foo/bar.txt> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///home/me> against <file:///tmp/mock/path> 
+PASS Parsing: <//> against <file:///tmp/mock/path> 
+PASS Parsing: <///> against <file:///tmp/mock/path> 
+PASS Parsing: <///test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/test> against <file:///tmp/mock/path> 
+PASS Parsing: <test> against <file:///tmp/mock/path> 
+PASS Parsing: <file:test> against <file:///tmp/mock/path> 
+PASS Parsing: <http://example.com/././foo> against <about:blank> 
+PASS Parsing: <http://example.com/./.foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo/.> against <about:blank> 
+PASS Parsing: <http://example.com/foo/./> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../> against <about:blank> 
+PASS Parsing: <http://example.com/foo/..bar> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
+FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+PASS Parsing: <http://example.com////../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
+PASS Parsing: <http://example.com/foo> against <about:blank> 
+PASS Parsing: <http://example.com/%20foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo%> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%41%7a> against <about:blank> 
+PASS Parsing: <http://example.com/foo  \91%91> against <about:blank> 
+PASS Parsing: <http://example.com/foo%00%51> against <about:blank> 
+PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank> 
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank> 
+PASS Parsing: <http://example.com/foo  bar> against <about:blank> 
+PASS Parsing: <http://example.com\\foo\\bar> against <about:blank> 
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> 
+PASS Parsing: <http://example.com/@asdf%40> against <about:blank> 
+PASS Parsing: <http://example.com/你好你好> against <about:blank> 
+PASS Parsing: <http://example.com/‥/foo> against <about:blank> 
+PASS Parsing: <http://example.com//foo> against <about:blank> 
+PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank> 
+PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank> 
+FAIL Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank> assert_equals: href expected "http://www.google.com/foo?bar=baz# »" but got "http://www.google.com/foo?bar=baz# %C2%BB"
+FAIL Parsing: <data:test# »> against <about:blank> assert_equals: href expected "data:test# »" but got "data:test# %C2%BB"
+PASS Parsing: <http://[www.google.com]/> against <about:blank> 
+PASS Parsing: <http://www.google.com> against <about:blank> 
+FAIL Parsing: <http://192.0x00A80001> against <about:blank> assert_equals: href expected "http://192.168.0.1/" but got "http://192.0x00a80001/"
+FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
+FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://user:pass@/> against <about:blank> 
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
+PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
+PASS Parsing: <http://foo:80/> against <about:blank> 
+PASS Parsing: <http://foo:81/> against <about:blank> 
+FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: origin expected "null" but got "httpa://foo:80"
+PASS Parsing: <http://foo:-80/> against <about:blank> 
+PASS Parsing: <https://foo:443/> against <about:blank> 
+PASS Parsing: <https://foo:80/> against <about:blank> 
+PASS Parsing: <ftp://foo:21/> against <about:blank> 
+PASS Parsing: <ftp://foo:80/> against <about:blank> 
+PASS Parsing: <gopher://foo:70/> against <about:blank> 
+PASS Parsing: <gopher://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:80/> against <about:blank> 
+PASS Parsing: <ws://foo:81/> against <about:blank> 
+PASS Parsing: <ws://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:815/> against <about:blank> 
+PASS Parsing: <wss://foo:80/> against <about:blank> 
+PASS Parsing: <wss://foo:81/> against <about:blank> 
+PASS Parsing: <wss://foo:443/> against <about:blank> 
+PASS Parsing: <wss://foo:815/> against <about:blank> 
+PASS Parsing: <http:/example.com/> against <about:blank> 
+PASS Parsing: <ftp:/example.com/> against <about:blank> 
+PASS Parsing: <https:/example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <about:blank> 
+FAIL Parsing: <ftps:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <about:blank> 
+PASS Parsing: <ws:/example.com/> against <about:blank> 
+PASS Parsing: <wss:/example.com/> against <about:blank> 
+PASS Parsing: <data:/example.com/> against <about:blank> 
+PASS Parsing: <javascript:/example.com/> against <about:blank> 
+FAIL Parsing: <mailto:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <about:blank> 
+PASS Parsing: <ftp:example.com/> against <about:blank> 
+PASS Parsing: <https:example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <about:blank> 
+PASS Parsing: <ws:example.com/> against <about:blank> 
+PASS Parsing: <wss:example.com/> against <about:blank> 
+PASS Parsing: <data:example.com/> against <about:blank> 
+PASS Parsing: <javascript:example.com/> against <about:blank> 
+FAIL Parsing: <mailto:example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:@www.example.com> against <about:blank> 
+PASS Parsing: <http:/@www.example.com> against <about:blank> 
+PASS Parsing: <http://@www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://@pple.com> against <about:blank> 
+PASS Parsing: <http::b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:@/www.example.com> against <about:blank> 
+PASS Parsing: <http://user@/www.example.com> against <about:blank> 
+PASS Parsing: <http:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/@/www.example.com> against <about:blank> 
+PASS Parsing: <http://@/www.example.com> against <about:blank> 
+PASS Parsing: <https:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http::@/www.example.com> against <about:blank> 
+FAIL Parsing: <http:a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http:/a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http://a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+PASS Parsing: <http://www.@pple.com> against <about:blank> 
+PASS Parsing: <http:@:www.example.com> against <about:blank> 
+PASS Parsing: <http:/@:www.example.com> against <about:blank> 
+PASS Parsing: <http://@:www.example.com> against <about:blank> 
+FAIL Parsing: <http://:@www.example.com> against <about:blank> assert_equals: href expected "http://:@www.example.com/" but got "http://www.example.com/"
+PASS Parsing: </> against <http://www.example.com/test> 
+PASS Parsing: </test.txt> against <http://www.example.com/test> 
+PASS Parsing: <.> against <http://www.example.com/test> 
+PASS Parsing: <..> against <http://www.example.com/test> 
+PASS Parsing: <test.txt> against <http://www.example.com/test> 
+PASS Parsing: <./test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../aaa/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <中/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <http://www.example2.com> against <http://www.example.com/test> 
+PASS Parsing: <//www.example2.com> against <http://www.example.com/test> 
+FAIL Parsing: <file:...> against <http://www.example.com/test> assert_equals: href expected "file:///..." but got "file://..."
+FAIL Parsing: <file:..> against <http://www.example.com/test> assert_equals: href expected "file:///" but got "file://.."
+FAIL Parsing: <file:a> against <http://www.example.com/test> assert_equals: href expected "file:///a" but got "file://a"
+PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/> 
+PASS Parsing: <http://example example.com> against <http://other.com/> 
+PASS Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> 
+FAIL Parsing: <http://[]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://[:]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://GOO  goo.com> against <http://other.com/> 
+PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/> 
+PASS Parsing: <http://www.foo。bar.com> against <http://other.com/> 
+FAIL Parsing: <http://﷐zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://﷐zyx.com" but got "about:blank"
+FAIL Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://Go.com> against <http://other.com/> 
+FAIL Parsing: <http://%41.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%00.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://你好你好> against <http://other.com/> assert_equals: origin expected "http://你好你好" but got "http://xn--6qqa088eba"
+FAIL Parsing: <http://%zz%66%a.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%25> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://hello%00> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01/"
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01%2e/"
+FAIL Parsing: <http://192.168.0.257> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://192.168.0.1 hello> against <http://other.com/> 
+FAIL Parsing: <http://0Xc0.0250.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://0xc0.0250.01/"
+PASS Parsing: <http://[google.com]> against <http://other.com/> 
+FAIL Parsing: <http://foo:💩@example.com/bar> against <http://other.com/> assert_equals: href expected "http://foo:%F0%9F%92%A9@example.com/bar" but got "http://foo:💩@example.com/bar"
+FAIL Parsing: <#> against <test:test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <#x> against <mailto:x@x.com> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <#x> against <data:,> 
+PASS Parsing: <#x> against <about:blank> 
+FAIL Parsing: <#> against <test:test?test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/> assert_equals: href expected "https://%40test%40test@example:800/" but got "https://@test@test@example:800/"
+FAIL Parsing: <https://@@@example> against <http://doesnotmatter/> assert_equals: href expected "https://%40%40@example/" but got "https://@@@example"
+FAIL Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> assert_equals: href expected "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}" but got "http://`{}:`{}@h/`{}?`{}"
+PASS Parsing: </some/path> against <http://user@example.org/smth> 
+PASS Parsing: <> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: <i> against <sc:sd> 
+PASS Parsing: <i> against <sc:sd/sd> 
+FAIL Parsing: <i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <../i> against <sc:sd> 
+PASS Parsing: <../i> against <sc:sd/sd> 
+FAIL Parsing: <../i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <../i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <../i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: </i> against <sc:sd> 
+PASS Parsing: </i> against <sc:sd/sd> 
+FAIL Parsing: </i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: </i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: </i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:/i"
+PASS Parsing: <?i> against <sc:sd> 
+PASS Parsing: <?i> against <sc:sd/sd> 
+FAIL Parsing: <?i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <?i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <?i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd/sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <about:/../> against <about:blank> 
+PASS Parsing: <data:/../> against <about:blank> 
+PASS Parsing: <javascript:/../> against <about:blank> 
+FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: origin expected "null" but got "sc://xn--ida.test"
+FAIL Parsing: <sc:\../> against <about:blank> assert_equals: href expected "sc:\\../" but got "sc:/"
+FAIL Parsing: <sc::a@example.net> against <about:blank> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank> 
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> 
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> 
+PASS Parsing: <h       t
+t
+p://h  o
+s
+t:9    0
+0
+0/p    a
+t
+h?q    u
+e
+ry#f   r
+a
+g> against <about:blank> 
+PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar> 
+PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar> 
+PASS Parsing: <http:> against <http://example.org/foo/bar> 
+FAIL Parsing: <http:> against <https://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <sc:> against <https://example.org/foo/bar> assert_equals: origin expected "null" but got "sc://"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml-expected.txt
new file mode 100644 (file)
index 0000000..e006a2f
--- /dev/null
@@ -0,0 +1,340 @@
+
+PASS Loading data… 
+PASS Parsing: <http://example  .
+org> against <http://example.org/foo/bar> 
+PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> 
+PASS Parsing: <http:foo.com> against <http://example.org/foo/bar> 
+PASS Parsing: <           :foo.com   
+> against <http://example.org/foo/bar> 
+PASS Parsing: < foo.com  > against <http://example.org/foo/bar> 
+FAIL Parsing: <a:       foo.com> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "a://"
+PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:0/c> against <http://example.org/foo/bar> assert_equals: origin expected "http://f:0" but got "http://f"
+FAIL Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f:0/c" but got "http://f:00000000000000/c"
+FAIL Parsing: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f/c" but got "http://f:00000000000000000000080/c"
+PASS Parsing: <http://f:b/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f: /c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:
+/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:999999/c> against <http://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: 21 / b ? d # e " but got "http://f: 21 / b ? d # e"
+PASS Parsing: <> against <http://example.org/foo/bar> 
+PASS Parsing: <        > against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <:> against <http://example.org/foo/bar> 
+PASS Parsing: <:a> against <http://example.org/foo/bar> 
+PASS Parsing: <:/> against <http://example.org/foo/bar> 
+PASS Parsing: <:\> against <http://example.org/foo/bar> 
+PASS Parsing: <:#> against <http://example.org/foo/bar> 
+PASS Parsing: <#> against <http://example.org/foo/bar> 
+PASS Parsing: <#/> against <http://example.org/foo/bar> 
+PASS Parsing: <#\> against <http://example.org/foo/bar> 
+PASS Parsing: <#;?> against <http://example.org/foo/bar> 
+PASS Parsing: <?> against <http://example.org/foo/bar> 
+PASS Parsing: </> against <http://example.org/foo/bar> 
+PASS Parsing: <:23> against <http://example.org/foo/bar> 
+PASS Parsing: </:23> against <http://example.org/foo/bar> 
+PASS Parsing: <::> against <http://example.org/foo/bar> 
+PASS Parsing: <::23> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo://> against <http://example.org/foo/bar> assert_equals: href expected "foo:///" but got "foo://"
+PASS Parsing: <http://a:b@c:29/d> against <http://example.org/foo/bar> 
+PASS Parsing: <http::@c:29> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> assert_equals: href expected "http://&a:foo(b%5Dc@d:2/" but got "http://&a:foo(b]c@d:2/"
+FAIL Parsing: <http://::@c@d:2> against <http://example.org/foo/bar> assert_equals: href expected "http://:%3A%40c@d:2/" but got "http://::@c@d:2"
+PASS Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo.com/\@> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo:/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:/bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:////://///> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <c:/foo> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "c://"
+PASS Parsing: <//foo/bar> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> 
+PASS Parsing: <[61:24:74]:98> against <http://example.org/foo/bar> 
+PASS Parsing: <http:[61:27]/:foo> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[1::2]:3:4> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]:80> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar> 
+FAIL Parsing: <http:/example.com/> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/example.com/" but got "http://example.com/"
+PASS Parsing: <ftp:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <ftps:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ftp:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: </a/b/c> against <http://example.org/foo/bar> 
+PASS Parsing: </a/ /c> against <http://example.org/foo/bar> 
+PASS Parsing: </a%2fc> against <http://example.org/foo/bar> 
+PASS Parsing: </a/%2f/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <#β> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/foo/bar#β" but got "http://example.org/foo/bar#%CE%B2"
+PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar> 
+FAIL Parsing: <tel:1234567890> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "tel://"
+FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
+FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c|////foo/bar.html"
+FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C|/foo/bar"
+FAIL Parsing: </C|\foo\bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///C|/foo/bar"
+FAIL Parsing: <//C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "//C|/foo/bar"
+PASS Parsing: <//server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <\\server\file> against <file:///tmp/mock/path> 
+PASS Parsing: </\server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///foo/bar.txt> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///home/me> against <file:///tmp/mock/path> 
+PASS Parsing: <//> against <file:///tmp/mock/path> 
+PASS Parsing: <///> against <file:///tmp/mock/path> 
+PASS Parsing: <///test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/test> against <file:///tmp/mock/path> 
+PASS Parsing: <test> against <file:///tmp/mock/path> 
+PASS Parsing: <file:test> against <file:///tmp/mock/path> 
+PASS Parsing: <http://example.com/././foo> against <about:blank> 
+PASS Parsing: <http://example.com/./.foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo/.> against <about:blank> 
+PASS Parsing: <http://example.com/foo/./> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../> against <about:blank> 
+PASS Parsing: <http://example.com/foo/..bar> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
+FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+PASS Parsing: <http://example.com////../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
+PASS Parsing: <http://example.com/foo> against <about:blank> 
+PASS Parsing: <http://example.com/%20foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo%> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%41%7a> against <about:blank> 
+PASS Parsing: <http://example.com/foo  \91%91> against <about:blank> 
+PASS Parsing: <http://example.com/foo%00%51> against <about:blank> 
+PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank> 
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank> 
+PASS Parsing: <http://example.com/foo  bar> against <about:blank> 
+PASS Parsing: <http://example.com\\foo\\bar> against <about:blank> 
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> 
+PASS Parsing: <http://example.com/@asdf%40> against <about:blank> 
+PASS Parsing: <http://example.com/你好你好> against <about:blank> 
+PASS Parsing: <http://example.com/‥/foo> against <about:blank> 
+PASS Parsing: <http://example.com//foo> against <about:blank> 
+PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank> 
+PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank> 
+FAIL Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank> assert_equals: href expected "http://www.google.com/foo?bar=baz# »" but got "http://www.google.com/foo?bar=baz# %C2%BB"
+FAIL Parsing: <data:test# »> against <about:blank> assert_equals: href expected "data:test# »" but got "data:test# %C2%BB"
+PASS Parsing: <http://[www.google.com]/> against <about:blank> 
+PASS Parsing: <http://www.google.com> against <about:blank> 
+FAIL Parsing: <http://192.0x00A80001> against <about:blank> assert_equals: href expected "http://192.168.0.1/" but got "http://192.0x00a80001/"
+FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
+FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://user:pass@/> against <about:blank> 
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
+PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
+PASS Parsing: <http://foo:80/> against <about:blank> 
+PASS Parsing: <http://foo:81/> against <about:blank> 
+FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: origin expected "null" but got "httpa://foo:80"
+PASS Parsing: <http://foo:-80/> against <about:blank> 
+PASS Parsing: <https://foo:443/> against <about:blank> 
+PASS Parsing: <https://foo:80/> against <about:blank> 
+PASS Parsing: <ftp://foo:21/> against <about:blank> 
+PASS Parsing: <ftp://foo:80/> against <about:blank> 
+PASS Parsing: <gopher://foo:70/> against <about:blank> 
+PASS Parsing: <gopher://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:80/> against <about:blank> 
+PASS Parsing: <ws://foo:81/> against <about:blank> 
+PASS Parsing: <ws://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:815/> against <about:blank> 
+PASS Parsing: <wss://foo:80/> against <about:blank> 
+PASS Parsing: <wss://foo:81/> against <about:blank> 
+PASS Parsing: <wss://foo:443/> against <about:blank> 
+PASS Parsing: <wss://foo:815/> against <about:blank> 
+PASS Parsing: <http:/example.com/> against <about:blank> 
+PASS Parsing: <ftp:/example.com/> against <about:blank> 
+PASS Parsing: <https:/example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <about:blank> 
+FAIL Parsing: <ftps:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <about:blank> 
+PASS Parsing: <ws:/example.com/> against <about:blank> 
+PASS Parsing: <wss:/example.com/> against <about:blank> 
+PASS Parsing: <data:/example.com/> against <about:blank> 
+PASS Parsing: <javascript:/example.com/> against <about:blank> 
+FAIL Parsing: <mailto:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <about:blank> 
+PASS Parsing: <ftp:example.com/> against <about:blank> 
+PASS Parsing: <https:example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <about:blank> 
+PASS Parsing: <ws:example.com/> against <about:blank> 
+PASS Parsing: <wss:example.com/> against <about:blank> 
+PASS Parsing: <data:example.com/> against <about:blank> 
+PASS Parsing: <javascript:example.com/> against <about:blank> 
+FAIL Parsing: <mailto:example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:@www.example.com> against <about:blank> 
+PASS Parsing: <http:/@www.example.com> against <about:blank> 
+PASS Parsing: <http://@www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://@pple.com> against <about:blank> 
+PASS Parsing: <http::b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:@/www.example.com> against <about:blank> 
+PASS Parsing: <http://user@/www.example.com> against <about:blank> 
+PASS Parsing: <http:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/@/www.example.com> against <about:blank> 
+PASS Parsing: <http://@/www.example.com> against <about:blank> 
+PASS Parsing: <https:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http::@/www.example.com> against <about:blank> 
+FAIL Parsing: <http:a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http:/a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http://a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+PASS Parsing: <http://www.@pple.com> against <about:blank> 
+PASS Parsing: <http:@:www.example.com> against <about:blank> 
+PASS Parsing: <http:/@:www.example.com> against <about:blank> 
+PASS Parsing: <http://@:www.example.com> against <about:blank> 
+FAIL Parsing: <http://:@www.example.com> against <about:blank> assert_equals: href expected "http://:@www.example.com/" but got "http://www.example.com/"
+PASS Parsing: </> against <http://www.example.com/test> 
+PASS Parsing: </test.txt> against <http://www.example.com/test> 
+PASS Parsing: <.> against <http://www.example.com/test> 
+PASS Parsing: <..> against <http://www.example.com/test> 
+PASS Parsing: <test.txt> against <http://www.example.com/test> 
+PASS Parsing: <./test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../aaa/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <中/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <http://www.example2.com> against <http://www.example.com/test> 
+PASS Parsing: <//www.example2.com> against <http://www.example.com/test> 
+FAIL Parsing: <file:...> against <http://www.example.com/test> assert_equals: href expected "file:///..." but got "file://..."
+FAIL Parsing: <file:..> against <http://www.example.com/test> assert_equals: href expected "file:///" but got "file://.."
+FAIL Parsing: <file:a> against <http://www.example.com/test> assert_equals: href expected "file:///a" but got "file://a"
+PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/> 
+PASS Parsing: <http://example example.com> against <http://other.com/> 
+PASS Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> 
+FAIL Parsing: <http://[]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://[:]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://GOO  goo.com> against <http://other.com/> 
+PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/> 
+PASS Parsing: <http://www.foo。bar.com> against <http://other.com/> 
+FAIL Parsing: <http://﷐zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://﷐zyx.com" but got "about:blank"
+FAIL Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://Go.com> against <http://other.com/> 
+FAIL Parsing: <http://%41.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%00.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://你好你好> against <http://other.com/> assert_equals: origin expected "http://你好你好" but got "http://xn--6qqa088eba"
+FAIL Parsing: <http://%zz%66%a.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%25> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://hello%00> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01/"
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01%2e/"
+FAIL Parsing: <http://192.168.0.257> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code
+PASS Parsing: <http://192.168.0.1 hello> against <http://other.com/> 
+FAIL Parsing: <http://0Xc0.0250.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://0xc0.0250.01/"
+PASS Parsing: <http://[google.com]> against <http://other.com/> 
+FAIL Parsing: <http://foo:💩@example.com/bar> against <http://other.com/> assert_equals: href expected "http://foo:%F0%9F%92%A9@example.com/bar" but got "http://foo:💩@example.com/bar"
+FAIL Parsing: <#> against <test:test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <#x> against <mailto:x@x.com> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <#x> against <data:,> 
+PASS Parsing: <#x> against <about:blank> 
+FAIL Parsing: <#> against <test:test?test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/> assert_equals: href expected "https://%40test%40test@example:800/" but got "https://@test@test@example:800/"
+FAIL Parsing: <https://@@@example> against <http://doesnotmatter/> assert_equals: href expected "https://%40%40@example/" but got "https://@@@example"
+FAIL Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> assert_equals: href expected "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}" but got "http://`{}:`{}@h/`{}?`{}"
+PASS Parsing: </some/path> against <http://user@example.org/smth> 
+PASS Parsing: <> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: <i> against <sc:sd> 
+PASS Parsing: <i> against <sc:sd/sd> 
+FAIL Parsing: <i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <../i> against <sc:sd> 
+PASS Parsing: <../i> against <sc:sd/sd> 
+FAIL Parsing: <../i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <../i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <../i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: </i> against <sc:sd> 
+PASS Parsing: </i> against <sc:sd/sd> 
+FAIL Parsing: </i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: </i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: </i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:/i"
+PASS Parsing: <?i> against <sc:sd> 
+PASS Parsing: <?i> against <sc:sd/sd> 
+FAIL Parsing: <?i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <?i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <?i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd/sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <about:/../> against <about:blank> 
+PASS Parsing: <data:/../> against <about:blank> 
+PASS Parsing: <javascript:/../> against <about:blank> 
+FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: origin expected "null" but got "sc://xn--ida.test"
+FAIL Parsing: <sc:\../> against <about:blank> assert_equals: href expected "sc:\\../" but got "sc:/"
+FAIL Parsing: <sc::a@example.net> against <about:blank> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank> 
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> 
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> 
+PASS Parsing: <h       t
+t
+p://h  o
+s
+t:9    0
+0
+0/p    a
+t
+h?q    u
+e
+ry#f   r
+a
+g> against <about:blank> 
+PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar> 
+PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar> 
+PASS Parsing: <http:> against <http://example.org/foo/bar> 
+FAIL Parsing: <http:> against <https://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code
+FAIL Parsing: <sc:> against <https://example.org/foo/bar> assert_equals: origin expected "null" but got "sc://"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml.xhtml b/LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml.xhtml
new file mode 100644 (file)
index 0000000..7e11e6d
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>URL Test</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <base id="base"/>
+  </head>
+  <body>
+    <div id="log"></div>
+    <script src="a-element.js"></script>
+  </body>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/a-element.html b/LayoutTests/imported/w3c/web-platform-tests/url/a-element.html
new file mode 100644 (file)
index 0000000..b190b94
--- /dev/null
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<base id=base>
+<div id=log></div>
+<script src=a-element.js></script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/a-element.js b/LayoutTests/imported/w3c/web-platform-tests/url/a-element.js
new file mode 100644 (file)
index 0000000..c77df5b
--- /dev/null
@@ -0,0 +1,55 @@
+var setup = async_test("Loading data…")
+setup.step(function() {
+  var request = new XMLHttpRequest()
+  request.open("GET", "urltestdata.json")
+  request.send()
+  request.responseType = "json"
+  request.onload = setup.step_func(function() {
+    runURLTests(request.response)
+    setup.done()
+  })
+})
+
+function setBase(base) {
+  document.getElementById("base").href = base
+}
+
+function bURL(url, base) {
+  base = base || "about:blank"
+  setBase(base)
+  var a = document.createElement("a")
+  a.setAttribute("href", url)
+  return a
+}
+
+function runURLTests(urltests) {
+  for(var i = 0, l = urltests.length; i < l; i++) {
+    var expected = urltests[i]
+    if (typeof expected === "string") continue // skip comments
+
+    test(function() {
+      var url = bURL(expected.input, expected.base)
+      if(expected.failure) {
+        if(url.protocol !== ':') {
+          assert_unreached("Expected URL to fail parsing")
+        }
+        assert_equals(url.href, expected.input, "failure should set href to input")
+        return
+      }
+
+      assert_equals(url.href, expected.href, "href")
+      if ("origin" in expected) {
+        assert_equals(url.origin, expected.origin, "origin")
+      }
+      assert_equals(url.protocol, expected.protocol, "protocol")
+      assert_equals(url.username, expected.username, "username")
+      assert_equals(url.password, expected.password, "password")
+      assert_equals(url.host, expected.host, "host")
+      assert_equals(url.hostname, expected.hostname, "hostname")
+      assert_equals(url.port, expected.port, "port")
+      assert_equals(url.pathname, expected.pathname, "pathname")
+      assert_equals(url.search, expected.search, "search")
+      assert_equals(url.hash, expected.hash, "hash")
+    }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+  }
+}
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/historical-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/historical-expected.txt
new file mode 100644 (file)
index 0000000..5f82319
--- /dev/null
@@ -0,0 +1,8 @@
+
+PASS searchParams on location object 
+PASS searchParams on a element 
+PASS searchParams on area element 
+FAIL Setting URL's href attribute and base URLs assert_throws: function "function () {
+    url.href = "./bar";
+  }" did not throw
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/historical.html b/LayoutTests/imported/w3c/web-platform-tests/url/historical.html
new file mode 100644 (file)
index 0000000..17fdb97
--- /dev/null
@@ -0,0 +1,29 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>URL historical tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+var objects = [
+  [function() { return window.location }, "location object"],
+  [function() { return document.createElement("a") }, "a element"],
+  [function() { return document.createElement("area") }, "area element"],
+];
+
+objects.forEach(function(o) {
+  test(function() {
+    var object = o[0]();
+    assert_false("searchParams" in object,
+                 o[1] + " should not have a searchParams attribute");
+  }, "searchParams on " + o[1]);
+});
+
+test(function() {
+  var url = new URL("./foo", "http://www.example.org");
+  assert_equals(url.href, "http://www.example.org/foo");
+  assert_throws(new TypeError(), function() {
+    url.href = "./bar";
+  });
+}, "Setting URL's href attribute and base URLs");
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/historical.worker.js b/LayoutTests/imported/w3c/web-platform-tests/url/historical.worker.js
new file mode 100644 (file)
index 0000000..d90915a
--- /dev/null
@@ -0,0 +1,16 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+  assert_false("searchParams" in self.location,
+               "location object should not have a searchParams attribute");
+}, "searchParams on location object");
+
+test(function() {
+  var url = new URL("./foo", "http://www.example.org");
+  assert_equals(url.href, "http://www.example.org/foo");
+  assert_throws(new TypeError(), function() {
+    url.href = "./bar";
+  });
+}, "Setting URL's href attribute and base URLs");
+
+done();
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/interfaces-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/interfaces-expected.txt
new file mode 100644 (file)
index 0000000..752ca86
--- /dev/null
@@ -0,0 +1,53 @@
+URL IDL tests
+
+
+PASS URL interface: existence and properties of interface object 
+PASS URL interface object length 
+PASS URL interface object name 
+PASS URL interface: existence and properties of interface prototype object 
+PASS URL interface: existence and properties of interface prototype object's "constructor" property 
+FAIL URL interface: operation domainToASCII(USVString) assert_own_property: interface object missing static operation expected property "domainToASCII" missing
+FAIL URL interface: operation domainToUnicode(USVString) assert_own_property: interface object missing static operation expected property "domainToUnicode" missing
+PASS URL interface: attribute href 
+PASS URL interface: attribute origin 
+PASS URL interface: attribute protocol 
+PASS URL interface: attribute username 
+PASS URL interface: attribute password 
+PASS URL interface: attribute host 
+PASS URL interface: attribute hostname 
+PASS URL interface: attribute port 
+PASS URL interface: attribute pathname 
+PASS URL interface: attribute search 
+FAIL URL interface: attribute searchParams assert_true: The prototype object must have a property "searchParams" expected true got false
+PASS URL interface: attribute hash 
+PASS URL must be primary interface of new URL("http://foo") 
+PASS Stringification of new URL("http://foo") 
+PASS URL interface: new URL("http://foo") must inherit property "domainToASCII" with the proper type (0) 
+PASS URL interface: calling domainToASCII(USVString) on new URL("http://foo") with too few arguments must throw TypeError 
+PASS URL interface: new URL("http://foo") must inherit property "domainToUnicode" with the proper type (1) 
+PASS URL interface: calling domainToUnicode(USVString) on new URL("http://foo") with too few arguments must throw TypeError 
+PASS URL interface: new URL("http://foo") must inherit property "href" with the proper type (2) 
+PASS URL interface: new URL("http://foo") must inherit property "origin" with the proper type (3) 
+PASS URL interface: new URL("http://foo") must inherit property "protocol" with the proper type (4) 
+PASS URL interface: new URL("http://foo") must inherit property "username" with the proper type (5) 
+PASS URL interface: new URL("http://foo") must inherit property "password" with the proper type (6) 
+PASS URL interface: new URL("http://foo") must inherit property "host" with the proper type (7) 
+PASS URL interface: new URL("http://foo") must inherit property "hostname" with the proper type (8) 
+PASS URL interface: new URL("http://foo") must inherit property "port" with the proper type (9) 
+PASS URL interface: new URL("http://foo") must inherit property "pathname" with the proper type (10) 
+PASS URL interface: new URL("http://foo") must inherit property "search" with the proper type (11) 
+FAIL URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type (12) assert_inherits: property "searchParams" not found in prototype chain
+PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type (13) 
+FAIL URLSearchParams interface: existence and properties of interface object assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface object length assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface object name assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: existence and properties of interface prototype object assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation append(USVString,USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation delete(USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation get(USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation getAll(USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation has(USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: operation set(USVString,USVString) assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+FAIL URLSearchParams interface: stringifier assert_own_property: self does not have own property "URLSearchParams" expected property "URLSearchParams" missing
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/interfaces.html b/LayoutTests/imported/w3c/web-platform-tests/url/interfaces.html
new file mode 100644 (file)
index 0000000..254242f
--- /dev/null
@@ -0,0 +1,65 @@
+<!doctype html>
+<title>URL IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>URL IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+[Constructor(USVString url, optional USVString base),
+ Exposed=(Window,Worker)]
+interface URL {
+  static USVString domainToASCII(USVString domain);
+  static USVString domainToUnicode(USVString domain);
+
+  stringifier attribute USVString href;
+  readonly attribute USVString origin;
+           attribute USVString protocol;
+           attribute USVString username;
+           attribute USVString password;
+           attribute USVString host;
+           attribute USVString hostname;
+           attribute USVString port;
+           attribute USVString pathname;
+           attribute USVString search;
+  readonly attribute URLSearchParams searchParams;
+           attribute USVString hash;
+};
+
+[Constructor(optional (USVString or URLSearchParams) init = ""),
+ Exposed=(Window,Worker)]
+interface URLSearchParams {
+  void append(USVString name, USVString value);
+  void delete(USVString name);
+  USVString? get(USVString name);
+  sequence<USVString> getAll(USVString name);
+  boolean has(USVString name);
+  void set(USVString name, USVString value);
+  iterable<USVString, USVString>;
+  stringifier;
+};
+</script>
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+  idlArray = new IdlArray();
+  [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+    if (node.className == "untested") {
+      idlArray.add_untested_idls(node.textContent);
+    } else {
+      idlArray.add_idls(node.textContent);
+    }
+  });
+}, {explicit_done:true});
+window.onload = function() {
+  idlArray.add_objects({
+    URL: ['new URL("http://foo")']
+  });
+  idlArray.test();
+  done();
+};
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/setters_tests.json b/LayoutTests/imported/w3c/web-platform-tests/url/setters_tests.json
new file mode 100644 (file)
index 0000000..9512d25
--- /dev/null
@@ -0,0 +1,1130 @@
+{
+    "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:"
+            }
+        },
+        {
+            "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 special scheme to non-special. Note: this may change, see https://github.com/whatwg/url/issues/104",
+            "href": "http://example.net",
+            "new_value": "b",
+            "expected": {
+                "href": "http://example.net/",
+                "protocol": "http:"
+            }
+        },
+        {
+            "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. Note: this may change, see https://github.com/whatwg/url/issues/104",
+            "href": "ssh://me@example.net",
+            "new_value": "http",
+            "expected": {
+                "href": "ssh://me@example.net/",
+                "protocol": "ssh:"
+            }
+        },
+        {
+            "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:"
+            }
+        }
+    ],
+    "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": "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"
+            }
+        }
+    ],
+    "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"
+            }
+        }
+    ],
+    "host": [
+        {
+            "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 password",
+            "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 unchanges if empty in the new value. Note: this may change, see https://github.com/whatwg/url/pull/113",
+            "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": "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": "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",
+            "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, and it’s invalid in a domain",
+            "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": "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": ""
+            }
+        }
+    ],
+    "hostname": [
+        {
+            "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 password",
+            "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": "Stuff after a : delimiter is ignored",
+            "href": "http://example.net/path",
+            "new_value": "example.com: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:8080/path",
+            "new_value": "example.com:",
+            "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?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, and it’s invalid in a domain",
+            "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": ""
+            }
+        }
+    ],
+    "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 unchanged if empty in the new value. Note: this may change, see https://github.com/whatwg/url/pull/113",
+            "href": "http://example.net:8080",
+            "new_value": "",
+            "expected": {
+                "href": "http://example.net:8080/",
+                "host": "example.net:8080",
+                "hostname": "example.net",
+                "port": "8080"
+            }
+        },
+        {
+            "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"
+            }
+        }
+    ],
+    "pathname": [
+        {
+            "comment": "Cannot-be-a-base don’t have a path",
+            "href": "mailto:me@example.net",
+            "new_value": "/foo",
+            "expected": {
+                "href": "mailto:me@example.net",
+                "pathname": "me@example.net"
+            }
+        },
+        {
+            "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\\.\\b\\..\\c?lang=fr#nav",
+                "pathname": "/\\a\\.\\b\\..\\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[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9",
+                "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
+            }
+        },
+        {
+            "comment": "Bytes already percent-encoded are left as-is, except %2E.",
+            "href": "http://example.net",
+            "new_value": "%2e%2E%c3%89té",
+            "expected": {
+                "href": "http://example.net/..%c3%89t%C3%A9",
+                "pathname": "/..%c3%89t%C3%A9"
+            }
+        }
+    ],
+    "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"
+            }
+        }
+    ],
+    "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": ""
+            }
+        },
+        {
+            "comment": "No percent-encoding at all (!); nuls, tabs, and newlines are removed",
+            "href": "a:/",
+            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
+            "expected": {
+                "href": "a:/#\u0001\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
+                "hash": "#\u0001\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé"
+            }
+        },
+        {
+            "comment": "Bytes already percent-encoded are left as-is",
+            "href": "http://example.net",
+            "new_value": "%c3%89té",
+            "expected": {
+                "href": "http://example.net/#%c3%89té",
+                "hash": "#%c3%89té"
+            }
+        }
+    ]
+}
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-constructor-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/url-constructor-expected.txt
new file mode 100644 (file)
index 0000000..2bda6ab
--- /dev/null
@@ -0,0 +1,358 @@
+
+FAIL URL.searchParams getter assert_true: expected true got false
+FAIL URL.searchParams updating, clearing assert_true: expected true got false
+FAIL URL.searchParams setter, invalid values assert_throws: function "function () { url.searchParams = new URLSearchParams(urlS..." threw object "ReferenceError: Can't find variable: URLSearchParams" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL URL.searchParams and URL.search setters, update propagation assert_true: expected true got false
+PASS Loading data… 
+PASS Parsing: <http://example  .
+org> against <http://example.org/foo/bar> 
+PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> 
+PASS Parsing: <http:foo.com> against <http://example.org/foo/bar> 
+PASS Parsing: <           :foo.com   
+> against <http://example.org/foo/bar> 
+PASS Parsing: < foo.com  > against <http://example.org/foo/bar> 
+FAIL Parsing: <a:       foo.com> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "a://"
+PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:0/c> against <http://example.org/foo/bar> assert_equals: origin expected "http://f:0" but got "http://f"
+FAIL Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f:0/c" but got "http://f:00000000000000/c"
+FAIL Parsing: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> assert_equals: href expected "http://f/c" but got "http://f:00000000000000000000080/c"
+PASS Parsing: <http://f:b/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f: /c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:
+/c> against <http://example.org/foo/bar> 
+PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://f:999999/c> against <http://example.org/foo/bar> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+PASS Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar> 
+PASS Parsing: <> against <http://example.org/foo/bar> 
+PASS Parsing: <        > against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <:foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <:> against <http://example.org/foo/bar> 
+PASS Parsing: <:a> against <http://example.org/foo/bar> 
+PASS Parsing: <:/> against <http://example.org/foo/bar> 
+PASS Parsing: <:\> against <http://example.org/foo/bar> 
+PASS Parsing: <:#> against <http://example.org/foo/bar> 
+PASS Parsing: <#> against <http://example.org/foo/bar> 
+PASS Parsing: <#/> against <http://example.org/foo/bar> 
+PASS Parsing: <#\> against <http://example.org/foo/bar> 
+PASS Parsing: <#;?> against <http://example.org/foo/bar> 
+PASS Parsing: <?> against <http://example.org/foo/bar> 
+PASS Parsing: </> against <http://example.org/foo/bar> 
+PASS Parsing: <:23> against <http://example.org/foo/bar> 
+PASS Parsing: </:23> against <http://example.org/foo/bar> 
+PASS Parsing: <::> against <http://example.org/foo/bar> 
+PASS Parsing: <::23> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo://> against <http://example.org/foo/bar> assert_equals: href expected "foo:///" but got "foo://"
+PASS Parsing: <http://a:b@c:29/d> against <http://example.org/foo/bar> 
+PASS Parsing: <http::@c:29> against <http://example.org/foo/bar> 
+FAIL Parsing: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> Type error
+FAIL Parsing: <http://::@c@d:2> against <http://example.org/foo/bar> Type error
+PASS Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo.com/\@> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\foo.com\> against <http://example.org/foo/bar> 
+PASS Parsing: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> 
+FAIL Parsing: <foo:/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:/bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <foo:////://///> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "foo://"
+FAIL Parsing: <c:/foo> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "c://"
+PASS Parsing: <//foo/bar> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> 
+PASS Parsing: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> 
+PASS Parsing: <[61:24:74]:98> against <http://example.org/foo/bar> 
+PASS Parsing: <http:[61:27]/:foo> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[1::2]:3:4> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://2001::1]:80> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar> 
+PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar> 
+FAIL Parsing: <http:/example.com/> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/example.com/" but got "http://example.com/"
+PASS Parsing: <ftp:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <ftps:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:/example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:/example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ftp:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <https:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <madeupscheme:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <ws:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <wss:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <data:example.com/> against <http://example.org/foo/bar> 
+PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar> 
+FAIL Parsing: <mailto:example.com/> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: </a/b/c> against <http://example.org/foo/bar> 
+PASS Parsing: </a/ /c> against <http://example.org/foo/bar> 
+PASS Parsing: </a%2fc> against <http://example.org/foo/bar> 
+PASS Parsing: </a/%2f/c> against <http://example.org/foo/bar> 
+FAIL Parsing: <#β> against <http://example.org/foo/bar> assert_equals: href expected "http://example.org/foo/bar#β" but got "http://example.org/foo/bar#%CE%B2"
+PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar> 
+FAIL Parsing: <tel:1234567890> against <http://example.org/foo/bar> assert_equals: origin expected "null" but got "tel://"
+FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html"
+FAIL Parsing: <  File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c|////foo/bar.html"
+FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C|/foo/bar"
+FAIL Parsing: </C|\foo\bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///C|/foo/bar"
+FAIL Parsing: <//C|/foo/bar> against <file:///tmp/mock/path> Type error
+PASS Parsing: <//server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <\\server\file> against <file:///tmp/mock/path> 
+PASS Parsing: </\server/file> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///foo/bar.txt> against <file:///tmp/mock/path> 
+PASS Parsing: <file:///home/me> against <file:///tmp/mock/path> 
+PASS Parsing: <//> against <file:///tmp/mock/path> 
+PASS Parsing: <///> against <file:///tmp/mock/path> 
+PASS Parsing: <///test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://test> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/> against <file:///tmp/mock/path> 
+PASS Parsing: <file://localhost/test> against <file:///tmp/mock/path> 
+PASS Parsing: <test> against <file:///tmp/mock/path> 
+PASS Parsing: <file:test> against <file:///tmp/mock/path> 
+PASS Parsing: <http://example.com/././foo> against <about:blank> 
+PASS Parsing: <http://example.com/./.foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo/.> against <about:blank> 
+PASS Parsing: <http://example.com/foo/./> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../> against <about:blank> 
+PASS Parsing: <http://example.com/foo/..bar> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> 
+FAIL Parsing: <http://example.com/foo/%2e> against <about:blank> assert_equals: href expected "http://example.com/foo/" but got "http://example.com/foo/%2e"
+FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/.%2" but got "http://example.com/foo/%2e%2"
+FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/..bar" but got "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar"
+PASS Parsing: <http://example.com////../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> 
+PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> 
+PASS Parsing: <http://example.com/foo> against <about:blank> 
+PASS Parsing: <http://example.com/%20foo> against <about:blank> 
+PASS Parsing: <http://example.com/foo%> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank> 
+PASS Parsing: <http://example.com/foo%41%7a> against <about:blank> 
+PASS Parsing: <http://example.com/foo  \91%91> against <about:blank> 
+PASS Parsing: <http://example.com/foo%00%51> against <about:blank> 
+PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank> 
+PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank> 
+PASS Parsing: <http://example.com/foo  bar> against <about:blank> 
+PASS Parsing: <http://example.com\\foo\\bar> against <about:blank> 
+PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> 
+PASS Parsing: <http://example.com/@asdf%40> against <about:blank> 
+PASS Parsing: <http://example.com/你好你好> against <about:blank> 
+PASS Parsing: <http://example.com/‥/foo> against <about:blank> 
+PASS Parsing: <http://example.com//foo> against <about:blank> 
+PASS Parsing: <http://example.com/‮/foo/‭/bar> against <about:blank> 
+PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank> 
+FAIL Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank> assert_equals: href expected "http://www.google.com/foo?bar=baz# »" but got "http://www.google.com/foo?bar=baz# %C2%BB"
+FAIL Parsing: <data:test# »> against <about:blank> assert_equals: href expected "data:test# »" but got "data:test# %C2%BB"
+PASS Parsing: <http://[www.google.com]/> against <about:blank> 
+PASS Parsing: <http://www.google.com> against <about:blank> 
+FAIL Parsing: <http://192.0x00A80001> against <about:blank> assert_equals: href expected "http://192.168.0.1/" but got "http://192.0x00a80001/"
+FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo.html" but got "http://www/foo%2Ehtml"
+FAIL Parsing: <http://www/foo/%2E/html> against <about:blank> assert_equals: href expected "http://www/foo/html" but got "http://www/foo/%2E/html"
+PASS Parsing: <http://user:pass@/> against <about:blank> 
+PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> 
+PASS Parsing: <http:\\www.google.com\foo> against <about:blank> 
+PASS Parsing: <http://foo:80/> against <about:blank> 
+PASS Parsing: <http://foo:81/> against <about:blank> 
+FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: origin expected "null" but got "httpa://foo:80"
+PASS Parsing: <http://foo:-80/> against <about:blank> 
+PASS Parsing: <https://foo:443/> against <about:blank> 
+PASS Parsing: <https://foo:80/> against <about:blank> 
+PASS Parsing: <ftp://foo:21/> against <about:blank> 
+PASS Parsing: <ftp://foo:80/> against <about:blank> 
+PASS Parsing: <gopher://foo:70/> against <about:blank> 
+PASS Parsing: <gopher://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:80/> against <about:blank> 
+PASS Parsing: <ws://foo:81/> against <about:blank> 
+PASS Parsing: <ws://foo:443/> against <about:blank> 
+PASS Parsing: <ws://foo:815/> against <about:blank> 
+PASS Parsing: <wss://foo:80/> against <about:blank> 
+PASS Parsing: <wss://foo:81/> against <about:blank> 
+PASS Parsing: <wss://foo:443/> against <about:blank> 
+PASS Parsing: <wss://foo:815/> against <about:blank> 
+PASS Parsing: <http:/example.com/> against <about:blank> 
+PASS Parsing: <ftp:/example.com/> against <about:blank> 
+PASS Parsing: <https:/example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+PASS Parsing: <file:/example.com/> against <about:blank> 
+FAIL Parsing: <ftps:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:/example.com/> against <about:blank> 
+PASS Parsing: <ws:/example.com/> against <about:blank> 
+PASS Parsing: <wss:/example.com/> against <about:blank> 
+PASS Parsing: <data:/example.com/> against <about:blank> 
+PASS Parsing: <javascript:/example.com/> against <about:blank> 
+FAIL Parsing: <mailto:/example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:example.com/> against <about:blank> 
+PASS Parsing: <ftp:example.com/> against <about:blank> 
+PASS Parsing: <https:example.com/> against <about:blank> 
+FAIL Parsing: <madeupscheme:example.com/> against <about:blank> assert_equals: origin expected "null" but got "madeupscheme://"
+FAIL Parsing: <ftps:example.com/> against <about:blank> assert_equals: origin expected "null" but got "ftps://"
+PASS Parsing: <gopher:example.com/> against <about:blank> 
+PASS Parsing: <ws:example.com/> against <about:blank> 
+PASS Parsing: <wss:example.com/> against <about:blank> 
+PASS Parsing: <data:example.com/> against <about:blank> 
+PASS Parsing: <javascript:example.com/> against <about:blank> 
+FAIL Parsing: <mailto:example.com/> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <http:@www.example.com> against <about:blank> 
+PASS Parsing: <http:/@www.example.com> against <about:blank> 
+PASS Parsing: <http://@www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://@pple.com> against <about:blank> 
+PASS Parsing: <http::b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:b@www.example.com> against <about:blank> 
+PASS Parsing: <http://:b@www.example.com> against <about:blank> 
+PASS Parsing: <http:/:@/www.example.com> against <about:blank> 
+PASS Parsing: <http://user@/www.example.com> against <about:blank> 
+PASS Parsing: <http:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/@/www.example.com> against <about:blank> 
+PASS Parsing: <http://@/www.example.com> against <about:blank> 
+PASS Parsing: <https:@/www.example.com> against <about:blank> 
+PASS Parsing: <http:a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http:/a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http://a:b@/www.example.com> against <about:blank> 
+PASS Parsing: <http::@/www.example.com> against <about:blank> 
+FAIL Parsing: <http:a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http:/a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+FAIL Parsing: <http://a:@www.example.com> against <about:blank> assert_equals: href expected "http://a:@www.example.com/" but got "http://a@www.example.com/"
+PASS Parsing: <http://www.@pple.com> against <about:blank> 
+PASS Parsing: <http:@:www.example.com> against <about:blank> 
+PASS Parsing: <http:/@:www.example.com> against <about:blank> 
+PASS Parsing: <http://@:www.example.com> against <about:blank> 
+FAIL Parsing: <http://:@www.example.com> against <about:blank> assert_equals: href expected "http://:@www.example.com/" but got "http://www.example.com/"
+PASS Parsing: </> against <http://www.example.com/test> 
+PASS Parsing: </test.txt> against <http://www.example.com/test> 
+PASS Parsing: <.> against <http://www.example.com/test> 
+PASS Parsing: <..> against <http://www.example.com/test> 
+PASS Parsing: <test.txt> against <http://www.example.com/test> 
+PASS Parsing: <./test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../aaa/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <../../test.txt> against <http://www.example.com/test> 
+PASS Parsing: <中/test.txt> against <http://www.example.com/test> 
+PASS Parsing: <http://www.example2.com> against <http://www.example.com/test> 
+PASS Parsing: <//www.example2.com> against <http://www.example.com/test> 
+FAIL Parsing: <file:...> against <http://www.example.com/test> assert_equals: href expected "file:///..." but got "file://..."
+FAIL Parsing: <file:..> against <http://www.example.com/test> assert_equals: href expected "file:///" but got "file://.."
+FAIL Parsing: <file:a> against <http://www.example.com/test> assert_equals: href expected "file:///a" but got "file://a"
+PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/> 
+PASS Parsing: <http://example example.com> against <http://other.com/> 
+PASS Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> 
+FAIL Parsing: <http://[]> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://[:]> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+PASS Parsing: <http://GOO  goo.com> against <http://other.com/> 
+PASS Parsing: <http://GOO​⁠goo.com> against <http://other.com/> 
+PASS Parsing: <http://www.foo。bar.com> against <http://other.com/> 
+PASS Parsing: <http://﷐zyx.com> against <http://other.com/> 
+FAIL Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+PASS Parsing: <http://Go.com> against <http://other.com/> 
+FAIL Parsing: <http://%41.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%00.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://你好你好> against <http://other.com/> assert_equals: origin expected "http://你好你好" but got "http://xn--6qqa088eba"
+FAIL Parsing: <http://%zz%66%a.com> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%25> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://hello%00> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01/"
+FAIL Parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://%30%78%63%30%2e%30%32%35%30.01%2e/"
+FAIL Parsing: <http://192.168.0.257> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+PASS Parsing: <http://192.168.0.1 hello> against <http://other.com/> 
+FAIL Parsing: <http://0Xc0.0250.01> against <http://other.com/> assert_equals: href expected "http://192.168.0.1/" but got "http://0xc0.0250.01/"
+PASS Parsing: <http://[google.com]> against <http://other.com/> 
+FAIL Parsing: <http://foo:💩@example.com/bar> against <http://other.com/> Type error
+FAIL Parsing: <#> against <test:test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <#x> against <mailto:x@x.com> assert_equals: origin expected "null" but got "mailto://"
+PASS Parsing: <#x> against <data:,> 
+PASS Parsing: <#x> against <about:blank> 
+FAIL Parsing: <#> against <test:test?test> assert_equals: origin expected "null" but got "test://"
+FAIL Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/> Type error
+FAIL Parsing: <https://@@@example> against <http://doesnotmatter/> Type error
+FAIL Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> Type error
+PASS Parsing: </some/path> against <http://user@example.org/smth> 
+PASS Parsing: <> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth> 
+PASS Parsing: <i> against <sc:sd> 
+PASS Parsing: <i> against <sc:sd/sd> 
+FAIL Parsing: <i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <../i> against <sc:sd> 
+PASS Parsing: <../i> against <sc:sd/sd> 
+FAIL Parsing: <../i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <../i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <../i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: </i> against <sc:sd> 
+PASS Parsing: </i> against <sc:sd/sd> 
+FAIL Parsing: </i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: </i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: </i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:/i"
+PASS Parsing: <?i> against <sc:sd> 
+PASS Parsing: <?i> against <sc:sd/sd> 
+FAIL Parsing: <?i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <?i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <?i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:sd/sd> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc:/pa/pa> assert_equals: origin expected "null" but got "sc://"
+FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: origin expected "null" but got "sc://ho"
+FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <about:/../> against <about:blank> 
+PASS Parsing: <data:/../> against <about:blank> 
+PASS Parsing: <javascript:/../> against <about:blank> 
+FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: origin expected "null" but got "mailto://"
+FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: origin expected "null" but got "sc://xn--ida.test"
+FAIL Parsing: <sc:\../> against <about:blank> assert_equals: href expected "sc:\\../" but got "sc:/"
+FAIL Parsing: <sc::a@example.net> against <about:blank> assert_equals: origin expected "null" but got "sc://"
+PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank> 
+PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> 
+PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> 
+PASS Parsing: <h       t
+t
+p://h  o
+s
+t:9    0
+0
+0/p    a
+t
+h?q    u
+e
+ry#f   r
+a
+g> against <about:blank> 
+FAIL Parsing: <?a=b&c=d> against <http://example.org/foo/bar> assert_true: expected true got false
+FAIL Parsing: <??a=b&c=d> against <http://example.org/foo/bar> assert_true: expected true got false
+FAIL Parsing: <http:> against <http://example.org/foo/bar> assert_true: expected true got false
+FAIL Parsing: <http:> against <https://example.org/foo/bar> assert_throws: function "function () {
+          bURL(expected.input, expected.bas..." did not throw
+FAIL Parsing: <sc:> against <https://example.org/foo/bar> assert_equals: origin expected "null" but got "sc://"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-constructor.html b/LayoutTests/imported/w3c/web-platform-tests/url/url-constructor.html
new file mode 100644 (file)
index 0000000..8eacce6
--- /dev/null
@@ -0,0 +1,129 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+function runURLConstructorTests() {
+  var setup = async_test("Loading data…")
+  setup.step(function() {
+    var request = new XMLHttpRequest()
+    request.open("GET", "urltestdata.json")
+    request.send()
+    request.responseType = "json"
+    request.onload = setup.step_func(function() {
+      runURLTests(request.response)
+      setup.done()
+    })
+  })
+}
+
+function bURL(url, base) {
+  return new URL(url, base || "about:blank")
+}
+
+function runURLTests(urltests) {
+  for(var i = 0, l = urltests.length; i < l; i++) {
+    var expected = urltests[i]
+    if (typeof expected === "string") continue // skip comments
+
+    test(function() {
+      if (expected.failure) {
+        assert_throws(new TypeError(), function() {
+          bURL(expected.input, expected.base)
+        })
+        return
+      }
+
+      var url = bURL(expected.input, expected.base)
+      assert_equals(url.href, expected.href, "href")
+      if ("origin" in expected) {
+        assert_equals(url.origin, expected.origin, "origin")
+      }
+      assert_equals(url.protocol, expected.protocol, "protocol")
+      assert_equals(url.username, expected.username, "username")
+      assert_equals(url.password, expected.password, "password")
+      assert_equals(url.host, expected.host, "host")
+      assert_equals(url.hostname, expected.hostname, "hostname")
+      assert_equals(url.port, expected.port, "port")
+      assert_equals(url.pathname, expected.pathname, "pathname")
+      assert_equals(url.search, expected.search, "search")
+      if ("searchParams" in expected) {
+        assert_true("searchParams" in url)
+        assert_equals(url.searchParams.toString(), expected.searchParams, "searchParams")
+      }
+      assert_equals(url.hash, expected.hash, "hash")
+    }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+  }
+}
+
+function runURLSearchParamTests() {
+  test(function() {
+    var url = bURL('http://example.org/?a=b')
+    assert_true("searchParams" in url)
+    var searchParams = url.searchParams
+    assert_true(url.searchParams === searchParams, 'Object identity should hold.')
+  }, 'URL.searchParams getter')
+
+  test(function() {
+    var url = bURL('http://example.org/?a=b')
+    assert_true("searchParams" in url)
+    var searchParams = url.searchParams
+    assert_equals(searchParams.toString(), 'a=b')
+
+    searchParams.set('a', 'b')
+    assert_equals(url.searchParams.toString(), 'a=b')
+    assert_equals(url.search, '?a=b')
+    url.search = ''
+    assert_equals(url.searchParams.toString(), '')
+    assert_equals(url.search, '')
+    assert_equals(searchParams.toString(), '')
+  }, 'URL.searchParams updating, clearing')
+
+  test(function() {
+    'use strict'
+    var urlString = 'http://example.org'
+    var url = bURL(urlString)
+    assert_throws(TypeError(), function() { url.searchParams = new URLSearchParams(urlString) })
+  }, 'URL.searchParams setter, invalid values')
+
+  test(function() {
+    var url = bURL('http://example.org/file?a=b&c=d')
+    assert_true("searchParams" in url)
+    var searchParams = url.searchParams
+    assert_equals(url.search, '?a=b&c=d')
+    assert_equals(searchParams.toString(), 'a=b&c=d')
+
+    // Test that setting 'search' propagates to the URL object's query object.
+    url.search = 'e=f&g=h'
+    assert_equals(url.search, '?e=f&g=h')
+    assert_equals(searchParams.toString(), 'e=f&g=h')
+
+    // ..and same but with a leading '?'.
+    url.search = '?e=f&g=h'
+    assert_equals(url.search, '?e=f&g=h')
+    assert_equals(searchParams.toString(), 'e=f&g=h')
+
+    // And in the other direction, altering searchParams propagates
+    // back to 'search'.
+    searchParams.append('i', ' j ')
+    assert_equals(url.search, '?e=f&g=h&i=+j+')
+    assert_equals(url.searchParams.toString(), 'e=f&g=h&i=+j+')
+    assert_equals(searchParams.get('i'), ' j ')
+
+    searchParams.set('e', 'updated')
+    assert_equals(url.search, '?e=updated&g=h&i=+j+')
+    assert_equals(searchParams.get('e'), 'updated')
+
+    var url2 = bURL('http://example.org/file??a=b&c=d')
+    assert_equals(url2.search, '??a=b&c=d')
+    assert_equals(url2.searchParams.toString(), '%3Fa=b&c=d')
+
+    url2.href = 'http://example.org/file??a=b'
+    assert_equals(url2.search, '??a=b')
+    assert_equals(url2.searchParams.toString(), '%3Fa=b')
+  }, 'URL.searchParams and URL.search setters, update propagation')
+}
+runURLSearchParamTests()
+runURLConstructorTests()
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode-expected.txt
new file mode 100644 (file)
index 0000000..ad549a9
--- /dev/null
@@ -0,0 +1,5 @@
+
+FAIL URL.domainToUnicode valid input URL.domainToUnicode is not a function. (In 'URL.domainToUnicode(domain)', 'URL.domainToUnicode' is undefined)
+FAIL URL.domainToUnicode valid encoded input URL.domainToUnicode is not a function. (In 'URL.domainToUnicode(domain)', 'URL.domainToUnicode' is undefined)
+FAIL URL.domainToUnicode invalid input URL.domainToUnicode is not a function. (In 'URL.domainToUnicode(domain)', 'URL.domainToUnicode' is undefined)
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode.html b/LayoutTests/imported/w3c/web-platform-tests/url/url-domainToUnicode.html
new file mode 100644 (file)
index 0000000..1bd5536
--- /dev/null
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset="utf-8">
+<title></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  test(function() {
+    var domain = 'example.org'
+    assert_true(URL.domainToUnicode(domain) === domain, 'Ascii domain should be parsed correctly.')
+  }, 'URL.domainToUnicode valid input')
+
+  test(function() {
+    var domain = 'xn--maana-pta.com'
+    assert_true(URL.domainToUnicode(domain) === 'mañana.com', ' Ascii encoded domain should be parsed correctly.')
+  }, 'URL.domainToUnicode valid encoded input')
+
+  test(function() {
+    var domain = 'http://not.a.domain'
+    assert_true(URL.domainToUnicode(domain) === "", 'Invalid domain should be return an empty string.')
+  }, 'URL.domainToUnicode invalid input')
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-setters-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/url-setters-expected.txt
new file mode 100644 (file)
index 0000000..545a017
--- /dev/null
@@ -0,0 +1,24 @@
+
+PASS Loading data… 
+FAIL Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <a://example.net>.protocol = 'b' assert_equals: expected "b://example.net/" but got "b://example.net"
+FAIL Setting <a://example.net>.protocol = 'B' Upper-case ASCII is lower-cased assert_equals: expected "b://example.net/" but got "b://example.net"
+FAIL Setting <a://example.net>.protocol = 'é' Non-ASCII is rejected assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <a://example.net>.protocol = '0b' No leading digit assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <a://example.net>.protocol = '+b' No leading punctuation assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <a://example.net>.protocol = 'bC0+-.' assert_equals: expected "bc0+-.://example.net/" but got "bc0+-.://example.net"
+FAIL Setting <a://example.net>.protocol = 'b,c' Only some punctuation is acceptable assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <a://example.net>.protocol = 'bé' Non-ASCII is rejected assert_equals: expected "a://example.net/" but got "a://example.net"
+FAIL Setting <http://example.net>.protocol = 'b' Can’t switch from special scheme to non-special. Note: this may change, see https://github.com/whatwg/url/issues/104 assert_equals: expected "http://example.net/" but got "b://example.net/"
+FAIL Setting <mailto:me@example.net>.protocol = 'http' Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must. assert_equals: expected "mailto:me@example.net" but got "http://me@example.net/"
+FAIL Setting <ssh://me@example.net>.protocol = 'http' Can’t switch from non-special scheme to special. Note: this may change, see https://github.com/whatwg/url/issues/104 assert_equals: expected "ssh://me@example.net/" but got "http://me@example.net/"
+PASS Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored 
+PASS Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored 
+FAIL Setting <file:///home/you/index.html>.username = 'me' No host means no username assert_equals: expected "file:///home/you/index.html" but got "file://me@/home/you/index.html"
+FAIL Setting <unix:/run/foo.socket>.username = 'me' No host means no username assert_equals: expected "unix:/run/foo.socket" but got "unix://me@/run/foo.socket"
+FAIL Setting <mailto:you@example.net>.username = 'me' Cannot-be-a-base means no username assert_equals: expected "mailto:you@example.net" but got "mailto://me@you@example.net"
+PASS Setting <http://example.net>.username = 'me' 
+PASS Setting <http://:secret@example.net>.username = 'me' 
+PASS Setting <http://me@example.net>.username = '' 
+PASS Setting <http://me:secret@example.net>.username = '' 
+FAIL Setting <http://example.net>.username = '
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/url-setters.html b/LayoutTests/imported/w3c/web-platform-tests/url/url-setters.html
new file mode 100644 (file)
index 0000000..32f52ee
--- /dev/null
@@ -0,0 +1,46 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+function startURLSettersTests() {
+  var setup = async_test("Loading data…")
+  setup.step(function() {
+    var request = new XMLHttpRequest()
+    request.open("GET", "setters_tests.json")
+    request.send()
+    request.responseType = "json"
+    request.onload = setup.step_func(function() {
+      runURLSettersTests(request.response)
+      setup.done()
+    })
+  })
+}
+
+function runURLSettersTests(all_test_cases) {
+  for (var attribute_to_be_set in all_test_cases) {
+    if (attribute_to_be_set == "comment") {
+      continue;
+    }
+    var test_cases = all_test_cases[attribute_to_be_set];
+    for(var i = 0, l = test_cases.length; i < l; i++) {
+      var test_case = test_cases[i];
+      var name = "Setting <" + test_case.href + ">." + attribute_to_be_set +
+                 " = '" + test_case.new_value + "'";
+      if ("comment" in test_case) {
+        name += " " + test_case.comment;
+      }
+      test(function() {
+        var url = new URL(test_case.href);
+        url[attribute_to_be_set] = test_case.new_value;
+        for (var attribute in test_case.expected) {
+          assert_equals(url[attribute], test_case.expected[attribute])
+        }
+      }, name)
+    }
+  }
+}
+
+startURLSettersTests()
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append-expected.txt
new file mode 100644 (file)
index 0000000..7a1814e
--- /dev/null
@@ -0,0 +1,6 @@
+
+FAIL Append same name Can't find variable: URLSearchParams
+FAIL Append empty strings Can't find variable: URLSearchParams
+FAIL Append null Can't find variable: URLSearchParams
+FAIL Append multiple Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-append.html
new file mode 100644 (file)
index 0000000..78a8986
--- /dev/null
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-append">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b');
+    assert_equals(params + '', 'a=b');
+    params.append('a', 'b');
+    assert_equals(params + '', 'a=b&a=b');
+    params.append('a', 'c');
+    assert_equals(params + '', 'a=b&a=b&a=c');
+}, 'Append same name');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('', '');
+    assert_equals(params + '', '=');
+    params.append('', '');
+    assert_equals(params + '', '=&=');
+}, 'Append empty strings');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append(null, null);
+    assert_equals(params + '', 'null=null');
+    params.append(null, null);
+    assert_equals(params + '', 'null=null&null=null');
+}, 'Append null');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('first', 1);
+    params.append('second', 2);
+    params.append('third', '');
+    params.append('first', 10);
+    assert_true(params.has('first'), 'Search params object has name "first"');
+    assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"');
+    assert_equals(params.get('second'), '2', 'Search params object has name "second" with value "2"');
+    assert_equals(params.get('third'), '', 'Search params object has name "third" with value ""');
+    params.append('first', 10);
+    assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"');
+}, 'Append multiple');
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor-expected.txt
new file mode 100644 (file)
index 0000000..71d9ef0
--- /dev/null
@@ -0,0 +1,15 @@
+
+FAIL Basic URLSearchParams construction Can't find variable: URLSearchParams
+FAIL URLSearchParams constructor, empty. assert_throws: Calling 'URLSearchParams' without 'new' should throw. function "function () { URLSearchParams(); }" threw object "ReferenceError: Can't find variable: URLSearchParams" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL URLSearchParams constructor, string. Can't find variable: URLSearchParams
+FAIL URLSearchParams constructor, object. Can't find variable: URLSearchParams
+FAIL Parse + Can't find variable: URLSearchParams
+FAIL Parse space Can't find variable: URLSearchParams
+FAIL Parse %20 Can't find variable: URLSearchParams
+FAIL Parse \0 Can't find variable: URLSearchParams
+FAIL Parse %00 Can't find variable: URLSearchParams
+FAIL Parse ⎄ Can't find variable: URLSearchParams
+FAIL Parse %e2%8e%84 Can't find variable: URLSearchParams
+FAIL Parse 💩 Can't find variable: URLSearchParams
+FAIL Parse %f0%9f%92%a9 Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-constructor.html
new file mode 100644 (file)
index 0000000..4e4d5da
--- /dev/null
@@ -0,0 +1,129 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#urlsearchparams">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams();
+    assert_equals(params + '', '');
+    params = new URLSearchParams('');
+    assert_equals(params + '', '');
+    params = new URLSearchParams('a=b');
+    assert_equals(params + '', 'a=b');
+    params = new URLSearchParams(params);
+    assert_equals(params + '', 'a=b');
+}, 'Basic URLSearchParams construction');
+
+test(function() {
+    assert_throws(new TypeError(), function () { URLSearchParams(); },
+                  'Calling \'URLSearchParams\' without \'new\' should throw.');
+    assert_throws(new TypeError(), function () { new URLSearchParams(DOMException.prototype); });
+    var params = new URLSearchParams('');
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_equals(params.__proto__, URLSearchParams.prototype, 'expected URLSearchParams.prototype as prototype.');
+    params = new URLSearchParams({});
+    assert_equals(params + '', '%5Bobject+Object%5D=');
+}, 'URLSearchParams constructor, empty.');
+
+test(function() {
+    var params = new URLSearchParams('a=b');
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_false(params.has('b'), 'Search params object has not got name "b"');
+    var params = new URLSearchParams('a=b&c');
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_true(params.has('c'), 'Search params object has name "c"');
+    var params = new URLSearchParams('&a&&& &&&&&a+b=& c&m%c3%b8%c3%b8');
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_true(params.has('a b'), 'Search params object has name "a b"');
+    assert_true(params.has(' '), 'Search params object has name " "');
+    assert_false(params.has('c'), 'Search params object did not have the name "c"');
+    assert_true(params.has(' c'), 'Search params object has name " c"');
+    assert_true(params.has('møø'), 'Search params object has name "møø"');
+}, 'URLSearchParams constructor, string.');
+
+test(function() {
+    var seed = new URLSearchParams('a=b&c=d');
+    var params = new URLSearchParams(seed);
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_equals(params.get('a'), 'b');
+    assert_equals(params.get('c'), 'd');
+    assert_false(params.has('d'));
+    // The name-value pairs are copied when created; later updates
+    // should not be observable.
+    seed.append('e', 'f');
+    assert_false(params.has('e'));
+    params.append('g', 'h');
+    assert_false(seed.has('g'));
+}, 'URLSearchParams constructor, object.');
+
+test(function() {
+    var params = new URLSearchParams('a=b+c');
+    assert_equals(params.get('a'), 'b c');
+    params = new URLSearchParams('a+b=c');
+    assert_equals(params.get('a b'), 'c');
+}, 'Parse +');
+
+test(function() {
+    var params = new URLSearchParams('a=b c');
+    assert_equals(params.get('a'), 'b c');
+    params = new URLSearchParams('a b=c');
+    assert_equals(params.get('a b'), 'c');
+}, 'Parse space');
+
+test(function() {
+    var params = new URLSearchParams('a=b%20c');
+    assert_equals(params.get('a'), 'b c');
+    params = new URLSearchParams('a%20b=c');
+    assert_equals(params.get('a b'), 'c');
+}, 'Parse %20');
+
+test(function() {
+    var params = new URLSearchParams('a=b\0c');
+    assert_equals(params.get('a'), 'b\0c');
+    params = new URLSearchParams('a\0b=c');
+    assert_equals(params.get('a\0b'), 'c');
+}, 'Parse \\0');
+
+test(function() {
+    var params = new URLSearchParams('a=b%00c');
+    assert_equals(params.get('a'), 'b\0c');
+    params = new URLSearchParams('a%00b=c');
+    assert_equals(params.get('a\0b'), 'c');
+}, 'Parse %00');
+
+test(function() {
+    var params = new URLSearchParams('a=b\u2384');
+    assert_equals(params.get('a'), 'b\u2384');
+    params = new URLSearchParams('a\u2384b=c');
+    assert_equals(params.get('a\u2384b'), 'c');
+}, 'Parse \u2384');  // Unicode Character 'COMPOSITION SYMBOL' (U+2384)
+
+test(function() {
+    var params = new URLSearchParams('a=b%e2%8e%84');
+    assert_equals(params.get('a'), 'b\u2384');
+    params = new URLSearchParams('a%e2%8e%84b=c');
+    assert_equals(params.get('a\u2384b'), 'c');
+}, 'Parse %e2%8e%84');  // Unicode Character 'COMPOSITION SYMBOL' (U+2384)
+
+test(function() {
+    var params = new URLSearchParams('a=b\uD83D\uDCA9c');
+    assert_equals(params.get('a'), 'b\uD83D\uDCA9c');
+    params = new URLSearchParams('a\uD83D\uDCA9b=c');
+    assert_equals(params.get('a\uD83D\uDCA9b'), 'c');
+}, 'Parse \uD83D\uDCA9');  // Unicode Character 'PILE OF POO' (U+1F4A9)
+
+test(function() {
+    var params = new URLSearchParams('a=b%f0%9f%92%a9c');
+    assert_equals(params.get('a'), 'b\uD83D\uDCA9c');
+    params = new URLSearchParams('a%f0%9f%92%a9b=c');
+    assert_equals(params.get('a\uD83D\uDCA9b'), 'c');
+}, 'Parse %f0%9f%92%a9');  // Unicode Character 'PILE OF POO' (U+1F4A9)
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete-expected.txt
new file mode 100644 (file)
index 0000000..3ae250e
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL Delete basics Can't find variable: URLSearchParams
+FAIL Deleting appended multiple Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-delete.html
new file mode 100644 (file)
index 0000000..f44de89
--- /dev/null
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-delete">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams('a=b&c=d');
+    params.delete('a');
+    assert_equals(params + '', 'c=d');
+    params = new URLSearchParams('a=a&b=b&a=a&c=c');
+    params.delete('a');
+    assert_equals(params + '', 'b=b&c=c');
+    params = new URLSearchParams('a=a&=&b=b&c=c');
+    params.delete('');
+    assert_equals(params + '', 'a=a&b=b&c=c');
+    params = new URLSearchParams('a=a&null=null&b=b');
+    params.delete(null);
+    assert_equals(params + '', 'a=a&b=b');
+    params = new URLSearchParams('a=a&undefined=undefined&b=b');
+    params.delete(undefined);
+    assert_equals(params + '', 'a=a&b=b');
+}, 'Delete basics');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('first', 1);
+    assert_true(params.has('first'), 'Search params object has name "first"');
+    assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"');
+    params.delete('first');
+    assert_false(params.has('first'), 'Search params object has no "first" name');
+    params.append('first', 1);
+    params.append('first', 10);
+    params.delete('first');
+    assert_false(params.has('first'), 'Search params object has no "first" name');
+}, 'Deleting appended multiple');
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get-expected.txt
new file mode 100644 (file)
index 0000000..a944a5a
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL Get basics Can't find variable: URLSearchParams
+FAIL More get() basics Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-get.html
new file mode 100644 (file)
index 0000000..ff87825
--- /dev/null
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-get">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams('a=b&c=d');
+    assert_equals(params.get('a'), 'b');
+    assert_equals(params.get('c'), 'd');
+    assert_equals(params.get('e'), null);
+    params = new URLSearchParams('a=b&c=d&a=e');
+    assert_equals(params.get('a'), 'b');
+    params = new URLSearchParams('=b&c=d');
+    assert_equals(params.get(''), 'b');
+    params = new URLSearchParams('a=&c=d&a=e');
+    assert_equals(params.get('a'), '');
+}, 'Get basics');
+
+test(function() {
+    var params = new URLSearchParams('first=second&third&&');
+    assert_true(params != null, 'constructor returned non-null value.');
+    assert_true(params.has('first'), 'Search params object has name "first"');
+    assert_equals(params.get('first'), 'second', 'Search params object has name "first" with value "second"');
+    assert_equals(params.get('third'), '', 'Search params object has name "third" with the empty value.');
+    assert_equals(params.get('fourth'), null, 'Search params object has no "fourth" name and value.');
+}, 'More get() basics');
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall-expected.txt
new file mode 100644 (file)
index 0000000..9856e17
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL getAll() basics Can't find variable: URLSearchParams
+FAIL getAll() multiples Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-getall.html
new file mode 100644 (file)
index 0000000..4285fa2
--- /dev/null
@@ -0,0 +1,37 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-getAll">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams('a=b&c=d');
+    assert_array_equals(params.getAll('a'), ['b']);
+    assert_array_equals(params.getAll('c'), ['d']);
+    assert_array_equals(params.getAll('e'), []);
+    params = new URLSearchParams('a=b&c=d&a=e');
+    assert_array_equals(params.getAll('a'), ['b', 'e']);
+    params = new URLSearchParams('=b&c=d');
+    assert_array_equals(params.getAll(''), ['b']);
+    params = new URLSearchParams('a=&c=d&a=e');
+    assert_array_equals(params.getAll('a'), ['', 'e']);
+}, 'getAll() basics');
+
+test(function() {
+    var params = new URLSearchParams('a=1&a=2&a=3&a');
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    var matches = params.getAll('a');
+    assert_true(matches && matches.length == 4, 'Search params object has values for name "a"');
+    assert_array_equals(matches, ['1', '2', '3', ''], 'Search params object has expected name "a" values');
+    params.set('a', 'one');
+    assert_equals(params.get('a'), 'one', 'Search params object has name "a" with value "one"');
+    var matches = params.getAll('a');
+    assert_true(matches && matches.length == 1, 'Search params object has values for name "a"');
+    assert_array_equals(matches, ['one'], 'Search params object has expected name "a" values');
+}, 'getAll() multiples');
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has-expected.txt
new file mode 100644 (file)
index 0000000..340709c
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL Has basics Can't find variable: URLSearchParams
+FAIL has() following delete() Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-has.html
new file mode 100644 (file)
index 0000000..1e583c6
--- /dev/null
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-has">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams('a=b&c=d');
+    assert_true(params.has('a'));
+    assert_true(params.has('c'));
+    assert_false(params.has('e'));
+    params = new URLSearchParams('a=b&c=d&a=e');
+    assert_true(params.has('a'));
+    params = new URLSearchParams('=b&c=d');
+    assert_true(params.has(''));
+    params = new URLSearchParams('null=a');
+    assert_true(params.has(null));
+}, 'Has basics');
+
+test(function() {
+    var params = new URLSearchParams('a=b&c=d&&');
+    params.append('first', 1);
+    params.append('first', 2);
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_true(params.has('c'), 'Search params object has name "c"');
+    assert_true(params.has('first'), 'Search params object has name "first"');
+    assert_false(params.has('d'), 'Search params object has no name "d"');
+    params.delete('first');
+    assert_false(params.has('first'), 'Search params object has no name "first"');
+}, 'has() following delete()');
+</script>
+</head>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set-expected.txt
new file mode 100644 (file)
index 0000000..a1ee62f
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL Set basics Can't find variable: URLSearchParams
+FAIL URLSearchParams.set Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-set.html
new file mode 100644 (file)
index 0000000..db0e7a6
--- /dev/null
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-set">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams('a=b&c=d');
+    params.set('a', 'B');
+    assert_equals(params + '', 'a=B&c=d');
+    params = new URLSearchParams('a=b&c=d&a=e');
+    params.set('a', 'B');
+    assert_equals(params + '', 'a=B&c=d')
+    params.set('e', 'f');
+    assert_equals(params + '', 'a=B&c=d&e=f')
+}, 'Set basics');
+
+test(function() {
+    var params = new URLSearchParams('a=1&a=2&a=3');
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_equals(params.get('a'), '1', 'Search params object has name "a" with value "1"');
+    params.set('first', 4);
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_equals(params.get('a'), '1', 'Search params object has name "a" with value "1"');
+    params.set('a', 4);
+    assert_true(params.has('a'), 'Search params object has name "a"');
+    assert_equals(params.get('a'), '4', 'Search params object has name "a" with value "4"');
+}, 'URLSearchParams.set');
+</script>
+</head>
+</html>
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier-expected.txt
new file mode 100644 (file)
index 0000000..75648d1
--- /dev/null
@@ -0,0 +1,14 @@
+
+FAIL Serialize space Can't find variable: URLSearchParams
+FAIL Serialize empty value Can't find variable: URLSearchParams
+FAIL Serialize empty name Can't find variable: URLSearchParams
+FAIL Serialize empty name and value Can't find variable: URLSearchParams
+FAIL Serialize + Can't find variable: URLSearchParams
+FAIL Serialize = Can't find variable: URLSearchParams
+FAIL Serialize & Can't find variable: URLSearchParams
+FAIL Serialize *-._ Can't find variable: URLSearchParams
+FAIL Serialize % Can't find variable: URLSearchParams
+FAIL Serialize \0 Can't find variable: URLSearchParams
+FAIL Serialize 💩 Can't find variable: URLSearchParams
+FAIL URLSearchParams.toString Can't find variable: URLSearchParams
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier.html b/LayoutTests/imported/w3c/web-platform-tests/url/urlsearchparams-stringifier.html
new file mode 100644 (file)
index 0000000..4215a21
--- /dev/null
@@ -0,0 +1,123 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf8">
+<link rel="help" href="http://url.spec.whatwg.org/#dom-urlsearchparams-set">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/testharness-extras.js"></script>
+<script>
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b c');
+    assert_equals(params + '', 'a=b+c');
+    params.delete('a');
+    params.append('a b', 'c');
+    assert_equals(params + '', 'a+b=c');
+}, 'Serialize space');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', '');
+    assert_equals(params + '', 'a=');
+    params.append('a', '');
+    assert_equals(params + '', 'a=&a=');
+    params.append('', 'b');
+    assert_equals(params + '', 'a=&a=&=b');
+    params.append('', '');
+    assert_equals(params + '', 'a=&a=&=b&=');
+    params.append('', '');
+    assert_equals(params + '', 'a=&a=&=b&=&=');
+}, 'Serialize empty value');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('', 'b');
+    assert_equals(params + '', '=b');
+    params.append('', 'b');
+    assert_equals(params + '', '=b&=b');
+}, 'Serialize empty name');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('', '');
+    assert_equals(params + '', '=');
+    params.append('', '');
+    assert_equals(params + '', '=&=');
+}, 'Serialize empty name and value');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b+c');
+    assert_equals(params + '', 'a=b%2Bc');
+    params.delete('a');
+    params.append('a+b', 'c');
+    assert_equals(params + '', 'a%2Bb=c');
+}, 'Serialize +');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('=', 'a');
+    assert_equals(params + '', '%3D=a');
+    params.append('b', '=');
+    assert_equals(params + '', '%3D=a&b=%3D');
+}, 'Serialize =');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('&', 'a');
+    assert_equals(params + '', '%26=a');
+    params.append('b', '&');
+    assert_equals(params + '', '%26=a&b=%26');
+}, 'Serialize &');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', '*-._');
+    assert_equals(params + '', 'a=*-._');
+    params.delete('a');
+    params.append('*-._', 'c');
+    assert_equals(params + '', '*-._=c');
+}, 'Serialize *-._');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b%c');
+    assert_equals(params + '', 'a=b%25c');
+    params.delete('a');
+    params.append('a%b', 'c');
+    assert_equals(params + '', 'a%25b=c');
+}, 'Serialize %');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b\0c');
+    assert_equals(params + '', 'a=b%00c');
+    params.delete('a');
+    params.append('a\0b', 'c');
+    assert_equals(params + '', 'a%00b=c');
+}, 'Serialize \\0');
+
+test(function() {
+    var params = new URLSearchParams();
+    params.append('a', 'b\uD83D\uDCA9c');
+    assert_equals(params + '', 'a=b%F0%9F%92%A9c');
+    params.delete('a');
+    params.append('a\uD83D\uDCA9b', 'c');
+    assert_equals(params + '', 'a%F0%9F%92%A9b=c');
+}, 'Serialize \uD83D\uDCA9');  // Unicode Character 'PILE OF POO' (U+1F4A9)
+
+test(function() {
+    var params;
+    params = new URLSearchParams('a=b&c=d&&e&&');
+    assert_equals(params.toString(), 'a=b&c=d&e=');
+    params = new URLSearchParams('a = b &a=b&c=d%20');
+    assert_equals(params.toString(), 'a+=+b+&a=b&c=d+');
+    // The lone '=' _does_ survive the roundtrip.
+    params = new URLSearchParams('a=&a=b');
+    assert_equals(params.toString(), 'a=&a=b');
+}, 'URLSearchParams.toString');
+</script>
+</head>
+</html>
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/url/urltestdata.json b/LayoutTests/imported/w3c/web-platform-tests/url/urltestdata.json
new file mode 100644 (file)
index 0000000..f5a915f
--- /dev/null
@@ -0,0 +1,4330 @@
+[
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js",
+  {
+    "input": "http://example\t.\norg",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://user:pass@foo:21/bar;par?b#c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://user:pass@foo:21/bar;par?b#c",
+    "origin": "http://foo:21",
+    "protocol": "http:",
+    "username": "user",
+    "password": "pass",
+    "host": "foo:21",
+    "hostname": "foo",
+    "port": "21",
+    "pathname": "/bar;par",
+    "search": "?b",
+    "hash": "#c"
+  },
+  {
+    "input": "http:foo.com",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/foo.com",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/foo.com",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "\t   :foo.com   \n",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:foo.com",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:foo.com",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": " foo.com  ",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/foo.com",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/foo.com",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "a:\t foo.com",
+    "base": "http://example.org/foo/bar",
+    "href": "a: foo.com",
+    "origin": "null",
+    "protocol": "a:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": " foo.com",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:21/ b ? d # e ",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f:21/%20b%20?%20d%20# e",
+    "origin": "http://f:21",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f:21",
+    "hostname": "f",
+    "port": "21",
+    "pathname": "/%20b%20",
+    "search": "?%20d%20",
+    "hash": "# e"
+  },
+  {
+    "input": "http://f:/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f/c",
+    "origin": "http://f",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f",
+    "hostname": "f",
+    "port": "",
+    "pathname": "/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:0/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f:0/c",
+    "origin": "http://f:0",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f:0",
+    "hostname": "f",
+    "port": "0",
+    "pathname": "/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:00000000000000/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f:0/c",
+    "origin": "http://f:0",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f:0",
+    "hostname": "f",
+    "port": "0",
+    "pathname": "/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:00000000000000000000080/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f/c",
+    "origin": "http://f",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f",
+    "hostname": "f",
+    "port": "",
+    "pathname": "/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:b/c",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://f: /c",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://f:\n/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://f/c",
+    "origin": "http://f",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "f",
+    "hostname": "f",
+    "port": "",
+    "pathname": "/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://f:fifty-two/c",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://f:999999/c",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://f: 21 / b ? d # e ",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "  \t",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":foo.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:foo.com/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:foo.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":foo.com\\",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:foo.com/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:foo.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":a",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:a",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:a",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":\\",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":#",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:#",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "#",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar#",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "#/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar#/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": "#/"
+  },
+  {
+    "input": "#\\",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar#\\",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": "#\\"
+  },
+  {
+    "input": "#;?",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar#;?",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": "#;?"
+  },
+  {
+    "input": "?",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar?",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ":23",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:23",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:23",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/:23",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/:23",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/:23",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "::",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/::",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/::",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "::23",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/::23",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/::23",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo://",
+    "base": "http://example.org/foo/bar",
+    "href": "foo:///",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://a:b@c:29/d",
+    "base": "http://example.org/foo/bar",
+    "href": "http://a:b@c:29/d",
+    "origin": "http://c:29",
+    "protocol": "http:",
+    "username": "a",
+    "password": "b",
+    "host": "c:29",
+    "hostname": "c",
+    "port": "29",
+    "pathname": "/d",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http::@c:29",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/:@c:29",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/:@c:29",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://&a:foo(b]c@d:2/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://&a:foo(b%5Dc@d:2/",
+    "origin": "http://d:2",
+    "protocol": "http:",
+    "username": "&a",
+    "password": "foo(b%5Dc",
+    "host": "d:2",
+    "hostname": "d",
+    "port": "2",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://::@c@d:2",
+    "base": "http://example.org/foo/bar",
+    "href": "http://:%3A%40c@d:2/",
+    "origin": "http://d:2",
+    "protocol": "http:",
+    "username": "",
+    "password": "%3A%40c",
+    "host": "d:2",
+    "hostname": "d",
+    "port": "2",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo.com:b@d/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo.com:b@d/",
+    "origin": "http://d",
+    "protocol": "http:",
+    "username": "foo.com",
+    "password": "b",
+    "host": "d",
+    "hostname": "d",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo.com/\\@",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo.com//@",
+    "origin": "http://foo.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo.com",
+    "hostname": "foo.com",
+    "port": "",
+    "pathname": "//@",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:\\\\foo.com\\",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo.com/",
+    "origin": "http://foo.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo.com",
+    "hostname": "foo.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:\\\\a\\b:c\\d@foo.com\\",
+    "base": "http://example.org/foo/bar",
+    "href": "http://a/b:c/d@foo.com/",
+    "origin": "http://a",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "a",
+    "hostname": "a",
+    "port": "",
+    "pathname": "/b:c/d@foo.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo:/",
+    "base": "http://example.org/foo/bar",
+    "href": "foo:/",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo:/bar.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "foo:/bar.com/",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/bar.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo://///////",
+    "base": "http://example.org/foo/bar",
+    "href": "foo://///////",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "///////",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo://///////bar.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "foo://///////bar.com/",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "///////bar.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "foo:////://///",
+    "base": "http://example.org/foo/bar",
+    "href": "foo:////://///",
+    "origin": "null",
+    "protocol": "foo:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "//://///",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "c:/foo",
+    "base": "http://example.org/foo/bar",
+    "href": "c:/foo",
+    "origin": "null",
+    "protocol": "c:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "//foo/bar",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo/bar",
+    "origin": "http://foo",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo/path;a??e#f#g",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo/path;a??e#f#g",
+    "origin": "http://foo",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/path;a",
+    "search": "??e",
+    "hash": "#f#g"
+  },
+  {
+    "input": "http://foo/abcd?efgh?ijkl",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo/abcd?efgh?ijkl",
+    "origin": "http://foo",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/abcd",
+    "search": "?efgh?ijkl",
+    "hash": ""
+  },
+  {
+    "input": "http://foo/abcd#foo?bar",
+    "base": "http://example.org/foo/bar",
+    "href": "http://foo/abcd#foo?bar",
+    "origin": "http://foo",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/abcd",
+    "search": "",
+    "hash": "#foo?bar"
+  },
+  {
+    "input": "[61:24:74]:98",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/[61:24:74]:98",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/[61:24:74]:98",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:[61:27]/:foo",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/[61:27]/:foo",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/[61:27]/:foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://[1::2]:3:4",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://2001::1",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://2001::1]",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://2001::1]:80",
+    "base": "http://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "http://[2001::1]",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[2001::1]/",
+    "origin": "http://[2001::1]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[2001::1]",
+    "hostname": "[2001::1]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://[2001::1]:80",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[2001::1]/",
+    "origin": "http://[2001::1]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[2001::1]",
+    "hostname": "[2001::1]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/example.com/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ftp://example.com/",
+    "origin": "ftp://example.com",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "https://example.com/",
+    "origin": "https://example.com",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "madeupscheme:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "madeupscheme:/example.com/",
+    "origin": "null",
+    "protocol": "madeupscheme:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "file:///example.com/",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftps:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ftps:/example.com/",
+    "origin": "null",
+    "protocol": "ftps:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "gopher://example.com/",
+    "origin": "gopher://example.com",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ws://example.com/",
+    "origin": "ws://example.com",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "wss://example.com/",
+    "origin": "wss://example.com",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "data:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "data:/example.com/",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "javascript:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "javascript:/example.com/",
+    "origin": "null",
+    "protocol": "javascript:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "mailto:/example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "mailto:/example.com/",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/example.com/",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ftp://example.com/",
+    "origin": "ftp://example.com",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "https://example.com/",
+    "origin": "https://example.com",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "madeupscheme:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "madeupscheme:example.com/",
+    "origin": "null",
+    "protocol": "madeupscheme:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftps:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ftps:example.com/",
+    "origin": "null",
+    "protocol": "ftps:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "gopher://example.com/",
+    "origin": "gopher://example.com",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "ws://example.com/",
+    "origin": "ws://example.com",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "wss://example.com/",
+    "origin": "wss://example.com",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "data:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "data:example.com/",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "javascript:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "javascript:example.com/",
+    "origin": "null",
+    "protocol": "javascript:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "mailto:example.com/",
+    "base": "http://example.org/foo/bar",
+    "href": "mailto:example.com/",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/a/b/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/a/b/c",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/a/b/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/a/ /c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/a/%20/c",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/a/%20/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/a%2fc",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/a%2fc",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/a%2fc",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/a/%2f/c",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/a/%2f/c",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/a/%2f/c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "#β",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar#β",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "hash": "#β"
+  },
+  {
+    "input": "data:text/html,test#test",
+    "base": "http://example.org/foo/bar",
+    "href": "data:text/html,test#test",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "text/html,test",
+    "search": "",
+    "hash": "#test"
+  },
+  {
+    "input": "tel:1234567890",
+    "base": "http://example.org/foo/bar",
+    "href": "tel:1234567890",
+    "origin": "null",
+    "protocol": "tel:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "1234567890",
+    "search": "",
+    "hash": ""
+  },
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html",
+  {
+    "input": "file:c:\\foo\\bar.html",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///c:/foo/bar.html",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/c:/foo/bar.html",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "  File:c|////foo\\bar.html",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///c:////foo/bar.html",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/c:////foo/bar.html",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "C|/foo/bar",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///C:/foo/bar",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/C:/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/C|\\foo\\bar",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///C:/foo/bar",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/C:/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "//C|/foo/bar",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///C:/foo/bar",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/C:/foo/bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "//server/file",
+    "base": "file:///tmp/mock/path",
+    "href": "file://server/file",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "server",
+    "hostname": "server",
+    "port": "",
+    "pathname": "/file",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "\\\\server\\file",
+    "base": "file:///tmp/mock/path",
+    "href": "file://server/file",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "server",
+    "hostname": "server",
+    "port": "",
+    "pathname": "/file",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/\\server/file",
+    "base": "file:///tmp/mock/path",
+    "href": "file://server/file",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "server",
+    "hostname": "server",
+    "port": "",
+    "pathname": "/file",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:///foo/bar.txt",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///foo/bar.txt",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/foo/bar.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:///home/me",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///home/me",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/home/me",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "//",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "///",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "///test",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///test",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/test",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file://test",
+    "base": "file:///tmp/mock/path",
+    "href": "file://test/",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "test",
+    "hostname": "test",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file://localhost",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file://localhost/",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file://localhost/test",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///test",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/test",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "test",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///tmp/mock/test",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/tmp/mock/test",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:test",
+    "base": "file:///tmp/mock/path",
+    "href": "file:///tmp/mock/test",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/tmp/mock/test",
+    "search": "",
+    "hash": ""
+  },
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/path.js",
+  {
+    "input": "http://example.com/././foo",
+    "base": "about:blank",
+    "href": "http://example.com/foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/./.foo",
+    "base": "about:blank",
+    "href": "http://example.com/.foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/.foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/.",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/./",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar/..",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar/../",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/..bar",
+    "base": "about:blank",
+    "href": "http://example.com/foo/..bar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/..bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar/../ton",
+    "base": "about:blank",
+    "href": "http://example.com/foo/ton",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/ton",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar/../ton/../../a",
+    "base": "about:blank",
+    "href": "http://example.com/a",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/a",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/../../..",
+    "base": "about:blank",
+    "href": "http://example.com/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/../../../ton",
+    "base": "about:blank",
+    "href": "http://example.com/ton",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/ton",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/%2e",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/%2e%2",
+    "base": "about:blank",
+    "href": "http://example.com/foo/.%2",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/.%2",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar",
+    "base": "about:blank",
+    "href": "http://example.com/..bar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/..bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com////../..",
+    "base": "about:blank",
+    "href": "http://example.com//",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "//",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar//../..",
+    "base": "about:blank",
+    "href": "http://example.com/foo/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo/bar//..",
+    "base": "about:blank",
+    "href": "http://example.com/foo/bar/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo/bar/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo",
+    "base": "about:blank",
+    "href": "http://example.com/foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/%20foo",
+    "base": "about:blank",
+    "href": "http://example.com/%20foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%20foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%",
+    "base": "about:blank",
+    "href": "http://example.com/foo%",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%2",
+    "base": "about:blank",
+    "href": "http://example.com/foo%2",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%2",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%2zbar",
+    "base": "about:blank",
+    "href": "http://example.com/foo%2zbar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%2zbar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%2©zbar",
+    "base": "about:blank",
+    "href": "http://example.com/foo%2%C3%82%C2%A9zbar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%2%C3%82%C2%A9zbar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%41%7a",
+    "base": "about:blank",
+    "href": "http://example.com/foo%41%7a",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%41%7a",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo\t\u0091%91",
+    "base": "about:blank",
+    "href": "http://example.com/foo%C2%91%91",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%C2%91%91",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo%00%51",
+    "base": "about:blank",
+    "href": "http://example.com/foo%00%51",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foo%00%51",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/(%28:%3A%29)",
+    "base": "about:blank",
+    "href": "http://example.com/(%28:%3A%29)",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/(%28:%3A%29)",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/%3A%3a%3C%3c",
+    "base": "about:blank",
+    "href": "http://example.com/%3A%3a%3C%3c",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%3A%3a%3C%3c",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/foo\tbar",
+    "base": "about:blank",
+    "href": "http://example.com/foobar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/foobar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com\\\\foo\\\\bar",
+    "base": "about:blank",
+    "href": "http://example.com//foo//bar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "//foo//bar",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd",
+    "base": "about:blank",
+    "href": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%7Ffp3%3Eju%3Dduvgw%3Dd",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/@asdf%40",
+    "base": "about:blank",
+    "href": "http://example.com/@asdf%40",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/@asdf%40",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/你好你好",
+    "base": "about:blank",
+    "href": "http://example.com/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/‥/foo",
+    "base": "about:blank",
+    "href": "http://example.com/%E2%80%A5/foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%E2%80%A5/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com//foo",
+    "base": "about:blank",
+    "href": "http://example.com/%EF%BB%BF/foo",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%EF%BB%BF/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example.com/‮/foo/‭/bar",
+    "base": "about:blank",
+    "href": "http://example.com/%E2%80%AE/foo/%E2%80%AD/bar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/%E2%80%AE/foo/%E2%80%AD/bar",
+    "search": "",
+    "hash": ""
+  },
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/relative.js",
+  {
+    "input": "http://www.google.com/foo?bar=baz#",
+    "base": "about:blank",
+    "href": "http://www.google.com/foo?bar=baz#",
+    "origin": "http://www.google.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.google.com",
+    "hostname": "www.google.com",
+    "port": "",
+    "pathname": "/foo",
+    "search": "?bar=baz",
+    "hash": ""
+  },
+  {
+    "input": "http://www.google.com/foo?bar=baz# »",
+    "base": "about:blank",
+    "href": "http://www.google.com/foo?bar=baz# »",
+    "origin": "http://www.google.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.google.com",
+    "hostname": "www.google.com",
+    "port": "",
+    "pathname": "/foo",
+    "search": "?bar=baz",
+    "hash": "# »"
+  },
+  {
+    "input": "data:test# »",
+    "base": "about:blank",
+    "href": "data:test# »",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "test",
+    "search": "",
+    "hash": "# »"
+  },
+  {
+    "input": "http://[www.google.com]/",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://www.google.com",
+    "base": "about:blank",
+    "href": "http://www.google.com/",
+    "origin": "http://www.google.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.google.com",
+    "hostname": "www.google.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://192.0x00A80001",
+    "base": "about:blank",
+    "href": "http://192.168.0.1/",
+    "origin": "http://192.168.0.1",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "192.168.0.1",
+    "hostname": "192.168.0.1",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://www/foo%2Ehtml",
+    "base": "about:blank",
+    "href": "http://www/foo.html",
+    "origin": "http://www",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www",
+    "hostname": "www",
+    "port": "",
+    "pathname": "/foo.html",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://www/foo/%2E/html",
+    "base": "about:blank",
+    "href": "http://www/foo/html",
+    "origin": "http://www",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www",
+    "hostname": "www",
+    "port": "",
+    "pathname": "/foo/html",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://user:pass@/",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://%25DOMAIN:foobar@foodomain.com/",
+    "base": "about:blank",
+    "href": "http://%25DOMAIN:foobar@foodomain.com/",
+    "origin": "http://foodomain.com",
+    "protocol": "http:",
+    "username": "%25DOMAIN",
+    "password": "foobar",
+    "host": "foodomain.com",
+    "hostname": "foodomain.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:\\\\www.google.com\\foo",
+    "base": "about:blank",
+    "href": "http://www.google.com/foo",
+    "origin": "http://www.google.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.google.com",
+    "hostname": "www.google.com",
+    "port": "",
+    "pathname": "/foo",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo:80/",
+    "base": "about:blank",
+    "href": "http://foo/",
+    "origin": "http://foo",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo:81/",
+    "base": "about:blank",
+    "href": "http://foo:81/",
+    "origin": "http://foo:81",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "foo:81",
+    "hostname": "foo",
+    "port": "81",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "httpa://foo:80/",
+    "base": "about:blank",
+    "href": "httpa://foo:80/",
+    "origin": "null",
+    "protocol": "httpa:",
+    "username": "",
+    "password": "",
+    "host": "foo:80",
+    "hostname": "foo",
+    "port": "80",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://foo:-80/",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "https://foo:443/",
+    "base": "about:blank",
+    "href": "https://foo/",
+    "origin": "https://foo",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https://foo:80/",
+    "base": "about:blank",
+    "href": "https://foo:80/",
+    "origin": "https://foo:80",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "foo:80",
+    "hostname": "foo",
+    "port": "80",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp://foo:21/",
+    "base": "about:blank",
+    "href": "ftp://foo/",
+    "origin": "ftp://foo",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp://foo:80/",
+    "base": "about:blank",
+    "href": "ftp://foo:80/",
+    "origin": "ftp://foo:80",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "foo:80",
+    "hostname": "foo",
+    "port": "80",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher://foo:70/",
+    "base": "about:blank",
+    "href": "gopher://foo/",
+    "origin": "gopher://foo",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher://foo:443/",
+    "base": "about:blank",
+    "href": "gopher://foo:443/",
+    "origin": "gopher://foo:443",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "foo:443",
+    "hostname": "foo",
+    "port": "443",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws://foo:80/",
+    "base": "about:blank",
+    "href": "ws://foo/",
+    "origin": "ws://foo",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws://foo:81/",
+    "base": "about:blank",
+    "href": "ws://foo:81/",
+    "origin": "ws://foo:81",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "foo:81",
+    "hostname": "foo",
+    "port": "81",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws://foo:443/",
+    "base": "about:blank",
+    "href": "ws://foo:443/",
+    "origin": "ws://foo:443",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "foo:443",
+    "hostname": "foo",
+    "port": "443",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws://foo:815/",
+    "base": "about:blank",
+    "href": "ws://foo:815/",
+    "origin": "ws://foo:815",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "foo:815",
+    "hostname": "foo",
+    "port": "815",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss://foo:80/",
+    "base": "about:blank",
+    "href": "wss://foo:80/",
+    "origin": "wss://foo:80",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "foo:80",
+    "hostname": "foo",
+    "port": "80",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss://foo:81/",
+    "base": "about:blank",
+    "href": "wss://foo:81/",
+    "origin": "wss://foo:81",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "foo:81",
+    "hostname": "foo",
+    "port": "81",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss://foo:443/",
+    "base": "about:blank",
+    "href": "wss://foo/",
+    "origin": "wss://foo",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "foo",
+    "hostname": "foo",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss://foo:815/",
+    "base": "about:blank",
+    "href": "wss://foo:815/",
+    "origin": "wss://foo:815",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "foo:815",
+    "hostname": "foo",
+    "port": "815",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/example.com/",
+    "base": "about:blank",
+    "href": "http://example.com/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp:/example.com/",
+    "base": "about:blank",
+    "href": "ftp://example.com/",
+    "origin": "ftp://example.com",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https:/example.com/",
+    "base": "about:blank",
+    "href": "https://example.com/",
+    "origin": "https://example.com",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "madeupscheme:/example.com/",
+    "base": "about:blank",
+    "href": "madeupscheme:/example.com/",
+    "origin": "null",
+    "protocol": "madeupscheme:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:/example.com/",
+    "base": "about:blank",
+    "href": "file:///example.com/",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftps:/example.com/",
+    "base": "about:blank",
+    "href": "ftps:/example.com/",
+    "origin": "null",
+    "protocol": "ftps:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher:/example.com/",
+    "base": "about:blank",
+    "href": "gopher://example.com/",
+    "origin": "gopher://example.com",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws:/example.com/",
+    "base": "about:blank",
+    "href": "ws://example.com/",
+    "origin": "ws://example.com",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss:/example.com/",
+    "base": "about:blank",
+    "href": "wss://example.com/",
+    "origin": "wss://example.com",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "data:/example.com/",
+    "base": "about:blank",
+    "href": "data:/example.com/",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "javascript:/example.com/",
+    "base": "about:blank",
+    "href": "javascript:/example.com/",
+    "origin": "null",
+    "protocol": "javascript:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "mailto:/example.com/",
+    "base": "about:blank",
+    "href": "mailto:/example.com/",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:example.com/",
+    "base": "about:blank",
+    "href": "http://example.com/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftp:example.com/",
+    "base": "about:blank",
+    "href": "ftp://example.com/",
+    "origin": "ftp://example.com",
+    "protocol": "ftp:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https:example.com/",
+    "base": "about:blank",
+    "href": "https://example.com/",
+    "origin": "https://example.com",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "madeupscheme:example.com/",
+    "base": "about:blank",
+    "href": "madeupscheme:example.com/",
+    "origin": "null",
+    "protocol": "madeupscheme:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ftps:example.com/",
+    "base": "about:blank",
+    "href": "ftps:example.com/",
+    "origin": "null",
+    "protocol": "ftps:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "gopher:example.com/",
+    "base": "about:blank",
+    "href": "gopher://example.com/",
+    "origin": "gopher://example.com",
+    "protocol": "gopher:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "ws:example.com/",
+    "base": "about:blank",
+    "href": "ws://example.com/",
+    "origin": "ws://example.com",
+    "protocol": "ws:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "wss:example.com/",
+    "base": "about:blank",
+    "href": "wss://example.com/",
+    "origin": "wss://example.com",
+    "protocol": "wss:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "data:example.com/",
+    "base": "about:blank",
+    "href": "data:example.com/",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "javascript:example.com/",
+    "base": "about:blank",
+    "href": "javascript:example.com/",
+    "origin": "null",
+    "protocol": "javascript:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "mailto:example.com/",
+    "base": "about:blank",
+    "href": "mailto:example.com/",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "example.com/",
+    "search": "",
+    "hash": ""
+  },
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/segments-userinfo-vs-host.html",
+  {
+    "input": "http:@www.example.com",
+    "base": "about:blank",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/@www.example.com",
+    "base": "about:blank",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://@www.example.com",
+    "base": "about:blank",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:a:b@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/a:b@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://a:b@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://@pple.com",
+    "base": "about:blank",
+    "href": "http://pple.com/",
+    "origin": "http://pple.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "pple.com",
+    "hostname": "pple.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http::b@www.example.com",
+    "base": "about:blank",
+    "href": "http://:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/:b@www.example.com",
+    "base": "about:blank",
+    "href": "http://:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://:b@www.example.com",
+    "base": "about:blank",
+    "href": "http://:b@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "b",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/:@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://user@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:/@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "https:@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:a:b@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:/a:b@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://a:b@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http::@/www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a:@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://www.@pple.com",
+    "base": "about:blank",
+    "href": "http://www.@pple.com/",
+    "origin": "http://pple.com",
+    "protocol": "http:",
+    "username": "www.",
+    "password": "",
+    "host": "pple.com",
+    "hostname": "pple.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:@:www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http:/@:www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://@:www.example.com",
+    "base": "about:blank",
+    "failure": true
+  },
+  {
+    "input": "http://:@www.example.com",
+    "base": "about:blank",
+    "href": "http://:@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "# Others",
+  {
+    "input": "/",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": ".",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "..",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "./test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../aaa/test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/aaa/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/aaa/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../../test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "中/test.txt",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example.com/%E4%B8%AD/test.txt",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/%E4%B8%AD/test.txt",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://www.example2.com",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example2.com/",
+    "origin": "http://www.example2.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example2.com",
+    "hostname": "www.example2.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "//www.example2.com",
+    "base": "http://www.example.com/test",
+    "href": "http://www.example2.com/",
+    "origin": "http://www.example2.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example2.com",
+    "hostname": "www.example2.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:...",
+    "base": "http://www.example.com/test",
+    "href": "file:///...",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/...",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:..",
+    "base": "http://www.example.com/test",
+    "href": "file:///",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "file:a",
+    "base": "http://www.example.com/test",
+    "href": "file:///a",
+    "protocol": "file:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/a",
+    "search": "",
+    "hash": ""
+  },
+  "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/host.html",
+  "Basic canonicalization, uppercase should be converted to lowercase",
+  {
+    "input": "http://ExAmPlE.CoM",
+    "base": "http://other.com/",
+    "href": "http://example.com/",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://example example.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://Goo%20 goo%7C|.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://[]",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://[:]",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "U+3000 is mapped to U+0020 (space) which is disallowed",
+  {
+    "input": "http://GOO\u00a0\u3000goo.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Other types of space (no-break, zero-width, zero-width-no-break) are name-prepped away to nothing. U+200B, U+2060, and U+FEFF, are ignored",
+  {
+    "input": "http://GOO\u200b\u2060\ufeffgoo.com",
+    "base": "http://other.com/",
+    "href": "http://googoo.com/",
+    "origin": "http://googoo.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "googoo.com",
+    "hostname": "googoo.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "Ideographic full stop (full-width period for Chinese, etc.) should be treated as a dot. U+3002 is mapped to U+002E (dot)",
+  {
+    "input": "http://www.foo。bar.com",
+    "base": "http://other.com/",
+    "href": "http://www.foo.bar.com/",
+    "origin": "http://www.foo.bar.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.foo.bar.com",
+    "hostname": "www.foo.bar.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "Invalid unicode characters should fail... U+FDD0 is disallowed; %ef%b7%90 is U+FDD0",
+  {
+    "input": "http://\ufdd0zyx.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "This is the same as previous but escaped",
+  {
+    "input": "http://%ef%b7%90zyx.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.",
+  {
+    "input": "http://Go.com",
+    "base": "http://other.com/",
+    "href": "http://go.com/",
+    "origin": "http://go.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "go.com",
+    "hostname": "go.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "URL spec forbids the following. https://www.w3.org/Bugs/Public/show_bug.cgi?id=24257",
+  {
+    "input": "http://%41.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://%ef%bc%85%ef%bc%94%ef%bc%91.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "...%00 in fullwidth should fail (also as escaped UTF-8 input)",
+  {
+    "input": "http://%00.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://%ef%bc%85%ef%bc%90%ef%bc%90.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Basic IDN support, UTF-8 and UTF-16 input should be converted to IDN",
+  {
+    "input": "http://你好你好",
+    "base": "http://other.com/",
+    "href": "http://xn--6qqa088eba/",
+    "origin": "http://你好你好",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "xn--6qqa088eba",
+    "hostname": "xn--6qqa088eba",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "Invalid escaped characters should fail and the percents should be escaped. https://www.w3.org/Bugs/Public/show_bug.cgi?id=24191",
+  {
+    "input": "http://%zz%66%a.com",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "If we get an invalid character that has been escaped.",
+  {
+    "input": "http://%25",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  {
+    "input": "http://hello%00",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Escaped numbers should be treated like IP addresses if they are.",
+  {
+    "input": "http://%30%78%63%30%2e%30%32%35%30.01",
+    "base": "http://other.com/",
+    "href": "http://192.168.0.1/",
+    "origin": "http://192.168.0.1",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "192.168.0.1",
+    "hostname": "192.168.0.1",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://%30%78%63%30%2e%30%32%35%30.01%2e",
+    "base": "http://other.com/",
+    "href": "http://192.168.0.1/",
+    "origin": "http://192.168.0.1",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "192.168.0.1",
+    "hostname": "192.168.0.1",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://192.168.0.257",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Invalid escaping should trigger the regular host error handling",
+  {
+    "input": "http://%3g%78%63%30%2e%30%32%35%30%2E.01",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Something that isn't exactly an IP should get treated as a host and spaces escaped",
+  {
+    "input": "http://192.168.0.1 hello",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Fullwidth and escaped UTF-8 fullwidth should still be treated as IP",
+  {
+    "input": "http://0Xc0.0250.01",
+    "base": "http://other.com/",
+    "href": "http://192.168.0.1/",
+    "origin": "http://192.168.0.1",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "192.168.0.1",
+    "hostname": "192.168.0.1",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "Broken IPv6",
+  {
+    "input": "http://[google.com]",
+    "base": "http://other.com/",
+    "failure": true
+  },
+  "Misc Unicode",
+  {
+    "input": "http://foo:💩@example.com/bar",
+    "base": "http://other.com/",
+    "href": "http://foo:%F0%9F%92%A9@example.com/bar",
+    "origin": "http://example.com",
+    "protocol": "http:",
+    "username": "foo",
+    "password": "%F0%9F%92%A9",
+    "host": "example.com",
+    "hostname": "example.com",
+    "port": "",
+    "pathname": "/bar",
+    "search": "",
+    "hash": ""
+  },
+  "# resolving a fragment against any scheme succeeds",
+  {
+    "input": "#",
+    "base": "test:test",
+    "href": "test:test#",
+    "origin": "null",
+    "protocol": "test:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "test",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "#x",
+    "base": "mailto:x@x.com",
+    "href": "mailto:x@x.com#x",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "x@x.com",
+    "search": "",
+    "hash": "#x"
+  },
+  {
+    "input": "#x",
+    "base": "data:,",
+    "href": "data:,#x",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": ",",
+    "search": "",
+    "hash": "#x"
+  },
+  {
+    "input": "#x",
+    "base": "about:blank",
+    "href": "about:blank#x",
+    "origin": "null",
+    "protocol": "about:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "blank",
+    "search": "",
+    "hash": "#x"
+  },
+  {
+    "input": "#",
+    "base": "test:test?test",
+    "href": "test:test?test#",
+    "origin": "null",
+    "protocol": "test:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "test",
+    "search": "?test",
+    "hash": ""
+  },
+  "# multiple @ in authority state",
+  {
+    "input": "https://@test@test@example:800/",
+    "base": "http://doesnotmatter/",
+    "href": "https://%40test%40test@example:800/",
+    "origin": "https://example:800",
+    "protocol": "https:",
+    "username": "%40test%40test",
+    "password": "",
+    "host": "example:800",
+    "hostname": "example",
+    "port": "800",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https://@@@example",
+    "base": "http://doesnotmatter/",
+    "href": "https://%40%40@example/",
+    "origin": "https://example",
+    "protocol": "https:",
+    "username": "%40%40",
+    "password": "",
+    "host": "example",
+    "hostname": "example",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "non-az-09 characters",
+  {
+    "input": "http://`{}:`{}@h/`{}?`{}",
+    "base": "http://doesnotmatter/",
+    "href": "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}",
+    "origin": "http://h",
+    "protocol": "http:",
+    "username": "%60%7B%7D",
+    "password": "%60%7B%7D",
+    "host": "h",
+    "hostname": "h",
+    "port": "",
+    "pathname": "/%60%7B%7D",
+    "search": "?`{}",
+    "hash": ""
+  },
+  "# Credentials in base",
+  {
+    "input": "/some/path",
+    "base": "http://user@example.org/smth",
+    "href": "http://user@example.org/some/path",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "user",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/some/path",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "",
+    "base": "http://user:pass@example.org:21/smth",
+    "href": "http://user:pass@example.org:21/smth",
+    "origin": "http://example.org:21",
+    "protocol": "http:",
+    "username": "user",
+    "password": "pass",
+    "host": "example.org:21",
+    "hostname": "example.org",
+    "port": "21",
+    "pathname": "/smth",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/some/path",
+    "base": "http://user:pass@example.org:21/smth",
+    "href": "http://user:pass@example.org:21/some/path",
+    "origin": "http://example.org:21",
+    "protocol": "http:",
+    "username": "user",
+    "password": "pass",
+    "host": "example.org:21",
+    "hostname": "example.org",
+    "port": "21",
+    "pathname": "/some/path",
+    "search": "",
+    "hash": ""
+  },
+  "# a set of tests designed by zcorpan for relative URLs with unknown schemes",
+  {
+    "input": "i",
+    "base": "sc:sd",
+    "failure": true
+  },
+  {
+    "input": "i",
+    "base": "sc:sd/sd",
+    "failure": true
+  },
+  {
+    "input": "i",
+    "base": "sc:/pa/pa",
+    "href": "sc:/pa/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "i",
+    "base": "sc://ho/pa",
+    "href": "sc://ho/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "ho",
+    "hostname": "ho",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "i",
+    "base": "sc:///pa/pa",
+    "href": "sc:///pa/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../i",
+    "base": "sc:sd",
+    "failure": true
+  },
+  {
+    "input": "../i",
+    "base": "sc:sd/sd",
+    "failure": true
+  },
+  {
+    "input": "../i",
+    "base": "sc:/pa/pa",
+    "href": "sc:/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../i",
+    "base": "sc://ho/pa",
+    "href": "sc://ho/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "ho",
+    "hostname": "ho",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "../i",
+    "base": "sc:///pa/pa",
+    "href": "sc:///i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/i",
+    "base": "sc:sd",
+    "failure": true
+  },
+  {
+    "input": "/i",
+    "base": "sc:sd/sd",
+    "failure": true
+  },
+  {
+    "input": "/i",
+    "base": "sc:/pa/pa",
+    "href": "sc:/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/i",
+    "base": "sc://ho/pa",
+    "href": "sc://ho/i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "ho",
+    "hostname": "ho",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "/i",
+    "base": "sc:///pa/pa",
+    "href": "sc:///i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/i",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "?i",
+    "base": "sc:sd",
+    "failure": true
+  },
+  {
+    "input": "?i",
+    "base": "sc:sd/sd",
+    "failure": true
+  },
+  {
+    "input": "?i",
+    "base": "sc:/pa/pa",
+    "href": "sc:/pa/pa?i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/pa",
+    "search": "?i",
+    "hash": ""
+  },
+  {
+    "input": "?i",
+    "base": "sc://ho/pa",
+    "href": "sc://ho/pa?i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "ho",
+    "hostname": "ho",
+    "port": "",
+    "pathname": "/pa",
+    "search": "?i",
+    "hash": ""
+  },
+  {
+    "input": "?i",
+    "base": "sc:///pa/pa",
+    "href": "sc:///pa/pa?i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/pa",
+    "search": "?i",
+    "hash": ""
+  },
+  {
+    "input": "#i",
+    "base": "sc:sd",
+    "href": "sc:sd#i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "sd",
+    "search": "",
+    "hash": "#i"
+  },
+  {
+    "input": "#i",
+    "base": "sc:sd/sd",
+    "href": "sc:sd/sd#i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "sd/sd",
+    "search": "",
+    "hash": "#i"
+  },
+  {
+    "input": "#i",
+    "base": "sc:/pa/pa",
+    "href": "sc:/pa/pa#i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/pa",
+    "search": "",
+    "hash": "#i"
+  },
+  {
+    "input": "#i",
+    "base": "sc://ho/pa",
+    "href": "sc://ho/pa#i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "ho",
+    "hostname": "ho",
+    "port": "",
+    "pathname": "/pa",
+    "search": "",
+    "hash": "#i"
+  },
+  {
+    "input": "#i",
+    "base": "sc:///pa/pa",
+    "href": "sc:///pa/pa#i",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/pa/pa",
+    "search": "",
+    "hash": "#i"
+  },
+  "# make sure that relative URL logic works on known typically non-relative schemes too",
+  {
+    "input": "about:/../",
+    "base": "about:blank",
+    "href": "about:/",
+    "origin": "null",
+    "protocol": "about:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "data:/../",
+    "base": "about:blank",
+    "href": "data:/",
+    "origin": "null",
+    "protocol": "data:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "javascript:/../",
+    "base": "about:blank",
+    "href": "javascript:/",
+    "origin": "null",
+    "protocol": "javascript:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "mailto:/../",
+    "base": "about:blank",
+    "href": "mailto:/",
+    "origin": "null",
+    "protocol": "mailto:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "# unknown schemes and non-ASCII domains",
+  {
+    "input": "sc://ñ.test/",
+    "base": "about:blank",
+    "href": "sc://xn--ida.test/",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "xn--ida.test",
+    "hostname": "xn--ida.test",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  "# unknown schemes and backslashes",
+  {
+    "input": "sc:\\../",
+    "base": "about:blank",
+    "href": "sc:\\../",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "\\../",
+    "search": "",
+    "hash": ""
+  },
+  "# unknown scheme with path looking like a password",
+  {
+    "input": "sc::a@example.net",
+    "base": "about:blank",
+    "href": "sc::a@example.net",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": ":a@example.net",
+    "search": "",
+    "hash": ""
+  },
+  "# tests from jsdom/whatwg-url designed for code coverage",
+  {
+    "input": "http://127.0.0.1:10100/relative_import.html",
+    "base": "about:blank",
+    "href": "http://127.0.0.1:10100/relative_import.html",
+    "origin": "http://127.0.0.1:10100",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "127.0.0.1:10100",
+    "hostname": "127.0.0.1",
+    "port": "10100",
+    "pathname": "/relative_import.html",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://facebook.com/?foo=%7B%22abc%22",
+    "base": "about:blank",
+    "href": "http://facebook.com/?foo=%7B%22abc%22",
+    "origin": "http://facebook.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "facebook.com",
+    "hostname": "facebook.com",
+    "port": "",
+    "pathname": "/",
+    "search": "?foo=%7B%22abc%22",
+    "hash": ""
+  },
+  {
+    "input": "https://localhost:3000/jqueryui@1.2.3",
+    "base": "about:blank",
+    "href": "https://localhost:3000/jqueryui@1.2.3",
+    "origin": "https://localhost:3000",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "localhost:3000",
+    "hostname": "localhost",
+    "port": "3000",
+    "pathname": "/jqueryui@1.2.3",
+    "search": "",
+    "hash": ""
+  },
+  "# tab/LF/CR",
+  {
+    "input": "h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg",
+    "base": "about:blank",
+    "href": "http://host:9000/path?query#frag",
+    "origin": "http://host:9000",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "host:9000",
+    "hostname": "host",
+    "port": "9000",
+    "pathname": "/path",
+    "search": "?query",
+    "hash": "#frag"
+  },
+  "# Stringification of URL.searchParams",
+  {
+    "input": "?a=b&c=d",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar?a=b&c=d",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "?a=b&c=d",
+    "searchParams": "a=b&c=d",
+    "hash": ""
+  },
+  {
+    "input": "??a=b&c=d",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar??a=b&c=d",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "??a=b&c=d",
+    "searchParams": "%3Fa=b&c=d",
+    "hash": ""
+  },
+  "# Scheme only",
+  {
+    "input": "http:",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "searchParams": "",
+    "hash": ""
+  },
+  {
+    "input": "http:",
+    "base": "https://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "sc:",
+    "base": "https://example.org/foo/bar",
+    "href": "sc:",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "",
+    "search": "",
+    "searchParams": "",
+    "hash": ""
+  }
+]
index 6a4d24d9437b935dab9fdf201f356b4111838142..201a007d81f23697d921d85130555f1e8643d231 100644 (file)
@@ -1,3 +1,29 @@
+2016-08-24  Alex Christensen  <achristensen@webkit.org>
+
+        Import w3c URL tests
+        https://bugs.webkit.org/show_bug.cgi?id=161177
+
+        Reviewed by Tim Horton.
+
+        Tests: imported/w3c/web-platform-tests/url/a-element-xhtml.xhtml
+               imported/w3c/web-platform-tests/url/a-element.html
+               imported/w3c/web-platform-tests/url/historical.html
+               imported/w3c/web-platform-tests/url/interfaces.html
+               imported/w3c/web-platform-tests/url/url-constructor.html
+               imported/w3c/web-platform-tests/url/url-domainToUnicode.html
+               imported/w3c/web-platform-tests/url/url-setters.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-append.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-constructor.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-delete.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-get.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-getall.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-has.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-set.html
+               imported/w3c/web-platform-tests/url/urlsearchparams-stringifier.html
+
+        * platform/URL.cpp:
+        (WebCore::URL::setQuery):
+
 2016-08-24  Ryan Haddad  <ryanhaddad@apple.com>
 
         Rebaseline bindings tests after r204923.
index 006056967499af60779d829092f5ab7364a0b59c..c24925b6c02e04daac73639d09e50751070e7016 100644 (file)
@@ -1037,6 +1037,7 @@ void URL::setQuery(const String& query)
     // FIXME: '#' and non-ASCII characters must be encoded and escaped.
     // Usually, the query is encoded using document encoding, not UTF-8, but we don't have
     // access to the document in this function.
+    // https://webkit.org/b/161176
     if ((query.isEmpty() || query[0] != '?') && !query.isNull())
         parse(m_string.left(m_pathEnd) + "?" + query + m_string.substring(m_queryEnd));
     else