tor-browser

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

urlpatterntestdata.json (90790B)


      1 [
      2  {
      3    "pattern": [{ "pathname": "/foo/bar" }],
      4    "inputs": [{ "pathname": "/foo/bar" }],
      5    "expected_match": {
      6      "pathname": { "input": "/foo/bar", "groups": {} }
      7    }
      8  },
      9  {
     10    "pattern": [{ "pathname": "/foo/bar" }],
     11    "inputs": [{ "pathname": "/foo/ba" }],
     12    "expected_match": null
     13  },
     14  {
     15    "pattern": [{ "pathname": "/foo/bar" }],
     16    "inputs": [{ "pathname": "/foo/bar/" }],
     17    "expected_match": null
     18  },
     19  {
     20    "pattern": [{ "pathname": "/foo/bar" }],
     21    "inputs": [{ "pathname": "/foo/bar/baz" }],
     22    "expected_match": null
     23  },
     24  {
     25    "pattern": [{ "pathname": "/foo/bar" }],
     26    "inputs": [ "https://example.com/foo/bar" ],
     27    "expected_match": {
     28      "hostname": { "input": "example.com", "groups": { "0": "example.com" } },
     29      "pathname": { "input": "/foo/bar", "groups": {} },
     30      "protocol": { "input": "https", "groups": { "0": "https" } }
     31    }
     32  },
     33  {
     34    "pattern": [{ "pathname": "/foo/bar" }],
     35    "inputs": [ "https://example.com/foo/bar/baz" ],
     36    "expected_match": null
     37  },
     38  {
     39    "pattern": [{ "pathname": "/foo/bar" }],
     40    "inputs": [{ "hostname": "example.com", "pathname": "/foo/bar" }],
     41    "expected_match": {
     42      "hostname": { "input": "example.com", "groups": { "0": "example.com" } },
     43      "pathname": { "input": "/foo/bar", "groups": {} }
     44    }
     45  },
     46  {
     47    "pattern": [{ "pathname": "/foo/bar" }],
     48    "inputs": [{ "hostname": "example.com", "pathname": "/foo/bar/baz" }],
     49    "expected_match": null
     50  },
     51  {
     52    "pattern": [{ "pathname": "/foo/bar" }],
     53    "inputs": [{ "pathname": "/foo/bar", "baseURL": "https://example.com" }],
     54    "expected_match": {
     55      "hostname": { "input": "example.com", "groups": { "0": "example.com" } },
     56      "pathname": { "input": "/foo/bar", "groups": {} },
     57      "protocol": { "input": "https", "groups": { "0": "https" } }
     58    }
     59  },
     60  {
     61    "pattern": [{ "pathname": "/foo/bar" }],
     62    "inputs": [{ "pathname": "/foo/bar/baz",
     63                 "baseURL": "https://example.com" }],
     64    "expected_match": null
     65  },
     66  {
     67    "pattern": [{ "pathname": "/foo/bar",
     68                 "baseURL": "https://example.com?query#hash" }],
     69    "inputs": [{ "pathname": "/foo/bar" }],
     70    "expected_match": null
     71  },
     72  {
     73    "pattern": [{ "pathname": "/foo/bar",
     74                 "baseURL": "https://example.com?query#hash" }],
     75    "inputs": [{ "hostname": "example.com", "pathname": "/foo/bar" }],
     76    "expected_match": null
     77  },
     78  {
     79    "pattern": [{ "pathname": "/foo/bar",
     80                 "baseURL": "https://example.com?query#hash" }],
     81    "inputs": [{ "protocol": "https", "hostname": "example.com",
     82                 "pathname": "/foo/bar" }],
     83    "exactly_empty_components": [ "port" ],
     84    "expected_match": {
     85      "hostname": { "input": "example.com", "groups": {} },
     86      "pathname": { "input": "/foo/bar", "groups": {} },
     87      "protocol": { "input": "https", "groups": {} }
     88    }
     89  },
     90  {
     91    "pattern": [{ "pathname": "/foo/bar",
     92                 "baseURL": "https://example.com" }],
     93    "inputs": [{ "protocol": "https", "hostname": "example.com",
     94                 "pathname": "/foo/bar" }],
     95    "exactly_empty_components": [ "port" ],
     96    "expected_match": {
     97      "hostname": { "input": "example.com", "groups": {} },
     98      "pathname": { "input": "/foo/bar", "groups": {} },
     99      "protocol": { "input": "https", "groups": {} }
    100    }
    101  },
    102  {
    103    "pattern": [{ "pathname": "/foo/bar",
    104                 "baseURL": "https://example.com" }],
    105    "inputs": [{ "protocol": "https", "hostname": "example.com",
    106                 "pathname": "/foo/bar/baz" }],
    107    "expected_match": null
    108  },
    109  {
    110    "pattern": [{ "pathname": "/foo/bar",
    111                 "baseURL": "https://example.com?query#hash" }],
    112    "inputs": [{ "protocol": "https", "hostname": "example.com",
    113                 "pathname": "/foo/bar", "search": "otherquery",
    114                 "hash": "otherhash" }],
    115    "exactly_empty_components": [ "port" ],
    116    "expected_match": {
    117      "hash": { "input": "otherhash", "groups": { "0": "otherhash" } },
    118      "hostname": { "input": "example.com", "groups": {} },
    119      "pathname": { "input": "/foo/bar", "groups": {} },
    120      "protocol": { "input": "https", "groups": {} },
    121      "search": { "input": "otherquery", "groups": { "0": "otherquery" } }
    122    }
    123  },
    124  {
    125    "pattern": [{ "pathname": "/foo/bar",
    126                 "baseURL": "https://example.com" }],
    127    "inputs": [{ "protocol": "https", "hostname": "example.com",
    128                 "pathname": "/foo/bar", "search": "otherquery",
    129                 "hash": "otherhash" }],
    130    "exactly_empty_components": [ "port" ],
    131    "expected_match": {
    132      "hash": { "input": "otherhash", "groups": { "0": "otherhash" } },
    133      "hostname": { "input": "example.com", "groups": {} },
    134      "pathname": { "input": "/foo/bar", "groups": {} },
    135      "protocol": { "input": "https", "groups": {} },
    136      "search": { "input": "otherquery", "groups": { "0": "otherquery" } }
    137    }
    138  },
    139  {
    140    "pattern": [{ "pathname": "/foo/bar",
    141                 "baseURL": "https://example.com?otherquery#otherhash" }],
    142    "inputs": [{ "protocol": "https", "hostname": "example.com",
    143                 "pathname": "/foo/bar", "search": "otherquery",
    144                 "hash": "otherhash" }],
    145    "exactly_empty_components": [ "port" ],
    146    "expected_match": {
    147      "hash": { "input": "otherhash", "groups": { "0": "otherhash" } },
    148      "hostname": { "input": "example.com", "groups": {} },
    149      "pathname": { "input": "/foo/bar", "groups": {} },
    150      "protocol": { "input": "https", "groups": {} },
    151      "search": { "input": "otherquery", "groups": { "0": "otherquery" } }
    152    }
    153  },
    154  {
    155    "pattern": [{ "pathname": "/foo/bar",
    156                 "baseURL": "https://example.com?query#hash" }],
    157    "inputs": [ "https://example.com/foo/bar" ],
    158    "exactly_empty_components": [ "port" ],
    159    "expected_match": {
    160      "hostname": { "input": "example.com", "groups": {} },
    161      "pathname": { "input": "/foo/bar", "groups": {} },
    162      "protocol": { "input": "https", "groups": {} }
    163    }
    164  },
    165  {
    166    "pattern": [{ "pathname": "/foo/bar",
    167                 "baseURL": "https://example.com?query#hash" }],
    168    "inputs": [ "https://example.com/foo/bar?otherquery#otherhash" ],
    169    "exactly_empty_components": [ "port" ],
    170    "expected_match": {
    171      "hash": { "input": "otherhash", "groups": { "0": "otherhash" } },
    172      "hostname": { "input": "example.com", "groups": {} },
    173      "pathname": { "input": "/foo/bar", "groups": {} },
    174      "protocol": { "input": "https", "groups": {} },
    175      "search": { "input": "otherquery", "groups": { "0": "otherquery" } }
    176    }
    177  },
    178  {
    179    "pattern": [{ "pathname": "/foo/bar",
    180                 "baseURL": "https://example.com?query#hash" }],
    181    "inputs": [ "https://example.com/foo/bar?query#hash" ],
    182    "exactly_empty_components": [ "port" ],
    183    "expected_match": {
    184      "hash": { "input": "hash", "groups": { "0": "hash" } },
    185      "hostname": { "input": "example.com", "groups": {} },
    186      "pathname": { "input": "/foo/bar", "groups": {} },
    187      "protocol": { "input": "https", "groups": {} },
    188      "search": { "input": "query", "groups": { "0": "query" } }
    189    }
    190  },
    191  {
    192    "pattern": [{ "pathname": "/foo/bar",
    193                 "baseURL": "https://example.com?query#hash" }],
    194    "inputs": [ "https://example.com/foo/bar/baz" ],
    195    "expected_match": null
    196  },
    197  {
    198    "pattern": [{ "pathname": "/foo/bar",
    199                 "baseURL": "https://example.com?query#hash" }],
    200    "inputs": [ "https://other.com/foo/bar" ],
    201    "expected_match": null
    202  },
    203  {
    204    "pattern": [{ "pathname": "/foo/bar",
    205                 "baseURL": "https://example.com?query#hash" }],
    206    "inputs": [ "http://other.com/foo/bar" ],
    207    "expected_match": null
    208  },
    209  {
    210    "pattern": [{ "pathname": "/foo/bar",
    211                 "baseURL": "https://example.com?query#hash" }],
    212    "inputs": [{ "pathname": "/foo/bar", "baseURL": "https://example.com" }],
    213    "exactly_empty_components": [ "port" ],
    214    "expected_match": {
    215      "hostname": { "input": "example.com", "groups": {} },
    216      "pathname": { "input": "/foo/bar", "groups": {} },
    217      "protocol": { "input": "https", "groups": {} }
    218    }
    219  },
    220  {
    221    "pattern": [{ "pathname": "/foo/bar",
    222                 "baseURL": "https://example.com?query#hash" }],
    223    "inputs": [{ "pathname": "/foo/bar",
    224                 "baseURL": "https://example.com?query#hash" }],
    225    "exactly_empty_components": [ "port" ],
    226    "expected_match": {
    227      "hostname": { "input": "example.com", "groups": {} },
    228      "pathname": { "input": "/foo/bar", "groups": {} },
    229      "protocol": { "input": "https", "groups": {} }
    230    }
    231  },
    232  {
    233    "pattern": [{ "pathname": "/foo/bar",
    234                 "baseURL": "https://example.com?query#hash" }],
    235    "inputs": [{ "pathname": "/foo/bar/baz",
    236                 "baseURL": "https://example.com" }],
    237    "expected_match": null
    238  },
    239  {
    240    "pattern": [{ "pathname": "/foo/bar",
    241                 "baseURL": "https://example.com?query#hash" }],
    242    "inputs": [{ "pathname": "/foo/bar", "baseURL": "https://other.com" }],
    243    "expected_match": null
    244  },
    245  {
    246    "pattern": [{ "pathname": "/foo/bar",
    247                 "baseURL": "https://example.com?query#hash" }],
    248    "inputs": [{ "pathname": "/foo/bar", "baseURL": "http://example.com" }],
    249    "expected_match": null
    250  },
    251  {
    252    "pattern": [{ "pathname": "/foo/:bar" }],
    253    "inputs": [{ "pathname": "/foo/bar" }],
    254    "expected_match": {
    255      "pathname": { "input": "/foo/bar", "groups": { "bar": "bar" } }
    256    }
    257  },
    258  {
    259    "pattern": [{ "pathname": "/foo/([^\\/]+?)" }],
    260    "inputs": [{ "pathname": "/foo/bar" }],
    261    "expected_match": {
    262      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    263    }
    264  },
    265  {
    266    "pattern": [{ "pathname": "/foo/:bar" }],
    267    "inputs": [{ "pathname": "/foo/index.html" }],
    268    "expected_match": {
    269      "pathname": { "input": "/foo/index.html", "groups": { "bar": "index.html" } }
    270    }
    271  },
    272  {
    273    "pattern": [{ "pathname": "/foo/:bar" }],
    274    "inputs": [{ "pathname": "/foo/bar/" }],
    275    "expected_match": null
    276  },
    277  {
    278    "pattern": [{ "pathname": "/foo/:bar" }],
    279    "inputs": [{ "pathname": "/foo/" }],
    280    "expected_match": null
    281  },
    282  {
    283    "pattern": [{ "pathname": "/foo/(.*)" }],
    284    "inputs": [{ "pathname": "/foo/bar" }],
    285    "expected_obj": {
    286      "pathname": "/foo/*"
    287    },
    288    "expected_match": {
    289      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    290    }
    291  },
    292  {
    293    "pattern": [{ "pathname": "/foo/*" }],
    294    "inputs": [{ "pathname": "/foo/bar" }],
    295    "expected_match": {
    296      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    297    }
    298  },
    299  {
    300    "pattern": [{ "pathname": "/foo/(.*)" }],
    301    "inputs": [{ "pathname": "/foo/bar/baz" }],
    302    "expected_obj": {
    303      "pathname": "/foo/*"
    304    },
    305    "expected_match": {
    306      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    307    }
    308  },
    309  {
    310    "pattern": [{ "pathname": "/foo/*" }],
    311    "inputs": [{ "pathname": "/foo/bar/baz" }],
    312    "expected_match": {
    313      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    314    }
    315  },
    316  {
    317    "pattern": [{ "pathname": "/foo/(.*)" }],
    318    "inputs": [{ "pathname": "/foo/" }],
    319    "expected_obj": {
    320      "pathname": "/foo/*"
    321    },
    322    "expected_match": {
    323      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    324    }
    325  },
    326  {
    327    "pattern": [{ "pathname": "/foo/*" }],
    328    "inputs": [{ "pathname": "/foo/" }],
    329    "expected_match": {
    330      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    331    }
    332  },
    333  {
    334    "pattern": [{ "pathname": "/foo/(.*)" }],
    335    "inputs": [{ "pathname": "/foo" }],
    336    "expected_obj": {
    337      "pathname": "/foo/*"
    338    },
    339    "expected_match": null
    340  },
    341  {
    342    "pattern": [{ "pathname": "/foo/*" }],
    343    "inputs": [{ "pathname": "/foo" }],
    344    "expected_match": null
    345  },
    346  {
    347    "pattern": [{ "pathname": "/foo/:bar(.*)" }],
    348    "inputs": [{ "pathname": "/foo/bar" }],
    349    "expected_match": {
    350      "pathname": { "input": "/foo/bar", "groups": { "bar": "bar" } }
    351    }
    352  },
    353  {
    354    "pattern": [{ "pathname": "/foo/:bar(.*)" }],
    355    "inputs": [{ "pathname": "/foo/bar/baz" }],
    356    "expected_match": {
    357      "pathname": { "input": "/foo/bar/baz", "groups": { "bar": "bar/baz" } }
    358    }
    359  },
    360  {
    361    "pattern": [{ "pathname": "/foo/:bar(.*)" }],
    362    "inputs": [{ "pathname": "/foo/" }],
    363    "expected_match": {
    364      "pathname": { "input": "/foo/", "groups": { "bar": "" } }
    365    }
    366  },
    367  {
    368    "pattern": [{ "pathname": "/foo/:bar(.*)" }],
    369    "inputs": [{ "pathname": "/foo" }],
    370    "expected_match": null
    371  },
    372  {
    373    "pattern": [{ "pathname": "/foo/:bar?" }],
    374    "inputs": [{ "pathname": "/foo/bar" }],
    375    "expected_match": {
    376      "pathname": { "input": "/foo/bar", "groups": { "bar": "bar" } }
    377    }
    378  },
    379  {
    380    "pattern": [{ "pathname": "/foo/:bar?" }],
    381    "inputs": [{ "pathname": "/foo" }],
    382    "//": "The `null` below is translated to undefined in the test harness.",
    383    "expected_match": {
    384      "pathname": { "input": "/foo", "groups": { "bar": null } }
    385    }
    386  },
    387  {
    388    "pattern": [{ "pathname": "/foo/:bar?" }],
    389    "inputs": [{ "pathname": "/foo/" }],
    390    "expected_match": null
    391  },
    392  {
    393    "pattern": [{ "pathname": "/foo/:bar?" }],
    394    "inputs": [{ "pathname": "/foobar" }],
    395    "expected_match": null
    396  },
    397  {
    398    "pattern": [{ "pathname": "/foo/:bar?" }],
    399    "inputs": [{ "pathname": "/foo/bar/baz" }],
    400    "expected_match": null
    401  },
    402  {
    403    "pattern": [{ "pathname": "/foo/:bar+" }],
    404    "inputs": [{ "pathname": "/foo/bar" }],
    405    "expected_match": {
    406      "pathname": { "input": "/foo/bar", "groups": { "bar": "bar" } }
    407    }
    408  },
    409  {
    410    "pattern": [{ "pathname": "/foo/:bar+" }],
    411    "inputs": [{ "pathname": "/foo/bar/baz" }],
    412    "expected_match": {
    413      "pathname": { "input": "/foo/bar/baz", "groups": { "bar": "bar/baz" } }
    414    }
    415  },
    416  {
    417    "pattern": [{ "pathname": "/foo/:bar+" }],
    418    "inputs": [{ "pathname": "/foo" }],
    419    "expected_match": null
    420  },
    421  {
    422    "pattern": [{ "pathname": "/foo/:bar+" }],
    423    "inputs": [{ "pathname": "/foo/" }],
    424    "expected_match": null
    425  },
    426  {
    427    "pattern": [{ "pathname": "/foo/:bar+" }],
    428    "inputs": [{ "pathname": "/foobar" }],
    429    "expected_match": null
    430  },
    431  {
    432    "pattern": [{ "pathname": "/foo/:bar*" }],
    433    "inputs": [{ "pathname": "/foo/bar" }],
    434    "expected_match": {
    435      "pathname": { "input": "/foo/bar", "groups": { "bar": "bar" } }
    436    }
    437  },
    438  {
    439    "pattern": [{ "pathname": "/foo/:bar*" }],
    440    "inputs": [{ "pathname": "/foo/bar/baz" }],
    441    "expected_match": {
    442      "pathname": { "input": "/foo/bar/baz", "groups": { "bar": "bar/baz" } }
    443    }
    444  },
    445  {
    446    "pattern": [{ "pathname": "/foo/:bar*" }],
    447    "inputs": [{ "pathname": "/foo" }],
    448    "//": "The `null` below is translated to undefined in the test harness.",
    449    "expected_match": {
    450      "pathname": { "input": "/foo", "groups": { "bar": null } }
    451    }
    452  },
    453  {
    454    "pattern": [{ "pathname": "/foo/:bar*" }],
    455    "inputs": [{ "pathname": "/foo/" }],
    456    "expected_match": null
    457  },
    458  {
    459    "pattern": [{ "pathname": "/foo/:bar*" }],
    460    "inputs": [{ "pathname": "/foobar" }],
    461    "expected_match": null
    462  },
    463  {
    464    "pattern": [{ "pathname": "/foo/(.*)?" }],
    465    "inputs": [{ "pathname": "/foo/bar" }],
    466    "expected_obj": {
    467      "pathname": "/foo/*?"
    468    },
    469    "expected_match": {
    470      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    471    }
    472  },
    473  {
    474    "pattern": [{ "pathname": "/foo/*?" }],
    475    "inputs": [{ "pathname": "/foo/bar" }],
    476    "expected_match": {
    477      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    478    }
    479  },
    480  {
    481    "pattern": [{ "pathname": "/foo/(.*)?" }],
    482    "inputs": [{ "pathname": "/foo/bar/baz" }],
    483    "expected_obj": {
    484      "pathname": "/foo/*?"
    485    },
    486    "expected_match": {
    487      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    488    }
    489  },
    490  {
    491    "pattern": [{ "pathname": "/foo/*?" }],
    492    "inputs": [{ "pathname": "/foo/bar/baz" }],
    493    "expected_match": {
    494      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    495    }
    496  },
    497  {
    498    "pattern": [{ "pathname": "/foo/(.*)?" }],
    499    "inputs": [{ "pathname": "/foo" }],
    500    "expected_obj": {
    501      "pathname": "/foo/*?"
    502    },
    503    "//": "The `null` below is translated to undefined in the test harness.",
    504    "expected_match": {
    505      "pathname": { "input": "/foo", "groups": { "0": null } }
    506    }
    507  },
    508  {
    509    "pattern": [{ "pathname": "/foo/*?" }],
    510    "inputs": [{ "pathname": "/foo" }],
    511    "//": "The `null` below is translated to undefined in the test harness.",
    512    "expected_match": {
    513      "pathname": { "input": "/foo", "groups": { "0": null } }
    514    }
    515  },
    516  {
    517    "pattern": [{ "pathname": "/foo/(.*)?" }],
    518    "inputs": [{ "pathname": "/foo/" }],
    519    "expected_obj": {
    520      "pathname": "/foo/*?"
    521    },
    522    "expected_match": {
    523      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    524    }
    525  },
    526  {
    527    "pattern": [{ "pathname": "/foo/*?" }],
    528    "inputs": [{ "pathname": "/foo/" }],
    529    "expected_match": {
    530      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    531    }
    532  },
    533  {
    534    "pattern": [{ "pathname": "/foo/(.*)?" }],
    535    "inputs": [{ "pathname": "/foobar" }],
    536    "expected_obj": {
    537      "pathname": "/foo/*?"
    538    },
    539    "expected_match": null
    540  },
    541  {
    542    "pattern": [{ "pathname": "/foo/*?" }],
    543    "inputs": [{ "pathname": "/foobar" }],
    544    "expected_match": null
    545  },
    546  {
    547    "pattern": [{ "pathname": "/foo/(.*)?" }],
    548    "inputs": [{ "pathname": "/fo" }],
    549    "expected_obj": {
    550      "pathname": "/foo/*?"
    551    },
    552    "expected_match": null
    553  },
    554  {
    555    "pattern": [{ "pathname": "/foo/*?" }],
    556    "inputs": [{ "pathname": "/fo" }],
    557    "expected_match": null
    558  },
    559  {
    560    "pattern": [{ "pathname": "/foo/(.*)+" }],
    561    "inputs": [{ "pathname": "/foo/bar" }],
    562    "expected_obj": {
    563      "pathname": "/foo/*+"
    564    },
    565    "expected_match": {
    566      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    567    }
    568  },
    569  {
    570    "pattern": [{ "pathname": "/foo/*+" }],
    571    "inputs": [{ "pathname": "/foo/bar" }],
    572    "expected_match": {
    573      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    574    }
    575  },
    576  {
    577    "pattern": [{ "pathname": "/foo/(.*)+" }],
    578    "inputs": [{ "pathname": "/foo/bar/baz" }],
    579    "expected_obj": {
    580      "pathname": "/foo/*+"
    581    },
    582    "expected_match": {
    583      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    584    }
    585  },
    586  {
    587    "pattern": [{ "pathname": "/foo/*+" }],
    588    "inputs": [{ "pathname": "/foo/bar/baz" }],
    589    "expected_match": {
    590      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    591    }
    592  },
    593  {
    594    "pattern": [{ "pathname": "/foo/(.*)+" }],
    595    "inputs": [{ "pathname": "/foo" }],
    596    "expected_obj": {
    597      "pathname": "/foo/*+"
    598    },
    599    "expected_match": null
    600  },
    601  {
    602    "pattern": [{ "pathname": "/foo/*+" }],
    603    "inputs": [{ "pathname": "/foo" }],
    604    "expected_match": null
    605  },
    606  {
    607    "pattern": [{ "pathname": "/foo/(.*)+" }],
    608    "inputs": [{ "pathname": "/foo/" }],
    609    "expected_obj": {
    610      "pathname": "/foo/*+"
    611    },
    612    "expected_match": {
    613      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    614    }
    615  },
    616  {
    617    "pattern": [{ "pathname": "/foo/*+" }],
    618    "inputs": [{ "pathname": "/foo/" }],
    619    "expected_match": {
    620      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    621    }
    622  },
    623  {
    624    "pattern": [{ "pathname": "/foo/(.*)+" }],
    625    "inputs": [{ "pathname": "/foobar" }],
    626    "expected_obj": {
    627      "pathname": "/foo/*+"
    628    },
    629    "expected_match": null
    630  },
    631  {
    632    "pattern": [{ "pathname": "/foo/*+" }],
    633    "inputs": [{ "pathname": "/foobar" }],
    634    "expected_match": null
    635  },
    636  {
    637    "pattern": [{ "pathname": "/foo/(.*)+" }],
    638    "inputs": [{ "pathname": "/fo" }],
    639    "expected_obj": {
    640      "pathname": "/foo/*+"
    641    },
    642    "expected_match": null
    643  },
    644  {
    645    "pattern": [{ "pathname": "/foo/*+" }],
    646    "inputs": [{ "pathname": "/fo" }],
    647    "expected_match": null
    648  },
    649  {
    650    "pattern": [{ "pathname": "/foo/(.*)*" }],
    651    "inputs": [{ "pathname": "/foo/bar" }],
    652    "expected_obj": {
    653      "pathname": "/foo/**"
    654    },
    655    "expected_match": {
    656      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    657    }
    658  },
    659  {
    660    "pattern": [{ "pathname": "/foo/**" }],
    661    "inputs": [{ "pathname": "/foo/bar" }],
    662    "expected_match": {
    663      "pathname": { "input": "/foo/bar", "groups": { "0": "bar" } }
    664    }
    665  },
    666  {
    667    "pattern": [{ "pathname": "/foo/(.*)*" }],
    668    "inputs": [{ "pathname": "/foo/bar/baz" }],
    669    "expected_obj": {
    670      "pathname": "/foo/**"
    671    },
    672    "expected_match": {
    673      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    674    }
    675  },
    676  {
    677    "pattern": [{ "pathname": "/foo/**" }],
    678    "inputs": [{ "pathname": "/foo/bar/baz" }],
    679    "expected_match": {
    680      "pathname": { "input": "/foo/bar/baz", "groups": { "0": "bar/baz" } }
    681    }
    682  },
    683  {
    684    "pattern": [{ "pathname": "/foo/(.*)*" }],
    685    "inputs": [{ "pathname": "/foo" }],
    686    "expected_obj": {
    687      "pathname": "/foo/**"
    688    },
    689    "//": "The `null` below is translated to undefined in the test harness.",
    690    "expected_match": {
    691      "pathname": { "input": "/foo", "groups": { "0": null } }
    692    }
    693  },
    694  {
    695    "pattern": [{ "pathname": "/foo/**" }],
    696    "inputs": [{ "pathname": "/foo" }],
    697    "//": "The `null` below is translated to undefined in the test harness.",
    698    "expected_match": {
    699      "pathname": { "input": "/foo", "groups": { "0": null } }
    700    }
    701  },
    702  {
    703    "pattern": [{ "pathname": "/foo/(.*)*" }],
    704    "inputs": [{ "pathname": "/foo/" }],
    705    "expected_obj": {
    706      "pathname": "/foo/**"
    707    },
    708    "expected_match": {
    709      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    710    }
    711  },
    712  {
    713    "pattern": [{ "pathname": "/foo/**" }],
    714    "inputs": [{ "pathname": "/foo/" }],
    715    "expected_match": {
    716      "pathname": { "input": "/foo/", "groups": { "0": "" } }
    717    }
    718  },
    719  {
    720    "pattern": [{ "pathname": "/foo/(.*)*" }],
    721    "inputs": [{ "pathname": "/foobar" }],
    722    "expected_obj": {
    723      "pathname": "/foo/**"
    724    },
    725    "expected_match": null
    726  },
    727  {
    728    "pattern": [{ "pathname": "/foo/**" }],
    729    "inputs": [{ "pathname": "/foobar" }],
    730    "expected_match": null
    731  },
    732  {
    733    "pattern": [{ "pathname": "/foo/(.*)*" }],
    734    "inputs": [{ "pathname": "/fo" }],
    735    "expected_obj": {
    736      "pathname": "/foo/**"
    737    },
    738    "expected_match": null
    739  },
    740  {
    741    "pattern": [{ "pathname": "/foo/**" }],
    742    "inputs": [{ "pathname": "/fo" }],
    743    "expected_match": null
    744  },
    745  {
    746    "pattern": [{ "pathname": "/foo{/bar}" }],
    747    "inputs": [{ "pathname": "/foo/bar" }],
    748    "expected_obj": {
    749      "pathname": "/foo/bar"
    750    },
    751    "expected_match": {
    752      "pathname": { "input": "/foo/bar", "groups": {} }
    753    }
    754  },
    755  {
    756    "pattern": [{ "pathname": "/foo{/bar}" }],
    757    "inputs": [{ "pathname": "/foo/bar/baz" }],
    758    "expected_obj": {
    759      "pathname": "/foo/bar"
    760    },
    761    "expected_match": null
    762  },
    763  {
    764    "pattern": [{ "pathname": "/foo{/bar}" }],
    765    "inputs": [{ "pathname": "/foo" }],
    766    "expected_obj": {
    767      "pathname": "/foo/bar"
    768    },
    769    "expected_match": null
    770  },
    771  {
    772    "pattern": [{ "pathname": "/foo{/bar}" }],
    773    "inputs": [{ "pathname": "/foo/" }],
    774    "expected_obj": {
    775      "pathname": "/foo/bar"
    776    },
    777    "expected_match": null
    778  },
    779  {
    780    "pattern": [{ "pathname": "/foo{/bar}?" }],
    781    "inputs": [{ "pathname": "/foo/bar" }],
    782    "expected_match": {
    783      "pathname": { "input": "/foo/bar", "groups": {} }
    784    }
    785  },
    786  {
    787    "pattern": [{ "pathname": "/foo{/bar}?" }],
    788    "inputs": [{ "pathname": "/foo/bar/baz" }],
    789    "expected_match": null
    790  },
    791  {
    792    "pattern": [{ "pathname": "/foo{/bar}?" }],
    793    "inputs": [{ "pathname": "/foo" }],
    794    "expected_match": {
    795      "pathname": { "input": "/foo", "groups": {} }
    796    }
    797  },
    798  {
    799    "pattern": [{ "pathname": "/foo{/bar}?" }],
    800    "inputs": [{ "pathname": "/foo/" }],
    801    "expected_match": null
    802  },
    803  {
    804    "pattern": [{ "pathname": "/foo{/bar}+" }],
    805    "inputs": [{ "pathname": "/foo/bar" }],
    806    "expected_match": {
    807      "pathname": { "input": "/foo/bar", "groups": {} }
    808    }
    809  },
    810  {
    811    "pattern": [{ "pathname": "/foo{/bar}+" }],
    812    "inputs": [{ "pathname": "/foo/bar/bar" }],
    813    "expected_match": {
    814      "pathname": { "input": "/foo/bar/bar", "groups": {} }
    815    }
    816  },
    817  {
    818    "pattern": [{ "pathname": "/foo{/bar}+" }],
    819    "inputs": [{ "pathname": "/foo/bar/baz" }],
    820    "expected_match": null
    821  },
    822  {
    823    "pattern": [{ "pathname": "/foo{/bar}+" }],
    824    "inputs": [{ "pathname": "/foo" }],
    825    "expected_match": null
    826  },
    827  {
    828    "pattern": [{ "pathname": "/foo{/bar}+" }],
    829    "inputs": [{ "pathname": "/foo/" }],
    830    "expected_match": null
    831  },
    832  {
    833    "pattern": [{ "pathname": "/foo{/bar}*" }],
    834    "inputs": [{ "pathname": "/foo/bar" }],
    835    "expected_match": {
    836      "pathname": { "input": "/foo/bar", "groups": {} }
    837    }
    838  },
    839  {
    840    "pattern": [{ "pathname": "/foo{/bar}*" }],
    841    "inputs": [{ "pathname": "/foo/bar/bar" }],
    842    "expected_match": {
    843      "pathname": { "input": "/foo/bar/bar", "groups": {} }
    844    }
    845  },
    846  {
    847    "pattern": [{ "pathname": "/foo{/bar}*" }],
    848    "inputs": [{ "pathname": "/foo/bar/baz" }],
    849    "expected_match": null
    850  },
    851  {
    852    "pattern": [{ "pathname": "/foo{/bar}*" }],
    853    "inputs": [{ "pathname": "/foo" }],
    854    "expected_match": {
    855      "pathname": { "input": "/foo", "groups": {} }
    856    }
    857  },
    858  {
    859    "pattern": [{ "pathname": "/foo{/bar}*" }],
    860    "inputs": [{ "pathname": "/foo/" }],
    861    "expected_match": null
    862  },
    863  {
    864    "pattern": [{ "protocol": "(café)" }],
    865    "expected_obj": "error"
    866  },
    867  {
    868    "pattern": [{ "username": "(café)" }],
    869    "expected_obj": "error"
    870  },
    871  {
    872    "pattern": [{ "password": "(café)" }],
    873    "expected_obj": "error"
    874  },
    875  {
    876    "pattern": [{ "hostname": "(café)" }],
    877    "expected_obj": "error"
    878  },
    879  {
    880    "pattern": [{ "pathname": "(café)" }],
    881    "expected_obj": "error"
    882  },
    883  {
    884    "pattern": [{ "search": "(café)" }],
    885    "expected_obj": "error"
    886  },
    887  {
    888    "pattern": [{ "hash": "(café)" }],
    889    "expected_obj": "error"
    890  },
    891  {
    892    "pattern": [{ "protocol": ":café" }],
    893    "inputs": [{ "protocol": "foo" }],
    894    "expected_match": {
    895      "protocol": { "input": "foo", "groups": { "café": "foo" } }
    896    }
    897  },
    898  {
    899    "pattern": [{ "username": ":café" }],
    900    "inputs": [{ "username": "foo" }],
    901    "expected_match": {
    902      "username": { "input": "foo", "groups": { "café": "foo" } }
    903    }
    904  },
    905  {
    906    "pattern": [{ "password": ":café" }],
    907    "inputs": [{ "password": "foo" }],
    908    "expected_match": {
    909      "password": { "input": "foo", "groups": { "café": "foo" } }
    910    }
    911  },
    912  {
    913    "pattern": [{ "hostname": ":café" }],
    914    "inputs": [{ "hostname": "foo" }],
    915    "expected_match": {
    916      "hostname": { "input": "foo", "groups": { "café": "foo" } }
    917    }
    918  },
    919  {
    920    "pattern": [{ "pathname": "/:café" }],
    921    "inputs": [{ "pathname": "/foo" }],
    922    "expected_match": {
    923      "pathname": { "input": "/foo", "groups": { "café": "foo" } }
    924    }
    925  },
    926  {
    927    "pattern": [{ "search": ":café" }],
    928    "inputs": [{ "search": "foo" }],
    929    "expected_match": {
    930      "search": { "input": "foo", "groups": { "café": "foo" } }
    931    }
    932  },
    933  {
    934    "pattern": [{ "hash": ":café" }],
    935    "inputs": [{ "hash": "foo" }],
    936    "expected_match": {
    937      "hash": { "input": "foo", "groups": { "café": "foo" } }
    938    }
    939  },
    940  {
    941    "pattern": [{ "protocol": ":\u2118" }],
    942    "inputs": [{ "protocol": "foo" }],
    943    "expected_match": {
    944      "protocol": { "input": "foo", "groups": { "\u2118": "foo" } }
    945    }
    946  },
    947  {
    948    "pattern": [{ "username": ":\u2118" }],
    949    "inputs": [{ "username": "foo" }],
    950    "expected_match": {
    951      "username": { "input": "foo", "groups": { "\u2118": "foo" } }
    952    }
    953  },
    954  {
    955    "pattern": [{ "password": ":\u2118" }],
    956    "inputs": [{ "password": "foo" }],
    957    "expected_match": {
    958      "password": { "input": "foo", "groups": { "\u2118": "foo" } }
    959    }
    960  },
    961  {
    962    "pattern": [{ "hostname": ":\u2118" }],
    963    "inputs": [{ "hostname": "foo" }],
    964    "expected_match": {
    965      "hostname": { "input": "foo", "groups": { "\u2118": "foo" } }
    966    }
    967  },
    968  {
    969    "pattern": [{ "pathname": "/:\u2118" }],
    970    "inputs": [{ "pathname": "/foo" }],
    971    "expected_match": {
    972      "pathname": { "input": "/foo", "groups": { "\u2118": "foo" } }
    973    }
    974  },
    975  {
    976    "pattern": [{ "search": ":\u2118" }],
    977    "inputs": [{ "search": "foo" }],
    978    "expected_match": {
    979      "search": { "input": "foo", "groups": { "\u2118": "foo" } }
    980    }
    981  },
    982  {
    983    "pattern": [{ "hash": ":\u2118" }],
    984    "inputs": [{ "hash": "foo" }],
    985    "expected_match": {
    986      "hash": { "input": "foo", "groups": { "\u2118": "foo" } }
    987    }
    988  },
    989  {
    990    "pattern": [{ "protocol": ":\u3400" }],
    991    "inputs": [{ "protocol": "foo" }],
    992    "expected_match": {
    993      "protocol": { "input": "foo", "groups": { "\u3400": "foo" } }
    994    }
    995  },
    996  {
    997    "pattern": [{ "username": ":\u3400" }],
    998    "inputs": [{ "username": "foo" }],
    999    "expected_match": {
   1000      "username": { "input": "foo", "groups": { "\u3400": "foo" } }
   1001    }
   1002  },
   1003  {
   1004    "pattern": [{ "password": ":\u3400" }],
   1005    "inputs": [{ "password": "foo" }],
   1006    "expected_match": {
   1007      "password": { "input": "foo", "groups": { "\u3400": "foo" } }
   1008    }
   1009  },
   1010  {
   1011    "pattern": [{ "hostname": ":\u3400" }],
   1012    "inputs": [{ "hostname": "foo" }],
   1013    "expected_match": {
   1014      "hostname": { "input": "foo", "groups": { "\u3400": "foo" } }
   1015    }
   1016  },
   1017  {
   1018    "pattern": [{ "pathname": "/:\u3400" }],
   1019    "inputs": [{ "pathname": "/foo" }],
   1020    "expected_match": {
   1021      "pathname": { "input": "/foo", "groups": { "\u3400": "foo" } }
   1022    }
   1023  },
   1024  {
   1025    "pattern": [{ "search": ":\u3400" }],
   1026    "inputs": [{ "search": "foo" }],
   1027    "expected_match": {
   1028      "search": { "input": "foo", "groups": { "\u3400": "foo" } }
   1029    }
   1030  },
   1031  {
   1032    "pattern": [{ "hash": ":\u3400" }],
   1033    "inputs": [{ "hash": "foo" }],
   1034    "expected_match": {
   1035      "hash": { "input": "foo", "groups": { "\u3400": "foo" } }
   1036    }
   1037  },
   1038  {
   1039    "pattern": [{ "protocol": "(.*)" }],
   1040    "inputs": [{ "protocol" : "café" }],
   1041    "expected_obj": {
   1042      "protocol": "*"
   1043    },
   1044    "expected_match": null
   1045  },
   1046  {
   1047    "pattern": [{ "protocol": "(.*)" }],
   1048    "inputs": [{ "protocol": "cafe" }],
   1049    "expected_obj": {
   1050      "protocol": "*"
   1051    },
   1052    "expected_match": {
   1053      "protocol": { "input": "cafe", "groups": { "0": "cafe" }}
   1054    }
   1055  },
   1056  {
   1057    "pattern": [{ "protocol": "foo-bar" }],
   1058    "inputs": [{ "protocol": "foo-bar" }],
   1059    "expected_match": {
   1060      "protocol": { "input": "foo-bar", "groups": {} }
   1061    }
   1062  },
   1063  {
   1064    "pattern": [{ "username": "caf%C3%A9" }],
   1065    "inputs": [{ "username" : "café" }],
   1066    "expected_match": {
   1067      "username": { "input": "caf%C3%A9", "groups": {}}
   1068    }
   1069  },
   1070  {
   1071    "pattern": [{ "username": "café" }],
   1072    "inputs": [{ "username" : "café" }],
   1073    "expected_obj": {
   1074      "username": "caf%C3%A9"
   1075    },
   1076    "expected_match": {
   1077      "username": { "input": "caf%C3%A9", "groups": {}}
   1078    }
   1079  },
   1080  {
   1081    "pattern": [{ "username": "caf%c3%a9" }],
   1082    "inputs": [{ "username" : "café" }],
   1083    "expected_match": null
   1084  },
   1085  {
   1086    "pattern": [{ "password": "caf%C3%A9" }],
   1087    "inputs": [{ "password" : "café" }],
   1088    "expected_match": {
   1089      "password": { "input": "caf%C3%A9", "groups": {}}
   1090    }
   1091  },
   1092  {
   1093    "pattern": [{ "password": "café" }],
   1094    "inputs": [{ "password" : "café" }],
   1095    "expected_obj": {
   1096      "password": "caf%C3%A9"
   1097    },
   1098    "expected_match": {
   1099      "password": { "input": "caf%C3%A9", "groups": {}}
   1100    }
   1101  },
   1102  {
   1103    "pattern": [{ "password": "caf%c3%a9" }],
   1104    "inputs": [{ "password" : "café" }],
   1105    "expected_match": null
   1106  },
   1107  {
   1108    "pattern": [{ "hostname": "xn--caf-dma.com" }],
   1109    "inputs": [{ "hostname" : "café.com" }],
   1110    "expected_match": {
   1111      "hostname": { "input": "xn--caf-dma.com", "groups": {}}
   1112    }
   1113  },
   1114  {
   1115    "pattern": [{ "hostname": "café.com" }],
   1116    "inputs": [{ "hostname" : "café.com" }],
   1117    "expected_obj": {
   1118      "hostname": "xn--caf-dma.com"
   1119    },
   1120    "expected_match": {
   1121      "hostname": { "input": "xn--caf-dma.com", "groups": {}}
   1122    }
   1123  },
   1124  {
   1125    "pattern": ["http://\uD83D\uDEB2.com/"],
   1126    "inputs": ["http://\uD83D\uDEB2.com/"],
   1127    "exactly_empty_components": [ "port" ],
   1128    "expected_obj": {
   1129      "protocol": "http",
   1130      "hostname": "xn--h78h.com",
   1131      "pathname": "/"
   1132    },
   1133    "expected_match": {
   1134      "protocol": { "input": "http", "groups": {}},
   1135      "hostname": { "input": "xn--h78h.com", "groups": {}},
   1136      "pathname": { "input": "/", "groups": {}}
   1137    }
   1138  },
   1139  {
   1140    "pattern": ["http://\uD83D \uDEB2"],
   1141    "expected_obj": "error"
   1142  },
   1143  {
   1144    "pattern": [{"hostname":"\uD83D \uDEB2"}],
   1145    "expected_obj": "error"
   1146  },
   1147  {
   1148    "pattern": [{"pathname":"\uD83D \uDEB2"}],
   1149    "inputs": [],
   1150    "expected_obj": {
   1151      "pathname": "%EF%BF%BD%20%EF%BF%BD"
   1152    },
   1153    "expected_match": null
   1154  },
   1155  {
   1156    "pattern": [{"pathname":":\uD83D \uDEB2"}],
   1157    "expected_obj": "error"
   1158  },
   1159  {
   1160    "pattern": [{"pathname":":a\uDB40\uDD00b"}],
   1161    "inputs": [],
   1162    "expected_obj": {
   1163      "pathname": ":a\uDB40\uDD00b"
   1164    },
   1165    "expected_match": null
   1166  },
   1167  {
   1168    "pattern": [{"pathname":"test/:a\uD801\uDC50b"}],
   1169    "inputs": [{"pathname":"test/foo"}],
   1170    "expected_obj": {
   1171      "pathname": "test/:a\uD801\uDC50b"
   1172    },
   1173    "expected_match": {
   1174      "pathname": { "input": "test/foo", "groups": { "a\uD801\uDC50b": "foo" }}
   1175    }
   1176  },
   1177  {
   1178    "pattern": [{"pathname":":\uD83D\uDEB2"}],
   1179    "expected_obj": "error"
   1180  },
   1181  {
   1182    "pattern": [{ "port": "" }],
   1183    "inputs": [{ "protocol": "http", "port": "80" }],
   1184    "exactly_empty_components": [ "port" ],
   1185    "expected_match": {
   1186      "protocol": { "input": "http", "groups": { "0": "http" }}
   1187    }
   1188  },
   1189  {
   1190    "pattern": [{ "protocol": "http", "port": "80" }],
   1191    "inputs": [{ "protocol": "http", "port": "80" }],
   1192    "exactly_empty_components": [ "port" ],
   1193    "expected_match": {
   1194      "protocol": { "input": "http", "groups": {}}
   1195    }
   1196  },
   1197  {
   1198    "pattern": [{ "protocol": "http", "port": "80{20}?" }],
   1199    "inputs": [{ "protocol": "http", "port": "80" }],
   1200    "expected_match": null
   1201  },
   1202  {
   1203    "pattern": [{ "protocol": "http", "port": "80 " }],
   1204    "inputs": [{ "protocol": "http", "port": "80" }],
   1205    "expected_obj": {
   1206      "protocol": "http",
   1207      "port": "80"
   1208    },
   1209    "expected_match": null
   1210  },
   1211  {
   1212    "pattern": [{ "protocol": "http", "port": "100000" }],
   1213    "inputs": [{ "protocol": "http", "port": "100000" }],
   1214    "expected_obj": "error"
   1215  },
   1216  {
   1217    "pattern": [{ "port": "80" }],
   1218    "inputs": [{ "protocol": "http", "port": "80" }],
   1219    "expected_match": null
   1220  },
   1221  {
   1222    "pattern": [{ "protocol": "http{s}?", "port": "80" }],
   1223    "inputs": [{ "protocol": "http", "port": "80" }],
   1224    "expected_match": null
   1225  },
   1226  {
   1227    "pattern": [{ "port": "80" }],
   1228    "inputs": [{ "port": "80" }],
   1229    "expected_match": {
   1230      "port": { "input": "80", "groups": {}}
   1231    }
   1232  },
   1233  {
   1234    "pattern": [{ "port": "80" }],
   1235    "inputs": [{ "port": "8\t0" }],
   1236    "expected_match": {
   1237      "port": { "input": "80", "groups": {}}
   1238    }
   1239  },
   1240  {
   1241    "pattern": [{ "port": "80" }],
   1242    "inputs": [{ "port": "80x" }],
   1243    "expected_match": {
   1244      "port": { "input": "80", "groups": {}}
   1245    }
   1246  },
   1247  {
   1248    "pattern": [{ "port": "80" }],
   1249    "inputs": [{ "port": "80?x" }],
   1250    "expected_match": {
   1251      "port": { "input": "80", "groups": {}}
   1252    }
   1253  },
   1254  {
   1255    "pattern": [{ "port": "80" }],
   1256    "inputs": [{ "port": "80\\x" }],
   1257    "expected_match": {
   1258      "port": { "input": "80", "groups": {}}
   1259    }
   1260  },
   1261  {
   1262    "pattern": [{ "port": "(.*)" }],
   1263    "inputs": [{ "port": "invalid80" }],
   1264    "expected_obj": {
   1265      "port": "*"
   1266    },
   1267    "expected_match": null
   1268  },
   1269  {
   1270    "pattern": [{ "pathname": "/foo/bar" }],
   1271    "inputs": [{ "pathname": "/foo/./bar" }],
   1272    "expected_match": {
   1273      "pathname": { "input": "/foo/bar", "groups": {}}
   1274    }
   1275  },
   1276  {
   1277    "pattern": [{ "pathname": "/foo/baz" }],
   1278    "inputs": [{ "pathname": "/foo/bar/../baz" }],
   1279    "expected_match": {
   1280      "pathname": { "input": "/foo/baz", "groups": {}}
   1281    }
   1282  },
   1283  {
   1284    "pattern": [{ "pathname": "/caf%C3%A9" }],
   1285    "inputs": [{ "pathname": "/café" }],
   1286    "expected_match": {
   1287      "pathname": { "input": "/caf%C3%A9", "groups": {}}
   1288    }
   1289  },
   1290  {
   1291    "pattern": [{ "pathname": "/café" }],
   1292    "inputs": [{ "pathname": "/café" }],
   1293    "expected_obj": {
   1294      "pathname": "/caf%C3%A9"
   1295    },
   1296    "expected_match": {
   1297      "pathname": { "input": "/caf%C3%A9", "groups": {}}
   1298    }
   1299  },
   1300  {
   1301    "pattern": [{ "pathname": "/caf%c3%a9" }],
   1302    "inputs": [{ "pathname": "/café" }],
   1303    "expected_match": null
   1304  },
   1305  {
   1306    "pattern": [{ "pathname": "/foo/bar" }],
   1307    "inputs": [{ "pathname": "foo/bar" }],
   1308    "expected_match": null
   1309  },
   1310  {
   1311    "pattern": [{ "pathname": "/foo/bar" }],
   1312    "inputs": [{ "pathname": "foo/bar", "baseURL": "https://example.com" }],
   1313    "expected_match": {
   1314      "protocol": { "input": "https", "groups": { "0": "https" }},
   1315      "hostname": { "input": "example.com", "groups": { "0": "example.com" }},
   1316      "pathname": { "input": "/foo/bar", "groups": {}}
   1317    }
   1318  },
   1319  {
   1320    "pattern": [{ "pathname": "/foo/../bar" }],
   1321    "inputs": [{ "pathname": "/bar" }],
   1322    "expected_obj": {
   1323      "pathname": "/bar"
   1324    },
   1325    "expected_match": {
   1326      "pathname": { "input": "/bar", "groups": {}}
   1327    }
   1328  },
   1329  {
   1330    "pattern": [{ "pathname": "./foo/bar", "baseURL": "https://example.com" }],
   1331    "inputs": [{ "pathname": "foo/bar", "baseURL": "https://example.com" }],
   1332    "exactly_empty_components": [ "port" ],
   1333    "expected_obj": {
   1334      "pathname": "/foo/bar"
   1335    },
   1336    "expected_match": {
   1337      "protocol": { "input": "https", "groups": {}},
   1338      "hostname": { "input": "example.com", "groups": {}},
   1339      "pathname": { "input": "/foo/bar", "groups": {}}
   1340    }
   1341  },
   1342  {
   1343    "pattern": [{ "pathname": "", "baseURL": "https://example.com" }],
   1344    "inputs": [{ "pathname": "/", "baseURL": "https://example.com" }],
   1345    "exactly_empty_components": [ "port" ],
   1346    "expected_obj": {
   1347      "pathname": "/"
   1348    },
   1349    "expected_match": {
   1350      "protocol": { "input": "https", "groups": {}},
   1351      "hostname": { "input": "example.com", "groups": {}},
   1352      "pathname": { "input": "/", "groups": {}}
   1353    }
   1354  },
   1355  {
   1356    "pattern": [{ "pathname": "{/bar}", "baseURL": "https://example.com/foo/" }],
   1357    "inputs": [{ "pathname": "./bar", "baseURL": "https://example.com/foo/" }],
   1358    "exactly_empty_components": [ "port" ],
   1359    "expected_obj": {
   1360      "pathname": "/bar"
   1361    },
   1362    "expected_match": null
   1363  },
   1364  {
   1365    "pattern": [{ "pathname": "\\/bar", "baseURL": "https://example.com/foo/" }],
   1366    "inputs": [{ "pathname": "./bar", "baseURL": "https://example.com/foo/" }],
   1367    "exactly_empty_components": [ "port" ],
   1368    "expected_obj": {
   1369      "pathname": "/bar"
   1370    },
   1371    "expected_match": null
   1372  },
   1373  {
   1374    "pattern": [{ "pathname": "b", "baseURL": "https://example.com/foo/" }],
   1375    "inputs": [{ "pathname": "./b", "baseURL": "https://example.com/foo/" }],
   1376    "exactly_empty_components": [ "port" ],
   1377    "expected_obj": {
   1378      "pathname": "/foo/b"
   1379    },
   1380    "expected_match": {
   1381      "protocol": { "input": "https", "groups": {}},
   1382      "hostname": { "input": "example.com", "groups": {}},
   1383      "pathname": { "input": "/foo/b", "groups": {}}
   1384    }
   1385  },
   1386  {
   1387    "pattern": [{ "pathname": "foo/bar" }],
   1388    "inputs": [ "https://example.com/foo/bar" ],
   1389    "expected_match": null
   1390  },
   1391  {
   1392    "pattern": [{ "pathname": "foo/bar", "baseURL": "https://example.com" }],
   1393    "inputs": [ "https://example.com/foo/bar" ],
   1394    "exactly_empty_components": [ "port" ],
   1395    "expected_obj": {
   1396      "pathname": "/foo/bar"
   1397    },
   1398    "expected_match": {
   1399      "protocol": { "input": "https", "groups": {}},
   1400      "hostname": { "input": "example.com", "groups": {}},
   1401      "pathname": { "input": "/foo/bar", "groups": {}}
   1402    }
   1403  },
   1404  {
   1405    "pattern": [{ "pathname": ":name.html", "baseURL": "https://example.com" }],
   1406    "inputs": [ "https://example.com/foo.html"] ,
   1407    "exactly_empty_components": [ "port" ],
   1408    "expected_obj": {
   1409      "pathname": "/:name.html"
   1410    },
   1411    "expected_match": {
   1412      "protocol": { "input": "https", "groups": {}},
   1413      "hostname": { "input": "example.com", "groups": {}},
   1414      "pathname": { "input": "/foo.html", "groups": { "name": "foo" }}
   1415    }
   1416  },
   1417  {
   1418    "pattern": [{ "search": "q=caf%C3%A9" }],
   1419    "inputs": [{ "search": "q=café" }],
   1420    "expected_match": {
   1421      "search": { "input": "q=caf%C3%A9", "groups": {}}
   1422    }
   1423  },
   1424  {
   1425    "pattern": [{ "search": "q=café" }],
   1426    "inputs": [{ "search": "q=café" }],
   1427    "expected_obj": {
   1428      "search": "q=caf%C3%A9"
   1429    },
   1430    "expected_match": {
   1431      "search": { "input": "q=caf%C3%A9", "groups": {}}
   1432    }
   1433  },
   1434  {
   1435    "pattern": [{ "search": "q=caf%c3%a9" }],
   1436    "inputs": [{ "search": "q=café" }],
   1437    "expected_match": null
   1438  },
   1439  {
   1440    "pattern": [{ "hash": "caf%C3%A9" }],
   1441    "inputs": [{ "hash": "café" }],
   1442    "expected_match": {
   1443      "hash": { "input": "caf%C3%A9", "groups": {}}
   1444    }
   1445  },
   1446  {
   1447    "pattern": [{ "hash": "café" }],
   1448    "inputs": [{ "hash": "café" }],
   1449    "expected_obj": {
   1450      "hash": "caf%C3%A9"
   1451    },
   1452    "expected_match": {
   1453      "hash": { "input": "caf%C3%A9", "groups": {}}
   1454    }
   1455  },
   1456  {
   1457    "pattern": [{ "hash": "caf%c3%a9" }],
   1458    "inputs": [{ "hash": "café" }],
   1459    "expected_match": null
   1460  },
   1461  {
   1462    "pattern": [{ "protocol": "about", "pathname": "(blank|sourcedoc)" }],
   1463    "inputs": [ "about:blank" ],
   1464    "expected_match": {
   1465      "protocol": { "input": "about", "groups": {}},
   1466      "pathname": { "input": "blank", "groups": { "0": "blank" }}
   1467    }
   1468  },
   1469  {
   1470    "pattern": [{ "protocol": "data", "pathname": ":number([0-9]+)" }],
   1471    "inputs": [ "data:8675309" ],
   1472    "expected_match": {
   1473      "protocol": { "input": "data", "groups": {}},
   1474      "pathname": { "input": "8675309", "groups": { "number": "8675309" }}
   1475    }
   1476  },
   1477  {
   1478    "pattern": [{ "pathname": "/(\\m)" }],
   1479    "expected_obj": "error"
   1480  },
   1481  {
   1482    "pattern": [{ "pathname": "/foo!" }],
   1483    "inputs": [{ "pathname": "/foo!" }],
   1484    "expected_match": {
   1485      "pathname": { "input": "/foo!", "groups": {}}
   1486    }
   1487  },
   1488  {
   1489    "pattern": [{ "pathname": "/foo\\:" }],
   1490    "inputs": [{ "pathname": "/foo:" }],
   1491    "expected_match": {
   1492      "pathname": { "input": "/foo:", "groups": {}}
   1493    }
   1494  },
   1495  {
   1496    "pattern": [{ "pathname": "/foo\\{" }],
   1497    "inputs": [{ "pathname": "/foo{" }],
   1498    "expected_obj": {
   1499      "pathname": "/foo%7B"
   1500    },
   1501    "expected_match": {
   1502      "pathname": { "input": "/foo%7B", "groups": {}}
   1503    }
   1504  },
   1505  {
   1506    "pattern": [{ "pathname": "/foo\\(" }],
   1507    "inputs": [{ "pathname": "/foo(" }],
   1508    "expected_match": {
   1509      "pathname": { "input": "/foo(", "groups": {}}
   1510    }
   1511  },
   1512  {
   1513    "pattern": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1514    "inputs": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1515    "expected_match": {
   1516      "protocol": { "input": "javascript", "groups": {}},
   1517      "pathname": { "input": "var x = 1;", "groups": {}}
   1518    }
   1519  },
   1520  {
   1521    "pattern": [{ "pathname": "var x = 1;" }],
   1522    "inputs": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1523    "expected_obj": {
   1524      "pathname": "var%20x%20=%201;"
   1525    },
   1526    "expected_match": null
   1527  },
   1528  {
   1529    "pattern": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1530    "inputs": [{ "baseURL": "javascript:var x = 1;" }],
   1531    "expected_match": {
   1532      "protocol": { "input": "javascript", "groups": {}},
   1533      "pathname": { "input": "var x = 1;", "groups": {}}
   1534    }
   1535  },
   1536  {
   1537    "pattern": [{ "protocol": "(data|javascript)", "pathname": "var x = 1;" }],
   1538    "inputs": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1539    "expected_match": {
   1540      "protocol": { "input": "javascript", "groups": {"0": "javascript"}},
   1541      "pathname": { "input": "var x = 1;", "groups": {}}
   1542    }
   1543  },
   1544  {
   1545    "pattern": [{ "protocol": "(https|javascript)", "pathname": "var x = 1;" }],
   1546    "inputs": [{ "protocol": "javascript", "pathname": "var x = 1;" }],
   1547    "expected_obj": {
   1548      "pathname": "var%20x%20=%201;"
   1549    },
   1550    "expected_match": null
   1551  },
   1552  {
   1553    "pattern": [{ "pathname": "var x = 1;" }],
   1554    "inputs": [{ "pathname": "var x = 1;" }],
   1555    "expected_obj": {
   1556      "pathname": "var%20x%20=%201;"
   1557    },
   1558    "expected_match": {
   1559      "pathname": { "input": "var%20x%20=%201;", "groups": {}}
   1560    }
   1561  },
   1562  {
   1563    "pattern": [{ "pathname": "/foo/bar" }],
   1564    "inputs": [ "./foo/bar", "https://example.com" ],
   1565    "expected_match": {
   1566      "hostname": { "input": "example.com", "groups": { "0": "example.com" } },
   1567      "pathname": { "input": "/foo/bar", "groups": {} },
   1568      "protocol": { "input": "https", "groups": { "0": "https" } }
   1569    }
   1570  },
   1571  {
   1572    "pattern": [{ "pathname": "/foo/bar" }],
   1573    "inputs": [ { "pathname": "/foo/bar" }, "https://example.com" ],
   1574    "expected_match": "error"
   1575  },
   1576  {
   1577    "pattern": [ "https://example.com:8080/foo?bar#baz" ],
   1578    "inputs": [{ "pathname": "/foo", "search": "bar", "hash": "baz",
   1579                 "baseURL": "https://example.com:8080" }],
   1580    "expected_obj": {
   1581      "protocol": "https",
   1582      "username": "*",
   1583      "password": "*",
   1584      "hostname": "example.com",
   1585      "port": "8080",
   1586      "pathname": "/foo",
   1587      "search": "bar",
   1588      "hash": "baz"
   1589    },
   1590    "expected_match": {
   1591      "protocol": { "input": "https", "groups": {} },
   1592      "hostname": { "input": "example.com", "groups": {} },
   1593      "port": { "input": "8080", "groups": {} },
   1594      "pathname": { "input": "/foo", "groups": {} },
   1595      "search": { "input": "bar", "groups": {} },
   1596      "hash": { "input": "baz", "groups": {} }
   1597    }
   1598  },
   1599  {
   1600    "pattern": [ "/foo?bar#baz", "https://example.com:8080" ],
   1601    "inputs": [{ "pathname": "/foo", "search": "bar", "hash": "baz",
   1602                 "baseURL": "https://example.com:8080" }],
   1603    "expected_obj": {
   1604      "pathname": "/foo",
   1605      "search": "bar",
   1606      "hash": "baz"
   1607    },
   1608    "expected_match": {
   1609      "protocol": { "input": "https", "groups": {} },
   1610      "hostname": { "input": "example.com", "groups": {} },
   1611      "port": { "input": "8080", "groups": {} },
   1612      "pathname": { "input": "/foo", "groups": {} },
   1613      "search": { "input": "bar", "groups": {} },
   1614      "hash": { "input": "baz", "groups": {} }
   1615    }
   1616  },
   1617  {
   1618    "pattern": [ "/foo" ],
   1619    "expected_obj": "error"
   1620  },
   1621  {
   1622    "pattern": [ "example.com/foo" ],
   1623    "expected_obj": "error"
   1624  },
   1625  {
   1626    "pattern": [ "http{s}?://{*.}?example.com/:product/:endpoint" ],
   1627    "inputs": [ "https://sub.example.com/foo/bar" ],
   1628    "exactly_empty_components": [ "port" ],
   1629    "expected_obj": {
   1630      "protocol": "http{s}?",
   1631      "hostname": "{*.}?example.com",
   1632      "pathname": "/:product/:endpoint"
   1633    },
   1634    "expected_match": {
   1635      "protocol": { "input": "https", "groups": {} },
   1636      "hostname": { "input": "sub.example.com", "groups": { "0": "sub" } },
   1637      "pathname": { "input": "/foo/bar", "groups": { "product": "foo",
   1638                                                     "endpoint": "bar" } }
   1639    }
   1640  },
   1641  {
   1642    "pattern": [ "https://example.com?foo" ],
   1643    "inputs": [ "https://example.com/?foo" ],
   1644    "exactly_empty_components": [ "port" ],
   1645    "expected_obj": {
   1646      "protocol": "https",
   1647      "hostname": "example.com",
   1648      "pathname": "/",
   1649      "search": "foo"
   1650    },
   1651    "expected_match": {
   1652      "protocol": { "input": "https", "groups": {} },
   1653      "hostname": { "input": "example.com", "groups": {} },
   1654      "pathname": { "input": "/", "groups": {} },
   1655      "search": { "input": "foo", "groups": {} }
   1656    }
   1657  },
   1658  {
   1659    "pattern": [ "https://example.com#foo" ],
   1660    "inputs": [ "https://example.com/#foo" ],
   1661    "exactly_empty_components": [ "port", "search" ],
   1662    "expected_obj": {
   1663      "protocol": "https",
   1664      "hostname": "example.com",
   1665      "pathname": "/",
   1666      "hash": "foo"
   1667    },
   1668    "expected_match": {
   1669      "protocol": { "input": "https", "groups": {} },
   1670      "hostname": { "input": "example.com", "groups": {} },
   1671      "pathname": { "input": "/", "groups": {} },
   1672      "hash": { "input": "foo", "groups": {} }
   1673    }
   1674  },
   1675  {
   1676    "pattern": [ "https://example.com:8080?foo" ],
   1677    "inputs": [ "https://example.com:8080/?foo" ],
   1678    "expected_obj": {
   1679      "protocol": "https",
   1680      "hostname": "example.com",
   1681      "port": "8080",
   1682      "pathname": "/",
   1683      "search": "foo"
   1684    },
   1685    "expected_match": {
   1686      "protocol": { "input": "https", "groups": {} },
   1687      "hostname": { "input": "example.com", "groups": {} },
   1688      "port": { "input": "8080", "groups": {} },
   1689      "pathname": { "input": "/", "groups": {} },
   1690      "search": { "input": "foo", "groups": {} }
   1691    }
   1692  },
   1693  {
   1694    "pattern": [ "https://example.com:8080#foo" ],
   1695    "inputs": [ "https://example.com:8080/#foo" ],
   1696    "exactly_empty_components": [ "search" ],
   1697    "expected_obj": {
   1698      "protocol": "https",
   1699      "hostname": "example.com",
   1700      "port": "8080",
   1701      "pathname": "/",
   1702      "hash": "foo"
   1703    },
   1704    "expected_match": {
   1705      "protocol": { "input": "https", "groups": {} },
   1706      "hostname": { "input": "example.com", "groups": {} },
   1707      "port": { "input": "8080", "groups": {} },
   1708      "pathname": { "input": "/", "groups": {} },
   1709      "hash": { "input": "foo", "groups": {} }
   1710    }
   1711  },
   1712  {
   1713    "pattern": [ "https://example.com/?foo" ],
   1714    "inputs": [ "https://example.com/?foo" ],
   1715    "exactly_empty_components": [ "port" ],
   1716    "expected_obj": {
   1717      "protocol": "https",
   1718      "hostname": "example.com",
   1719      "pathname": "/",
   1720      "search": "foo"
   1721    },
   1722    "expected_match": {
   1723      "protocol": { "input": "https", "groups": {} },
   1724      "hostname": { "input": "example.com", "groups": {} },
   1725      "pathname": { "input": "/", "groups": {} },
   1726      "search": { "input": "foo", "groups": {} }
   1727    }
   1728  },
   1729  {
   1730    "pattern": [ "https://example.com/#foo" ],
   1731    "inputs": [ "https://example.com/#foo" ],
   1732    "exactly_empty_components": [ "port", "search" ],
   1733    "expected_obj": {
   1734      "protocol": "https",
   1735      "hostname": "example.com",
   1736      "pathname": "/",
   1737      "hash": "foo"
   1738    },
   1739    "expected_match": {
   1740      "protocol": { "input": "https", "groups": {} },
   1741      "hostname": { "input": "example.com", "groups": {} },
   1742      "pathname": { "input": "/", "groups": {} },
   1743      "hash": { "input": "foo", "groups": {} }
   1744    }
   1745  },
   1746  {
   1747    "pattern": [ "https://example.com/*?foo" ],
   1748    "inputs": [ "https://example.com/?foo" ],
   1749    "exactly_empty_components": [ "port" ],
   1750    "expected_obj": {
   1751      "protocol": "https",
   1752      "hostname": "example.com",
   1753      "pathname": "/*?foo"
   1754    },
   1755    "expected_match": null
   1756  },
   1757  {
   1758    "pattern": [ "https://example.com/*\\?foo" ],
   1759    "inputs": [ "https://example.com/?foo" ],
   1760    "exactly_empty_components": [ "port" ],
   1761    "expected_obj": {
   1762      "protocol": "https",
   1763      "hostname": "example.com",
   1764      "pathname": "/*",
   1765      "search": "foo"
   1766    },
   1767    "expected_match": {
   1768      "protocol": { "input": "https", "groups": {} },
   1769      "hostname": { "input": "example.com", "groups": {} },
   1770      "pathname": { "input": "/", "groups": { "0": "" } },
   1771      "search": { "input": "foo", "groups": {} }
   1772    }
   1773  },
   1774  {
   1775    "pattern": [ "https://example.com/:name?foo" ],
   1776    "inputs": [ "https://example.com/bar?foo" ],
   1777    "exactly_empty_components": [ "port" ],
   1778    "expected_obj": {
   1779      "protocol": "https",
   1780      "hostname": "example.com",
   1781      "pathname": "/:name?foo"
   1782    },
   1783    "expected_match": null
   1784  },
   1785  {
   1786    "pattern": [ "https://example.com/:name\\?foo" ],
   1787    "inputs": [ "https://example.com/bar?foo" ],
   1788    "exactly_empty_components": [ "port" ],
   1789    "expected_obj": {
   1790      "protocol": "https",
   1791      "hostname": "example.com",
   1792      "pathname": "/:name",
   1793      "search": "foo"
   1794    },
   1795    "expected_match": {
   1796      "protocol": { "input": "https", "groups": {} },
   1797      "hostname": { "input": "example.com", "groups": {} },
   1798      "pathname": { "input": "/bar", "groups": { "name": "bar" } },
   1799      "search": { "input": "foo", "groups": {} }
   1800    }
   1801  },
   1802  {
   1803    "pattern": [ "https://example.com/(bar)?foo" ],
   1804    "inputs": [ "https://example.com/bar?foo" ],
   1805    "exactly_empty_components": [ "port" ],
   1806    "expected_obj": {
   1807      "protocol": "https",
   1808      "hostname": "example.com",
   1809      "pathname": "/(bar)?foo"
   1810    },
   1811    "expected_match": null
   1812  },
   1813  {
   1814    "pattern": [ "https://example.com/(bar)\\?foo" ],
   1815    "inputs": [ "https://example.com/bar?foo" ],
   1816    "exactly_empty_components": [ "port" ],
   1817    "expected_obj": {
   1818      "protocol": "https",
   1819      "hostname": "example.com",
   1820      "pathname": "/(bar)",
   1821      "search": "foo"
   1822    },
   1823    "expected_match": {
   1824      "protocol": { "input": "https", "groups": {} },
   1825      "hostname": { "input": "example.com", "groups": {} },
   1826      "pathname": { "input": "/bar", "groups": { "0": "bar" } },
   1827      "search": { "input": "foo", "groups": {} }
   1828    }
   1829  },
   1830  {
   1831    "pattern": [ "https://example.com/{bar}?foo" ],
   1832    "inputs": [ "https://example.com/bar?foo" ],
   1833    "exactly_empty_components": [ "port" ],
   1834    "expected_obj": {
   1835      "protocol": "https",
   1836      "hostname": "example.com",
   1837      "pathname": "/{bar}?foo"
   1838    },
   1839    "expected_match": null
   1840  },
   1841  {
   1842    "pattern": [ "https://example.com/{bar}\\?foo" ],
   1843    "inputs": [ "https://example.com/bar?foo" ],
   1844    "exactly_empty_components": [ "port" ],
   1845    "expected_obj": {
   1846      "protocol": "https",
   1847      "hostname": "example.com",
   1848      "pathname": "/bar",
   1849      "search": "foo"
   1850    },
   1851    "expected_match": {
   1852      "protocol": { "input": "https", "groups": {} },
   1853      "hostname": { "input": "example.com", "groups": {} },
   1854      "pathname": { "input": "/bar", "groups": {} },
   1855      "search": { "input": "foo", "groups": {} }
   1856    }
   1857  },
   1858  {
   1859    "pattern": [ "https://example.com/" ],
   1860    "inputs": [ "https://example.com:8080/" ],
   1861    "exactly_empty_components": [ "port" ],
   1862    "expected_obj": {
   1863      "protocol": "https",
   1864      "hostname": "example.com",
   1865      "port": "",
   1866      "pathname": "/"
   1867    },
   1868    "expected_match": null
   1869  },
   1870  {
   1871    "pattern": [ "data:foobar" ],
   1872    "inputs": [ "data:foobar" ],
   1873    "expected_obj": "error"
   1874  },
   1875  {
   1876    "pattern": [ "data\\:foobar" ],
   1877    "inputs": [ "data:foobar" ],
   1878    "exactly_empty_components": [ "hostname", "port" ],
   1879    "expected_obj": {
   1880      "protocol": "data",
   1881      "pathname": "foobar"
   1882    },
   1883    "expected_match": {
   1884      "protocol": { "input": "data", "groups": {} },
   1885      "pathname": { "input": "foobar", "groups": {} }
   1886    }
   1887  },
   1888  {
   1889    "pattern": [ "https://{sub.}?example.com/foo" ],
   1890    "inputs": [ "https://example.com/foo" ],
   1891    "exactly_empty_components": [ "port" ],
   1892    "expected_obj": {
   1893      "protocol": "https",
   1894      "hostname": "{sub.}?example.com",
   1895      "pathname": "/foo"
   1896    },
   1897    "expected_match": {
   1898      "protocol": { "input": "https", "groups": {} },
   1899      "hostname": { "input": "example.com", "groups": {} },
   1900      "pathname": { "input": "/foo", "groups": {} }
   1901    }
   1902  },
   1903  {
   1904    "pattern": [ "https://{sub.}?example{.com/}foo" ],
   1905    "inputs": [ "https://example.com/foo" ],
   1906    "exactly_empty_components": [ "port" ],
   1907    "expected_obj": {
   1908      "protocol": "https",
   1909      "hostname": "{sub.}?example.com",
   1910      "pathname": "*"
   1911    },
   1912    "expected_match": {
   1913      "protocol": { "input": "https", "groups": {} },
   1914      "hostname": { "input": "example.com", "groups": {} },
   1915      "pathname": { "input": "/foo", "groups": { "0": "/foo" } }
   1916    }
   1917  },
   1918  {
   1919    "pattern": [ "{https://}example.com/foo" ],
   1920    "inputs": [ "https://example.com/foo" ],
   1921    "expected_obj": "error"
   1922  },
   1923  {
   1924    "pattern": [ "https://(sub.)?example.com/foo" ],
   1925    "inputs": [ "https://example.com/foo" ],
   1926    "exactly_empty_components": [ "port" ],
   1927    "expected_obj": {
   1928      "protocol": "https",
   1929      "hostname": "(sub.)?example.com",
   1930      "pathname": "/foo"
   1931    },
   1932    "//": "The `null` below is translated to undefined in the test harness.",
   1933    "expected_match": {
   1934      "protocol": { "input": "https", "groups": {} },
   1935      "hostname": { "input": "example.com", "groups": { "0": null } },
   1936      "pathname": { "input": "/foo", "groups": {} }
   1937    }
   1938  },
   1939  {
   1940    "pattern": [ "https://(sub.)?example(.com/)foo" ],
   1941    "inputs": [ "https://example.com/foo" ],
   1942    "exactly_empty_components": [ "port" ],
   1943    "expected_obj": {
   1944      "protocol": "https",
   1945      "hostname": "(sub.)?example(.com/)foo",
   1946      "pathname": "*"
   1947    },
   1948    "expected_match": null
   1949  },
   1950  {
   1951    "pattern": [ "(https://)example.com/foo" ],
   1952    "inputs": [ "https://example.com/foo" ],
   1953    "expected_obj": "error"
   1954  },
   1955  {
   1956    "pattern": [ "https://{sub{.}}example.com/foo" ],
   1957    "inputs": [ "https://example.com/foo" ],
   1958    "expected_obj": "error"
   1959  },
   1960  {
   1961    "pattern": [ "https://(sub(?:.))?example.com/foo" ],
   1962    "inputs": [ "https://example.com/foo" ],
   1963    "exactly_empty_components": [ "port" ],
   1964    "expected_obj": {
   1965      "protocol": "https",
   1966      "hostname": "(sub(?:.))?example.com",
   1967      "pathname": "/foo"
   1968    },
   1969    "//": "The `null` below is translated to undefined in the test harness.",
   1970    "expected_match": {
   1971      "protocol": { "input": "https", "groups": {} },
   1972      "hostname": { "input": "example.com", "groups": { "0": null } },
   1973      "pathname": { "input": "/foo", "groups": {} }
   1974    }
   1975  },
   1976  {
   1977    "pattern": [ "file:///foo/bar" ],
   1978    "inputs": [ "file:///foo/bar" ],
   1979    "exactly_empty_components": [ "hostname", "port" ],
   1980    "expected_obj": {
   1981      "protocol": "file",
   1982      "pathname": "/foo/bar"
   1983    },
   1984    "expected_match": {
   1985      "protocol": { "input": "file", "groups": {} },
   1986      "pathname": { "input": "/foo/bar", "groups": {} }
   1987    }
   1988  },
   1989  {
   1990    "pattern": [ "data:" ],
   1991    "inputs": [ "data:" ],
   1992    "exactly_empty_components": [ "hostname", "port", "pathname" ],
   1993    "expected_obj": {
   1994      "protocol": "data"
   1995    },
   1996    "expected_match": {
   1997      "protocol": { "input": "data", "groups": {} }
   1998    }
   1999  },
   2000  {
   2001    "pattern": [ "foo://bar" ],
   2002    "inputs": [ "foo://bad_url_browser_interop" ],
   2003    "exactly_empty_components": [ "port" ],
   2004    "expected_obj": {
   2005      "protocol": "foo",
   2006      "hostname": "bar"
   2007    },
   2008    "expected_match": null
   2009  },
   2010  {
   2011    "pattern": [ "(café)://foo" ],
   2012    "expected_obj": "error"
   2013  },
   2014  {
   2015    "pattern": [ "https://example.com/foo?bar#baz" ],
   2016    "inputs": [{ "protocol": "https:",
   2017                 "search": "?bar",
   2018                 "hash": "#baz",
   2019                 "baseURL": "http://example.com/foo" }],
   2020    "exactly_empty_components": [ "port" ],
   2021    "expected_obj": {
   2022      "protocol": "https",
   2023      "hostname": "example.com",
   2024      "pathname": "/foo",
   2025      "search": "bar",
   2026      "hash": "baz"
   2027    },
   2028    "expected_match": null
   2029  },
   2030  {
   2031    "pattern": [{ "protocol": "http{s}?:",
   2032                  "search": "?bar",
   2033                  "hash": "#baz" }],
   2034    "inputs": [ "http://example.com/foo?bar#baz" ],
   2035    "expected_obj": {
   2036      "protocol": "http{s}?",
   2037      "search": "bar",
   2038      "hash": "baz"
   2039    },
   2040    "expected_match": {
   2041      "protocol": { "input": "http", "groups": {} },
   2042      "hostname": { "input": "example.com", "groups": { "0": "example.com" }},
   2043      "pathname": { "input": "/foo", "groups": { "0": "/foo" }},
   2044      "search": { "input": "bar", "groups": {} },
   2045      "hash": { "input": "baz", "groups": {} }
   2046    }
   2047  },
   2048  {
   2049    "pattern": [ "?bar#baz", "https://example.com/foo" ],
   2050    "inputs": [ "?bar#baz", "https://example.com/foo" ],
   2051    "exactly_empty_components": [ "port" ],
   2052    "expected_obj": {
   2053      "protocol": "https",
   2054      "hostname": "example.com",
   2055      "pathname": "/foo",
   2056      "search": "bar",
   2057      "hash": "baz"
   2058    },
   2059    "expected_match": {
   2060      "protocol": { "input": "https", "groups": {} },
   2061      "hostname": { "input": "example.com", "groups": {} },
   2062      "pathname": { "input": "/foo", "groups": {} },
   2063      "search": { "input": "bar", "groups": {} },
   2064      "hash": { "input": "baz", "groups": {} }
   2065    }
   2066  },
   2067  {
   2068    "pattern": [ "?bar", "https://example.com/foo#baz" ],
   2069    "inputs": [ "?bar", "https://example.com/foo#snafu" ],
   2070    "exactly_empty_components": [ "port" ],
   2071    "expected_obj": {
   2072      "protocol": "https",
   2073      "hostname": "example.com",
   2074      "pathname": "/foo",
   2075      "search": "bar",
   2076      "hash": "*"
   2077    },
   2078    "expected_match": {
   2079      "protocol": { "input": "https", "groups": {} },
   2080      "hostname": { "input": "example.com", "groups": {} },
   2081      "pathname": { "input": "/foo", "groups": {} },
   2082      "search": { "input": "bar", "groups": {} }
   2083    }
   2084  },
   2085  {
   2086    "pattern": [ "#baz", "https://example.com/foo?bar" ],
   2087    "inputs": [ "#baz", "https://example.com/foo?bar" ],
   2088    "exactly_empty_components": [ "port" ],
   2089    "expected_obj": {
   2090      "protocol": "https",
   2091      "hostname": "example.com",
   2092      "pathname": "/foo",
   2093      "search": "bar",
   2094      "hash": "baz"
   2095    },
   2096    "expected_match": {
   2097      "protocol": { "input": "https", "groups": {} },
   2098      "hostname": { "input": "example.com", "groups": {} },
   2099      "pathname": { "input": "/foo", "groups": {} },
   2100      "search": { "input": "bar", "groups": {} },
   2101      "hash": { "input": "baz", "groups": {} }
   2102    }
   2103  },
   2104  {
   2105    "pattern": [ "#baz", "https://example.com/foo" ],
   2106    "inputs": [ "#baz", "https://example.com/foo" ],
   2107    "exactly_empty_components": [ "port", "search" ],
   2108    "expected_obj": {
   2109      "protocol": "https",
   2110      "hostname": "example.com",
   2111      "pathname": "/foo",
   2112      "hash": "baz"
   2113    },
   2114    "expected_match": {
   2115      "protocol": { "input": "https", "groups": {} },
   2116      "hostname": { "input": "example.com", "groups": {} },
   2117      "pathname": { "input": "/foo", "groups": {} },
   2118      "hash": { "input": "baz", "groups": {} }
   2119    }
   2120  },
   2121  {
   2122    "pattern": [{ "pathname": "*" }],
   2123    "inputs": [ "foo", "data:data-urls-cannot-be-base-urls" ],
   2124    "expected_match": null
   2125  },
   2126  {
   2127    "pattern": [{ "pathname": "*" }],
   2128    "inputs": [ "foo", "not|a|valid|url" ],
   2129    "expected_match": null
   2130  },
   2131  {
   2132    "pattern": [ "https://foo\\:bar@example.com" ],
   2133    "inputs": [ "https://foo:bar@example.com" ],
   2134    "exactly_empty_components": [ "port" ],
   2135    "expected_obj": {
   2136      "protocol": "https",
   2137      "username": "foo",
   2138      "password": "bar",
   2139      "hostname": "example.com",
   2140      "pathname": "*"
   2141    },
   2142    "expected_match": {
   2143      "protocol": { "input": "https", "groups": {} },
   2144      "username": { "input": "foo", "groups": {} },
   2145      "password": { "input": "bar", "groups": {} },
   2146      "hostname": { "input": "example.com", "groups": {} },
   2147      "pathname": { "input": "/", "groups": { "0": "/" } }
   2148    }
   2149  },
   2150  {
   2151    "pattern": [ "https://foo@example.com" ],
   2152    "inputs": [ "https://foo@example.com" ],
   2153    "exactly_empty_components": [ "port" ],
   2154    "expected_obj": {
   2155      "protocol": "https",
   2156      "username": "foo",
   2157      "hostname": "example.com",
   2158      "pathname": "*"
   2159    },
   2160    "expected_match": {
   2161      "protocol": { "input": "https", "groups": {} },
   2162      "username": { "input": "foo", "groups": {} },
   2163      "hostname": { "input": "example.com", "groups": {} },
   2164      "pathname": { "input": "/", "groups": { "0": "/" } }
   2165    }
   2166  },
   2167  {
   2168    "pattern": [ "https://\\:bar@example.com" ],
   2169    "inputs": [ "https://:bar@example.com" ],
   2170    "exactly_empty_components": [ "username", "port" ],
   2171    "expected_obj": {
   2172      "protocol": "https",
   2173      "password": "bar",
   2174      "hostname": "example.com",
   2175      "pathname": "*"
   2176    },
   2177    "expected_match": {
   2178      "protocol": { "input": "https", "groups": {} },
   2179      "password": { "input": "bar", "groups": {} },
   2180      "hostname": { "input": "example.com", "groups": {} },
   2181      "pathname": { "input": "/", "groups": { "0": "/" } }
   2182    }
   2183  },
   2184  {
   2185    "pattern": [ "https://:user::pass@example.com" ],
   2186    "inputs": [ "https://foo:bar@example.com" ],
   2187    "exactly_empty_components": [ "port" ],
   2188    "expected_obj": {
   2189      "protocol": "https",
   2190      "username": ":user",
   2191      "password": ":pass",
   2192      "hostname": "example.com",
   2193      "pathname": "*"
   2194    },
   2195    "expected_match": {
   2196      "protocol": { "input": "https", "groups": {} },
   2197      "username": { "input": "foo", "groups": { "user": "foo" } },
   2198      "password": { "input": "bar", "groups": { "pass": "bar" } },
   2199      "hostname": { "input": "example.com", "groups": {} },
   2200      "pathname": { "input": "/", "groups": { "0": "/" } }
   2201    }
   2202  },
   2203  {
   2204    "pattern": [ "https\\:foo\\:bar@example.com" ],
   2205    "inputs": [ "https:foo:bar@example.com" ],
   2206    "exactly_empty_components": [ "port" ],
   2207    "expected_obj": {
   2208      "protocol": "https",
   2209      "username": "foo",
   2210      "password": "bar",
   2211      "hostname": "example.com",
   2212      "pathname": "*"
   2213    },
   2214    "expected_match": {
   2215      "protocol": { "input": "https", "groups": {} },
   2216      "username": { "input": "foo", "groups": {} },
   2217      "password": { "input": "bar", "groups": {} },
   2218      "hostname": { "input": "example.com", "groups": {} },
   2219      "pathname": { "input": "/", "groups": { "0": "/" } }
   2220    }
   2221  },
   2222  {
   2223    "pattern": [ "data\\:foo\\:bar@example.com" ],
   2224    "inputs": [ "data:foo:bar@example.com" ],
   2225    "exactly_empty_components": [ "hostname", "port" ],
   2226    "expected_obj": {
   2227      "protocol": "data",
   2228      "pathname": "foo\\:bar@example.com"
   2229    },
   2230    "expected_match": {
   2231      "protocol": { "input": "data", "groups": {} },
   2232      "pathname": { "input": "foo:bar@example.com", "groups": {} }
   2233    }
   2234  },
   2235  {
   2236    "pattern": [ "https://foo{\\:}bar@example.com" ],
   2237    "inputs": [ "https://foo:bar@example.com" ],
   2238    "exactly_empty_components": [ "port" ],
   2239    "expected_obj": {
   2240      "protocol": "https",
   2241      "username": "foo%3Abar",
   2242      "hostname": "example.com"
   2243    },
   2244    "expected_match": null
   2245  },
   2246  {
   2247    "pattern": [ "data{\\:}channel.html", "https://example.com" ],
   2248    "inputs": [ "https://example.com/data:channel.html" ],
   2249    "exactly_empty_components": [ "port" ],
   2250    "expected_obj": {
   2251      "protocol": "https",
   2252      "hostname": "example.com",
   2253      "pathname": "/data\\:channel.html",
   2254      "search": "*",
   2255      "hash": "*"
   2256    },
   2257    "expected_match": {
   2258      "protocol": { "input": "https", "groups": {} },
   2259      "hostname": { "input": "example.com", "groups": {} },
   2260      "pathname": { "input": "/data:channel.html", "groups": {} }
   2261    }
   2262  },
   2263  {
   2264    "pattern": [ "http://[\\:\\:1]/" ],
   2265    "inputs": [ "http://[::1]/" ],
   2266    "exactly_empty_components": [ "port" ],
   2267    "expected_obj": {
   2268      "protocol": "http",
   2269      "hostname": "[\\:\\:1]",
   2270      "pathname": "/"
   2271    },
   2272    "expected_match": {
   2273      "protocol": { "input": "http", "groups": {} },
   2274      "hostname": { "input": "[::1]", "groups": {} },
   2275      "pathname": { "input": "/", "groups": {} }
   2276    }
   2277  },
   2278  {
   2279    "pattern": [ "http://[\\:\\:1]:8080/" ],
   2280    "inputs": [ "http://[::1]:8080/" ],
   2281    "expected_obj": {
   2282      "protocol": "http",
   2283      "hostname": "[\\:\\:1]",
   2284      "port": "8080",
   2285      "pathname": "/"
   2286    },
   2287    "expected_match": {
   2288      "protocol": { "input": "http", "groups": {} },
   2289      "hostname": { "input": "[::1]", "groups": {} },
   2290      "port": { "input": "8080", "groups": {} },
   2291      "pathname": { "input": "/", "groups": {} }
   2292    }
   2293  },
   2294  {
   2295    "pattern": [ "http://[\\:\\:a]/" ],
   2296    "inputs": [ "http://[::a]/" ],
   2297    "exactly_empty_components": [ "port" ],
   2298    "expected_obj": {
   2299      "protocol": "http",
   2300      "hostname": "[\\:\\:a]",
   2301      "pathname": "/"
   2302    },
   2303    "expected_match": {
   2304      "protocol": { "input": "http", "groups": {} },
   2305      "hostname": { "input": "[::a]", "groups": {} },
   2306      "pathname": { "input": "/", "groups": {} }
   2307    }
   2308  },
   2309  {
   2310    "pattern": [ "http://[:address]/" ],
   2311    "inputs": [ "http://[::1]/" ],
   2312    "exactly_empty_components": [ "port" ],
   2313    "expected_obj": {
   2314      "protocol": "http",
   2315      "hostname": "[:address]",
   2316      "pathname": "/"
   2317    },
   2318    "expected_match": {
   2319      "protocol": { "input": "http", "groups": {} },
   2320      "hostname": { "input": "[::1]", "groups": { "address": "::1" }},
   2321      "pathname": { "input": "/", "groups": {} }
   2322    }
   2323  },
   2324  {
   2325    "pattern": [ "http://[\\:\\:AB\\::num]/" ],
   2326    "inputs": [ "http://[::ab:1]/" ],
   2327    "exactly_empty_components": [ "port" ],
   2328    "expected_obj": {
   2329      "protocol": "http",
   2330      "hostname": "[\\:\\:ab\\::num]",
   2331      "pathname": "/"
   2332    },
   2333    "expected_match": {
   2334      "protocol": { "input": "http", "groups": {} },
   2335      "hostname": { "input": "[::ab:1]", "groups": { "num": "1" }},
   2336      "pathname": { "input": "/", "groups": {} }
   2337    }
   2338  },
   2339  {
   2340    "pattern": [{ "hostname": "[\\:\\:AB\\::num]" }],
   2341    "inputs": [{ "hostname": "[::ab:1]" }],
   2342    "expected_obj": {
   2343      "hostname": "[\\:\\:ab\\::num]"
   2344    },
   2345    "expected_match": {
   2346      "hostname": { "input": "[::ab:1]", "groups": { "num": "1" }}
   2347    }
   2348  },
   2349  {
   2350    "pattern": [{ "hostname": "[\\:\\:xY\\::num]" }],
   2351    "expected_obj": "error"
   2352  },
   2353  {
   2354    "pattern": [{ "hostname": "{[\\:\\:ab\\::num]}" }],
   2355    "inputs": [{ "hostname": "[::ab:1]" }],
   2356    "expected_match": {
   2357      "hostname": { "input": "[::ab:1]", "groups": { "num": "1" }}
   2358    }
   2359  },
   2360  {
   2361    "pattern": [{ "hostname": "{[\\:\\:fé\\::num]}" }],
   2362    "expected_obj": "error"
   2363  },
   2364  {
   2365    "pattern": [{ "hostname": "{[\\:\\::num\\:1]}" }],
   2366    "inputs": [{ "hostname": "[::ab:1]" }],
   2367    "expected_match": {
   2368      "hostname": { "input": "[::ab:1]", "groups": { "num": "ab" }}
   2369    }
   2370  },
   2371  {
   2372    "pattern": [{ "hostname": "{[\\:\\::num\\:fé]}" }],
   2373    "expected_obj": "error"
   2374  },
   2375  {
   2376    "pattern": [{ "hostname": "[*\\:1]" }],
   2377    "inputs": [{ "hostname": "[::ab:1]" }],
   2378    "expected_match": {
   2379      "hostname": { "input": "[::ab:1]", "groups": { "0": "::ab" }}
   2380    }
   2381  },
   2382  {
   2383    "pattern": [{ "hostname": "*\\:1]" }],
   2384    "expected_obj": "error"
   2385  },
   2386  {
   2387    "pattern": [ "https://foo{{@}}example.com" ],
   2388    "inputs": [ "https://foo@example.com" ],
   2389    "expected_obj": "error"
   2390  },
   2391  {
   2392    "pattern": [ "https://foo{@example.com" ],
   2393    "inputs": [ "https://foo@example.com" ],
   2394    "expected_obj": "error"
   2395  },
   2396  {
   2397    "pattern": [ "data\\:text/javascript,let x = 100/:tens?5;" ],
   2398    "inputs": [ "data:text/javascript,let x = 100/5;" ],
   2399    "exactly_empty_components": [ "hostname", "port" ],
   2400    "expected_obj": {
   2401      "protocol": "data",
   2402      "pathname": "text/javascript,let x = 100/:tens?5;"
   2403    },
   2404    "//": "The `null` below is translated to undefined in the test harness.",
   2405    "expected_match": {
   2406      "protocol": { "input": "data", "groups": {} },
   2407      "pathname": { "input": "text/javascript,let x = 100/5;", "groups": { "tens": null } }
   2408    }
   2409  },
   2410  {
   2411    "pattern": [{ "pathname": "/:id/:id" }],
   2412    "expected_obj": "error"
   2413  },
   2414  {
   2415    "pattern": [{ "pathname": "/foo", "baseURL": "" }],
   2416    "expected_obj": "error"
   2417  },
   2418  {
   2419    "pattern": [ "/foo", "" ],
   2420    "expected_obj": "error"
   2421  },
   2422  {
   2423    "pattern": [{ "pathname": "/foo" }, "https://example.com" ],
   2424    "expected_obj": "error"
   2425  },
   2426  {
   2427    "pattern": [{ "pathname": ":name*" }],
   2428    "inputs": [{ "pathname": "foobar" }],
   2429    "expected_match": {
   2430      "pathname": { "input": "foobar", "groups": { "name": "foobar" }}
   2431    }
   2432  },
   2433  {
   2434    "pattern": [{ "pathname": ":name+" }],
   2435    "inputs": [{ "pathname": "foobar" }],
   2436    "expected_match": {
   2437      "pathname": { "input": "foobar", "groups": { "name": "foobar" }}
   2438    }
   2439  },
   2440  {
   2441    "pattern": [{ "pathname": ":name" }],
   2442    "inputs": [{ "pathname": "foobar" }],
   2443    "expected_match": {
   2444      "pathname": { "input": "foobar", "groups": { "name": "foobar" }}
   2445    }
   2446  },
   2447  {
   2448    "pattern": [{ "protocol": ":name*" }],
   2449    "inputs": [{ "protocol": "foobar" }],
   2450    "expected_match": {
   2451      "protocol": { "input": "foobar", "groups": { "name": "foobar" }}
   2452    }
   2453  },
   2454  {
   2455    "pattern": [{ "protocol": ":name+" }],
   2456    "inputs": [{ "protocol": "foobar" }],
   2457    "expected_match": {
   2458      "protocol": { "input": "foobar", "groups": { "name": "foobar" }}
   2459    }
   2460  },
   2461  {
   2462    "pattern": [{ "protocol": ":name" }],
   2463    "inputs": [{ "protocol": "foobar" }],
   2464    "expected_match": {
   2465      "protocol": { "input": "foobar", "groups": { "name": "foobar" }}
   2466    }
   2467  },
   2468  {
   2469    "pattern": [{ "hostname": "bad hostname" }],
   2470    "expected_obj": "error"
   2471  },
   2472  {
   2473    "pattern": [{ "hostname": "bad#hostname" }],
   2474    "inputs": [{ "hostname":  "bad" }],
   2475    "expected_obj": {
   2476      "hostname": "bad"
   2477    },
   2478    "expected_match": {
   2479      "hostname": { "input": "bad", "groups": {} }
   2480    }
   2481  },
   2482  {
   2483    "pattern": [{ "hostname": "bad%hostname" }],
   2484    "expected_obj": "error"
   2485  },
   2486  {
   2487    "pattern": [{ "hostname": "bad/hostname" }],
   2488    "inputs": [{ "hostname": "bad" }],
   2489    "expected_obj": {
   2490      "hostname": "bad"
   2491    },
   2492    "expected_match": {
   2493      "hostname": { "input": "bad", "groups": {} }
   2494    }
   2495  },
   2496  {
   2497    "pattern": [{ "hostname": "bad\\:hostname" }],
   2498    "expected_obj": "error"
   2499  },
   2500  {
   2501    "pattern": [{ "hostname": "bad<hostname" }],
   2502    "expected_obj": "error"
   2503  },
   2504  {
   2505    "pattern": [{ "hostname": "bad>hostname" }],
   2506    "expected_obj": "error"
   2507  },
   2508  {
   2509    "pattern": [{ "hostname": "bad?hostname" }],
   2510    "expected_obj": "error"
   2511  },
   2512  {
   2513    "pattern": [{ "hostname": "bad@hostname" }],
   2514    "expected_obj": "error"
   2515  },
   2516  {
   2517    "pattern": [{ "hostname": "bad[hostname" }],
   2518    "expected_obj": "error"
   2519  },
   2520  {
   2521    "pattern": [{ "hostname": "bad]hostname" }],
   2522    "expected_obj": "error"
   2523  },
   2524  {
   2525    "pattern": [{ "hostname": "bad\\\\hostname" }],
   2526    "inputs": [{ "hostname": "badhostname" }],
   2527    "expected_obj": {
   2528      "hostname": "bad"
   2529    },
   2530    "expected_match": null
   2531  },
   2532  {
   2533    "pattern": [{ "hostname": "bad^hostname" }],
   2534    "expected_obj": "error"
   2535  },
   2536  {
   2537    "pattern": [{ "hostname": "bad|hostname" }],
   2538    "expected_obj": "error"
   2539  },
   2540  {
   2541    "pattern": [{ "hostname": "bad\nhostname" }],
   2542    "inputs": [{ "hostname": "badhostname" }],
   2543    "expected_obj": {
   2544      "hostname": "badhostname"
   2545    },
   2546    "expected_match": {
   2547      "hostname": { "input": "badhostname", "groups": {} }
   2548    }
   2549  },
   2550  {
   2551    "pattern": [{ "hostname": "bad\rhostname" }],
   2552    "inputs": [{ "hostname": "badhostname" }],
   2553    "expected_obj": {
   2554      "hostname": "badhostname"
   2555    },
   2556    "expected_match": {
   2557      "hostname": { "input": "badhostname", "groups": {} }
   2558    }
   2559  },
   2560  {
   2561    "pattern": [{ "hostname": "bad\thostname" }],
   2562    "inputs": [{ "hostname": "badhostname" }],
   2563    "expected_obj": {
   2564      "hostname": "badhostname"
   2565    },
   2566    "expected_match": {
   2567      "hostname": { "input": "badhostname", "groups": {} }
   2568    }
   2569  },
   2570  {
   2571    "pattern": [{}],
   2572    "inputs": ["https://example.com/"],
   2573    "expected_match": {
   2574      "protocol": { "input": "https", "groups": { "0": "https" }},
   2575      "hostname": { "input": "example.com", "groups": { "0": "example.com" }},
   2576      "pathname": { "input": "/", "groups": { "0": "/" }}
   2577    }
   2578  },
   2579  {
   2580    "pattern": [],
   2581    "inputs": ["https://example.com/"],
   2582    "expected_match": {
   2583      "protocol": { "input": "https", "groups": { "0": "https" }},
   2584      "hostname": { "input": "example.com", "groups": { "0": "example.com" }},
   2585      "pathname": { "input": "/", "groups": { "0": "/" }}
   2586    }
   2587  },
   2588  {
   2589    "pattern": [],
   2590    "inputs": [{}],
   2591    "expected_match": {}
   2592  },
   2593  {
   2594    "pattern": [],
   2595    "inputs": [],
   2596    "expected_match": { "inputs": [{}] }
   2597  },
   2598  {
   2599    "pattern": [{ "pathname": "(foo)(.*)" }],
   2600    "inputs": [{ "pathname": "foobarbaz" }],
   2601    "expected_match": {
   2602      "pathname": { "input": "foobarbaz", "groups": { "0": "foo", "1": "barbaz" }}
   2603    }
   2604  },
   2605  {
   2606    "pattern": [{ "pathname": "{(foo)bar}(.*)" }],
   2607    "inputs": [{ "pathname": "foobarbaz" }],
   2608    "expected_match": {
   2609      "pathname": { "input": "foobarbaz", "groups": { "0": "foo", "1": "baz" }}
   2610    }
   2611  },
   2612  {
   2613    "pattern": [{ "pathname": "(foo)?(.*)" }],
   2614    "inputs": [{ "pathname": "foobarbaz" }],
   2615    "expected_obj": {
   2616      "pathname": "(foo)?*"
   2617    },
   2618    "expected_match": {
   2619      "pathname": { "input": "foobarbaz", "groups": { "0": "foo", "1": "barbaz" }}
   2620    }
   2621  },
   2622  {
   2623    "pattern": [{ "pathname": "{:foo}(.*)" }],
   2624    "inputs": [{ "pathname": "foobarbaz" }],
   2625    "expected_match": {
   2626      "pathname": { "input": "foobarbaz", "groups": { "foo": "f", "0": "oobarbaz" }}
   2627    }
   2628  },
   2629  {
   2630    "pattern": [{ "pathname": "{:foo}(barbaz)" }],
   2631    "inputs": [{ "pathname": "foobarbaz" }],
   2632    "expected_match": {
   2633      "pathname": { "input": "foobarbaz", "groups": { "foo": "foo", "0": "barbaz" }}
   2634    }
   2635  },
   2636  {
   2637    "pattern": [{ "pathname": "{:foo}{(.*)}" }],
   2638    "inputs": [{ "pathname": "foobarbaz" }],
   2639    "expected_obj": {
   2640      "pathname": "{:foo}(.*)"
   2641    },
   2642    "expected_match": {
   2643      "pathname": { "input": "foobarbaz", "groups": { "foo": "f", "0": "oobarbaz" }}
   2644    }
   2645  },
   2646  {
   2647    "pattern": [{ "pathname": "{:foo}{(.*)bar}" }],
   2648    "inputs": [{ "pathname": "foobarbaz" }],
   2649    "expected_obj": {
   2650      "pathname": ":foo{*bar}"
   2651    },
   2652    "expected_match": null
   2653  },
   2654  {
   2655    "pattern": [{ "pathname": "{:foo}{bar(.*)}" }],
   2656    "inputs": [{ "pathname": "foobarbaz" }],
   2657    "expected_obj": {
   2658      "pathname": ":foo{bar*}"
   2659    },
   2660    "expected_match": {
   2661      "pathname": { "input": "foobarbaz", "groups": { "foo": "foo", "0": "baz" }}
   2662    }
   2663  },
   2664  {
   2665    "pattern": [{ "pathname": "{:foo}:bar(.*)" }],
   2666    "inputs": [{ "pathname": "foobarbaz" }],
   2667    "expected_obj": {
   2668      "pathname": ":foo:bar(.*)"
   2669    },
   2670    "expected_match": {
   2671      "pathname": { "input": "foobarbaz", "groups": { "foo": "f", "bar": "oobarbaz" }}
   2672    }
   2673  },
   2674  {
   2675    "pattern": [{ "pathname": "{:foo}?(.*)" }],
   2676    "inputs": [{ "pathname": "foobarbaz" }],
   2677    "expected_obj": {
   2678      "pathname": ":foo?*"
   2679    },
   2680    "expected_match": {
   2681      "pathname": { "input": "foobarbaz", "groups": { "foo": "f", "0": "oobarbaz" }}
   2682    }
   2683  },
   2684  {
   2685    "pattern": [{ "pathname": "{:foo\\bar}" }],
   2686    "inputs": [{ "pathname": "foobar" }],
   2687    "expected_match": {
   2688      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2689    }
   2690  },
   2691  {
   2692    "pattern": [{ "pathname": "{:foo\\.bar}" }],
   2693    "inputs": [{ "pathname": "foo.bar" }],
   2694    "expected_obj": {
   2695      "pathname": "{:foo.bar}"
   2696    },
   2697    "expected_match": {
   2698      "pathname": { "input": "foo.bar", "groups": { "foo": "foo" }}
   2699    }
   2700  },
   2701  {
   2702    "pattern": [{ "pathname": "{:foo(foo)bar}" }],
   2703    "inputs": [{ "pathname": "foobar" }],
   2704    "expected_match": {
   2705      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2706    }
   2707  },
   2708  {
   2709    "pattern": [{ "pathname": "{:foo}bar" }],
   2710    "inputs": [{ "pathname": "foobar" }],
   2711    "expected_match": {
   2712      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2713    }
   2714  },
   2715  {
   2716    "pattern": [{ "pathname": ":foo\\bar" }],
   2717    "inputs": [{ "pathname": "foobar" }],
   2718    "expected_obj": {
   2719      "pathname": "{:foo}bar"
   2720    },
   2721    "expected_match": {
   2722      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2723    }
   2724  },
   2725  {
   2726    "pattern": [{ "pathname": ":foo{}(.*)" }],
   2727    "inputs": [{ "pathname": "foobar" }],
   2728    "expected_obj": {
   2729      "pathname": "{:foo}(.*)"
   2730    },
   2731    "expected_match": {
   2732      "pathname": { "input": "foobar", "groups": { "foo": "f", "0": "oobar" }}
   2733    }
   2734  },
   2735  {
   2736    "pattern": [{ "pathname": ":foo{}bar" }],
   2737    "inputs": [{ "pathname": "foobar" }],
   2738    "expected_obj": {
   2739      "pathname": "{:foo}bar"
   2740    },
   2741    "expected_match": {
   2742      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2743    }
   2744  },
   2745  {
   2746    "pattern": [{ "pathname": ":foo{}?bar" }],
   2747    "inputs": [{ "pathname": "foobar" }],
   2748    "expected_obj": {
   2749      "pathname": "{:foo}bar"
   2750    },
   2751    "expected_match": {
   2752      "pathname": { "input": "foobar", "groups": { "foo": "foo" }}
   2753    }
   2754  },
   2755  {
   2756    "pattern": [{ "pathname": "*{}**?" }],
   2757    "inputs": [{ "pathname": "foobar" }],
   2758    "expected_obj": {
   2759      "pathname": "*(.*)?"
   2760    },
   2761    "//": "The `null` below is translated to undefined in the test harness.",
   2762    "expected_match": {
   2763      "pathname": { "input": "foobar", "groups": { "0": "foobar", "1": null }}
   2764    }
   2765  },
   2766  {
   2767    "pattern": [{ "pathname": ":foo(baz)(.*)" }],
   2768    "inputs": [{ "pathname": "bazbar" }],
   2769    "expected_match": {
   2770      "pathname": { "input": "bazbar", "groups": { "foo": "baz", "0": "bar" }}
   2771    }
   2772  },
   2773  {
   2774    "pattern": [{ "pathname": ":foo(baz)bar" }],
   2775    "inputs": [{ "pathname": "bazbar" }],
   2776    "expected_match": {
   2777      "pathname": { "input": "bazbar", "groups": { "foo": "baz" }}
   2778    }
   2779  },
   2780  {
   2781    "pattern": [{ "pathname": "*/*" }],
   2782    "inputs": [{ "pathname": "foo/bar" }],
   2783    "expected_match": {
   2784      "pathname": { "input": "foo/bar", "groups": { "0": "foo", "1": "bar" }}
   2785    }
   2786  },
   2787  {
   2788    "pattern": [{ "pathname": "*\\/*" }],
   2789    "inputs": [{ "pathname": "foo/bar" }],
   2790    "expected_obj": {
   2791      "pathname": "*/{*}"
   2792    },
   2793    "expected_match": {
   2794      "pathname": { "input": "foo/bar", "groups": { "0": "foo", "1": "bar" }}
   2795    }
   2796  },
   2797  {
   2798    "pattern": [{ "pathname": "*/{*}" }],
   2799    "inputs": [{ "pathname": "foo/bar" }],
   2800    "expected_match": {
   2801      "pathname": { "input": "foo/bar", "groups": { "0": "foo", "1": "bar" }}
   2802    }
   2803  },
   2804  {
   2805    "pattern": [{ "pathname": "*//*" }],
   2806    "inputs": [{ "pathname": "foo/bar" }],
   2807    "expected_match": null
   2808  },
   2809  {
   2810    "pattern": [{ "pathname": "/:foo." }],
   2811    "inputs": [{ "pathname": "/bar." }],
   2812    "expected_match": {
   2813      "pathname": { "input": "/bar.", "groups": { "foo": "bar" } }
   2814    }
   2815  },
   2816  {
   2817    "pattern": [{ "pathname": "/:foo.." }],
   2818    "inputs": [{ "pathname": "/bar.." }],
   2819    "expected_match": {
   2820      "pathname": { "input": "/bar..", "groups": { "foo": "bar" } }
   2821    }
   2822  },
   2823  {
   2824    "pattern": [{ "pathname": "./foo" }],
   2825    "inputs": [{ "pathname": "./foo" }],
   2826    "expected_match": {
   2827      "pathname": { "input": "./foo", "groups": {}}
   2828    }
   2829  },
   2830  {
   2831    "pattern": [{ "pathname": "../foo" }],
   2832    "inputs": [{ "pathname": "../foo" }],
   2833    "expected_match": {
   2834      "pathname": { "input": "../foo", "groups": {}}
   2835    }
   2836  },
   2837  {
   2838    "pattern": [{ "pathname": ":foo./" }],
   2839    "inputs": [{ "pathname": "bar./" }],
   2840    "expected_match": {
   2841      "pathname": { "input": "bar./", "groups": { "foo": "bar" }}
   2842    }
   2843  },
   2844  {
   2845    "pattern": [{ "pathname": ":foo../" }],
   2846    "inputs": [{ "pathname": "bar../" }],
   2847    "expected_match": {
   2848      "pathname": { "input": "bar../", "groups": { "foo": "bar" }}
   2849    }
   2850  },
   2851  {
   2852    "pattern": [{ "pathname": "/:foo\\bar" }],
   2853    "inputs": [{ "pathname": "/bazbar" }],
   2854    "expected_obj": {
   2855      "pathname": "{/:foo}bar"
   2856    },
   2857    "expected_match": {
   2858      "pathname": { "input": "/bazbar", "groups": { "foo": "baz" }}
   2859    }
   2860  },
   2861  {
   2862    "pattern": [{ "pathname": "/foo/bar" }, { "ignoreCase": true }],
   2863    "inputs": [{ "pathname": "/FOO/BAR" }],
   2864    "expected_match": {
   2865      "pathname": { "input": "/FOO/BAR", "groups": {} }
   2866    }
   2867  },
   2868  {
   2869    "pattern": [{ "ignoreCase": true }],
   2870    "inputs": [{ "pathname": "/FOO/BAR" }],
   2871    "expected_match": {
   2872      "pathname": { "input": "/FOO/BAR", "groups": { "0": "/FOO/BAR" } }
   2873    }
   2874  },
   2875  {
   2876    "pattern": [ "https://example.com:8080/foo?bar#baz",
   2877                 { "ignoreCase": true }],
   2878    "inputs": [{ "pathname": "/FOO", "search": "BAR", "hash": "BAZ",
   2879                 "baseURL": "https://example.com:8080" }],
   2880    "expected_obj": {
   2881      "protocol": "https",
   2882      "hostname": "example.com",
   2883      "port": "8080",
   2884      "pathname": "/foo",
   2885      "search": "bar",
   2886      "hash": "baz"
   2887    },
   2888    "expected_match": {
   2889      "protocol": { "input": "https", "groups": {} },
   2890      "hostname": { "input": "example.com", "groups": {} },
   2891      "port": { "input": "8080", "groups": {} },
   2892      "pathname": { "input": "/FOO", "groups": {} },
   2893      "search": { "input": "BAR", "groups": {} },
   2894      "hash": { "input": "BAZ", "groups": {} }
   2895    }
   2896  },
   2897  {
   2898    "pattern": [ "/foo?bar#baz", "https://example.com:8080",
   2899                 { "ignoreCase": true }],
   2900    "inputs": [{ "pathname": "/FOO", "search": "BAR", "hash": "BAZ",
   2901                 "baseURL": "https://example.com:8080" }],
   2902    "expected_obj": {
   2903      "protocol": "https",
   2904      "hostname": "example.com",
   2905      "port": "8080",
   2906      "pathname": "/foo",
   2907      "search": "bar",
   2908      "hash": "baz"
   2909    },
   2910    "expected_match": {
   2911      "protocol": { "input": "https", "groups": {} },
   2912      "hostname": { "input": "example.com", "groups": {} },
   2913      "port": { "input": "8080", "groups": {} },
   2914      "pathname": { "input": "/FOO", "groups": {} },
   2915      "search": { "input": "BAR", "groups": {} },
   2916      "hash": { "input": "BAZ", "groups": {} }
   2917    }
   2918  },
   2919  {
   2920    "pattern": [ "/foo?bar#baz", { "ignoreCase": true },
   2921                 "https://example.com:8080" ],
   2922    "inputs": [{ "pathname": "/FOO", "search": "BAR", "hash": "BAZ",
   2923                 "baseURL": "https://example.com:8080" }],
   2924    "expected_obj": "error"
   2925  },
   2926  {
   2927    "pattern": [{ "search": "foo", "baseURL": "https://example.com/a/+/b" }],
   2928    "inputs": [{ "search": "foo", "baseURL": "https://example.com/a/+/b" }],
   2929    "exactly_empty_components": [ "port" ],
   2930    "expected_obj": {
   2931      "pathname": "/a/\\+/b"
   2932    },
   2933    "expected_match": {
   2934      "hostname": { "input": "example.com", "groups": {} },
   2935      "pathname": { "input": "/a/+/b", "groups": {} },
   2936      "protocol": { "input": "https", "groups": {} },
   2937      "search": { "input": "foo", "groups": {} }
   2938    }
   2939  },
   2940  {
   2941    "pattern": [{ "hash": "foo", "baseURL": "https://example.com/?q=*&v=?&hmm={}&umm=()" }],
   2942    "inputs": [{ "hash": "foo", "baseURL": "https://example.com/?q=*&v=?&hmm={}&umm=()" }],
   2943    "exactly_empty_components": [ "port" ],
   2944    "expected_obj": {
   2945      "search": "q=\\*&v=\\?&hmm=\\{\\}&umm=\\(\\)"
   2946    },
   2947    "expected_match": {
   2948      "hostname": { "input": "example.com", "groups": {} },
   2949      "pathname": { "input": "/", "groups": {} },
   2950      "protocol": { "input": "https", "groups": {} },
   2951      "search": { "input": "q=*&v=?&hmm={}&umm=()", "groups": {} },
   2952      "hash": { "input": "foo", "groups": {} }
   2953    }
   2954  },
   2955  {
   2956    "pattern": [ "#foo", "https://example.com/?q=*&v=?&hmm={}&umm=()" ],
   2957    "inputs": [ "https://example.com/?q=*&v=?&hmm={}&umm=()#foo" ],
   2958    "exactly_empty_components": [ "port" ],
   2959    "expected_obj": {
   2960      "search": "q=\\*&v=\\?&hmm=\\{\\}&umm=\\(\\)",
   2961      "hash": "foo"
   2962    },
   2963    "expected_match": {
   2964      "hostname": { "input": "example.com", "groups": {} },
   2965      "pathname": { "input": "/", "groups": {} },
   2966      "protocol": { "input": "https", "groups": {} },
   2967      "search": { "input": "q=*&v=?&hmm={}&umm=()", "groups": {} },
   2968      "hash": { "input": "foo", "groups": {} }
   2969    }
   2970  },
   2971  {
   2972    "pattern": [{ "pathname": "/([[a-z]--a])" }],
   2973    "inputs": [{ "pathname": "/a" }],
   2974    "expected_match": null
   2975  },
   2976  {
   2977    "pattern": [{ "pathname": "/([[a-z]--a])" }],
   2978    "inputs": [{ "pathname": "/z" }],
   2979    "expected_match": {
   2980      "pathname": { "input": "/z", "groups": { "0": "z" } }
   2981    }
   2982  },
   2983    {
   2984    "pattern": [{ "pathname": "/([\\d&&[0-1]])" }],
   2985    "inputs": [{ "pathname": "/0" }],
   2986    "expected_match": {
   2987      "pathname": { "input": "/0", "groups": { "0": "0" } }
   2988    }
   2989  },
   2990  {
   2991    "pattern": [{ "pathname": "/([\\d&&[0-1]])" }],
   2992    "inputs": [{ "pathname": "/3" }],
   2993    "expected_match": null
   2994  },
   2995  {
   2996    "pattern": [{ "protocol": "http", "hostname": "example.com/ignoredpath" }],
   2997    "inputs": ["http://example.com/"],
   2998    "expected_obj": {
   2999      "protocol": "http",
   3000      "hostname": "example.com",
   3001      "pathname": "*"
   3002    },
   3003    "expected_match": {
   3004      "protocol": { "input": "http", "groups": {} },
   3005      "hostname": { "input": "example.com", "groups": {} },
   3006      "pathname": { "input": "/", "groups": { "0": "/" } }
   3007    }
   3008  },
   3009  {
   3010    "pattern": [{ "protocol": "http", "hostname": "example.com\\?ignoredsearch" }],
   3011    "inputs": ["http://example.com/"],
   3012    "expected_obj": {
   3013      "protocol": "http",
   3014      "hostname": "example.com",
   3015      "search": "*"
   3016    },
   3017    "expected_match": {
   3018      "protocol": { "input": "http", "groups": {} },
   3019      "hostname": { "input": "example.com", "groups": {} },
   3020      "pathname": { "input": "/", "groups": { "0": "/" } }
   3021    }
   3022  },
   3023  {
   3024    "pattern": [{ "protocol": "http", "hostname": "example.com#ignoredhash" }],
   3025    "inputs": ["http://example.com/"],
   3026    "expected_obj": {
   3027      "protocol": "http",
   3028      "hostname": "example.com",
   3029      "hash": "*"
   3030    },
   3031    "expected_match": {
   3032      "protocol": { "input": "http", "groups": {} },
   3033      "hostname": { "input": "example.com", "groups": {} },
   3034      "pathname": { "input": "/", "groups": { "0": "/" } }
   3035    }
   3036  },
   3037  {
   3038    "pattern": ["https://www.example.com/*"],
   3039    "inputs": ["https://www.example.com/x"],
   3040    "exactly_empty_components": ["port"],
   3041    "expected_obj": {
   3042      "protocol": "https",
   3043      "hostname": "www.example.com",
   3044      "pathname": "/*"
   3045    },
   3046    "expected_match": {
   3047      "protocol": { "input": "https", "groups": {} },
   3048      "hostname": { "input": "www.example.com", "groups": {} },
   3049      "pathname": { "input": "/x", "groups": { "0": "x" } }
   3050    }
   3051  },
   3052  {
   3053    "pattern": ["https://www.example.com/*"],
   3054    "inputs": ["https://www.example.com/xyz"],
   3055    "exactly_empty_components": ["port"],
   3056    "expected_obj": {
   3057      "protocol": "https",
   3058      "hostname": "www.example.com",
   3059      "pathname": "/*"
   3060    },
   3061    "expected_match": {
   3062      "protocol": { "input": "https", "groups": {} },
   3063      "hostname": { "input": "www.example.com", "groups": {} },
   3064      "pathname": { "input": "/xyz", "groups": { "0": "xyz" } }
   3065    }
   3066  },
   3067  {
   3068    "pattern": ["https://www.example.com/*"],
   3069    "inputs": ["https://www.example.com/example"],
   3070    "exactly_empty_components": ["port"],
   3071    "expected_obj": {
   3072      "protocol": "https",
   3073      "hostname": "www.example.com",
   3074      "pathname": "/*"
   3075    },
   3076    "expected_match": {
   3077      "protocol": { "input": "https", "groups": {} },
   3078      "hostname": { "input": "www.example.com", "groups": {} },
   3079      "pathname": { "input": "/example", "groups": { "0": "example" } }
   3080    }
   3081  },
   3082  {
   3083    "pattern": ["https://www.example.com/*"],
   3084    "inputs": ["https://www.example.com/text"],
   3085    "exactly_empty_components": ["port"],
   3086    "expected_obj": {
   3087      "protocol": "https",
   3088      "hostname": "www.example.com",
   3089      "pathname": "/*"
   3090    },
   3091    "expected_match": {
   3092      "protocol": { "input": "https", "groups": {} },
   3093      "hostname": { "input": "www.example.com", "groups": {} },
   3094      "pathname": { "input": "/text", "groups": { "0": "text" } }
   3095    }
   3096  },
   3097  {
   3098    "pattern": ["https://www.example.com/*"],
   3099    "inputs": ["https://www.example.com/path/with/x"],
   3100    "exactly_empty_components": ["port"],
   3101    "expected_obj": {
   3102      "protocol": "https",
   3103      "hostname": "www.example.com",
   3104      "pathname": "/*"
   3105    },
   3106    "expected_match": {
   3107      "protocol": { "input": "https", "groups": {} },
   3108      "hostname": { "input": "www.example.com", "groups": {} },
   3109      "pathname": { "input": "/path/with/x", "groups": { "0": "path/with/x" } }
   3110    }
   3111  },
   3112  {
   3113    "pattern": [{ "hostname": ":domain(.*)" }],
   3114    "inputs": [{ "hostname": "localhost" }],
   3115    "expected_obj": {
   3116      "hostname": ":domain(.*)"
   3117    },
   3118    "expected_match": {
   3119      "hostname": { "input": "localhost", "groups": { "domain" : "localhost"} }
   3120    }
   3121  }
   3122 ]