From 0183f48a5df085c87bc33233a5da939e36fdb33c Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Tue, 18 Mar 2025 19:36:35 +1300 Subject: [PATCH] LibURL/Pattern: Complete the implementation of the constructor --- Libraries/LibURL/Pattern/Component.cpp | 19 ++ Libraries/LibURL/Pattern/Component.h | 2 + Libraries/LibURL/Pattern/Pattern.cpp | 104 ++++++--- .../wpt-import/urlpattern/urlpattern.any.txt | 218 +++++++++--------- 4 files changed, 208 insertions(+), 135 deletions(-) diff --git a/Libraries/LibURL/Pattern/Component.cpp b/Libraries/LibURL/Pattern/Component.cpp index d6d649e6c7a..1079af1a18d 100644 --- a/Libraries/LibURL/Pattern/Component.cpp +++ b/Libraries/LibURL/Pattern/Component.cpp @@ -8,9 +8,28 @@ #include #include #include +#include namespace URL::Pattern { +// https://urlpattern.spec.whatwg.org/#protocol-component-matches-a-special-scheme +bool protocol_component_matches_a_special_scheme(Component const& protocol_component) +{ + // 1. Let special scheme list be a list populated with all of the special schemes. + // 2. For each scheme of special scheme list: + for (StringView scheme : special_schemes()) { + // 1. Let test result be RegExpBuiltinExec(protocol component’s regular expression, scheme). + auto test_result = protocol_component.regular_expression->match(scheme); + + // 2. If test result is not null, then return true. + if (test_result.success) + return true; + } + + // 3. Return false. + return false; +} + // https://urlpattern.spec.whatwg.org/#generate-a-regular-expression-and-name-list struct RegularExpressionAndNameList { String regular_expression; diff --git a/Libraries/LibURL/Pattern/Component.h b/Libraries/LibURL/Pattern/Component.h index 5d7ec4dd017..9ac77ff36e8 100644 --- a/Libraries/LibURL/Pattern/Component.h +++ b/Libraries/LibURL/Pattern/Component.h @@ -34,4 +34,6 @@ struct Component { static PatternErrorOr compile(Utf8View const& input, PatternParser::EncodingCallback, Options const&); }; +bool protocol_component_matches_a_special_scheme(Component const& protocol_component); + } diff --git a/Libraries/LibURL/Pattern/Pattern.cpp b/Libraries/LibURL/Pattern/Pattern.cpp index f8b60441cd6..7b05e9f327c 100644 --- a/Libraries/LibURL/Pattern/Pattern.cpp +++ b/Libraries/LibURL/Pattern/Pattern.cpp @@ -4,21 +4,49 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include +#include namespace URL::Pattern { +// https://urlpattern.spec.whatwg.org/#hostname-pattern-is-an-ipv6-address +static bool hostname_pattern_is_an_ipv6_address(String const& input) +{ + // 1. If input’s code point length is less than 2, then return false. + if (input.bytes().size() < 2) + return false; + + // 2. Let input code points be input interpreted as a list of code points. + auto input_code_points = input.bytes(); + + // 3. If input code points[0] is U+005B ([), then return true. + if (input_code_points[0] == '[') + return true; + + // 4. If input code points[0] is U+007B ({) and input code points[1] is U+005B ([), then return true. + if (input_code_points[0] == '{' && input_code_points[1] == '[') + return true; + + // 5. If input code points[0] is U+005C (\) and input code points[1] is U+005B ([), then return true. + if (input_code_points[0] == '\\' && input_code_points[1] == '[') + return true; + + // 6. Return false. + return false; +} + // https://urlpattern.spec.whatwg.org/#url-pattern-create -PatternErrorOr Pattern::create(Input const& input, Optional const& base_url, IgnoreCase) +PatternErrorOr Pattern::create(Input const& input, Optional const& base_url, IgnoreCase ignore_case) { // 1. Let init be null. Init init; // 2. If input is a scalar value string then: - if (input.has()) { + if (auto const* input_string = input.get_pointer()) { // 1. Set init to the result of running parse a constructor string given input. - init = TRY(ConstructorStringParser::parse(input.get().code_points())); + init = TRY(ConstructorStringParser::parse(input_string->code_points())); // 2. If baseURL is null and init["protocol"] does not exist, then throw a TypeError. if (!base_url.has_value() && !init.protocol.has_value()) @@ -63,48 +91,72 @@ PatternErrorOr Pattern::create(Input const& input, Optional con if (!processed_init.hash.has_value()) processed_init.hash = "*"_string; - // FIXME: 6. If processedInit["protocol"] is a special scheme and processedInit["port"] is a string which represents its + // 6. If processedInit["protocol"] is a special scheme and processedInit["port"] is a string which represents its // corresponding default port in radix-10 using ASCII digits then set processedInit["port"] to the empty string. + if (is_special_scheme(processed_init.protocol.value())) { + auto maybe_port = processed_init.port->to_number(); + if (maybe_port.has_value() && *maybe_port == default_port_for_scheme(*processed_init.protocol).value()) + processed_init.port = String {}; + } // 7. Let urlPattern be a new URL pattern. Pattern url_pattern; - // FIXME: 8. Set urlPattern’s protocol component to the result of compiling a component given processedInit["protocol"], + // 8. Set urlPattern’s protocol component to the result of compiling a component given processedInit["protocol"], // canonicalize a protocol, and default options. + url_pattern.m_protocol_component = TRY(Component::compile(processed_init.protocol->code_points(), canonicalize_a_protocol, Options::default_())); - // FIXME: 9. Set urlPattern’s username component to the result of compiling a component given processedInit["username"], + // 9. Set urlPattern’s username component to the result of compiling a component given processedInit["username"], // canonicalize a username, and default options. + url_pattern.m_username_component = TRY(Component::compile(processed_init.username->code_points(), canonicalize_a_username, Options::default_())); - // FIXME: 10. Set urlPattern’s password component to the result of compiling a component given processedInit["password"], + // 10. Set urlPattern’s password component to the result of compiling a component given processedInit["password"], // canonicalize a password, and default options. + url_pattern.m_password_component = TRY(Component::compile(processed_init.password->code_points(), canonicalize_a_password, Options::default_())); - // FIXME: 11. If the result running hostname pattern is an IPv6 address given processedInit["hostname"] is true, then set + // 11. If the result running hostname pattern is an IPv6 address given processedInit["hostname"] is true, then set // urlPattern’s hostname component to the result of compiling a component given processedInit["hostname"], // canonicalize an IPv6 hostname, and hostname options. - - // FIXME: 12. Otherwise, set urlPattern’s hostname component to the result of compiling a component given - // processedInit["hostname"], canonicalize a hostname, and hostname options. - - // FIXME: 13. Set urlPattern’s port component to the result of compiling a component given processedInit["port"], - // canonicalize a port, and default options. - - // FIXME: 14. Let compileOptions be a copy of the default options with the ignore case property set to options["ignoreCase"]. - - // FIXME: 15. If the result of running protocol component matches a special scheme given urlPattern’s protocol component is true, then: - if (false) { - // FIXME: 1. Let pathCompileOptions be copy of the pathname options with the ignore case property set to options["ignoreCase"]. - - // FIXME: 2. Set urlPattern’s pathname component to the result of compiling a component given processedInit["pathname"], - // canonicalize a pathname, and pathCompileOptions. + if (hostname_pattern_is_an_ipv6_address(processed_init.hostname.value())) { + url_pattern.m_hostname_component = TRY(Component::compile(processed_init.hostname->code_points(), canonicalize_an_ipv6_hostname, Options::hostname())); } - // FIXME: 16. Otherwise set urlPattern’s pathname component to the result of compiling a component given + // 12. Otherwise, set urlPattern’s hostname component to the result of compiling a component given + // processedInit["hostname"], canonicalize a hostname, and hostname options. + else { + url_pattern.m_hostname_component = TRY(Component::compile(processed_init.hostname->code_points(), canonicalize_a_hostname, Options::hostname())); + } + + // 13. Set urlPattern’s port component to the result of compiling a component given processedInit["port"], + // canonicalize a port, and default options. + url_pattern.m_port_component = TRY(Component::compile(processed_init.port->code_points(), [](String const& value) { return canonicalize_a_port(value); }, Options::default_())); + + // 14. Let compileOptions be a copy of the default options with the ignore case property set to options["ignoreCase"]. + auto compile_options = Options::default_(); + compile_options.ignore_case = ignore_case == IgnoreCase::Yes; + + // 15. If the result of running protocol component matches a special scheme given urlPattern’s protocol component is true, then: + if (protocol_component_matches_a_special_scheme(url_pattern.m_protocol_component)) { + // 1. Let pathCompileOptions be copy of the pathname options with the ignore case property set to options["ignoreCase"]. + auto path_compile_options = Options::pathname(); + path_compile_options.ignore_case = ignore_case == IgnoreCase::Yes; + + // 2. Set urlPattern’s pathname component to the result of compiling a component given processedInit["pathname"], + // canonicalize a pathname, and pathCompileOptions. + url_pattern.m_pathname_component = TRY(Component::compile(processed_init.pathname->code_points(), canonicalize_a_pathname, path_compile_options)); + } + // 16. Otherwise set urlPattern’s pathname component to the result of compiling a component given // processedInit["pathname"], canonicalize an opaque pathname, and compileOptions. + else { + url_pattern.m_pathname_component = TRY(Component::compile(processed_init.pathname->code_points(), canonicalize_an_opaque_pathname, compile_options)); + } - // FIXME: 17. Set urlPattern’s search component to the result of compiling a component given processedInit["search"], + // 17. Set urlPattern’s search component to the result of compiling a component given processedInit["search"], // canonicalize a search, and compileOptions. + url_pattern.m_search_component = TRY(Component::compile(processed_init.search->code_points(), canonicalize_a_search, compile_options)); - // FIXME: 18. Set urlPattern’s hash component to the result of compiling a component given processedInit["hash"], + // 18. Set urlPattern’s hash component to the result of compiling a component given processedInit["hash"], // canonicalize a hash, and compileOptions. + url_pattern.m_hash_component = TRY(Component::compile(processed_init.hash->code_points(), canonicalize_a_hash, compile_options)); // 19. Return urlPattern. return url_pattern; diff --git a/Tests/LibWeb/Text/expected/wpt-import/urlpattern/urlpattern.any.txt b/Tests/LibWeb/Text/expected/wpt-import/urlpattern/urlpattern.any.txt index 1535fb577af..61119413549 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/urlpattern/urlpattern.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/urlpattern/urlpattern.any.txt @@ -2,70 +2,70 @@ Harness status: OK Found 350 tests -10 Pass -340 Fail +117 Pass +233 Fail Pass Loading data... Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/ba"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/ba"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: ["https://example.com/foo/bar"] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: ["https://example.com/foo/bar/baz"] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: ["https://example.com/foo/bar/baz"] Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/baz","baseURL":"https://example.com"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar/baz","baseURL":"https://example.com"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar","search":"otherquery","hash":"otherhash"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar","search":"otherquery","hash":"otherhash"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?otherquery#otherhash"}] Inputs: [{"protocol":"https","hostname":"example.com","pathname":"/foo/bar","search":"otherquery","hash":"otherhash"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar"] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar?otherquery#otherhash"] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar?query#hash"] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar/baz"] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://other.com/foo/bar"] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["http://other.com/foo/bar"] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar/baz"] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://other.com/foo/bar"] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["http://other.com/foo/bar"] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar/baz","baseURL":"https://example.com"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"https://other.com"}] -Fail Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"http://example.com"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar/baz","baseURL":"https://example.com"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"https://other.com"}] +Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: [{"pathname":"/foo/bar","baseURL":"http://example.com"}] Fail Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/([^\\/]+?)"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/index.html"}] -Fail Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/bar/"}] -Fail Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/bar/"}] +Pass Pattern: [{"pathname":"/foo/:bar"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo/(.*)"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/*"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/(.*)"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/*"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/(.*)"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo/*"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/(.*)"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo/*"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/(.*)"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/*"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/:bar(.*)"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/:bar(.*)"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/:bar(.*)"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/:bar(.*)"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/:bar(.*)"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/:bar?"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo/bar/baz"}] -Fail Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo/:bar+"}] Inputs: [{"pathname":"/foobar"}] Fail Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo/:bar*"}] Inputs: [{"pathname":"/foobar"}] Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foo/bar/baz"}] @@ -74,22 +74,22 @@ Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/fo"}] -Fail Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/(.*)?"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/*?"}] Inputs: [{"pathname":"/fo"}] Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foo/bar/baz"}] -Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/fo"}] -Fail Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/(.*)+"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/*+"}] Inputs: [{"pathname":"/fo"}] Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foo/bar/baz"}] @@ -98,35 +98,35 @@ Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/foobar"}] -Fail Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/fo"}] -Fail Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/foobar"}] +Pass Pattern: [{"pathname":"/foo/(.*)*"}] Inputs: [{"pathname":"/fo"}] +Pass Pattern: [{"pathname":"/foo/**"}] Inputs: [{"pathname":"/fo"}] Fail Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo/bar/baz"}] -Fail Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo{/bar}"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo/bar"}] -Fail Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo{/bar}?"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/bar/bar"}] -Fail Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/bar/baz"}] -Fail Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo"}] +Pass Pattern: [{"pathname":"/foo{/bar}+"}] Inputs: [{"pathname":"/foo/"}] Fail Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/bar"}] Fail Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/bar/bar"}] -Fail Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/bar/baz"}] +Pass Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/bar/baz"}] Fail Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo"}] -Fail Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/"}] -Fail Pattern: [{"protocol":"(café)"}] Inputs: undefined -Fail Pattern: [{"username":"(café)"}] Inputs: undefined -Fail Pattern: [{"password":"(café)"}] Inputs: undefined -Fail Pattern: [{"hostname":"(café)"}] Inputs: undefined -Fail Pattern: [{"pathname":"(café)"}] Inputs: undefined -Fail Pattern: [{"search":"(café)"}] Inputs: undefined -Fail Pattern: [{"hash":"(café)"}] Inputs: undefined +Pass Pattern: [{"pathname":"/foo{/bar}*"}] Inputs: [{"pathname":"/foo/"}] +Pass Pattern: [{"protocol":"(café)"}] Inputs: undefined +Pass Pattern: [{"username":"(café)"}] Inputs: undefined +Pass Pattern: [{"password":"(café)"}] Inputs: undefined +Pass Pattern: [{"hostname":"(café)"}] Inputs: undefined +Pass Pattern: [{"pathname":"(café)"}] Inputs: undefined +Pass Pattern: [{"search":"(café)"}] Inputs: undefined +Pass Pattern: [{"hash":"(café)"}] Inputs: undefined Fail Pattern: [{"protocol":":café"}] Inputs: [{"protocol":"foo"}] Fail Pattern: [{"username":":café"}] Inputs: [{"username":"foo"}] Fail Pattern: [{"password":":café"}] Inputs: [{"password":"foo"}] @@ -148,59 +148,59 @@ Fail Pattern: [{"hostname":":㐀"}] Inputs: [{"hostname":"foo"}] Fail Pattern: [{"pathname":"/:㐀"}] Inputs: [{"pathname":"/foo"}] Fail Pattern: [{"search":":㐀"}] Inputs: [{"search":"foo"}] Fail Pattern: [{"hash":":㐀"}] Inputs: [{"hash":"foo"}] -Fail Pattern: [{"protocol":"(.*)"}] Inputs: [{"protocol":"café"}] +Pass Pattern: [{"protocol":"(.*)"}] Inputs: [{"protocol":"café"}] Fail Pattern: [{"protocol":"(.*)"}] Inputs: [{"protocol":"cafe"}] Fail Pattern: [{"protocol":"foo-bar"}] Inputs: [{"protocol":"foo-bar"}] Fail Pattern: [{"username":"caf%C3%A9"}] Inputs: [{"username":"café"}] Fail Pattern: [{"username":"café"}] Inputs: [{"username":"café"}] -Fail Pattern: [{"username":"caf%c3%a9"}] Inputs: [{"username":"café"}] +Pass Pattern: [{"username":"caf%c3%a9"}] Inputs: [{"username":"café"}] Fail Pattern: [{"password":"caf%C3%A9"}] Inputs: [{"password":"café"}] Fail Pattern: [{"password":"café"}] Inputs: [{"password":"café"}] -Fail Pattern: [{"password":"caf%c3%a9"}] Inputs: [{"password":"café"}] +Pass Pattern: [{"password":"caf%c3%a9"}] Inputs: [{"password":"café"}] Fail Pattern: [{"hostname":"xn--caf-dma.com"}] Inputs: [{"hostname":"café.com"}] Fail Pattern: [{"hostname":"café.com"}] Inputs: [{"hostname":"café.com"}] Fail Pattern: ["http://U+deb2.com/"] Inputs: ["http://U+deb2.com/"] -Fail Pattern: ["http://\ud83d \udeb2"] Inputs: undefined -Fail Pattern: [{"hostname":"\ud83d \udeb2"}] Inputs: undefined +Pass Pattern: ["http://\ud83d \udeb2"] Inputs: undefined +Pass Pattern: [{"hostname":"\ud83d \udeb2"}] Inputs: undefined Fail Pattern: [{"pathname":"\ud83d \udeb2"}] Inputs: [] -Fail Pattern: [{"pathname":":\ud83d \udeb2"}] Inputs: undefined -Fail Pattern: [{"pathname":":aU+dd00b"}] Inputs: [] +Pass Pattern: [{"pathname":":\ud83d \udeb2"}] Inputs: undefined +Pass Pattern: [{"pathname":":aU+dd00b"}] Inputs: [] Fail Pattern: [{"pathname":"test/:aU+dc50b"}] Inputs: [{"pathname":"test/foo"}] -Fail Pattern: [{"pathname":":U+deb2"}] Inputs: undefined +Pass Pattern: [{"pathname":":U+deb2"}] Inputs: undefined Fail Pattern: [{"port":""}] Inputs: [{"protocol":"http","port":"80"}] Fail Pattern: [{"protocol":"http","port":"80"}] Inputs: [{"protocol":"http","port":"80"}] -Fail Pattern: [{"protocol":"http","port":"80{20}?"}] Inputs: [{"protocol":"http","port":"80"}] +Pass Pattern: [{"protocol":"http","port":"80{20}?"}] Inputs: [{"protocol":"http","port":"80"}] Fail Pattern: [{"protocol":"http","port":"80 "}] Inputs: [{"protocol":"http","port":"80"}] -Fail Pattern: [{"protocol":"http","port":"100000"}] Inputs: [{"protocol":"http","port":"100000"}] -Fail Pattern: [{"port":"80"}] Inputs: [{"protocol":"http","port":"80"}] -Fail Pattern: [{"protocol":"http{s}?","port":"80"}] Inputs: [{"protocol":"http","port":"80"}] +Pass Pattern: [{"protocol":"http","port":"100000"}] Inputs: [{"protocol":"http","port":"100000"}] +Pass Pattern: [{"port":"80"}] Inputs: [{"protocol":"http","port":"80"}] +Pass Pattern: [{"protocol":"http{s}?","port":"80"}] Inputs: [{"protocol":"http","port":"80"}] Fail Pattern: [{"port":"80"}] Inputs: [{"port":"80"}] -Fail Pattern: [{"port":"(.*)"}] Inputs: [{"port":"invalid80"}] +Pass Pattern: [{"port":"(.*)"}] Inputs: [{"port":"invalid80"}] Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/./bar"}] Fail Pattern: [{"pathname":"/foo/baz"}] Inputs: [{"pathname":"/foo/bar/../baz"}] Fail Pattern: [{"pathname":"/caf%C3%A9"}] Inputs: [{"pathname":"/café"}] Fail Pattern: [{"pathname":"/café"}] Inputs: [{"pathname":"/café"}] -Fail Pattern: [{"pathname":"/caf%c3%a9"}] Inputs: [{"pathname":"/café"}] -Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"foo/bar"}] +Pass Pattern: [{"pathname":"/caf%c3%a9"}] Inputs: [{"pathname":"/café"}] +Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"foo/bar"}] Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"foo/bar","baseURL":"https://example.com"}] Fail Pattern: [{"pathname":"/foo/../bar"}] Inputs: [{"pathname":"/bar"}] Fail Pattern: [{"pathname":"./foo/bar","baseURL":"https://example.com"}] Inputs: [{"pathname":"foo/bar","baseURL":"https://example.com"}] Fail Pattern: [{"pathname":"","baseURL":"https://example.com"}] Inputs: [{"pathname":"/","baseURL":"https://example.com"}] -Fail Pattern: [{"pathname":"{/bar}","baseURL":"https://example.com/foo/"}] Inputs: [{"pathname":"./bar","baseURL":"https://example.com/foo/"}] -Fail Pattern: [{"pathname":"\\/bar","baseURL":"https://example.com/foo/"}] Inputs: [{"pathname":"./bar","baseURL":"https://example.com/foo/"}] +Pass Pattern: [{"pathname":"{/bar}","baseURL":"https://example.com/foo/"}] Inputs: [{"pathname":"./bar","baseURL":"https://example.com/foo/"}] +Pass Pattern: [{"pathname":"\\/bar","baseURL":"https://example.com/foo/"}] Inputs: [{"pathname":"./bar","baseURL":"https://example.com/foo/"}] Fail Pattern: [{"pathname":"b","baseURL":"https://example.com/foo/"}] Inputs: [{"pathname":"./b","baseURL":"https://example.com/foo/"}] Fail Pattern: [{"pathname":"foo/bar"}] Inputs: ["https://example.com/foo/bar"] Fail Pattern: [{"pathname":"foo/bar","baseURL":"https://example.com"}] Inputs: ["https://example.com/foo/bar"] Fail Pattern: [{"pathname":":name.html","baseURL":"https://example.com"}] Inputs: ["https://example.com/foo.html"] Fail Pattern: [{"search":"q=caf%C3%A9"}] Inputs: [{"search":"q=café"}] Fail Pattern: [{"search":"q=café"}] Inputs: [{"search":"q=café"}] -Fail Pattern: [{"search":"q=caf%c3%a9"}] Inputs: [{"search":"q=café"}] +Pass Pattern: [{"search":"q=caf%c3%a9"}] Inputs: [{"search":"q=café"}] Fail Pattern: [{"hash":"caf%C3%A9"}] Inputs: [{"hash":"café"}] Fail Pattern: [{"hash":"café"}] Inputs: [{"hash":"café"}] -Fail Pattern: [{"hash":"caf%c3%a9"}] Inputs: [{"hash":"café"}] +Pass Pattern: [{"hash":"caf%c3%a9"}] Inputs: [{"hash":"café"}] Fail Pattern: [{"protocol":"about","pathname":"(blank|sourcedoc)"}] Inputs: ["about:blank"] Fail Pattern: [{"protocol":"data","pathname":":number([0-9]+)"}] Inputs: ["data:8675309"] -Fail Pattern: [{"pathname":"/(\\m)"}] Inputs: undefined +Pass Pattern: [{"pathname":"/(\\m)"}] Inputs: undefined Fail Pattern: [{"pathname":"/foo!"}] Inputs: [{"pathname":"/foo!"}] Fail Pattern: [{"pathname":"/foo\\:"}] Inputs: [{"pathname":"/foo:"}] Fail Pattern: [{"pathname":"/foo\\{"}] Inputs: [{"pathname":"/foo{"}] @@ -232,36 +232,36 @@ Fail Pattern: ["https://example.com/(bar)?foo"] Inputs: ["https://example.com/ba Fail Pattern: ["https://example.com/(bar)\\?foo"] Inputs: ["https://example.com/bar?foo"] Fail Pattern: ["https://example.com/{bar}?foo"] Inputs: ["https://example.com/bar?foo"] Fail Pattern: ["https://example.com/{bar}\\?foo"] Inputs: ["https://example.com/bar?foo"] -Fail Pattern: ["https://example.com/"] Inputs: ["https://example.com:8080/"] +Pass Pattern: ["https://example.com/"] Inputs: ["https://example.com:8080/"] Pass Pattern: ["data:foobar"] Inputs: ["data:foobar"] Fail Pattern: ["data\\:foobar"] Inputs: ["data:foobar"] Fail Pattern: ["https://{sub.}?example.com/foo"] Inputs: ["https://example.com/foo"] Fail Pattern: ["https://{sub.}?example{.com/}foo"] Inputs: ["https://example.com/foo"] Pass Pattern: ["{https://}example.com/foo"] Inputs: ["https://example.com/foo"] Fail Pattern: ["https://(sub.)?example.com/foo"] Inputs: ["https://example.com/foo"] -Fail Pattern: ["https://(sub.)?example(.com/)foo"] Inputs: ["https://example.com/foo"] +Pass Pattern: ["https://(sub.)?example(.com/)foo"] Inputs: ["https://example.com/foo"] Pass Pattern: ["(https://)example.com/foo"] Inputs: ["https://example.com/foo"] -Fail Pattern: ["https://{sub{.}}example.com/foo"] Inputs: ["https://example.com/foo"] +Pass Pattern: ["https://{sub{.}}example.com/foo"] Inputs: ["https://example.com/foo"] Fail Pattern: ["https://(sub(?:.))?example.com/foo"] Inputs: ["https://example.com/foo"] Fail Pattern: ["file:///foo/bar"] Inputs: ["file:///foo/bar"] Fail Pattern: ["data:"] Inputs: ["data:"] -Fail Pattern: ["foo://bar"] Inputs: ["foo://bad_url_browser_interop"] -Fail Pattern: ["(café)://foo"] Inputs: undefined -Fail Pattern: ["https://example.com/foo?bar#baz"] Inputs: [{"protocol":"https:","search":"?bar","hash":"#baz","baseURL":"http://example.com/foo"}] +Pass Pattern: ["foo://bar"] Inputs: ["foo://bad_url_browser_interop"] +Pass Pattern: ["(café)://foo"] Inputs: undefined +Pass Pattern: ["https://example.com/foo?bar#baz"] Inputs: [{"protocol":"https:","search":"?bar","hash":"#baz","baseURL":"http://example.com/foo"}] Fail Pattern: [{"protocol":"http{s}?:","search":"?bar","hash":"#baz"}] Inputs: ["http://example.com/foo?bar#baz"] Fail Pattern: ["?bar#baz","https://example.com/foo"] Inputs: ["?bar#baz","https://example.com/foo"] Fail Pattern: ["?bar","https://example.com/foo#baz"] Inputs: ["?bar","https://example.com/foo#snafu"] Fail Pattern: ["#baz","https://example.com/foo?bar"] Inputs: ["#baz","https://example.com/foo?bar"] Fail Pattern: ["#baz","https://example.com/foo"] Inputs: ["#baz","https://example.com/foo"] -Fail Pattern: [{"pathname":"*"}] Inputs: ["foo","data:data-urls-cannot-be-base-urls"] -Fail Pattern: [{"pathname":"*"}] Inputs: ["foo","not|a|valid|url"] +Pass Pattern: [{"pathname":"*"}] Inputs: ["foo","data:data-urls-cannot-be-base-urls"] +Pass Pattern: [{"pathname":"*"}] Inputs: ["foo","not|a|valid|url"] Fail Pattern: ["https://foo\\:bar@example.com"] Inputs: ["https://foo:bar@example.com"] Fail Pattern: ["https://foo@example.com"] Inputs: ["https://foo@example.com"] Fail Pattern: ["https://\\:bar@example.com"] Inputs: ["https://:bar@example.com"] Fail Pattern: ["https://:user::pass@example.com"] Inputs: ["https://foo:bar@example.com"] Fail Pattern: ["https\\:foo\\:bar@example.com"] Inputs: ["https:foo:bar@example.com"] Fail Pattern: ["data\\:foo\\:bar@example.com"] Inputs: ["data:foo:bar@example.com"] -Fail Pattern: ["https://foo{\\:}bar@example.com"] Inputs: ["https://foo:bar@example.com"] +Pass Pattern: ["https://foo{\\:}bar@example.com"] Inputs: ["https://foo:bar@example.com"] Fail Pattern: ["data{\\:}channel.html","https://example.com"] Inputs: ["https://example.com/data:channel.html"] Fail Pattern: ["http://[\\:\\:1]/"] Inputs: ["http://[::1]/"] Fail Pattern: ["http://[\\:\\:1]:8080/"] Inputs: ["http://[::1]:8080/"] @@ -269,17 +269,17 @@ Fail Pattern: ["http://[\\:\\:a]/"] Inputs: ["http://[::a]/"] Fail Pattern: ["http://[:address]/"] Inputs: ["http://[::1]/"] Fail Pattern: ["http://[\\:\\:AB\\::num]/"] Inputs: ["http://[::ab:1]/"] Fail Pattern: [{"hostname":"[\\:\\:AB\\::num]"}] Inputs: [{"hostname":"[::ab:1]"}] -Fail Pattern: [{"hostname":"[\\:\\:xY\\::num]"}] Inputs: undefined +Pass Pattern: [{"hostname":"[\\:\\:xY\\::num]"}] Inputs: undefined Fail Pattern: [{"hostname":"{[\\:\\:ab\\::num]}"}] Inputs: [{"hostname":"[::ab:1]"}] -Fail Pattern: [{"hostname":"{[\\:\\:fé\\::num]}"}] Inputs: undefined +Pass Pattern: [{"hostname":"{[\\:\\:fé\\::num]}"}] Inputs: undefined Fail Pattern: [{"hostname":"{[\\:\\::num\\:1]}"}] Inputs: [{"hostname":"[::ab:1]"}] -Fail Pattern: [{"hostname":"{[\\:\\::num\\:fé]}"}] Inputs: undefined +Pass Pattern: [{"hostname":"{[\\:\\::num\\:fé]}"}] Inputs: undefined Fail Pattern: [{"hostname":"[*\\:1]"}] Inputs: [{"hostname":"[::ab:1]"}] -Fail Pattern: [{"hostname":"*\\:1]"}] Inputs: undefined -Fail Pattern: ["https://foo{{@}}example.com"] Inputs: ["https://foo@example.com"] -Fail Pattern: ["https://foo{@example.com"] Inputs: ["https://foo@example.com"] +Pass Pattern: [{"hostname":"*\\:1]"}] Inputs: undefined +Pass Pattern: ["https://foo{{@}}example.com"] Inputs: ["https://foo@example.com"] +Pass Pattern: ["https://foo{@example.com"] Inputs: ["https://foo@example.com"] Fail Pattern: ["data\\:text/javascript,let x = 100/:tens?5;"] Inputs: ["data:text/javascript,let x = 100/5;"] -Fail Pattern: [{"pathname":"/:id/:id"}] Inputs: undefined +Pass Pattern: [{"pathname":"/:id/:id"}] Inputs: undefined Pass Pattern: [{"pathname":"/foo","baseURL":""}] Inputs: undefined Pass Pattern: ["/foo",""] Inputs: undefined Pass Pattern: [{"pathname":"/foo"},"https://example.com"] Inputs: undefined @@ -289,20 +289,20 @@ Fail Pattern: [{"pathname":":name"}] Inputs: [{"pathname":"foobar"}] Fail Pattern: [{"protocol":":name*"}] Inputs: [{"protocol":"foobar"}] Fail Pattern: [{"protocol":":name+"}] Inputs: [{"protocol":"foobar"}] Fail Pattern: [{"protocol":":name"}] Inputs: [{"protocol":"foobar"}] -Fail Pattern: [{"hostname":"bad hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad hostname"}] Inputs: undefined Fail Pattern: [{"hostname":"bad#hostname"}] Inputs: [{"hostname":"bad"}] Fail Pattern: [{"hostname":"bad%hostname"}] Inputs: undefined Fail Pattern: [{"hostname":"bad/hostname"}] Inputs: [{"hostname":"bad"}] Fail Pattern: [{"hostname":"bad\\:hostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"badhostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"bad?hostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"bad@hostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"bad[hostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"bad]hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"badhostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad?hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad@hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad[hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad]hostname"}] Inputs: undefined Fail Pattern: [{"hostname":"bad\\\\hostname"}] Inputs: [{"hostname":"badhostname"}] -Fail Pattern: [{"hostname":"bad^hostname"}] Inputs: undefined -Fail Pattern: [{"hostname":"bad|hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad^hostname"}] Inputs: undefined +Pass Pattern: [{"hostname":"bad|hostname"}] Inputs: undefined Fail Pattern: [{"hostname":"bad\nhostname"}] Inputs: [{"hostname":"badhostname"}] Fail Pattern: [{"hostname":"bad\rhostname"}] Inputs: [{"hostname":"badhostname"}] Fail Pattern: [{"hostname":"bad\thostname"}] Inputs: [{"hostname":"badhostname"}] @@ -334,7 +334,7 @@ Fail Pattern: [{"pathname":":foo(baz)bar"}] Inputs: [{"pathname":"bazbar"}] Fail Pattern: [{"pathname":"*/*"}] Inputs: [{"pathname":"foo/bar"}] Fail Pattern: [{"pathname":"*\\/*"}] Inputs: [{"pathname":"foo/bar"}] Fail Pattern: [{"pathname":"*/{*}"}] Inputs: [{"pathname":"foo/bar"}] -Fail Pattern: [{"pathname":"*//*"}] Inputs: [{"pathname":"foo/bar"}] +Pass Pattern: [{"pathname":"*//*"}] Inputs: [{"pathname":"foo/bar"}] Fail Pattern: [{"pathname":"/:foo."}] Inputs: [{"pathname":"/bar."}] Fail Pattern: [{"pathname":"/:foo.."}] Inputs: [{"pathname":"/bar.."}] Fail Pattern: [{"pathname":"./foo"}] Inputs: [{"pathname":"./foo"}] @@ -350,7 +350,7 @@ Pass Pattern: ["/foo?bar#baz",{"ignoreCase":true},"https://example.com:8080"] In Fail Pattern: [{"search":"foo","baseURL":"https://example.com/a/+/b"}] Inputs: [{"search":"foo","baseURL":"https://example.com/a/+/b"}] Fail Pattern: [{"hash":"foo","baseURL":"https://example.com/?q=*&v=?&hmm={}&umm=()"}] Inputs: [{"hash":"foo","baseURL":"https://example.com/?q=*&v=?&hmm={}&umm=()"}] Fail Pattern: ["#foo","https://example.com/?q=*&v=?&hmm={}&umm=()"] Inputs: ["https://example.com/?q=*&v=?&hmm={}&umm=()#foo"] -Fail Pattern: [{"pathname":"/([[a-z]--a])"}] Inputs: [{"pathname":"/a"}] +Pass Pattern: [{"pathname":"/([[a-z]--a])"}] Inputs: [{"pathname":"/a"}] Fail Pattern: [{"pathname":"/([[a-z]--a])"}] Inputs: [{"pathname":"/z"}] Fail Pattern: [{"pathname":"/([\\d&&[0-1]])"}] Inputs: [{"pathname":"/0"}] -Fail Pattern: [{"pathname":"/([\\d&&[0-1]])"}] Inputs: [{"pathname":"/3"}] \ No newline at end of file +Pass Pattern: [{"pathname":"/([\\d&&[0-1]])"}] Inputs: [{"pathname":"/3"}] \ No newline at end of file