• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1{
2    "comment": [
3        "# Pulled from https://github.com/web-platform-tests/wpt/blob/befe66343e5f21dc464c8c772c6d20695936714f/url/resources/setters_tests.json",
4        "## Tests for setters of https://url.spec.whatwg.org/#urlutils-members",
5        "",
6        "This file contains a JSON object.",
7        "Other than 'comment', each key is an attribute of the `URL` interface",
8        "defined in WHATWG’s URL Standard.",
9        "The values are arrays of test case objects for that attribute.",
10        "",
11        "To run a test case for the attribute `attr`:",
12        "",
13        "* Create a new `URL` object with the value for the 'href' key",
14        "  the constructor single parameter. (Without a base URL.)",
15        "  This must not throw.",
16        "* Set the attribute `attr` to (invoke its setter with)",
17        "  with the value of for 'new_value' key.",
18        "* The value for the 'expected' key is another object.",
19        "  For each `key` / `value` pair of that object,",
20        "  get the attribute `key` (invoke its getter).",
21        "  The returned string must be equal to `value`.",
22        "",
23        "Note: the 'href' setter is already covered by urltestdata.json."
24    ],
25    "protocol": [
26        {
27            "comment": "The empty string is not a valid scheme. Setter leaves the URL unchanged.",
28            "href": "a://example.net",
29            "new_value": "",
30            "expected": {
31                "href": "a://example.net",
32                "protocol": "a:"
33            }
34        },
35        {
36            "href": "a://example.net",
37            "new_value": "b",
38            "expected": {
39                "href": "b://example.net",
40                "protocol": "b:"
41            }
42        },
43        {
44            "href": "javascript:alert(1)",
45            "new_value": "defuse",
46            "expected": {
47                "href": "defuse:alert(1)",
48                "protocol": "defuse:"
49            }
50        },
51        {
52            "comment": "Upper-case ASCII is lower-cased",
53            "href": "a://example.net",
54            "new_value": "B",
55            "expected": {
56                "href": "b://example.net",
57                "protocol": "b:"
58            }
59        },
60        {
61            "comment": "Non-ASCII is rejected",
62            "href": "a://example.net",
63            "new_value": "é",
64            "expected": {
65                "href": "a://example.net",
66                "protocol": "a:"
67            }
68        },
69        {
70            "comment": "No leading digit",
71            "href": "a://example.net",
72            "new_value": "0b",
73            "expected": {
74                "href": "a://example.net",
75                "protocol": "a:"
76            }
77        },
78        {
79            "comment": "No leading punctuation",
80            "href": "a://example.net",
81            "new_value": "+b",
82            "expected": {
83                "href": "a://example.net",
84                "protocol": "a:"
85            }
86        },
87        {
88            "href": "a://example.net",
89            "new_value": "bC0+-.",
90            "expected": {
91                "href": "bc0+-.://example.net",
92                "protocol": "bc0+-.:"
93            }
94        },
95        {
96            "comment": "Only some punctuation is acceptable",
97            "href": "a://example.net",
98            "new_value": "b,c",
99            "expected": {
100                "href": "a://example.net",
101                "protocol": "a:"
102            }
103        },
104        {
105            "comment": "Non-ASCII is rejected",
106            "href": "a://example.net",
107            "new_value": "bé",
108            "expected": {
109                "href": "a://example.net",
110                "protocol": "a:"
111            }
112        },
113        {
114            "comment": "Can’t switch from URL containing username/password/port to file",
115            "href": "http://test@example.net",
116            "new_value": "file",
117            "expected": {
118                "href": "http://test@example.net/",
119                "protocol": "http:"
120            }
121        },
122        {
123            "href": "https://example.net:1234",
124            "new_value": "file",
125            "expected": {
126                "href": "https://example.net:1234/",
127                "protocol": "https:"
128            }
129        },
130        {
131            "href": "wss://x:x@example.net:1234",
132            "new_value": "file",
133            "expected": {
134                "href": "wss://x:x@example.net:1234/",
135                "protocol": "wss:"
136            }
137        },
138        {
139            "comment": "Can’t switch from file URL with no host",
140            "href": "file://localhost/",
141            "new_value": "http",
142            "expected": {
143                "href": "file:///",
144                "protocol": "file:"
145            }
146        },
147        {
148            "href": "file:///test",
149            "new_value": "https",
150            "expected": {
151                "href": "file:///test",
152                "protocol": "file:"
153            }
154        },
155        {
156            "href": "file:",
157            "new_value": "wss",
158            "expected": {
159                "href": "file:///",
160                "protocol": "file:"
161            }
162        },
163        {
164            "comment": "Can’t switch from special scheme to non-special",
165            "href": "http://example.net",
166            "new_value": "b",
167            "expected": {
168                "href": "http://example.net/",
169                "protocol": "http:"
170            }
171        },
172        {
173            "href": "file://hi/path",
174            "new_value": "s",
175            "expected": {
176                "href": "file://hi/path",
177                "protocol": "file:"
178            }
179        },
180        {
181            "href": "https://example.net",
182            "new_value": "s",
183            "expected": {
184                "href": "https://example.net/",
185                "protocol": "https:"
186            }
187        },
188        {
189            "href": "ftp://example.net",
190            "new_value": "test",
191            "expected": {
192                "href": "ftp://example.net/",
193                "protocol": "ftp:"
194            }
195        },
196        {
197            "comment": "Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.",
198            "href": "mailto:me@example.net",
199            "new_value": "http",
200            "expected": {
201                "href": "mailto:me@example.net",
202                "protocol": "mailto:"
203            }
204        },
205        {
206            "comment": "Can’t switch from non-special scheme to special",
207            "href": "ssh://me@example.net",
208            "new_value": "http",
209            "expected": {
210                "href": "ssh://me@example.net",
211                "protocol": "ssh:"
212            }
213        },
214        {
215            "href": "ssh://me@example.net",
216            "new_value": "https",
217            "expected": {
218                "href": "ssh://me@example.net",
219                "protocol": "ssh:"
220            }
221        },
222        {
223            "href": "ssh://me@example.net",
224            "new_value": "file",
225            "expected": {
226                "href": "ssh://me@example.net",
227                "protocol": "ssh:"
228            }
229        },
230        {
231            "href": "ssh://example.net",
232            "new_value": "file",
233            "expected": {
234                "href": "ssh://example.net",
235                "protocol": "ssh:"
236            }
237        },
238        {
239            "href": "nonsense:///test",
240            "new_value": "https",
241            "expected": {
242                "href": "nonsense:///test",
243                "protocol": "nonsense:"
244            }
245        },
246        {
247            "comment": "Stuff after the first ':' is ignored",
248            "href": "http://example.net",
249            "new_value": "https:foo : bar",
250            "expected": {
251                "href": "https://example.net/",
252                "protocol": "https:"
253            }
254        },
255        {
256            "comment": "Stuff after the first ':' is ignored",
257            "href": "data:text/html,<p>Test",
258            "new_value": "view-source+data:foo : bar",
259            "expected": {
260                "href": "view-source+data:text/html,<p>Test",
261                "protocol": "view-source+data:"
262            }
263        },
264        {
265            "comment": "Port is set to null if it is the default for new scheme.",
266            "href": "http://foo.com:443/",
267            "new_value": "https",
268            "expected": {
269                "href": "https://foo.com/",
270                "protocol": "https:",
271                "port": ""
272            }
273        },
274        {
275            "comment": "Tab and newline are stripped",
276            "href": "http://test/",
277            "new_value": "h\u000D\u000Att\u0009ps",
278            "expected": {
279              "href": "https://test/",
280              "protocol": "https:",
281              "port": ""
282            }
283        },
284        {
285            "href": "http://test/",
286            "new_value": "https\u000D",
287            "expected": {
288              "href": "https://test/",
289              "protocol": "https:"
290            }
291        },
292        {
293            "comment": "Non-tab/newline C0 controls result in no-op",
294            "href": "http://test/",
295            "new_value": "https\u0000",
296            "expected": {
297              "href": "http://test/",
298              "protocol": "http:"
299            }
300        },
301        {
302            "href": "http://test/",
303            "new_value": "https\u000C",
304            "expected": {
305              "href": "http://test/",
306              "protocol": "http:"
307            }
308        },
309        {
310            "href": "http://test/",
311            "new_value": "https\u000E",
312            "expected": {
313              "href": "http://test/",
314              "protocol": "http:"
315            }
316        },
317        {
318            "href": "http://test/",
319            "new_value": "https\u0020",
320            "expected": {
321              "href": "http://test/",
322              "protocol": "http:"
323            }
324        }
325    ],
326    "username": [
327        {
328            "comment": "No host means no username",
329            "href": "file:///home/you/index.html",
330            "new_value": "me",
331            "expected": {
332                "href": "file:///home/you/index.html",
333                "username": ""
334            }
335        },
336        {
337            "comment": "No host means no username",
338            "href": "unix:/run/foo.socket",
339            "new_value": "me",
340            "expected": {
341                "href": "unix:/run/foo.socket",
342                "username": ""
343            }
344        },
345        {
346            "comment": "Cannot-be-a-base means no username",
347            "href": "mailto:you@example.net",
348            "new_value": "me",
349            "expected": {
350                "href": "mailto:you@example.net",
351                "username": ""
352            }
353        },
354        {
355            "href": "javascript:alert(1)",
356            "new_value": "wario",
357            "expected": {
358                "href": "javascript:alert(1)",
359                "username": ""
360            }
361        },
362        {
363            "href": "http://example.net",
364            "new_value": "me",
365            "expected": {
366                "href": "http://me@example.net/",
367                "username": "me"
368            }
369        },
370        {
371            "href": "http://:secret@example.net",
372            "new_value": "me",
373            "expected": {
374                "href": "http://me:secret@example.net/",
375                "username": "me"
376            }
377        },
378        {
379            "href": "http://me@example.net",
380            "new_value": "",
381            "expected": {
382                "href": "http://example.net/",
383                "username": ""
384            }
385        },
386        {
387            "href": "http://me:secret@example.net",
388            "new_value": "",
389            "expected": {
390                "href": "http://:secret@example.net/",
391                "username": ""
392            }
393        },
394        {
395            "comment": "UTF-8 percent encoding with the userinfo encode set.",
396            "href": "http://example.net",
397            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
398            "expected": {
399                "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/",
400                "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"
401            }
402        },
403        {
404            "comment": "Bytes already percent-encoded are left as-is.",
405            "href": "http://example.net",
406            "new_value": "%c3%89té",
407            "expected": {
408                "href": "http://%c3%89t%C3%A9@example.net/",
409                "username": "%c3%89t%C3%A9"
410            }
411        },
412        {
413            "href": "sc:///",
414            "new_value": "x",
415            "expected": {
416                "href": "sc:///",
417                "username": ""
418            }
419        },
420        {
421            "href": "javascript://x/",
422            "new_value": "wario",
423            "expected": {
424                "href": "javascript://wario@x/",
425                "username": "wario"
426            }
427        },
428        {
429            "href": "file://test/",
430            "new_value": "test",
431            "expected": {
432                "href": "file://test/",
433                "username": ""
434            }
435        }
436    ],
437    "password": [
438        {
439            "comment": "No host means no password",
440            "href": "file:///home/me/index.html",
441            "new_value": "secret",
442            "expected": {
443                "href": "file:///home/me/index.html",
444                "password": ""
445            }
446        },
447        {
448            "comment": "No host means no password",
449            "href": "unix:/run/foo.socket",
450            "new_value": "secret",
451            "expected": {
452                "href": "unix:/run/foo.socket",
453                "password": ""
454            }
455        },
456        {
457            "comment": "Cannot-be-a-base means no password",
458            "href": "mailto:me@example.net",
459            "new_value": "secret",
460            "expected": {
461                "href": "mailto:me@example.net",
462                "password": ""
463            }
464        },
465        {
466            "href": "http://example.net",
467            "new_value": "secret",
468            "expected": {
469                "href": "http://:secret@example.net/",
470                "password": "secret"
471            }
472        },
473        {
474            "href": "http://me@example.net",
475            "new_value": "secret",
476            "expected": {
477                "href": "http://me:secret@example.net/",
478                "password": "secret"
479            }
480        },
481        {
482            "href": "http://:secret@example.net",
483            "new_value": "",
484            "expected": {
485                "href": "http://example.net/",
486                "password": ""
487            }
488        },
489        {
490            "href": "http://me:secret@example.net",
491            "new_value": "",
492            "expected": {
493                "href": "http://me@example.net/",
494                "password": ""
495            }
496        },
497        {
498            "comment": "UTF-8 percent encoding with the userinfo encode set.",
499            "href": "http://example.net",
500            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
501            "expected": {
502                "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/",
503                "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"
504            }
505        },
506        {
507            "comment": "Bytes already percent-encoded are left as-is.",
508            "href": "http://example.net",
509            "new_value": "%c3%89té",
510            "expected": {
511                "href": "http://:%c3%89t%C3%A9@example.net/",
512                "password": "%c3%89t%C3%A9"
513            }
514        },
515        {
516            "href": "sc:///",
517            "new_value": "x",
518            "expected": {
519                "href": "sc:///",
520                "password": ""
521            }
522        },
523        {
524            "href": "javascript://x/",
525            "new_value": "bowser",
526            "expected": {
527                "href": "javascript://:bowser@x/",
528                "password": "bowser"
529            }
530        },
531        {
532            "href": "file://test/",
533            "new_value": "test",
534            "expected": {
535                "href": "file://test/",
536                "password": ""
537            }
538        }
539    ],
540    "host": [
541        {
542            "comment": "Non-special scheme",
543            "href": "sc://x/",
544            "new_value": "\u0000",
545            "expected": {
546                "href": "sc://x/",
547                "host": "x",
548                "hostname": "x"
549            }
550        },
551        {
552            "href": "sc://x/",
553            "new_value": "\u0009",
554            "expected": {
555                "href": "sc:///",
556                "host": "",
557                "hostname": ""
558            }
559        },
560        {
561            "href": "sc://x/",
562            "new_value": "\u000A",
563            "expected": {
564                "href": "sc:///",
565                "host": "",
566                "hostname": ""
567            }
568        },
569        {
570            "href": "sc://x/",
571            "new_value": "\u000D",
572            "expected": {
573                "href": "sc:///",
574                "host": "",
575                "hostname": ""
576            }
577        },
578        {
579            "href": "sc://x/",
580            "new_value": " ",
581            "expected": {
582                "href": "sc://x/",
583                "host": "x",
584                "hostname": "x"
585            }
586        },
587        {
588            "href": "sc://x/",
589            "new_value": "#",
590            "expected": {
591                "href": "sc:///",
592                "host": "",
593                "hostname": ""
594            }
595        },
596        {
597            "href": "sc://x/",
598            "new_value": "/",
599            "expected": {
600                "href": "sc:///",
601                "host": "",
602                "hostname": ""
603            }
604        },
605        {
606            "href": "sc://x/",
607            "new_value": "?",
608            "expected": {
609                "href": "sc:///",
610                "host": "",
611                "hostname": ""
612            }
613        },
614        {
615            "href": "sc://x/",
616            "new_value": "@",
617            "expected": {
618                "href": "sc://x/",
619                "host": "x",
620                "hostname": "x"
621            }
622        },
623        {
624            "href": "sc://x/",
625            "new_value": "ß",
626            "expected": {
627                "href": "sc://%C3%9F/",
628                "host": "%C3%9F",
629                "hostname": "%C3%9F"
630            }
631        },
632        {
633            "comment": "IDNA Nontransitional_Processing",
634            "href": "https://x/",
635            "new_value": "ß",
636            "expected": {
637                "href": "https://xn--zca/",
638                "host": "xn--zca",
639                "hostname": "xn--zca"
640            }
641        },
642        {
643            "comment": "Cannot-be-a-base means no host",
644            "href": "mailto:me@example.net",
645            "new_value": "example.com",
646            "expected": {
647                "href": "mailto:me@example.net",
648                "host": ""
649            }
650        },
651        {
652            "comment": "Cannot-be-a-base means no host",
653            "href": "data:text/plain,Stuff",
654            "new_value": "example.net",
655            "expected": {
656                "href": "data:text/plain,Stuff",
657                "host": ""
658            }
659        },
660        {
661            "href": "http://example.net",
662            "new_value": "example.com:8080",
663            "expected": {
664                "href": "http://example.com:8080/",
665                "host": "example.com:8080",
666                "hostname": "example.com",
667                "port": "8080"
668            }
669        },
670        {
671            "comment": "Port number is unchanged if not specified in the new value",
672            "href": "http://example.net:8080",
673            "new_value": "example.com",
674            "expected": {
675                "href": "http://example.com:8080/",
676                "host": "example.com:8080",
677                "hostname": "example.com",
678                "port": "8080"
679            }
680        },
681        {
682            "comment": "Port number is unchanged if not specified",
683            "href": "http://example.net:8080",
684            "new_value": "example.com:",
685            "expected": {
686                "href": "http://example.com:8080/",
687                "host": "example.com:8080",
688                "hostname": "example.com",
689                "port": "8080"
690            }
691        },
692        {
693            "comment": "The empty host is not valid for special schemes",
694            "href": "http://example.net",
695            "new_value": "",
696            "expected": {
697                "href": "http://example.net/",
698                "host": "example.net"
699            }
700        },
701        {
702            "comment": "The empty host is OK for non-special schemes",
703            "href": "view-source+http://example.net/foo",
704            "new_value": "",
705            "expected": {
706                "href": "view-source+http:///foo",
707                "host": ""
708            }
709        },
710        {
711            "comment": "Path-only URLs can gain a host",
712            "href": "a:/foo",
713            "new_value": "example.net",
714            "expected": {
715                "href": "a://example.net/foo",
716                "host": "example.net"
717            }
718        },
719        {
720            "comment": "IPv4 address syntax is normalized",
721            "href": "http://example.net",
722            "new_value": "0x7F000001:8080",
723            "expected": {
724                "href": "http://127.0.0.1:8080/",
725                "host": "127.0.0.1:8080",
726                "hostname": "127.0.0.1",
727                "port": "8080"
728            }
729        },
730        {
731            "comment": "IPv6 address syntax is normalized",
732            "href": "http://example.net",
733            "new_value": "[::0:01]:2",
734            "expected": {
735                "href": "http://[::1]:2/",
736                "host": "[::1]:2",
737                "hostname": "[::1]",
738                "port": "2"
739            }
740        },
741        {
742            "comment": "IPv6 literal address with port, crbug.com/1012416",
743            "href": "http://example.net",
744            "new_value": "[2001:db8::2]:4002",
745            "expected": {
746                "href": "http://[2001:db8::2]:4002/",
747                "host": "[2001:db8::2]:4002",
748                "hostname": "[2001:db8::2]",
749                "port": "4002"
750             }
751        },
752        {
753            "comment": "Default port number is removed",
754            "href": "http://example.net",
755            "new_value": "example.com:80",
756            "expected": {
757                "href": "http://example.com/",
758                "host": "example.com",
759                "hostname": "example.com",
760                "port": ""
761            }
762        },
763        {
764            "comment": "Default port number is removed",
765            "href": "https://example.net",
766            "new_value": "example.com:443",
767            "expected": {
768                "href": "https://example.com/",
769                "host": "example.com",
770                "hostname": "example.com",
771                "port": ""
772            }
773        },
774        {
775            "comment": "Default port number is only removed for the relevant scheme",
776            "href": "https://example.net",
777            "new_value": "example.com:80",
778            "expected": {
779                "href": "https://example.com:80/",
780                "host": "example.com:80",
781                "hostname": "example.com",
782                "port": "80"
783            }
784        },
785        {
786            "comment": "Port number is removed if new port is scheme default and existing URL has a non-default port",
787            "href": "http://example.net:8080",
788            "new_value": "example.com:80",
789            "expected": {
790                "href": "http://example.com/",
791                "host": "example.com",
792                "hostname": "example.com",
793                "port": ""
794            }
795        },
796        {
797            "comment": "Stuff after a / delimiter is ignored",
798            "href": "http://example.net/path",
799            "new_value": "example.com/stuff",
800            "expected": {
801                "href": "http://example.com/path",
802                "host": "example.com",
803                "hostname": "example.com",
804                "port": ""
805            }
806        },
807        {
808            "comment": "Stuff after a / delimiter is ignored",
809            "href": "http://example.net/path",
810            "new_value": "example.com:8080/stuff",
811            "expected": {
812                "href": "http://example.com:8080/path",
813                "host": "example.com:8080",
814                "hostname": "example.com",
815                "port": "8080"
816            }
817        },
818        {
819            "comment": "Stuff after a ? delimiter is ignored",
820            "href": "http://example.net/path",
821            "new_value": "example.com?stuff",
822            "expected": {
823                "href": "http://example.com/path",
824                "host": "example.com",
825                "hostname": "example.com",
826                "port": ""
827            }
828        },
829        {
830            "comment": "Stuff after a ? delimiter is ignored",
831            "href": "http://example.net/path",
832            "new_value": "example.com:8080?stuff",
833            "expected": {
834                "href": "http://example.com:8080/path",
835                "host": "example.com:8080",
836                "hostname": "example.com",
837                "port": "8080"
838            }
839        },
840        {
841            "comment": "Stuff after a # delimiter is ignored",
842            "href": "http://example.net/path",
843            "new_value": "example.com#stuff",
844            "expected": {
845                "href": "http://example.com/path",
846                "host": "example.com",
847                "hostname": "example.com",
848                "port": ""
849            }
850        },
851        {
852            "comment": "Stuff after a # delimiter is ignored",
853            "href": "http://example.net/path",
854            "new_value": "example.com:8080#stuff",
855            "expected": {
856                "href": "http://example.com:8080/path",
857                "host": "example.com:8080",
858                "hostname": "example.com",
859                "port": "8080"
860            }
861        },
862        {
863            "comment": "Stuff after a \\ delimiter is ignored for special schemes",
864            "href": "http://example.net/path",
865            "new_value": "example.com\\stuff",
866            "expected": {
867                "href": "http://example.com/path",
868                "host": "example.com",
869                "hostname": "example.com",
870                "port": ""
871            }
872        },
873        {
874            "comment": "Stuff after a \\ delimiter is ignored for special schemes",
875            "href": "http://example.net/path",
876            "new_value": "example.com:8080\\stuff",
877            "expected": {
878                "href": "http://example.com:8080/path",
879                "host": "example.com:8080",
880                "hostname": "example.com",
881                "port": "8080"
882            }
883        },
884        {
885            "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
886            "href": "view-source+http://example.net/path",
887            "new_value": "example.com\\stuff",
888            "expected": {
889                "href": "view-source+http://example.net/path",
890                "host": "example.net",
891                "hostname": "example.net",
892                "port": ""
893            }
894        },
895        {
896            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
897            "href": "view-source+http://example.net/path",
898            "new_value": "example.com:8080stuff2",
899            "expected": {
900                "href": "view-source+http://example.com:8080/path",
901                "host": "example.com:8080",
902                "hostname": "example.com",
903                "port": "8080"
904            }
905        },
906        {
907            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
908            "href": "http://example.net/path",
909            "new_value": "example.com:8080stuff2",
910            "expected": {
911                "href": "http://example.com:8080/path",
912                "host": "example.com:8080",
913                "hostname": "example.com",
914                "port": "8080"
915            }
916        },
917        {
918            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
919            "href": "http://example.net/path",
920            "new_value": "example.com:8080+2",
921            "expected": {
922                "href": "http://example.com:8080/path",
923                "host": "example.com:8080",
924                "hostname": "example.com",
925                "port": "8080"
926            }
927        },
928        {
929            "comment": "Port numbers are 16 bit integers",
930            "href": "http://example.net/path",
931            "new_value": "example.com:65535",
932            "expected": {
933                "href": "http://example.com:65535/path",
934                "host": "example.com:65535",
935                "hostname": "example.com",
936                "port": "65535"
937            }
938        },
939        {
940            "comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.",
941            "href": "http://example.net/path",
942            "new_value": "example.com:65536",
943            "expected": {
944                "href": "http://example.com/path",
945                "host": "example.com",
946                "hostname": "example.com",
947                "port": ""
948            }
949        },
950        {
951            "comment": "Broken IPv6",
952            "href": "http://example.net/",
953            "new_value": "[google.com]",
954            "expected": {
955                "href": "http://example.net/",
956                "host": "example.net",
957                "hostname": "example.net"
958            }
959        },
960        {
961            "href": "http://example.net/",
962            "new_value": "[::1.2.3.4x]",
963            "expected": {
964                "href": "http://example.net/",
965                "host": "example.net",
966                "hostname": "example.net"
967            }
968        },
969        {
970            "href": "http://example.net/",
971            "new_value": "[::1.2.3.]",
972            "expected": {
973                "href": "http://example.net/",
974                "host": "example.net",
975                "hostname": "example.net"
976            }
977        },
978        {
979            "href": "http://example.net/",
980            "new_value": "[::1.2.]",
981            "expected": {
982                "href": "http://example.net/",
983                "host": "example.net",
984                "hostname": "example.net"
985            }
986        },
987        {
988            "href": "http://example.net/",
989            "new_value": "[::1.]",
990            "expected": {
991                "href": "http://example.net/",
992                "host": "example.net",
993                "hostname": "example.net"
994            }
995        },
996        {
997            "href": "file://y/",
998            "new_value": "x:123",
999            "expected": {
1000                "href": "file://y/",
1001                "host": "y",
1002                "hostname": "y",
1003                "port": ""
1004            }
1005        },
1006        {
1007            "href": "file://y/",
1008            "new_value": "loc%41lhost",
1009            "expected": {
1010                "href": "file:///",
1011                "host": "",
1012                "hostname": "",
1013                "port": ""
1014            }
1015        },
1016        {
1017            "href": "file://hi/x",
1018            "new_value": "",
1019            "expected": {
1020                "href": "file:///x",
1021                "host": "",
1022                "hostname": "",
1023                "port": ""
1024            }
1025        },
1026        {
1027            "href": "sc://test@test/",
1028            "new_value": "",
1029            "expected": {
1030                "href": "sc://test@test/",
1031                "host": "test",
1032                "hostname": "test",
1033                "username": "test"
1034            }
1035        },
1036        {
1037            "href": "sc://test:12/",
1038            "new_value": "",
1039            "expected": {
1040                "href": "sc://test:12/",
1041                "host": "test:12",
1042                "hostname": "test",
1043                "port": "12"
1044            }
1045        },
1046        {
1047            "comment": "Leading / is not stripped",
1048            "href": "http://example.com/",
1049            "new_value": "///bad.com",
1050            "expected": {
1051                "href": "http://example.com/",
1052                "host": "example.com",
1053                "hostname": "example.com"
1054            }
1055        },
1056        {
1057            "comment": "Leading / is not stripped",
1058            "href": "sc://example.com/",
1059            "new_value": "///bad.com",
1060            "expected": {
1061                "href": "sc:///",
1062                "host": "",
1063                "hostname": ""
1064            }
1065        },
1066        {
1067            "href": "https://example.com/",
1068            "new_value": "a%C2%ADb",
1069            "expected": {
1070                "href": "https://ab/",
1071                "host": "ab",
1072                "hostname": "ab"
1073            }
1074        },
1075        {
1076            "href": "https://example.com/",
1077            "new_value": "\u00AD",
1078            "expected": {
1079                "href": "https://example.com/",
1080                "host": "example.com",
1081                "hostname": "example.com"
1082            }
1083        },
1084        {
1085            "href": "https://example.com/",
1086            "new_value": "%C2%AD",
1087            "expected": {
1088                "href": "https://example.com/",
1089                "host": "example.com",
1090                "hostname": "example.com"
1091            }
1092        },
1093        {
1094            "href": "https://example.com/",
1095            "new_value": "xn--",
1096            "expected": {
1097                "href": "https://example.com/",
1098                "host": "example.com",
1099                "hostname": "example.com"
1100            }
1101        }
1102    ],
1103    "hostname": [
1104        {
1105            "comment": "Non-special scheme",
1106            "href": "sc://x/",
1107            "new_value": "\u0000",
1108            "expected": {
1109                "href": "sc://x/",
1110                "host": "x",
1111                "hostname": "x"
1112            }
1113        },
1114        {
1115            "href": "sc://x/",
1116            "new_value": "\u0009",
1117            "expected": {
1118                "href": "sc:///",
1119                "host": "",
1120                "hostname": ""
1121            }
1122        },
1123        {
1124            "href": "sc://x/",
1125            "new_value": "\u000A",
1126            "expected": {
1127                "href": "sc:///",
1128                "host": "",
1129                "hostname": ""
1130            }
1131        },
1132        {
1133            "href": "sc://x/",
1134            "new_value": "\u000D",
1135            "expected": {
1136                "href": "sc:///",
1137                "host": "",
1138                "hostname": ""
1139            }
1140        },
1141        {
1142            "href": "sc://x/",
1143            "new_value": " ",
1144            "expected": {
1145                "href": "sc://x/",
1146                "host": "x",
1147                "hostname": "x"
1148            }
1149        },
1150        {
1151            "href": "sc://x/",
1152            "new_value": "#",
1153            "expected": {
1154                "href": "sc:///",
1155                "host": "",
1156                "hostname": ""
1157            }
1158        },
1159        {
1160            "href": "sc://x/",
1161            "new_value": "/",
1162            "expected": {
1163                "href": "sc:///",
1164                "host": "",
1165                "hostname": ""
1166            }
1167        },
1168        {
1169            "href": "sc://x/",
1170            "new_value": "?",
1171            "expected": {
1172                "href": "sc:///",
1173                "host": "",
1174                "hostname": ""
1175            }
1176        },
1177        {
1178            "href": "sc://x/",
1179            "new_value": "@",
1180            "expected": {
1181                "href": "sc://x/",
1182                "host": "x",
1183                "hostname": "x"
1184            }
1185        },
1186        {
1187            "comment": "Cannot-be-a-base means no host",
1188            "href": "mailto:me@example.net",
1189            "new_value": "example.com",
1190            "expected": {
1191                "href": "mailto:me@example.net",
1192                "host": ""
1193            }
1194        },
1195        {
1196            "comment": "Cannot-be-a-base means no host",
1197            "href": "data:text/plain,Stuff",
1198            "new_value": "example.net",
1199            "expected": {
1200                "href": "data:text/plain,Stuff",
1201                "host": ""
1202            }
1203        },
1204        {
1205            "href": "http://example.net:8080",
1206            "new_value": "example.com",
1207            "expected": {
1208                "href": "http://example.com:8080/",
1209                "host": "example.com:8080",
1210                "hostname": "example.com",
1211                "port": "8080"
1212            }
1213        },
1214        {
1215            "comment": "The empty host is not valid for special schemes",
1216            "href": "http://example.net",
1217            "new_value": "",
1218            "expected": {
1219                "href": "http://example.net/",
1220                "host": "example.net"
1221            }
1222        },
1223        {
1224            "comment": "The empty host is OK for non-special schemes",
1225            "href": "view-source+http://example.net/foo",
1226            "new_value": "",
1227            "expected": {
1228                "href": "view-source+http:///foo",
1229                "host": ""
1230            }
1231        },
1232        {
1233            "comment": "Path-only URLs can gain a host",
1234            "href": "a:/foo",
1235            "new_value": "example.net",
1236            "expected": {
1237                "href": "a://example.net/foo",
1238                "host": "example.net"
1239            }
1240        },
1241        {
1242            "comment": "IPv4 address syntax is normalized",
1243            "href": "http://example.net:8080",
1244            "new_value": "0x7F000001",
1245            "expected": {
1246                "href": "http://127.0.0.1:8080/",
1247                "host": "127.0.0.1:8080",
1248                "hostname": "127.0.0.1",
1249                "port": "8080"
1250            }
1251        },
1252        {
1253            "comment": "IPv6 address syntax is normalized",
1254            "href": "http://example.net",
1255            "new_value": "[::0:01]",
1256            "expected": {
1257                "href": "http://[::1]/",
1258                "host": "[::1]",
1259                "hostname": "[::1]",
1260                "port": ""
1261            }
1262        },
1263        {
1264            "comment": ": delimiter invalidates entire value",
1265            "href": "http://example.net/path",
1266            "new_value": "example.com:8080",
1267            "expected": {
1268                "href": "http://example.net/path",
1269                "host": "example.net",
1270                "hostname": "example.net",
1271                "port": ""
1272            }
1273        },
1274        {
1275            "comment": ": delimiter invalidates entire value",
1276            "href": "http://example.net:8080/path",
1277            "new_value": "example.com:",
1278            "expected": {
1279                "href": "http://example.net:8080/path",
1280                "host": "example.net:8080",
1281                "hostname": "example.net",
1282                "port": "8080"
1283            }
1284        },
1285        {
1286            "comment": "Stuff after a / delimiter is ignored",
1287            "href": "http://example.net/path",
1288            "new_value": "example.com/stuff",
1289            "expected": {
1290                "href": "http://example.com/path",
1291                "host": "example.com",
1292                "hostname": "example.com",
1293                "port": ""
1294            }
1295        },
1296        {
1297            "comment": "Stuff after a ? delimiter is ignored",
1298            "href": "http://example.net/path",
1299            "new_value": "example.com?stuff",
1300            "expected": {
1301                "href": "http://example.com/path",
1302                "host": "example.com",
1303                "hostname": "example.com",
1304                "port": ""
1305            }
1306        },
1307        {
1308            "comment": "Stuff after a # delimiter is ignored",
1309            "href": "http://example.net/path",
1310            "new_value": "example.com#stuff",
1311            "expected": {
1312                "href": "http://example.com/path",
1313                "host": "example.com",
1314                "hostname": "example.com",
1315                "port": ""
1316            }
1317        },
1318        {
1319            "comment": "Stuff after a \\ delimiter is ignored for special schemes",
1320            "href": "http://example.net/path",
1321            "new_value": "example.com\\stuff",
1322            "expected": {
1323                "href": "http://example.com/path",
1324                "host": "example.com",
1325                "hostname": "example.com",
1326                "port": ""
1327            }
1328        },
1329        {
1330            "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
1331            "href": "view-source+http://example.net/path",
1332            "new_value": "example.com\\stuff",
1333            "expected": {
1334                "href": "view-source+http://example.net/path",
1335                "host": "example.net",
1336                "hostname": "example.net",
1337                "port": ""
1338            }
1339        },
1340        {
1341            "comment": "Broken IPv6",
1342            "href": "http://example.net/",
1343            "new_value": "[google.com]",
1344            "expected": {
1345                "href": "http://example.net/",
1346                "host": "example.net",
1347                "hostname": "example.net"
1348            }
1349        },
1350        {
1351            "href": "http://example.net/",
1352            "new_value": "[::1.2.3.4x]",
1353            "expected": {
1354                "href": "http://example.net/",
1355                "host": "example.net",
1356                "hostname": "example.net"
1357            }
1358        },
1359        {
1360            "href": "http://example.net/",
1361            "new_value": "[::1.2.3.]",
1362            "expected": {
1363                "href": "http://example.net/",
1364                "host": "example.net",
1365                "hostname": "example.net"
1366            }
1367        },
1368        {
1369            "href": "http://example.net/",
1370            "new_value": "[::1.2.]",
1371            "expected": {
1372                "href": "http://example.net/",
1373                "host": "example.net",
1374                "hostname": "example.net"
1375            }
1376        },
1377        {
1378            "href": "http://example.net/",
1379            "new_value": "[::1.]",
1380            "expected": {
1381                "href": "http://example.net/",
1382                "host": "example.net",
1383                "hostname": "example.net"
1384            }
1385        },
1386        {
1387            "href": "file://y/",
1388            "new_value": "x:123",
1389            "expected": {
1390                "href": "file://y/",
1391                "host": "y",
1392                "hostname": "y",
1393                "port": ""
1394            }
1395        },
1396        {
1397            "href": "file://y/",
1398            "new_value": "loc%41lhost",
1399            "expected": {
1400                "href": "file:///",
1401                "host": "",
1402                "hostname": "",
1403                "port": ""
1404            }
1405        },
1406        {
1407            "href": "file://hi/x",
1408            "new_value": "",
1409            "expected": {
1410                "href": "file:///x",
1411                "host": "",
1412                "hostname": "",
1413                "port": ""
1414            }
1415        },
1416        {
1417            "href": "sc://test@test/",
1418            "new_value": "",
1419            "expected": {
1420                "href": "sc://test@test/",
1421                "host": "test",
1422                "hostname": "test",
1423                "username": "test"
1424            }
1425        },
1426        {
1427            "href": "sc://test:12/",
1428            "new_value": "",
1429            "expected": {
1430                "href": "sc://test:12/",
1431                "host": "test:12",
1432                "hostname": "test",
1433                "port": "12"
1434            }
1435        },
1436        {
1437            "comment": "Drop /. from path",
1438            "href": "non-spec:/.//p",
1439            "new_value": "h",
1440            "expected": {
1441                "href": "non-spec://h//p",
1442                "host": "h",
1443                "hostname": "h",
1444                "pathname": "//p"
1445            }
1446        },
1447        {
1448            "href": "non-spec:/.//p",
1449            "new_value": "",
1450            "expected": {
1451                "href": "non-spec:////p",
1452                "host": "",
1453                "hostname": "",
1454                "pathname": "//p"
1455            }
1456        },
1457        {
1458            "comment": "Leading / is not stripped",
1459            "href": "http://example.com/",
1460            "new_value": "///bad.com",
1461            "expected": {
1462                "href": "http://example.com/",
1463                "host": "example.com",
1464                "hostname": "example.com"
1465            }
1466        },
1467        {
1468            "comment": "Leading / is not stripped",
1469            "href": "sc://example.com/",
1470            "new_value": "///bad.com",
1471            "expected": {
1472                "href": "sc:///",
1473                "host": "",
1474                "hostname": ""
1475            }
1476        },
1477        {
1478            "href": "https://example.com/",
1479            "new_value": "a%C2%ADb",
1480            "expected": {
1481                "href": "https://ab/",
1482                "host": "ab",
1483                "hostname": "ab"
1484            }
1485        },
1486        {
1487            "href": "https://example.com/",
1488            "new_value": "\u00AD",
1489            "expected": {
1490                "href": "https://example.com/",
1491                "host": "example.com",
1492                "hostname": "example.com"
1493            }
1494        },
1495        {
1496            "href": "https://example.com/",
1497            "new_value": "%C2%AD",
1498            "expected": {
1499                "href": "https://example.com/",
1500                "host": "example.com",
1501                "hostname": "example.com"
1502            }
1503        },
1504        {
1505            "href": "https://example.com/",
1506            "new_value": "xn--",
1507            "expected": {
1508                "href": "https://example.com/",
1509                "host": "example.com",
1510                "hostname": "example.com"
1511            }
1512        }
1513    ],
1514    "port": [
1515        {
1516            "href": "http://example.net",
1517            "new_value": "8080",
1518            "expected": {
1519                "href": "http://example.net:8080/",
1520                "host": "example.net:8080",
1521                "hostname": "example.net",
1522                "port": "8080"
1523            }
1524        },
1525        {
1526            "comment": "Port number is removed if empty is the new value",
1527            "href": "http://example.net:8080",
1528            "new_value": "",
1529            "expected": {
1530                "href": "http://example.net/",
1531                "host": "example.net",
1532                "hostname": "example.net",
1533                "port": ""
1534            }
1535        },
1536        {
1537            "comment": "Default port number is removed",
1538            "href": "http://example.net:8080",
1539            "new_value": "80",
1540            "expected": {
1541                "href": "http://example.net/",
1542                "host": "example.net",
1543                "hostname": "example.net",
1544                "port": ""
1545            }
1546        },
1547        {
1548            "comment": "Default port number is removed",
1549            "href": "https://example.net:4433",
1550            "new_value": "443",
1551            "expected": {
1552                "href": "https://example.net/",
1553                "host": "example.net",
1554                "hostname": "example.net",
1555                "port": ""
1556            }
1557        },
1558        {
1559            "comment": "Default port number is only removed for the relevant scheme",
1560            "href": "https://example.net",
1561            "new_value": "80",
1562            "expected": {
1563                "href": "https://example.net:80/",
1564                "host": "example.net:80",
1565                "hostname": "example.net",
1566                "port": "80"
1567            }
1568        },
1569        {
1570            "comment": "Stuff after a / delimiter is ignored",
1571            "href": "http://example.net/path",
1572            "new_value": "8080/stuff",
1573            "expected": {
1574                "href": "http://example.net:8080/path",
1575                "host": "example.net:8080",
1576                "hostname": "example.net",
1577                "port": "8080"
1578            }
1579        },
1580        {
1581            "comment": "Stuff after a ? delimiter is ignored",
1582            "href": "http://example.net/path",
1583            "new_value": "8080?stuff",
1584            "expected": {
1585                "href": "http://example.net:8080/path",
1586                "host": "example.net:8080",
1587                "hostname": "example.net",
1588                "port": "8080"
1589            }
1590        },
1591        {
1592            "comment": "Stuff after a # delimiter is ignored",
1593            "href": "http://example.net/path",
1594            "new_value": "8080#stuff",
1595            "expected": {
1596                "href": "http://example.net:8080/path",
1597                "host": "example.net:8080",
1598                "hostname": "example.net",
1599                "port": "8080"
1600            }
1601        },
1602        {
1603            "comment": "Stuff after a \\ delimiter is ignored for special schemes",
1604            "href": "http://example.net/path",
1605            "new_value": "8080\\stuff",
1606            "expected": {
1607                "href": "http://example.net:8080/path",
1608                "host": "example.net:8080",
1609                "hostname": "example.net",
1610                "port": "8080"
1611            }
1612        },
1613        {
1614            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
1615            "href": "view-source+http://example.net/path",
1616            "new_value": "8080stuff2",
1617            "expected": {
1618                "href": "view-source+http://example.net:8080/path",
1619                "host": "example.net:8080",
1620                "hostname": "example.net",
1621                "port": "8080"
1622            }
1623        },
1624        {
1625            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
1626            "href": "http://example.net/path",
1627            "new_value": "8080stuff2",
1628            "expected": {
1629                "href": "http://example.net:8080/path",
1630                "host": "example.net:8080",
1631                "hostname": "example.net",
1632                "port": "8080"
1633            }
1634        },
1635        {
1636            "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
1637            "href": "http://example.net/path",
1638            "new_value": "8080+2",
1639            "expected": {
1640                "href": "http://example.net:8080/path",
1641                "host": "example.net:8080",
1642                "hostname": "example.net",
1643                "port": "8080"
1644            }
1645        },
1646        {
1647            "comment": "Port numbers are 16 bit integers",
1648            "href": "http://example.net/path",
1649            "new_value": "65535",
1650            "expected": {
1651                "href": "http://example.net:65535/path",
1652                "host": "example.net:65535",
1653                "hostname": "example.net",
1654                "port": "65535"
1655            }
1656        },
1657        {
1658            "comment": "Port numbers are 16 bit integers, overflowing is an error",
1659            "href": "http://example.net:8080/path",
1660            "new_value": "65536",
1661            "expected": {
1662                "href": "http://example.net:8080/path",
1663                "host": "example.net:8080",
1664                "hostname": "example.net",
1665                "port": "8080"
1666            }
1667        },
1668        {
1669            "comment": "Setting port to a string that doesn't parse as a number",
1670            "href": "http://example.net:8080/path",
1671            "new_value": "randomstring",
1672            "expected": {
1673                "href": "http://example.net:8080/path",
1674                "host": "example.net:8080",
1675                "hostname": "example.net",
1676                "port": "8080"
1677            }
1678        },
1679        {
1680            "comment": "Port numbers are 16 bit integers, overflowing is an error",
1681            "href": "non-special://example.net:8080/path",
1682            "new_value": "65536",
1683            "expected": {
1684                "href": "non-special://example.net:8080/path",
1685                "host": "example.net:8080",
1686                "hostname": "example.net",
1687                "port": "8080"
1688            }
1689        },
1690        {
1691            "href": "file://test/",
1692            "new_value": "12",
1693            "expected": {
1694                "href": "file://test/",
1695                "port": ""
1696            }
1697        },
1698        {
1699            "href": "file://localhost/",
1700            "new_value": "12",
1701            "expected": {
1702                "href": "file:///",
1703                "port": ""
1704            }
1705        },
1706        {
1707            "href": "non-base:value",
1708            "new_value": "12",
1709            "expected": {
1710                "href": "non-base:value",
1711                "port": ""
1712            }
1713        },
1714        {
1715            "href": "sc:///",
1716            "new_value": "12",
1717            "expected": {
1718                "href": "sc:///",
1719                "port": ""
1720            }
1721        },
1722        {
1723            "href": "sc://x/",
1724            "new_value": "12",
1725            "expected": {
1726                "href": "sc://x:12/",
1727                "port": "12"
1728            }
1729        },
1730        {
1731            "href": "javascript://x/",
1732            "new_value": "12",
1733            "expected": {
1734                "href": "javascript://x:12/",
1735                "port": "12"
1736            }
1737        },
1738        {
1739            "comment": "Leading u0009 on special scheme",
1740            "href": "https://domain.com:443",
1741            "new_value": "\u00098080",
1742            "expected": {
1743                "port": "8080"
1744            }
1745        },
1746        {
1747            "comment": "Leading u0009 on non-special scheme",
1748            "href": "wpt++://domain.com:443",
1749            "new_value": "\u00098080",
1750            "expected": {
1751                "port": "8080"
1752            }
1753        },
1754        {
1755            "comment": "Should use all ascii prefixed characters as port",
1756            "href": "https://www.google.com:4343",
1757            "new_value": "4wpt",
1758            "expected": {
1759                "port": "4"
1760            }
1761        }
1762    ],
1763    "pathname": [
1764        {
1765            "comment": "Opaque paths cannot be set",
1766            "href": "mailto:me@example.net",
1767            "new_value": "/foo",
1768            "expected": {
1769                "href": "mailto:me@example.net",
1770                "pathname": "me@example.net"
1771            }
1772        },
1773        {
1774            "href": "data:original",
1775            "new_value": "new value",
1776            "expected": {
1777                "href": "data:original",
1778                "pathname": "original"
1779            }
1780        },
1781        {
1782            "href": "sc:original",
1783            "new_value": "new value",
1784            "expected": {
1785                "href": "sc:original",
1786                "pathname": "original"
1787            }
1788        },
1789        {
1790            "comment": "Special URLs cannot have their paths erased",
1791            "href": "file:///some/path",
1792            "new_value": "",
1793            "expected": {
1794                "href": "file:///",
1795                "pathname": "/"
1796            }
1797        },
1798        {
1799            "comment": "Non-special URLs can have their paths erased",
1800            "href": "foo://somehost/some/path",
1801            "new_value": "",
1802            "expected": {
1803                "href": "foo://somehost",
1804                "pathname": ""
1805            }
1806        },
1807        {
1808            "comment": "Non-special URLs with an empty host can have their paths erased",
1809            "href": "foo:///some/path",
1810            "new_value": "",
1811            "expected": {
1812                "href": "foo://",
1813                "pathname": ""
1814            }
1815        },
1816        {
1817            "comment": "Path-only URLs cannot have their paths erased",
1818            "href": "foo:/some/path",
1819            "new_value": "",
1820            "expected": {
1821                "href": "foo:/",
1822                "pathname": "/"
1823            }
1824        },
1825        {
1826            "comment": "Path-only URLs always have an initial slash",
1827            "href": "foo:/some/path",
1828            "new_value": "test",
1829            "expected": {
1830                "href": "foo:/test",
1831                "pathname": "/test"
1832            }
1833        },
1834        {
1835            "href": "unix:/run/foo.socket?timeout=10",
1836            "new_value": "/var/log/../run/bar.socket",
1837            "expected": {
1838                "href": "unix:/var/run/bar.socket?timeout=10",
1839                "pathname": "/var/run/bar.socket"
1840            }
1841        },
1842        {
1843            "href": "https://example.net#nav",
1844            "new_value": "home",
1845            "expected": {
1846                "href": "https://example.net/home#nav",
1847                "pathname": "/home"
1848            }
1849        },
1850        {
1851            "href": "https://example.net#nav",
1852            "new_value": "../home",
1853            "expected": {
1854                "href": "https://example.net/home#nav",
1855                "pathname": "/home"
1856            }
1857        },
1858        {
1859            "comment": "\\ is a segment delimiter for 'special' URLs",
1860            "href": "http://example.net/home?lang=fr#nav",
1861            "new_value": "\\a\\%2E\\b\\%2e.\\c",
1862            "expected": {
1863                "href": "http://example.net/a/c?lang=fr#nav",
1864                "pathname": "/a/c"
1865            }
1866        },
1867        {
1868            "comment": "\\ is *not* a segment delimiter for non-'special' URLs",
1869            "href": "view-source+http://example.net/home?lang=fr#nav",
1870            "new_value": "\\a\\%2E\\b\\%2e.\\c",
1871            "expected": {
1872                "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav",
1873                "pathname": "/\\a\\%2E\\b\\%2e.\\c"
1874            }
1875        },
1876        {
1877            "comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.",
1878            "href": "a:/",
1879            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
1880            "expected": {
1881                "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",
1882                "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
1883            }
1884        },
1885        {
1886            "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.",
1887            "href": "http://example.net",
1888            "new_value": "%2e%2E%c3%89té",
1889            "expected": {
1890                "href": "http://example.net/%2e%2E%c3%89t%C3%A9",
1891                "pathname": "/%2e%2E%c3%89t%C3%A9"
1892            }
1893        },
1894        {
1895            "comment": "? needs to be encoded",
1896            "href": "http://example.net",
1897            "new_value": "?",
1898            "expected": {
1899                "href": "http://example.net/%3F",
1900                "pathname": "/%3F"
1901            }
1902        },
1903        {
1904            "comment": "# needs to be encoded",
1905            "href": "http://example.net",
1906            "new_value": "#",
1907            "expected": {
1908                "href": "http://example.net/%23",
1909                "pathname": "/%23"
1910            }
1911        },
1912        {
1913            "comment": "? needs to be encoded, non-special scheme",
1914            "href": "sc://example.net",
1915            "new_value": "?",
1916            "expected": {
1917                "href": "sc://example.net/%3F",
1918                "pathname": "/%3F"
1919            }
1920        },
1921        {
1922            "comment": "# needs to be encoded, non-special scheme",
1923            "href": "sc://example.net",
1924            "new_value": "#",
1925            "expected": {
1926                "href": "sc://example.net/%23",
1927                "pathname": "/%23"
1928            }
1929        },
1930        {
1931            "comment": "? doesn't mess up encoding",
1932            "href": "http://example.net",
1933            "new_value": "/?é",
1934            "expected": {
1935                "href": "http://example.net/%3F%C3%A9",
1936                "pathname": "/%3F%C3%A9"
1937            }
1938        },
1939        {
1940            "comment": "# doesn't mess up encoding",
1941            "href": "http://example.net",
1942            "new_value": "/#é",
1943            "expected": {
1944                "href": "http://example.net/%23%C3%A9",
1945                "pathname": "/%23%C3%A9"
1946            }
1947        },
1948        {
1949            "comment": "File URLs and (back)slashes",
1950            "href": "file://monkey/",
1951            "new_value": "\\\\",
1952            "expected": {
1953                "href": "file://monkey//",
1954                "pathname": "//"
1955            }
1956        },
1957        {
1958            "comment": "File URLs and (back)slashes",
1959            "href": "file:///unicorn",
1960            "new_value": "//\\/",
1961            "expected": {
1962                "href": "file://////",
1963                "pathname": "////"
1964            }
1965        },
1966        {
1967            "comment": "File URLs and (back)slashes",
1968            "href": "file:///unicorn",
1969            "new_value": "//monkey/..//",
1970            "expected": {
1971                "href": "file://///",
1972                "pathname": "///"
1973            }
1974        },
1975        {
1976            "comment": "Serialize /. in path",
1977            "href": "non-spec:/",
1978            "new_value": "/.//p",
1979            "expected": {
1980                "href": "non-spec:/.//p",
1981                "pathname": "//p"
1982            }
1983        },
1984        {
1985            "href": "non-spec:/",
1986            "new_value": "/..//p",
1987            "expected": {
1988                "href": "non-spec:/.//p",
1989                "pathname": "//p"
1990            }
1991        },
1992        {
1993            "href": "non-spec:/",
1994            "new_value": "//p",
1995            "expected": {
1996                "href": "non-spec:/.//p",
1997                "pathname": "//p"
1998            }
1999        },
2000        {
2001            "comment": "Drop /. from path",
2002            "href": "non-spec:/.//",
2003            "new_value": "p",
2004            "expected": {
2005                "href": "non-spec:/p",
2006                "pathname": "/p"
2007            }
2008        },
2009        {
2010            "comment": "Non-special URLs with non-opaque paths percent-encode U+0020",
2011            "href": "data:/nospace",
2012            "new_value": "space ",
2013            "expected": {
2014                "href": "data:/space%20",
2015                "pathname": "/space%20"
2016            }
2017        },
2018        {
2019            "href": "sc:/nospace",
2020            "new_value": "space ",
2021            "expected": {
2022                "href": "sc:/space%20",
2023                "pathname": "/space%20"
2024            }
2025        },
2026        {
2027            "comment": "Trailing space should be encoded",
2028            "href": "http://example.net",
2029            "new_value": " ",
2030            "expected": {
2031                "href": "http://example.net/%20",
2032                "pathname": "/%20"
2033            }
2034        },
2035        {
2036            "comment": "Trailing C0 control should be encoded",
2037            "href": "http://example.net",
2038            "new_value": "\u0000",
2039            "expected": {
2040                "href": "http://example.net/%00",
2041                "pathname": "/%00"
2042            }
2043        }
2044    ],
2045    "search": [
2046        {
2047            "href": "https://example.net#nav",
2048            "new_value": "lang=fr",
2049            "expected": {
2050                "href": "https://example.net/?lang=fr#nav",
2051                "search": "?lang=fr"
2052            }
2053        },
2054        {
2055            "href": "https://example.net?lang=en-US#nav",
2056            "new_value": "lang=fr",
2057            "expected": {
2058                "href": "https://example.net/?lang=fr#nav",
2059                "search": "?lang=fr"
2060            }
2061        },
2062        {
2063            "href": "https://example.net?lang=en-US#nav",
2064            "new_value": "?lang=fr",
2065            "expected": {
2066                "href": "https://example.net/?lang=fr#nav",
2067                "search": "?lang=fr"
2068            }
2069        },
2070        {
2071            "href": "https://example.net?lang=en-US#nav",
2072            "new_value": "??lang=fr",
2073            "expected": {
2074                "href": "https://example.net/??lang=fr#nav",
2075                "search": "??lang=fr"
2076            }
2077        },
2078        {
2079            "href": "https://example.net?lang=en-US#nav",
2080            "new_value": "?",
2081            "expected": {
2082                "href": "https://example.net/?#nav",
2083                "search": ""
2084            }
2085        },
2086        {
2087            "href": "https://example.net?lang=en-US#nav",
2088            "new_value": "",
2089            "expected": {
2090                "href": "https://example.net/#nav",
2091                "search": ""
2092            }
2093        },
2094        {
2095            "href": "https://example.net?lang=en-US",
2096            "new_value": "",
2097            "expected": {
2098                "href": "https://example.net/",
2099                "search": ""
2100            }
2101        },
2102        {
2103            "href": "https://example.net",
2104            "new_value": "",
2105            "expected": {
2106                "href": "https://example.net/",
2107                "search": ""
2108            }
2109        },
2110        {
2111            "comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.",
2112            "href": "a:/",
2113            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
2114            "expected": {
2115                "href": "a:/?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
2116                "search": "?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
2117            }
2118        },
2119        {
2120            "comment": "Bytes already percent-encoded are left as-is",
2121            "href": "http://example.net",
2122            "new_value": "%c3%89té",
2123            "expected": {
2124                "href": "http://example.net/?%c3%89t%C3%A9",
2125                "search": "?%c3%89t%C3%A9"
2126            }
2127        },
2128        {
2129            "comment": "Drop trailing spaces from trailing opaque paths",
2130            "href": "data:space ?query",
2131            "new_value": "",
2132            "expected": {
2133                "href": "data:space",
2134                "pathname": "space",
2135                "search": ""
2136            }
2137        },
2138        {
2139            "href": "sc:space ?query",
2140            "new_value": "",
2141            "expected": {
2142                "href": "sc:space",
2143                "pathname": "space",
2144                "search": ""
2145            }
2146        },
2147        {
2148            "comment": "Do not drop trailing spaces from non-trailing opaque paths",
2149            "href": "data:space  ?query#fragment",
2150            "new_value": "",
2151            "expected": {
2152                "href": "data:space  #fragment",
2153                "search": ""
2154            }
2155        },
2156        {
2157            "href": "sc:space  ?query#fragment",
2158            "new_value": "",
2159            "expected": {
2160                "href": "sc:space  #fragment",
2161                "search": ""
2162            }
2163        },
2164        {
2165            "comment": "Trailing space should be encoded",
2166            "href": "http://example.net",
2167            "new_value": " ",
2168            "expected": {
2169                "href": "http://example.net/?%20",
2170                "search": "?%20"
2171            }
2172        },
2173        {
2174            "comment": "Trailing C0 control should be encoded",
2175            "href": "http://example.net",
2176            "new_value": "\u0000",
2177            "expected": {
2178                "href": "http://example.net/?%00",
2179                "search": "?%00"
2180            }
2181        }
2182    ],
2183    "hash": [
2184        {
2185            "href": "https://example.net",
2186            "new_value": "main",
2187            "expected": {
2188                "href": "https://example.net/#main",
2189                "hash": "#main"
2190            }
2191        },
2192        {
2193            "href": "https://example.net#nav",
2194            "new_value": "main",
2195            "expected": {
2196                "href": "https://example.net/#main",
2197                "hash": "#main"
2198            }
2199        },
2200        {
2201            "href": "https://example.net?lang=en-US",
2202            "new_value": "##nav",
2203            "expected": {
2204                "href": "https://example.net/?lang=en-US##nav",
2205                "hash": "##nav"
2206            }
2207        },
2208        {
2209            "href": "https://example.net?lang=en-US#nav",
2210            "new_value": "#main",
2211            "expected": {
2212                "href": "https://example.net/?lang=en-US#main",
2213                "hash": "#main"
2214            }
2215        },
2216        {
2217            "href": "https://example.net?lang=en-US#nav",
2218            "new_value": "#",
2219            "expected": {
2220                "href": "https://example.net/?lang=en-US#",
2221                "hash": ""
2222            }
2223        },
2224        {
2225            "href": "https://example.net?lang=en-US#nav",
2226            "new_value": "",
2227            "expected": {
2228                "href": "https://example.net/?lang=en-US",
2229                "hash": ""
2230            }
2231        },
2232        {
2233            "href": "http://example.net",
2234            "new_value": "#foo bar",
2235            "expected": {
2236                "href": "http://example.net/#foo%20bar",
2237                "hash": "#foo%20bar"
2238            }
2239        },
2240        {
2241            "href": "http://example.net",
2242            "new_value": "#foo\"bar",
2243            "expected": {
2244                "href": "http://example.net/#foo%22bar",
2245                "hash": "#foo%22bar"
2246            }
2247        },
2248        {
2249            "href": "http://example.net",
2250            "new_value": "#foo<bar",
2251            "expected": {
2252                "href": "http://example.net/#foo%3Cbar",
2253                "hash": "#foo%3Cbar"
2254            }
2255        },
2256        {
2257            "href": "http://example.net",
2258            "new_value": "#foo>bar",
2259            "expected": {
2260                "href": "http://example.net/#foo%3Ebar",
2261                "hash": "#foo%3Ebar"
2262            }
2263        },
2264        {
2265            "href": "http://example.net",
2266            "new_value": "#foo`bar",
2267            "expected": {
2268                "href": "http://example.net/#foo%60bar",
2269                "hash": "#foo%60bar"
2270            }
2271        },
2272        {
2273            "comment": "Simple percent-encoding; tabs and newlines are removed",
2274            "href": "a:/",
2275            "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
2276            "expected": {
2277                "href": "a:/#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
2278                "hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
2279            }
2280        },
2281        {
2282            "comment": "Percent-encode NULLs in fragment",
2283            "href": "http://example.net",
2284            "new_value": "a\u0000b",
2285            "expected": {
2286                "href": "http://example.net/#a%00b",
2287                "hash": "#a%00b"
2288            }
2289        },
2290        {
2291            "comment": "Percent-encode NULLs in fragment",
2292            "href": "non-spec:/",
2293            "new_value": "a\u0000b",
2294            "expected": {
2295                "href": "non-spec:/#a%00b",
2296                "hash": "#a%00b"
2297            }
2298        },
2299        {
2300            "comment": "Bytes already percent-encoded are left as-is",
2301            "href": "http://example.net",
2302            "new_value": "%c3%89té",
2303            "expected": {
2304                "href": "http://example.net/#%c3%89t%C3%A9",
2305                "hash": "#%c3%89t%C3%A9"
2306            }
2307        },
2308        {
2309            "href": "javascript:alert(1)",
2310            "new_value": "castle",
2311            "expected": {
2312                "href": "javascript:alert(1)#castle",
2313                "hash": "#castle"
2314            }
2315        },
2316        {
2317            "comment": "Drop trailing spaces from trailing opaque paths",
2318            "href": "data:space                                                                                                                                  #fragment",
2319            "new_value": "",
2320            "expected": {
2321                "href": "data:space",
2322                "pathname": "space",
2323                "hash": ""
2324            }
2325        },
2326        {
2327            "href": "sc:space    #fragment",
2328            "new_value": "",
2329            "expected": {
2330                "href": "sc:space",
2331                "pathname": "space",
2332                "hash": ""
2333            }
2334        },
2335        {
2336            "comment": "Do not drop trailing spaces from non-trailing opaque paths",
2337            "href": "data:space  ?query#fragment",
2338            "new_value": "",
2339            "expected": {
2340                "href": "data:space  ?query",
2341                "hash": ""
2342            }
2343        },
2344        {
2345            "href": "sc:space  ?query#fragment",
2346            "new_value": "",
2347            "expected": {
2348                "href": "sc:space  ?query",
2349                "hash": ""
2350            }
2351        },
2352        {
2353            "comment": "Trailing space should be encoded",
2354            "href": "http://example.net",
2355            "new_value": " ",
2356            "expected": {
2357                "href": "http://example.net/#%20",
2358                "hash": "#%20"
2359            }
2360        },
2361        {
2362            "comment": "Trailing C0 control should be encoded",
2363            "href": "http://example.net",
2364            "new_value": "\u0000",
2365            "expected": {
2366                "href": "http://example.net/#%00",
2367                "hash": "#%00"
2368            }
2369        }
2370    ],
2371    "href": [
2372        {
2373            "href": "file:///var/log/system.log",
2374            "new_value": "http://0300.168.0xF0",
2375            "expected": {
2376                "href": "http://192.168.0.240/",
2377                "protocol": "http:"
2378            }
2379        }
2380    ]
2381}
2382