tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

setters_tests.json (80168B)


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