mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 19:45:12 +00:00
LibURL/Pattern: Implement matching a URLPattern
This commit is contained in:
parent
2a44420e52
commit
6b1fa3ecd0
Notes:
github-actions[bot]
2025-04-06 12:27:06 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/6b1fa3ecd0d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3847 Reviewed-by: https://github.com/trflynn89
3 changed files with 270 additions and 46 deletions
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibURL/Parser.h>
|
||||
#include <LibURL/Pattern/Canonicalization.h>
|
||||
#include <LibURL/Pattern/ConstructorStringParser.h>
|
||||
#include <LibURL/Pattern/Pattern.h>
|
||||
|
@ -163,10 +164,232 @@ PatternErrorOr<Pattern> Pattern::create(Input const& input, Optional<String> con
|
|||
}
|
||||
|
||||
// https://urlpattern.spec.whatwg.org/#url-pattern-match
|
||||
PatternErrorOr<Optional<Result>> Pattern::match(Input const&, Optional<String> const&) const
|
||||
PatternErrorOr<Optional<Result>> Pattern::match(Variant<String, Init, URL> const& input, Optional<String> const& base_url_string) const
|
||||
{
|
||||
dbgln("FIXME: Implement URL::Pattern::match");
|
||||
return OptionalNone {};
|
||||
// 1. Let protocol be the empty string.
|
||||
String protocol;
|
||||
|
||||
// 2. Let username be the empty string.
|
||||
String username;
|
||||
|
||||
// 3. Let password be the empty string.
|
||||
String password;
|
||||
|
||||
// 4. Let hostname be the empty string.
|
||||
String hostname;
|
||||
|
||||
// 5. Let port be the empty string.
|
||||
String port;
|
||||
|
||||
// 6. Let pathname be the empty string.
|
||||
String pathname;
|
||||
|
||||
// 7. Let search be the empty string.
|
||||
String search;
|
||||
|
||||
// 8. Let hash be the empty string.
|
||||
String hash;
|
||||
|
||||
// 9. Let inputs be an empty list.
|
||||
Vector<Input> inputs;
|
||||
|
||||
// 10. If input is a URL, then append the serialization of input to inputs.
|
||||
if (auto const* input_url = input.get_pointer<URL>()) {
|
||||
inputs.append(input_url->serialize());
|
||||
}
|
||||
// 11. Otherwise, append input to inputs.
|
||||
else {
|
||||
inputs.append(input.downcast<Input>());
|
||||
}
|
||||
|
||||
// 12. If input is a URLPatternInit then:
|
||||
if (auto const* input_init = input.get_pointer<Init>()) {
|
||||
// 1. If baseURLString was given, throw a TypeError.
|
||||
if (base_url_string.has_value())
|
||||
return ErrorInfo { "Base URL cannot be provided when URLPatternInput is provided"_string };
|
||||
|
||||
// 2. Let applyResult be the result of process a URLPatternInit given input, "url", protocol, username, password,
|
||||
// hostname, port, pathname, search, and hash. If this throws an exception, catch it, and return null.
|
||||
auto apply_result_or_error = process_a_url_pattern_init(*input_init, PatternProcessType::URL,
|
||||
protocol, username, password, hostname, port, pathname, search, hash);
|
||||
if (apply_result_or_error.is_error())
|
||||
return OptionalNone {};
|
||||
auto apply_result = apply_result_or_error.release_value();
|
||||
|
||||
// 3. Set protocol to applyResult["protocol"].
|
||||
protocol = apply_result.protocol.value();
|
||||
|
||||
// 4. Set username to applyResult["username"].
|
||||
username = apply_result.username.value();
|
||||
|
||||
// 5. Set password to applyResult["password"].
|
||||
password = apply_result.password.value();
|
||||
|
||||
// 6. Set hostname to applyResult["hostname"].
|
||||
hostname = apply_result.hostname.value();
|
||||
|
||||
// 7. Set port to applyResult["port"].
|
||||
port = apply_result.port.value();
|
||||
|
||||
// 8. Set pathname to applyResult["pathname"].
|
||||
pathname = apply_result.pathname.value();
|
||||
|
||||
// 9. Set search to applyResult["search"].
|
||||
search = apply_result.search.value();
|
||||
|
||||
// 10. Set hash to applyResult["hash"].
|
||||
hash = apply_result.hash.value();
|
||||
}
|
||||
// 13. Otherwise:
|
||||
else {
|
||||
// 1. Let url be input.
|
||||
auto url_or_string = input.downcast<URL, String>();
|
||||
|
||||
// 2. If input is a USVString:
|
||||
if (auto const* input_string = input.get_pointer<String>()) {
|
||||
// 1. Let baseURL be null.
|
||||
Optional<URL> base_url;
|
||||
|
||||
// 2. If baseURLString was given, then:
|
||||
if (base_url_string.has_value()) {
|
||||
// 1. Set baseURL to the result of running the basic URL parser on baseURLString.
|
||||
base_url = Parser::basic_parse(base_url_string.value());
|
||||
|
||||
// 2. If baseURL is failure, return null.
|
||||
if (!base_url.has_value())
|
||||
return OptionalNone {};
|
||||
|
||||
// 3. Append baseURLString to inputs.
|
||||
inputs.append(base_url_string.value());
|
||||
}
|
||||
|
||||
// 3. Set url to the result of running the basic URL parser on input with baseURL.
|
||||
// 4. If url is failure, return null.
|
||||
auto maybe_url = Parser::basic_parse(*input_string, base_url);
|
||||
if (!maybe_url.has_value())
|
||||
return OptionalNone {};
|
||||
url_or_string = maybe_url.release_value();
|
||||
}
|
||||
|
||||
// 3. Assert: url is a URL.
|
||||
VERIFY(url_or_string.has<URL>());
|
||||
auto& url = url_or_string.get<URL>();
|
||||
|
||||
// 4. Set protocol to url’s scheme.
|
||||
protocol = url.scheme();
|
||||
|
||||
// 5. Set username to url’s username.
|
||||
username = url.username();
|
||||
|
||||
// 6. Set password to url’s password.
|
||||
password = url.password();
|
||||
|
||||
// 7. Set hostname to url’s host, serialized, or the empty string if the value is null.
|
||||
if (url.host().has_value())
|
||||
hostname = url.host()->serialize();
|
||||
else
|
||||
hostname = String {};
|
||||
|
||||
// 8. Set port to url’s port, serialized, or the empty string if the value is null.
|
||||
if (url.port().has_value())
|
||||
port = String::number(url.port().value());
|
||||
else
|
||||
port = String {};
|
||||
|
||||
// 9. Set pathname to the result of URL path serializing url.
|
||||
pathname = url.serialize_path();
|
||||
|
||||
// 10. Set search to url’s query or the empty string if the value is null.
|
||||
search = url.query().value_or(String {});
|
||||
|
||||
// 11. Set hash to url’s fragment or the empty string if the value is null.
|
||||
hash = url.fragment().value_or(String {});
|
||||
}
|
||||
|
||||
// 14. Let protocolExecResult be RegExpBuiltinExec(urlPattern’s protocol component's regular expression, protocol).
|
||||
auto protocol_exec_result = m_protocol_component.regular_expression->match(protocol);
|
||||
if (!protocol_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 15. Let usernameExecResult be RegExpBuiltinExec(urlPattern’s username component's regular expression, username).
|
||||
auto username_exec_result = m_username_component.regular_expression->match(username);
|
||||
if (!username_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 16. Let passwordExecResult be RegExpBuiltinExec(urlPattern’s password component's regular expression, password).
|
||||
auto password_exec_result = m_password_component.regular_expression->match(password);
|
||||
if (!password_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 17. Let hostnameExecResult be RegExpBuiltinExec(urlPattern’s hostname component's regular expression, hostname).
|
||||
auto hostname_exec_result = m_hostname_component.regular_expression->match(hostname);
|
||||
if (!hostname_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 18. Let portExecResult be RegExpBuiltinExec(urlPattern’s port component's regular expression, port).
|
||||
auto port_exec_result = m_port_component.regular_expression->match(port);
|
||||
if (!port_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 19. Let pathnameExecResult be RegExpBuiltinExec(urlPattern’s pathname component's regular expression, pathname).
|
||||
auto pathname_exec_result = m_pathname_component.regular_expression->match(pathname);
|
||||
if (!pathname_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 20. Let searchExecResult be RegExpBuiltinExec(urlPattern’s search component's regular expression, search).
|
||||
auto search_exec_result = m_search_component.regular_expression->match(search);
|
||||
if (!search_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 21. Let hashExecResult be RegExpBuiltinExec(urlPattern’s hash component's regular expression, hash).
|
||||
auto hash_exec_result = m_hash_component.regular_expression->match(hash);
|
||||
if (!hash_exec_result.success)
|
||||
return OptionalNone {};
|
||||
|
||||
// 22. If protocolExecResult, usernameExecResult, passwordExecResult, hostnameExecResult, portExecResult,
|
||||
// pathnameExecResult, searchExecResult, or hashExecResult are null then return null.
|
||||
// NOTE: Done in steps above at point of exec.
|
||||
|
||||
// 23. Let result be a new URLPatternResult.
|
||||
Result result;
|
||||
|
||||
// 24. Set result["inputs"] to inputs.
|
||||
result.inputs = move(inputs);
|
||||
|
||||
// 25. Set result["protocol"] to the result of creating a component match result given urlPattern’s protocol
|
||||
// component, protocol, and protocolExecResult.
|
||||
result.protocol = m_protocol_component.create_match_result(protocol, protocol_exec_result);
|
||||
|
||||
// 26. Set result["username"] to the result of creating a component match result given urlPattern’s username
|
||||
// component, username, and usernameExecResult.
|
||||
result.username = m_username_component.create_match_result(username, username_exec_result);
|
||||
|
||||
// 27. Set result["password"] to the result of creating a component match result given urlPattern’s password
|
||||
// component, password, and passwordExecResult.
|
||||
result.password = m_password_component.create_match_result(password, password_exec_result);
|
||||
|
||||
// 28. Set result["hostname"] to the result of creating a component match result given urlPattern’s hostname
|
||||
// component, hostname, and hostnameExecResult.
|
||||
result.hostname = m_hostname_component.create_match_result(hostname, hostname_exec_result);
|
||||
|
||||
// 29. Set result["port"] to the result of creating a component match result given urlPattern’s port component,
|
||||
// port, and portExecResult.
|
||||
result.port = m_port_component.create_match_result(port, port_exec_result);
|
||||
|
||||
// 30. Set result["pathname"] to the result of creating a component match result given urlPattern’s pathname
|
||||
// component, pathname, and pathnameExecResult.
|
||||
result.pathname = m_pathname_component.create_match_result(pathname, pathname_exec_result);
|
||||
|
||||
// 31. Set result["search"] to the result of creating a component match result given urlPattern’s search component,
|
||||
// search, and searchExecResult.
|
||||
result.search = m_search_component.create_match_result(search, search_exec_result);
|
||||
|
||||
// 32. Set result["hash"] to the result of creating a component match result given urlPattern’s hash component,
|
||||
// hash, and hashExecResult.
|
||||
result.hash = m_hash_component.create_match_result(hash, hash_exec_result);
|
||||
|
||||
// 33. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
// https://urlpattern.spec.whatwg.org/#url-pattern-has-regexp-groups
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <LibURL/Pattern/Component.h>
|
||||
#include <LibURL/Pattern/Init.h>
|
||||
#include <LibURL/Pattern/PatternError.h>
|
||||
#include <LibURL/URL.h>
|
||||
|
||||
namespace URL::Pattern {
|
||||
|
||||
|
@ -44,7 +45,7 @@ class Pattern {
|
|||
public:
|
||||
static PatternErrorOr<Pattern> create(Input const&, Optional<String> const& base_url = {}, IgnoreCase = IgnoreCase::No);
|
||||
|
||||
PatternErrorOr<Optional<Result>> match(Input const&, Optional<String> const& base_url_string) const;
|
||||
PatternErrorOr<Optional<Result>> match(Variant<String, Init, URL> const&, Optional<String> const& base_url_string) const;
|
||||
|
||||
bool has_regexp_groups() const;
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@ Harness status: OK
|
|||
|
||||
Found 350 tests
|
||||
|
||||
117 Pass
|
||||
233 Fail
|
||||
155 Pass
|
||||
195 Fail
|
||||
Pass Loading data...
|
||||
Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar"}]
|
||||
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"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: ["https://example.com/foo/bar"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: ["https://example.com/foo/bar/baz"]
|
||||
Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar"}]
|
||||
Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"hostname":"example.com","pathname":"/foo/bar/baz"}]
|
||||
|
@ -23,9 +23,9 @@ Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com"}] Inputs:
|
|||
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"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar?otherquery#otherhash"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar","baseURL":"https://example.com?query#hash"}] Inputs: ["https://example.com/foo/bar?query#hash"]
|
||||
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"]
|
||||
|
@ -175,7 +175,7 @@ Pass Pattern: [{"protocol":"http","port":"100000"}] Inputs: [{"protocol":"http",
|
|||
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"}]
|
||||
Pass Pattern: [{"port":"(.*)"}] Inputs: [{"port":"invalid80"}]
|
||||
Fail 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é"}]
|
||||
|
@ -190,7 +190,7 @@ Pass Pattern: [{"pathname":"{/bar}","baseURL":"https://example.com/foo/"}] Input
|
|||
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"]
|
||||
Pass 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é"}]
|
||||
|
@ -198,8 +198,8 @@ 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é"}]
|
||||
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"]
|
||||
Pass Pattern: [{"protocol":"about","pathname":"(blank|sourcedoc)"}] Inputs: ["about:blank"]
|
||||
Pass Pattern: [{"protocol":"data","pathname":":number([0-9]+)"}] Inputs: ["data:8675309"]
|
||||
Pass Pattern: [{"pathname":"/(\\m)"}] Inputs: undefined
|
||||
Fail Pattern: [{"pathname":"/foo!"}] Inputs: [{"pathname":"/foo!"}]
|
||||
Fail Pattern: [{"pathname":"/foo\\:"}] Inputs: [{"pathname":"/foo:"}]
|
||||
|
@ -211,63 +211,63 @@ Fail Pattern: [{"protocol":"javascript","pathname":"var x = 1;"}] Inputs: [{"bas
|
|||
Fail Pattern: [{"protocol":"(data|javascript)","pathname":"var x = 1;"}] Inputs: [{"protocol":"javascript","pathname":"var x = 1;"}]
|
||||
Fail Pattern: [{"protocol":"(https|javascript)","pathname":"var x = 1;"}] Inputs: [{"protocol":"javascript","pathname":"var x = 1;"}]
|
||||
Fail Pattern: [{"pathname":"var x = 1;"}] Inputs: [{"pathname":"var x = 1;"}]
|
||||
Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: ["./foo/bar","https://example.com"]
|
||||
Fail Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar"},"https://example.com"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: ["./foo/bar","https://example.com"]
|
||||
Pass Pattern: [{"pathname":"/foo/bar"}] Inputs: [{"pathname":"/foo/bar"},"https://example.com"]
|
||||
Fail Pattern: ["https://example.com:8080/foo?bar#baz"] Inputs: [{"pathname":"/foo","search":"bar","hash":"baz","baseURL":"https://example.com:8080"}]
|
||||
Fail Pattern: ["/foo?bar#baz","https://example.com:8080"] Inputs: [{"pathname":"/foo","search":"bar","hash":"baz","baseURL":"https://example.com:8080"}]
|
||||
Pass Pattern: ["/foo"] Inputs: undefined
|
||||
Pass Pattern: ["example.com/foo"] Inputs: undefined
|
||||
Fail Pattern: ["http{s}?://{*.}?example.com/:product/:endpoint"] Inputs: ["https://sub.example.com/foo/bar"]
|
||||
Pass Pattern: ["http{s}?://{*.}?example.com/:product/:endpoint"] Inputs: ["https://sub.example.com/foo/bar"]
|
||||
Fail Pattern: ["https://example.com?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Fail Pattern: ["https://example.com#foo"] Inputs: ["https://example.com/#foo"]
|
||||
Fail Pattern: ["https://example.com:8080?foo"] Inputs: ["https://example.com:8080/?foo"]
|
||||
Fail Pattern: ["https://example.com:8080#foo"] Inputs: ["https://example.com:8080/#foo"]
|
||||
Fail Pattern: ["https://example.com/?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Fail Pattern: ["https://example.com/#foo"] Inputs: ["https://example.com/#foo"]
|
||||
Pass Pattern: ["https://example.com/?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Pass Pattern: ["https://example.com/#foo"] Inputs: ["https://example.com/#foo"]
|
||||
Fail Pattern: ["https://example.com/*?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Fail Pattern: ["https://example.com/*\\?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Pass Pattern: ["https://example.com/*\\?foo"] Inputs: ["https://example.com/?foo"]
|
||||
Fail Pattern: ["https://example.com/:name?foo"] Inputs: ["https://example.com/bar?foo"]
|
||||
Fail Pattern: ["https://example.com/:name\\?foo"] Inputs: ["https://example.com/bar?foo"]
|
||||
Pass Pattern: ["https://example.com/:name\\?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"]
|
||||
Pass 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"]
|
||||
Pass Pattern: ["https://example.com/{bar}\\?foo"] Inputs: ["https://example.com/bar?foo"]
|
||||
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"]
|
||||
Pass 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"]
|
||||
Pass 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"]
|
||||
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:"]
|
||||
Pass Pattern: ["https://(sub(?:.))?example.com/foo"] Inputs: ["https://example.com/foo"]
|
||||
Pass Pattern: ["file:///foo/bar"] Inputs: ["file:///foo/bar"]
|
||||
Pass Pattern: ["data:"] Inputs: ["data:"]
|
||||
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"]
|
||||
Pass Pattern: [{"protocol":"http{s}?:","search":"?bar","hash":"#baz"}] Inputs: ["http://example.com/foo?bar#baz"]
|
||||
Pass Pattern: ["?bar#baz","https://example.com/foo"] Inputs: ["?bar#baz","https://example.com/foo"]
|
||||
Pass Pattern: ["?bar","https://example.com/foo#baz"] Inputs: ["?bar","https://example.com/foo#snafu"]
|
||||
Pass Pattern: ["#baz","https://example.com/foo?bar"] Inputs: ["#baz","https://example.com/foo?bar"]
|
||||
Pass Pattern: ["#baz","https://example.com/foo"] Inputs: ["#baz","https://example.com/foo"]
|
||||
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"]
|
||||
Pass Pattern: ["https://foo\\:bar@example.com"] Inputs: ["https://foo:bar@example.com"]
|
||||
Pass Pattern: ["https://foo@example.com"] Inputs: ["https://foo@example.com"]
|
||||
Pass Pattern: ["https://\\:bar@example.com"] Inputs: ["https://:bar@example.com"]
|
||||
Pass 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"]
|
||||
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/"]
|
||||
Fail Pattern: ["http://[\\:\\:a]/"] Inputs: ["http://[::a]/"]
|
||||
Fail Pattern: ["http://[:address]/"] Inputs: ["http://[::1]/"]
|
||||
Fail Pattern: ["http://[\\:\\:AB\\::num]/"] Inputs: ["http://[::ab:1]/"]
|
||||
Pass Pattern: ["data{\\:}channel.html","https://example.com"] Inputs: ["https://example.com/data:channel.html"]
|
||||
Pass Pattern: ["http://[\\:\\:1]/"] Inputs: ["http://[::1]/"]
|
||||
Pass Pattern: ["http://[\\:\\:1]:8080/"] Inputs: ["http://[::1]:8080/"]
|
||||
Pass Pattern: ["http://[\\:\\:a]/"] Inputs: ["http://[::a]/"]
|
||||
Pass Pattern: ["http://[:address]/"] Inputs: ["http://[::1]/"]
|
||||
Pass Pattern: ["http://[\\:\\:AB\\::num]/"] Inputs: ["http://[::ab:1]/"]
|
||||
Fail Pattern: [{"hostname":"[\\:\\:AB\\::num]"}] Inputs: [{"hostname":"[::ab:1]"}]
|
||||
Pass Pattern: [{"hostname":"[\\:\\:xY\\::num]"}] Inputs: undefined
|
||||
Fail Pattern: [{"hostname":"{[\\:\\:ab\\::num]}"}] Inputs: [{"hostname":"[::ab:1]"}]
|
||||
|
@ -306,8 +306,8 @@ 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"}]
|
||||
Fail Pattern: [{}] Inputs: ["https://example.com/"]
|
||||
Fail Pattern: [] Inputs: ["https://example.com/"]
|
||||
Pass Pattern: [{}] Inputs: ["https://example.com/"]
|
||||
Pass Pattern: [] Inputs: ["https://example.com/"]
|
||||
Fail Pattern: [] Inputs: [{}]
|
||||
Fail Pattern: [] Inputs: []
|
||||
Fail Pattern: [{"pathname":"(foo)(.*)"}] Inputs: [{"pathname":"foobarbaz"}]
|
||||
|
@ -349,7 +349,7 @@ Fail Pattern: ["/foo?bar#baz","https://example.com:8080",{"ignoreCase":true}] In
|
|||
Pass Pattern: ["/foo?bar#baz",{"ignoreCase":true},"https://example.com:8080"] Inputs: [{"pathname":"/FOO","search":"BAR","hash":"BAZ","baseURL":"https://example.com:8080"}]
|
||||
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"]
|
||||
Pass Pattern: ["#foo","https://example.com/?q=*&v=?&hmm={}&umm=()"] Inputs: ["https://example.com/?q=*&v=?&hmm={}&umm=()#foo"]
|
||||
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"}]
|
||||
|
|
Loading…
Add table
Reference in a new issue