From c23a457e72abe608715ac76f076f47dc42af07a5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 20:31:44 +0200 Subject: Merging upstream version 1.74.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/url/.cargo-checksum.json | 2 +- vendor/url/Cargo.toml | 47 +- vendor/url/README.md | 14 - vendor/url/src/lib.rs | 30 +- vendor/url/src/parser.rs | 16 +- vendor/url/src/path_segments.rs | 2 +- vendor/url/src/quirks.rs | 6 +- vendor/url/tests/data.rs | 260 ----- vendor/url/tests/debugger_visualizer.rs | 102 -- vendor/url/tests/expected_failures.txt | 53 + vendor/url/tests/setters_tests.json | 545 ++++++++++- vendor/url/tests/unit.rs | 10 +- vendor/url/tests/urltestdata.json | 1626 +++++++++++++++++++++---------- vendor/url/tests/wpt.rs | 477 +++++++++ 14 files changed, 2225 insertions(+), 965 deletions(-) delete mode 100644 vendor/url/README.md delete mode 100644 vendor/url/tests/data.rs delete mode 100644 vendor/url/tests/debugger_visualizer.rs create mode 100644 vendor/url/tests/expected_failures.txt create mode 100644 vendor/url/tests/wpt.rs (limited to 'vendor/url') diff --git a/vendor/url/.cargo-checksum.json b/vendor/url/.cargo-checksum.json index df3624ea0..601a2ddc8 100644 --- a/vendor/url/.cargo-checksum.json +++ b/vendor/url/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"81ec036a51f251210a8469d004611867b1b18cc5e6a5e27abefa86c80b057d75","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"76e972ac0f4ddb116e86e10100132a783931a596e7b9872eaa31be15cd4d751d","README.md":"71b01ec6f2f4ce47235ee430ba0c41afac563403a9dbcda23a584c3e915395ac","src/host.rs":"5e25476aaec0153b64d35b53940a72a1ec58e29a0e1fde36944f52eeb945c5f6","src/lib.rs":"fe1a969023cf7fca36cbd58f72b6cdb988d0ac58c0555d8ecc376dfd78d19a69","src/origin.rs":"19a4b451e8615bfef7239d2fc719c489398fe5044edb0df7c84b54eef4ceba1b","src/parser.rs":"8a928f10387b39fefbba9b22048452b1b1ae9cb46b3c349dea2a59d169e7aed8","src/path_segments.rs":"dd6b637245b2ad77ce96221df3f80c8b4ad858cd52aecc86b97166dec386882a","src/quirks.rs":"82903ff9c95604409cded330e36ebba0ede91c469d1aa40fb646186e2bef0769","src/slicing.rs":"39f4e624adbdbf952b7da8bfe6abdfa6e344193d6e1bbca1b0ccbfc821573f10","tests/data.rs":"35c8f1ab545c3e20a3895712ef235aed07dd8226bf9be6e7b21674fc0125c2be","tests/debugger_visualizer.rs":"d3a9466c636ee80ec9181817a8d30ea3e0cee699776ee4b805175981e4775448","tests/setters_tests.json":"486f6d129960d0d0d99b533caf9bef21113b31adcdb83296dfc4a59cd8431715","tests/unit.rs":"ff61fd7640cc84f45f6dd73d8785576d070506a62c48475bcbf927e9ae97edfd","tests/urltestdata.json":"4df7b990a7624da4fd94bee862fe1c3c1ded59fc27fb1cdf08d4a20b655aa3b7"},"package":"50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"} \ No newline at end of file +{"files":{"Cargo.toml":"e8485127c0165af45af4d307166b2db764ee5e1299b9a2cb81c144376361614e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"76e972ac0f4ddb116e86e10100132a783931a596e7b9872eaa31be15cd4d751d","src/host.rs":"5e25476aaec0153b64d35b53940a72a1ec58e29a0e1fde36944f52eeb945c5f6","src/lib.rs":"1491370cc37bcf7e86dcaa060e24fa83db5ee49c2b91637a188d1407caa1611e","src/origin.rs":"19a4b451e8615bfef7239d2fc719c489398fe5044edb0df7c84b54eef4ceba1b","src/parser.rs":"5427cd15caedc8e3c1418cc576a7263e96df26a51ad3ce88f8c32d3eb7d6dd2c","src/path_segments.rs":"29db87b6902da4ab1ae925b3874afdeff42b8ddfb46356af6a83b86f34e03b14","src/quirks.rs":"c9311e3dd6f701fb4b8e438b3e3960ff6f8c78a67ae763f3640b178f15c60e45","src/slicing.rs":"39f4e624adbdbf952b7da8bfe6abdfa6e344193d6e1bbca1b0ccbfc821573f10","tests/expected_failures.txt":"1afb47b036a9fd2a9db671f233ebfa2802b5cd27c4e65839b518ab0a24380ff2","tests/setters_tests.json":"a3a4cbd7b798bc2c4d9656dc50be7397a5a5ed1f0b52daa1da1ad654d38c1dcd","tests/unit.rs":"1abe0a410c5078e1ad9de8c93f2f2ae660ddb47b7efaac9047e952457b068ded","tests/urltestdata.json":"58d67bea710d5f46324fe6841df5fd82090fe4ec2d882bc0fc7c1784d4771884","tests/wpt.rs":"6302c008cde6e7c0df8626701cc825731363722d02e35804bb370c385b455145"},"package":"143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"} \ No newline at end of file diff --git a/vendor/url/Cargo.toml b/vendor/url/Cargo.toml index 311354ca2..f70606edb 100644 --- a/vendor/url/Cargo.toml +++ b/vendor/url/Cargo.toml @@ -13,46 +13,32 @@ edition = "2018" rust-version = "1.56" name = "url" -version = "2.4.0" +version = "2.4.1" authors = ["The rust-url developers"] -include = [ - "src/**/*", - "LICENSE-*", - "README.md", - "tests/**", -] +include = ["src/**/*", "LICENSE-*", "README.md", "tests/**"] description = "URL library for Rust, based on the WHATWG URL Standard" documentation = "https://docs.rs/url" -readme = "README.md" -keywords = [ - "url", - "parser", -] -categories = [ - "parser-implementations", - "web-programming", - "encoding", -] +readme = "../README.md" +keywords = ["url", "parser"] +categories = ["parser-implementations", "web-programming", "encoding"] license = "MIT OR Apache-2.0" repository = "https://github.com/servo/rust-url" - [package.metadata.docs.rs] features = ["serde"] +rustdoc-args = ["--generate-link-to-definition"] [package.metadata.playground] features = ["serde"] [[test]] -name = "debugger_visualizer" -path = "tests/debugger_visualizer.rs" -test = false -required-features = ["debugger_visualizer"] +name = "url_wpt" +path = "tests/wpt.rs" +harness = false [[bench]] name = "parse_url" path = "benches/parse_url.rs" harness = false - [dependencies.form_urlencoded] version = "1.2.0" @@ -66,15 +52,12 @@ version = "2.3.0" version = "1.0" features = ["derive"] optional = true - [dev-dependencies.bencher] version = "0.1" -[dev-dependencies.debugger_test] -version = "0.1" - -[dev-dependencies.debugger_test_parser] -version = "0.1" +[dev-dependencies.serde] +version = "1.0" +features = ["derive"] [dev-dependencies.serde_json] version = "1.0" @@ -83,9 +66,3 @@ version = "1.0" debugger_visualizer = [] default = [] expose_internals = [] - -[badges.appveyor] -repository = "Manishearth/rust-url" - -[badges.travis-ci] -repository = "servo/rust-url" diff --git a/vendor/url/README.md b/vendor/url/README.md deleted file mode 100644 index ab31bffc6..000000000 --- a/vendor/url/README.md +++ /dev/null @@ -1,14 +0,0 @@ -rust-url -======== - -[![Build status](https://github.com/servo/rust-url/workflows/CI/badge.svg)](https://github.com/servo/rust-url/actions?query=workflow%3ACI) -[![Coverage](https://codecov.io/gh/servo/rust-url/branch/master/graph/badge.svg)](https://codecov.io/gh/servo/rust-url) -[![Chat](https://img.shields.io/badge/chat-%23rust--url:mozilla.org-%2346BC99?logo=Matrix)](https://matrix.to/#/#rust-url:mozilla.org) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT) -[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE-APACHE) - -URL library for Rust, based on the [URL Standard](https://url.spec.whatwg.org/). - -[Documentation](https://docs.rs/url/) - -Please see [UPGRADING.md](https://github.com/servo/rust-url/blob/master/UPGRADING.md) if you are upgrading from a previous version. diff --git a/vendor/url/src/lib.rs b/vendor/url/src/lib.rs index ad3c89001..58c7c07cd 100644 --- a/vendor/url/src/lib.rs +++ b/vendor/url/src/lib.rs @@ -119,12 +119,24 @@ See [serde documentation](https://serde.rs) for more information. url = { version = "2", features = ["serde"] } ``` +# Feature: `debugger_visualizer` + +If you enable the `debugger_visualizer` feature, the `url` crate will include +a [natvis file](https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects) +for [Visual Studio](https://www.visualstudio.com/) that allows you to view +[`Url`](struct.Url.html) objects in the debugger. + +This feature requires Rust 1.71 or later. + +```toml +url = { version = "2", features = ["debugger_visualizer"] } +``` + */ -#![doc(html_root_url = "https://docs.rs/url/2.4.0")] +#![doc(html_root_url = "https://docs.rs/url/2.4.1")] #![cfg_attr( feature = "debugger_visualizer", - feature(debugger_visualizer), debugger_visualizer(natvis_file = "../../debug_metadata/url.natvis") )] @@ -1486,7 +1498,7 @@ impl Url { if let Some(input) = fragment { self.fragment_start = Some(to_u32(self.serialization.len()).unwrap()); self.serialization.push('#'); - self.mutate(|parser| parser.parse_fragment(parser::Input::no_trim(input))) + self.mutate(|parser| parser.parse_fragment(parser::Input::new_no_trim(input))) } else { self.fragment_start = None; self.strip_trailing_spaces_from_opaque_path(); @@ -1549,7 +1561,7 @@ impl Url { parser.parse_query( scheme_type, scheme_end, - parser::Input::trim_tab_and_newlines(input, vfn), + parser::Input::new_trim_tab_and_newlines(input, vfn), ) }); } else { @@ -1670,10 +1682,14 @@ impl Url { parser.serialization.push_str("%2F"); path = &path[1..]; } - parser.parse_cannot_be_a_base_path(parser::Input::new(path)); + parser.parse_cannot_be_a_base_path(parser::Input::new_no_trim(path)); } else { let mut has_host = true; // FIXME - parser.parse_path_start(scheme_type, &mut has_host, parser::Input::new(path)); + parser.parse_path_start( + scheme_type, + &mut has_host, + parser::Input::new_no_trim(path), + ); } }); self.restore_after_path(old_after_path_pos, &after_path); @@ -2343,7 +2359,7 @@ impl Url { #[allow(clippy::result_unit_err, clippy::suspicious_operation_groupings)] pub fn set_scheme(&mut self, scheme: &str) -> Result<(), ()> { let mut parser = Parser::for_setter(String::new()); - let remaining = parser.parse_scheme(parser::Input::new(scheme))?; + let remaining = parser.parse_scheme(parser::Input::new_no_trim(scheme))?; let new_scheme_type = SchemeType::from(&parser.serialization); let old_scheme_type = SchemeType::from(self.scheme()); // If url’s scheme is a special scheme and buffer is not a special scheme, then return. diff --git a/vendor/url/src/parser.rs b/vendor/url/src/parser.rs index 765cc027c..7d94d1d71 100644 --- a/vendor/url/src/parser.rs +++ b/vendor/url/src/parser.rs @@ -184,17 +184,13 @@ pub struct Input<'i> { } impl<'i> Input<'i> { - pub fn new(input: &'i str) -> Self { - Input::with_log(input, None) - } - - pub fn no_trim(input: &'i str) -> Self { + pub fn new_no_trim(input: &'i str) -> Self { Input { chars: input.chars(), } } - pub fn trim_tab_and_newlines( + pub fn new_trim_tab_and_newlines( original_input: &'i str, vfn: Option<&dyn Fn(SyntaxViolation)>, ) -> Self { @@ -212,7 +208,10 @@ impl<'i> Input<'i> { } } - pub fn with_log(original_input: &'i str, vfn: Option<&dyn Fn(SyntaxViolation)>) -> Self { + pub fn new_trim_c0_control_and_space( + original_input: &'i str, + vfn: Option<&dyn Fn(SyntaxViolation)>, + ) -> Self { let input = original_input.trim_matches(c0_control_or_space); if let Some(vfn) = vfn { if input.len() < original_input.len() { @@ -362,7 +361,7 @@ impl<'a> Parser<'a> { /// https://url.spec.whatwg.org/#concept-basic-url-parser pub fn parse_url(mut self, input: &str) -> ParseResult { - let input = Input::with_log(input, self.violation_fn); + let input = Input::new_trim_c0_control_and_space(input, self.violation_fn); if let Ok(remaining) = self.parse_scheme(input.clone()) { return self.parse_with_scheme(remaining); } @@ -1203,6 +1202,7 @@ impl<'a> Parser<'a> { _ => { self.check_url_code_point(c, &input); if scheme_type.is_file() + && self.serialization.len() > path_start && is_normalized_windows_drive_letter( &self.serialization[path_start + 1..], ) diff --git a/vendor/url/src/path_segments.rs b/vendor/url/src/path_segments.rs index 29afc1e7e..d8a78d785 100644 --- a/vendor/url/src/path_segments.rs +++ b/vendor/url/src/path_segments.rs @@ -237,7 +237,7 @@ impl<'a> PathSegmentsMut<'a> { scheme_type, &mut has_host, path_start, - parser::Input::new(segment), + parser::Input::new_no_trim(segment), ); } }); diff --git a/vendor/url/src/quirks.rs b/vendor/url/src/quirks.rs index 0674ebb62..3a99e22cf 100644 --- a/vendor/url/src/quirks.rs +++ b/vendor/url/src/quirks.rs @@ -152,7 +152,7 @@ pub fn set_host(url: &mut Url, new_host: &str) -> Result<(), ()> { } // Host parsing rules are strict, // We don't want to trim the input - let input = Input::no_trim(new_host); + let input = Input::new_no_trim(new_host); let host; let opt_port; { @@ -203,7 +203,7 @@ pub fn set_hostname(url: &mut Url, new_hostname: &str) -> Result<(), ()> { return Err(()); } // Host parsing rules are strict we don't want to trim the input - let input = Input::no_trim(new_hostname); + let input = Input::new_no_trim(new_hostname); let scheme_type = SchemeType::from(url.scheme()); if scheme_type == SchemeType::File && new_hostname.is_empty() { url.set_host_internal(Host::Domain(String::new()), None); @@ -249,7 +249,7 @@ pub fn set_port(url: &mut Url, new_port: &str) -> Result<(), ()> { return Err(()); } result = Parser::parse_port( - Input::new(new_port), + Input::new_no_trim(new_port), || default_port(scheme), Context::Setter, ) diff --git a/vendor/url/tests/data.rs b/vendor/url/tests/data.rs deleted file mode 100644 index dc4660b9b..000000000 --- a/vendor/url/tests/data.rs +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2013-2014 The rust-url developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Data-driven tests - -use std::str::FromStr; - -use serde_json::Value; -use url::{quirks, Url}; - -#[test] -fn urltestdata() { - // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/ - let mut json = Value::from_str(include_str!("urltestdata.json")) - .expect("JSON parse error in urltestdata.json"); - - let mut passed = true; - let mut skip_next = false; - for entry in json.as_array_mut().unwrap() { - if entry.is_string() { - if entry.as_str().unwrap() == "skip next" { - skip_next = true; - } - continue; // ignore comments - } - - if skip_next { - skip_next = false; - continue; - } - - let maybe_base = entry - .take_key("base") - .expect("missing base key") - .maybe_string(); - let input = entry.take_string("input"); - let failure = entry.take_key("failure").is_some(); - - let res = if let Some(base) = maybe_base { - let base = match Url::parse(&base) { - Ok(base) => base, - Err(_) if failure => continue, - Err(message) => { - eprint_failure( - format!(" failed: error parsing base {:?}: {}", base, message), - &format!("parse base for {:?}", input), - None, - ); - passed = false; - continue; - } - }; - base.join(&input) - } else { - Url::parse(&input) - }; - - let url = match (res, failure) { - (Ok(url), false) => url, - (Err(_), true) => continue, - (Err(message), false) => { - eprint_failure( - format!(" failed: {}", message), - &format!("parse URL for {:?}", input), - None, - ); - passed = false; - continue; - } - (Ok(_), true) => { - eprint_failure( - format!(" failed: expected parse error for URL {:?}", input), - &format!("parse URL for {:?}", input), - None, - ); - passed = false; - continue; - } - }; - - passed &= check_invariants(&url, &format!("invariants for {:?}", input), None); - - for &attr in ATTRIBS { - passed &= test_eq_eprint( - entry.take_string(attr), - get(&url, attr), - &format!("{:?} - {}", input, attr), - None, - ); - } - - if let Some(expected_origin) = entry.take_key("origin").map(|s| s.string()) { - passed &= test_eq_eprint( - expected_origin, - &quirks::origin(&url), - &format!("origin for {:?}", input), - None, - ); - } - } - - assert!(passed) -} - -#[test] -fn setters_tests() { - let mut json = Value::from_str(include_str!("setters_tests.json")) - .expect("JSON parse error in setters_tests.json"); - - let mut passed = true; - for &attr in ATTRIBS { - if attr == "href" { - continue; - } - - let mut tests = json.take_key(attr).unwrap(); - for mut test in tests.as_array_mut().unwrap().drain(..) { - let comment = test.take_key("comment").map(|s| s.string()); - { - if let Some(comment) = comment.as_ref() { - if comment.starts_with("IDNA Nontransitional_Processing") { - continue; - } - } - } - let href = test.take_string("href"); - let new_value = test.take_string("new_value"); - let name = format!("{:?}.{} = {:?}", href, attr, new_value); - let mut expected = test.take_key("expected").unwrap(); - - let mut url = Url::parse(&href).unwrap(); - let comment_ref = comment.as_deref(); - passed &= check_invariants(&url, &name, comment_ref); - set(&mut url, attr, &new_value); - - for attr in ATTRIBS { - if let Some(value) = expected.take_key(attr) { - passed &= test_eq_eprint(value.string(), get(&url, attr), &name, comment_ref); - }; - } - - passed &= check_invariants(&url, &name, comment_ref); - } - } - - assert!(passed); -} - -fn check_invariants(url: &Url, name: &str, comment: Option<&str>) -> bool { - let mut passed = true; - if let Err(e) = url.check_invariants() { - passed = false; - eprint_failure( - format!(" failed: invariants checked -> {:?}", e), - name, - comment, - ); - } - - #[cfg(feature = "serde")] - { - let bytes = serde_json::to_vec(url).unwrap(); - let new_url: Url = serde_json::from_slice(&bytes).unwrap(); - passed &= test_eq_eprint(url.to_string(), &new_url.to_string(), name, comment); - } - - passed -} - -trait JsonExt { - fn take_key(&mut self, key: &str) -> Option; - fn string(self) -> String; - fn maybe_string(self) -> Option; - fn take_string(&mut self, key: &str) -> String; -} - -impl JsonExt for Value { - fn take_key(&mut self, key: &str) -> Option { - self.as_object_mut().unwrap().remove(key) - } - - fn string(self) -> String { - self.maybe_string().expect("") - } - - fn maybe_string(self) -> Option { - match self { - Value::String(s) => Some(s), - Value::Null => None, - _ => panic!("Not a Value::String or Value::Null"), - } - } - - fn take_string(&mut self, key: &str) -> String { - self.take_key(key).unwrap().string() - } -} - -fn get<'a>(url: &'a Url, attr: &str) -> &'a str { - match attr { - "href" => quirks::href(url), - "protocol" => quirks::protocol(url), - "username" => quirks::username(url), - "password" => quirks::password(url), - "hostname" => quirks::hostname(url), - "host" => quirks::host(url), - "port" => quirks::port(url), - "pathname" => quirks::pathname(url), - "search" => quirks::search(url), - "hash" => quirks::hash(url), - _ => unreachable!(), - } -} - -#[allow(clippy::unit_arg)] -fn set(url: &mut Url, attr: &str, new: &str) { - let _ = match attr { - "protocol" => quirks::set_protocol(url, new), - "username" => quirks::set_username(url, new), - "password" => quirks::set_password(url, new), - "hostname" => quirks::set_hostname(url, new), - "host" => quirks::set_host(url, new), - "port" => quirks::set_port(url, new), - "pathname" => Ok(quirks::set_pathname(url, new)), - "search" => Ok(quirks::set_search(url, new)), - "hash" => Ok(quirks::set_hash(url, new)), - _ => unreachable!(), - }; -} - -fn test_eq_eprint(expected: String, actual: &str, name: &str, comment: Option<&str>) -> bool { - if expected == actual { - return true; - } - eprint_failure( - format!("expected: {}\n actual: {}", expected, actual), - name, - comment, - ); - false -} - -fn eprint_failure(err: String, name: &str, comment: Option<&str>) { - eprintln!(" test: {}\n{}", name, err); - if let Some(comment) = comment { - eprintln!("{}\n", comment); - } else { - eprintln!(); - } -} - -const ATTRIBS: &[&str] = &[ - "href", "protocol", "username", "password", "host", "hostname", "port", "pathname", "search", - "hash", -]; diff --git a/vendor/url/tests/debugger_visualizer.rs b/vendor/url/tests/debugger_visualizer.rs deleted file mode 100644 index 4558e0701..000000000 --- a/vendor/url/tests/debugger_visualizer.rs +++ /dev/null @@ -1,102 +0,0 @@ -use debugger_test::debugger_test; -use url::Url; - -#[inline(never)] -fn __break() {} - -#[debugger_test( - debugger = "cdb", - commands = " - .nvlist - - dx base_url - - dx url_with_non_special_scheme - - dx url_with_user_pass_port_query_fragments - - dx url_blob - - dx url_with_base - - dx url_with_base_replaced - - dx url_with_comma", - expected_statements = r#" - pattern:debugger_visualizer-.*\.exe \(embedded NatVis ".*-[0-9]+\.natvis"\) - - base_url : "http://example.org/foo/bar" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "http" - [host] : "example.org" - [path] : "/foo/bar" - - url_with_non_special_scheme : "non-special://test/x" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "non-special" - [host] : "test" - [path] : "/x" - - url_with_user_pass_port_query_fragments : "http://user:pass@foo:21/bar;par?b#c" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "http" - [username] : "user" - [host] : "foo" - [port] : 21 - [path] : "/bar;par" - [query] : "b" - [fragment] : "c" - - url_blob : "blob:https://example.com:443/" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "blob" - [path] : "https://example.com:443/" - - url_with_base : "http://example.org/a%2fc" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "http" - [host] : "example.org" - [path] : "/a%2fc" - - url_with_base_replaced : "http://[::7f00:1]/" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "http" - [host] : "[::7f00:1]" - [path] : "/" - - url_with_comma : "data:text/html,test#test" [Type: url::Url] - [] [Type: url::Url] - [scheme] : "data" - [path] : "text/html,test" - [fragment] : "test" - "# -)] -fn test_url_visualizer() { - // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/ - let base_url = Url::parse("http://example.org/foo/bar").unwrap(); - assert_eq!(base_url.as_str(), "http://example.org/foo/bar"); - - let url_with_non_special_scheme = Url::parse("non-special://:@test/x").unwrap(); - assert_eq!(url_with_non_special_scheme.as_str(), "non-special://test/x"); - - let url_with_user_pass_port_query_fragments = - Url::parse("http://user:pass@foo:21/bar;par?b#c").unwrap(); - assert_eq!( - url_with_user_pass_port_query_fragments.as_str(), - "http://user:pass@foo:21/bar;par?b#c" - ); - - let url_blob = Url::parse("blob:https://example.com:443/").unwrap(); - assert_eq!(url_blob.as_str(), "blob:https://example.com:443/"); - - let url_with_base = base_url.join("/a%2fc").unwrap(); - assert_eq!(url_with_base.as_str(), "http://example.org/a%2fc"); - - let url_with_base_replaced = base_url.join("http://[::127.0.0.1]").unwrap(); - assert_eq!(url_with_base_replaced.as_str(), "http://[::7f00:1]/"); - - let url_with_comma = base_url.join("data:text/html,test#test").unwrap(); - assert_eq!(url_with_comma.as_str(), "data:text/html,test#test"); - - __break(); -} diff --git a/vendor/url/tests/expected_failures.txt b/vendor/url/tests/expected_failures.txt new file mode 100644 index 000000000..1c404a8b7 --- /dev/null +++ b/vendor/url/tests/expected_failures.txt @@ -0,0 +1,53 @@ + against + + + + + + + + + against +<\\/localhost//pig> against + against + against + against + against + against + against + against + against + against + against + + + + against + against + against + against + + + + against + against + against + + + set hostname to + set hostname to + set hostname to + set hostname to <> + set pathname to <> + set pathname to <> + set port to + set href to + set search to <> + set search to <> + set pathname to <\\\\> + set pathname to + set pathname to + set pathname to + set pathname to + set pathname to + set pathname to

\ No newline at end of file diff --git a/vendor/url/tests/setters_tests.json b/vendor/url/tests/setters_tests.json index 4280032a2..2c6ebee64 100644 --- a/vendor/url/tests/setters_tests.json +++ b/vendor/url/tests/setters_tests.json @@ -1,6 +1,6 @@ { "comment": [ - "AS OF https://github.com/jsdom/whatwg-url/commit/35f04dfd3048cf6362f4398745bb13375c5020c2", + "# Pulled from https://github.com/web-platform-tests/wpt/blob/befe66343e5f21dc464c8c772c6d20695936714f/url/resources/setters_tests.json", "## Tests for setters of https://url.spec.whatwg.org/#urlutils-members", "", "This file contains a JSON object.", @@ -120,11 +120,11 @@ } }, { - "href": "gopher://example.net:1234", + "href": "https://example.net:1234", "new_value": "file", "expected": { - "href": "gopher://example.net:1234", - "protocol": "gopher:" + "href": "https://example.net:1234/", + "protocol": "https:" } }, { @@ -146,7 +146,7 @@ }, { "href": "file:///test", - "new_value": "gopher", + "new_value": "https", "expected": { "href": "file:///test", "protocol": "file:" @@ -270,6 +270,57 @@ "protocol": "https:", "port": "" } + }, + { + "comment": "Tab and newline are stripped", + "href": "http://test/", + "new_value": "h\u000D\u000Att\u0009ps", + "expected": { + "href": "https://test/", + "protocol": "https:", + "port": "" + } + }, + { + "href": "http://test/", + "new_value": "https\u000D", + "expected": { + "href": "https://test/", + "protocol": "https:" + } + }, + { + "comment": "Non-tab/newline C0 controls result in no-op", + "href": "http://test/", + "new_value": "https\u0000", + "expected": { + "href": "http://test/", + "protocol": "http:" + } + }, + { + "href": "http://test/", + "new_value": "https\u000C", + "expected": { + "href": "http://test/", + "protocol": "http:" + } + }, + { + "href": "http://test/", + "new_value": "https\u000E", + "expected": { + "href": "http://test/", + "protocol": "http:" + } + }, + { + "href": "http://test/", + "new_value": "https\u0020", + "expected": { + "href": "http://test/", + "protocol": "http:" + } } ], "username": [ @@ -962,6 +1013,16 @@ "port": "" } }, + { + "href": "file://hi/x", + "new_value": "", + "expected": { + "href": "file:///x", + "host": "", + "hostname": "", + "port": "" + } + }, { "href": "sc://test@test/", "new_value": "", @@ -981,6 +1042,62 @@ "hostname": "test", "port": "12" } + }, + { + "comment": "Leading / is not stripped", + "href": "http://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "http://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "comment": "Leading / is not stripped", + "href": "sc://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "sc:///", + "host": "", + "hostname": "" + } + }, + { + "href": "https://example.com/", + "new_value": "a%C2%ADb", + "expected": { + "href": "https://ab/", + "host": "ab", + "hostname": "ab" + } + }, + { + "href": "https://example.com/", + "new_value": "\u00AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "%C2%AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "xn--", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } } ], "hostname": [ @@ -1144,24 +1261,24 @@ } }, { - "comment": "Stuff after a : delimiter is ignored", + "comment": ": delimiter invalidates entire value", "href": "http://example.net/path", "new_value": "example.com:8080", "expected": { - "href": "http://example.com/path", - "host": "example.com", - "hostname": "example.com", + "href": "http://example.net/path", + "host": "example.net", + "hostname": "example.net", "port": "" } }, { - "comment": "Stuff after a : delimiter is ignored", + "comment": ": delimiter invalidates entire value", "href": "http://example.net:8080/path", "new_value": "example.com:", "expected": { - "href": "http://example.com:8080/path", - "host": "example.com:8080", - "hostname": "example.com", + "href": "http://example.net:8080/path", + "host": "example.net:8080", + "hostname": "example.net", "port": "8080" } }, @@ -1286,6 +1403,16 @@ "port": "" } }, + { + "href": "file://hi/x", + "new_value": "", + "expected": { + "href": "file:///x", + "host": "", + "hostname": "", + "port": "" + } + }, { "href": "sc://test@test/", "new_value": "", @@ -1305,6 +1432,83 @@ "hostname": "test", "port": "12" } + }, + { + "comment": "Drop /. from path", + "href": "non-spec:/.//p", + "new_value": "h", + "expected": { + "href": "non-spec://h//p", + "host": "h", + "hostname": "h", + "pathname": "//p" + } + }, + { + "href": "non-spec:/.//p", + "new_value": "", + "expected": { + "href": "non-spec:////p", + "host": "", + "hostname": "", + "pathname": "//p" + } + }, + { + "comment": "Leading / is not stripped", + "href": "http://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "http://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "comment": "Leading / is not stripped", + "href": "sc://example.com/", + "new_value": "///bad.com", + "expected": { + "href": "sc:///", + "host": "", + "hostname": "" + } + }, + { + "href": "https://example.com/", + "new_value": "a%C2%ADb", + "expected": { + "href": "https://ab/", + "host": "ab", + "hostname": "ab" + } + }, + { + "href": "https://example.com/", + "new_value": "\u00AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "%C2%AD", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } + }, + { + "href": "https://example.com/", + "new_value": "xn--", + "expected": { + "href": "https://example.com/", + "host": "example.com", + "hostname": "example.com" + } } ], "port": [ @@ -1461,6 +1665,17 @@ "port": "8080" } }, + { + "comment": "Setting port to a string that doesn't parse as a number", + "href": "http://example.net:8080/path", + "new_value": "randomstring", + "expected": { + "href": "http://example.net:8080/path", + "host": "example.net:8080", + "hostname": "example.net", + "port": "8080" + } + }, { "comment": "Port numbers are 16 bit integers, overflowing is an error", "href": "non-special://example.net:8080/path", @@ -1519,11 +1734,35 @@ "href": "javascript://x:12/", "port": "12" } + }, + { + "comment": "Leading u0009 on special scheme", + "href": "https://domain.com:443", + "new_value": "\u00098080", + "expected": { + "port": "8080" + } + }, + { + "comment": "Leading u0009 on non-special scheme", + "href": "wpt++://domain.com:443", + "new_value": "\u00098080", + "expected": { + "port": "8080" + } + }, + { + "comment": "Should use all ascii prefixed characters as port", + "href": "https://www.google.com:4343", + "new_value": "4wpt", + "expected": { + "port": "4" + } } ], "pathname": [ { - "comment": "Cannot-be-a-base don’t have a path", + "comment": "Opaque paths cannot be set", "href": "mailto:me@example.net", "new_value": "/foo", "expected": { @@ -1531,6 +1770,67 @@ "pathname": "me@example.net" } }, + { + "href": "data:original", + "new_value": "new value", + "expected": { + "href": "data:original", + "pathname": "original" + } + }, + { + "href": "sc:original", + "new_value": "new value", + "expected": { + "href": "sc:original", + "pathname": "original" + } + }, + { + "comment": "Special URLs cannot have their paths erased", + "href": "file:///some/path", + "new_value": "", + "expected": { + "href": "file:///", + "pathname": "/" + } + }, + { + "comment": "Non-special URLs can have their paths erased", + "href": "foo://somehost/some/path", + "new_value": "", + "expected": { + "href": "foo://somehost", + "pathname": "" + } + }, + { + "comment": "Non-special URLs with an empty host can have their paths erased", + "href": "foo:///some/path", + "new_value": "", + "expected": { + "href": "foo://", + "pathname": "" + } + }, + { + "comment": "Path-only URLs cannot have their paths erased", + "href": "foo:/some/path", + "new_value": "", + "expected": { + "href": "foo:/", + "pathname": "/" + } + }, + { + "comment": "Path-only URLs always have an initial slash", + "href": "foo:/some/path", + "new_value": "test", + "expected": { + "href": "foo:/test", + "pathname": "/test" + } + }, { "href": "unix:/run/foo.socket?timeout=10", "new_value": "/var/log/../run/bar.socket", @@ -1627,13 +1927,31 @@ "pathname": "/%23" } }, + { + "comment": "? doesn't mess up encoding", + "href": "http://example.net", + "new_value": "/?é", + "expected": { + "href": "http://example.net/%3F%C3%A9", + "pathname": "/%3F%C3%A9" + } + }, + { + "comment": "# doesn't mess up encoding", + "href": "http://example.net", + "new_value": "/#é", + "expected": { + "href": "http://example.net/%23%C3%A9", + "pathname": "/%23%C3%A9" + } + }, { "comment": "File URLs and (back)slashes", "href": "file://monkey/", "new_value": "\\\\", "expected": { - "href": "file://monkey/", - "pathname": "/" + "href": "file://monkey//", + "pathname": "//" } }, { @@ -1641,8 +1959,8 @@ "href": "file:///unicorn", "new_value": "//\\/", "expected": { - "href": "file:///", - "pathname": "/" + "href": "file://////", + "pathname": "////" } }, { @@ -1650,8 +1968,77 @@ "href": "file:///unicorn", "new_value": "//monkey/..//", "expected": { - "href": "file:///", - "pathname": "/" + "href": "file://///", + "pathname": "///" + } + }, + { + "comment": "Serialize /. in path", + "href": "non-spec:/", + "new_value": "/.//p", + "expected": { + "href": "non-spec:/.//p", + "pathname": "//p" + } + }, + { + "href": "non-spec:/", + "new_value": "/..//p", + "expected": { + "href": "non-spec:/.//p", + "pathname": "//p" + } + }, + { + "href": "non-spec:/", + "new_value": "//p", + "expected": { + "href": "non-spec:/.//p", + "pathname": "//p" + } + }, + { + "comment": "Drop /. from path", + "href": "non-spec:/.//", + "new_value": "p", + "expected": { + "href": "non-spec:/p", + "pathname": "/p" + } + }, + { + "comment": "Non-special URLs with non-opaque paths percent-encode U+0020", + "href": "data:/nospace", + "new_value": "space ", + "expected": { + "href": "data:/space%20", + "pathname": "/space%20" + } + }, + { + "href": "sc:/nospace", + "new_value": "space ", + "expected": { + "href": "sc:/space%20", + "pathname": "/space%20" + } + }, + { + "comment": "Trailing space should be encoded", + "href": "http://example.net", + "new_value": " ", + "expected": { + "href": "http://example.net/%20", + "pathname": "/%20" + } + }, + { + "comment": "Trailing C0 control should be encoded", + "href": "http://example.net", + "new_value": "\u0000", + "expected": { + "href": "http://example.net/%00", + "pathname": "/%00" } } ], @@ -1737,6 +2124,60 @@ "href": "http://example.net/?%c3%89t%C3%A9", "search": "?%c3%89t%C3%A9" } + }, + { + "comment": "Drop trailing spaces from trailing opaque paths", + "href": "data:space ?query", + "new_value": "", + "expected": { + "href": "data:space", + "pathname": "space", + "search": "" + } + }, + { + "href": "sc:space ?query", + "new_value": "", + "expected": { + "href": "sc:space", + "pathname": "space", + "search": "" + } + }, + { + "comment": "Do not drop trailing spaces from non-trailing opaque paths", + "href": "data:space ?query#fragment", + "new_value": "", + "expected": { + "href": "data:space #fragment", + "search": "" + } + }, + { + "href": "sc:space ?query#fragment", + "new_value": "", + "expected": { + "href": "sc:space #fragment", + "search": "" + } + }, + { + "comment": "Trailing space should be encoded", + "href": "http://example.net", + "new_value": " ", + "expected": { + "href": "http://example.net/?%20", + "search": "?%20" + } + }, + { + "comment": "Trailing C0 control should be encoded", + "href": "http://example.net", + "new_value": "\u0000", + "expected": { + "href": "http://example.net/?%00", + "search": "?%00" + } } ], "hash": [ @@ -1871,6 +2312,70 @@ "href": "javascript:alert(1)#castle", "hash": "#castle" } + }, + { + "comment": "Drop trailing spaces from trailing opaque paths", + "href": "data:space #fragment", + "new_value": "", + "expected": { + "href": "data:space", + "pathname": "space", + "hash": "" + } + }, + { + "href": "sc:space #fragment", + "new_value": "", + "expected": { + "href": "sc:space", + "pathname": "space", + "hash": "" + } + }, + { + "comment": "Do not drop trailing spaces from non-trailing opaque paths", + "href": "data:space ?query#fragment", + "new_value": "", + "expected": { + "href": "data:space ?query", + "hash": "" + } + }, + { + "href": "sc:space ?query#fragment", + "new_value": "", + "expected": { + "href": "sc:space ?query", + "hash": "" + } + }, + { + "comment": "Trailing space should be encoded", + "href": "http://example.net", + "new_value": " ", + "expected": { + "href": "http://example.net/#%20", + "hash": "#%20" + } + }, + { + "comment": "Trailing C0 control should be encoded", + "href": "http://example.net", + "new_value": "\u0000", + "expected": { + "href": "http://example.net/#%00", + "hash": "#%00" + } + } + ], + "href": [ + { + "href": "file:///var/log/system.log", + "new_value": "http://0300.168.0xF0", + "expected": { + "href": "http://192.168.0.240/", + "protocol": "http:" + } } ] } diff --git a/vendor/url/tests/unit.rs b/vendor/url/tests/unit.rs index 6cb0f37fe..c27f237ba 100644 --- a/vendor/url/tests/unit.rs +++ b/vendor/url/tests/unit.rs @@ -472,7 +472,7 @@ fn append_trailing_slash() { fn extend_query_pairs_then_mutate() { let mut url: Url = "http://localhost:6767/foo/bar".parse().unwrap(); url.query_pairs_mut() - .extend_pairs(vec![("auth", "my-token")].into_iter()); + .extend_pairs(vec![("auth", "my-token")]); url.check_invariants().unwrap(); assert_eq!( url.to_string(), @@ -1298,3 +1298,11 @@ fn test_file_with_drive_and_path() { let url2 = url::Url::join(&url, s2).unwrap(); assert_eq!(url2.to_string(), "file:///p:/a"); } + +#[test] +fn issue_864() { + let mut url = url::Url::parse("file://").unwrap(); + dbg!(&url); + url.set_path("x"); + dbg!(&url); +} diff --git a/vendor/url/tests/urltestdata.json b/vendor/url/tests/urltestdata.json index 53d036886..1e61729d1 100644 --- a/vendor/url/tests/urltestdata.json +++ b/vendor/url/tests/urltestdata.json @@ -1,5 +1,5 @@ [ - "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js", + "# Pulled from https://github.com/web-platform-tests/wpt/blob/befe66343e5f21dc464c8c772c6d20695936714f/url/resources/urltestdata.json", { "input": "http://example\t.\norg", "base": "http://example.org/foo/bar", @@ -32,7 +32,7 @@ }, { "input": "https://test:@test", - "base": "about:blank", + "base": null, "href": "https://test@test/", "origin": "https://test", "protocol": "https:", @@ -47,7 +47,7 @@ }, { "input": "https://:@test", - "base": "about:blank", + "base": null, "href": "https://test/", "origin": "https://test", "protocol": "https:", @@ -62,7 +62,7 @@ }, { "input": "non-special://test:@test/x", - "base": "about:blank", + "base": null, "href": "non-special://test@test/x", "origin": "null", "protocol": "non-special:", @@ -77,7 +77,7 @@ }, { "input": "non-special://:@test/x", - "base": "about:blank", + "base": null, "href": "non-special://test/x", "origin": "null", "protocol": "non-special:", @@ -167,7 +167,7 @@ }, { "input": "lolscheme:x x#x x", - "base": "about:blank", + "base": null, "href": "lolscheme:x x#x%20x", "protocol": "lolscheme:", "username": "", @@ -1075,22 +1075,22 @@ }, { "input": "file://example:1/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://example:test/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://example%/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://[example]/", - "base": "about:blank", + "base": null, "failure": true }, { @@ -1754,7 +1754,7 @@ "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/path.js", { "input": "http://example.com/././foo", - "base": "about:blank", + "base": null, "href": "http://example.com/foo", "origin": "http://example.com", "protocol": "http:", @@ -1769,7 +1769,7 @@ }, { "input": "http://example.com/./.foo", - "base": "about:blank", + "base": null, "href": "http://example.com/.foo", "origin": "http://example.com", "protocol": "http:", @@ -1784,7 +1784,7 @@ }, { "input": "http://example.com/foo/.", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1799,7 +1799,7 @@ }, { "input": "http://example.com/foo/./", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1814,7 +1814,7 @@ }, { "input": "http://example.com/foo/bar/..", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1829,7 +1829,7 @@ }, { "input": "http://example.com/foo/bar/../", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1844,7 +1844,7 @@ }, { "input": "http://example.com/foo/..bar", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/..bar", "origin": "http://example.com", "protocol": "http:", @@ -1859,7 +1859,7 @@ }, { "input": "http://example.com/foo/bar/../ton", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/ton", "origin": "http://example.com", "protocol": "http:", @@ -1874,7 +1874,7 @@ }, { "input": "http://example.com/foo/bar/../ton/../../a", - "base": "about:blank", + "base": null, "href": "http://example.com/a", "origin": "http://example.com", "protocol": "http:", @@ -1889,7 +1889,7 @@ }, { "input": "http://example.com/foo/../../..", - "base": "about:blank", + "base": null, "href": "http://example.com/", "origin": "http://example.com", "protocol": "http:", @@ -1904,7 +1904,7 @@ }, { "input": "http://example.com/foo/../../../ton", - "base": "about:blank", + "base": null, "href": "http://example.com/ton", "origin": "http://example.com", "protocol": "http:", @@ -1919,7 +1919,7 @@ }, { "input": "http://example.com/foo/%2e", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1934,7 +1934,7 @@ }, { "input": "http://example.com/foo/%2e%2", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/%2e%2", "origin": "http://example.com", "protocol": "http:", @@ -1949,7 +1949,7 @@ }, { "input": "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar", - "base": "about:blank", + "base": null, "href": "http://example.com/%2e.bar", "origin": "http://example.com", "protocol": "http:", @@ -1964,7 +1964,7 @@ }, { "input": "http://example.com////../..", - "base": "about:blank", + "base": null, "href": "http://example.com//", "origin": "http://example.com", "protocol": "http:", @@ -1979,7 +1979,7 @@ }, { "input": "http://example.com/foo/bar//../..", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/", "origin": "http://example.com", "protocol": "http:", @@ -1994,7 +1994,7 @@ }, { "input": "http://example.com/foo/bar//..", - "base": "about:blank", + "base": null, "href": "http://example.com/foo/bar/", "origin": "http://example.com", "protocol": "http:", @@ -2009,7 +2009,7 @@ }, { "input": "http://example.com/foo", - "base": "about:blank", + "base": null, "href": "http://example.com/foo", "origin": "http://example.com", "protocol": "http:", @@ -2024,7 +2024,7 @@ }, { "input": "http://example.com/%20foo", - "base": "about:blank", + "base": null, "href": "http://example.com/%20foo", "origin": "http://example.com", "protocol": "http:", @@ -2039,7 +2039,7 @@ }, { "input": "http://example.com/foo%", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%", "origin": "http://example.com", "protocol": "http:", @@ -2054,7 +2054,7 @@ }, { "input": "http://example.com/foo%2", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%2", "origin": "http://example.com", "protocol": "http:", @@ -2069,7 +2069,7 @@ }, { "input": "http://example.com/foo%2zbar", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%2zbar", "origin": "http://example.com", "protocol": "http:", @@ -2084,7 +2084,7 @@ }, { "input": "http://example.com/foo%2©zbar", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%2%C3%82%C2%A9zbar", "origin": "http://example.com", "protocol": "http:", @@ -2099,7 +2099,7 @@ }, { "input": "http://example.com/foo%41%7a", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%41%7a", "origin": "http://example.com", "protocol": "http:", @@ -2114,7 +2114,7 @@ }, { "input": "http://example.com/foo\t\u0091%91", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%C2%91%91", "origin": "http://example.com", "protocol": "http:", @@ -2129,7 +2129,7 @@ }, { "input": "http://example.com/foo%00%51", - "base": "about:blank", + "base": null, "href": "http://example.com/foo%00%51", "origin": "http://example.com", "protocol": "http:", @@ -2144,7 +2144,7 @@ }, { "input": "http://example.com/(%28:%3A%29)", - "base": "about:blank", + "base": null, "href": "http://example.com/(%28:%3A%29)", "origin": "http://example.com", "protocol": "http:", @@ -2159,7 +2159,7 @@ }, { "input": "http://example.com/%3A%3a%3C%3c", - "base": "about:blank", + "base": null, "href": "http://example.com/%3A%3a%3C%3c", "origin": "http://example.com", "protocol": "http:", @@ -2174,7 +2174,7 @@ }, { "input": "http://example.com/foo\tbar", - "base": "about:blank", + "base": null, "href": "http://example.com/foobar", "origin": "http://example.com", "protocol": "http:", @@ -2189,7 +2189,7 @@ }, { "input": "http://example.com\\\\foo\\\\bar", - "base": "about:blank", + "base": null, "href": "http://example.com//foo//bar", "origin": "http://example.com", "protocol": "http:", @@ -2204,7 +2204,7 @@ }, { "input": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd", - "base": "about:blank", + "base": null, "href": "http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd", "origin": "http://example.com", "protocol": "http:", @@ -2219,7 +2219,7 @@ }, { "input": "http://example.com/@asdf%40", - "base": "about:blank", + "base": null, "href": "http://example.com/@asdf%40", "origin": "http://example.com", "protocol": "http:", @@ -2234,7 +2234,7 @@ }, { "input": "http://example.com/你好你好", - "base": "about:blank", + "base": null, "href": "http://example.com/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD", "origin": "http://example.com", "protocol": "http:", @@ -2249,7 +2249,7 @@ }, { "input": "http://example.com/‥/foo", - "base": "about:blank", + "base": null, "href": "http://example.com/%E2%80%A5/foo", "origin": "http://example.com", "protocol": "http:", @@ -2264,7 +2264,7 @@ }, { "input": "http://example.com//foo", - "base": "about:blank", + "base": null, "href": "http://example.com/%EF%BB%BF/foo", "origin": "http://example.com", "protocol": "http:", @@ -2279,7 +2279,7 @@ }, { "input": "http://example.com/‮/foo/‭/bar", - "base": "about:blank", + "base": null, "href": "http://example.com/%E2%80%AE/foo/%E2%80%AD/bar", "origin": "http://example.com", "protocol": "http:", @@ -2295,7 +2295,7 @@ "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/relative.js", { "input": "http://www.google.com/foo?bar=baz#", - "base": "about:blank", + "base": null, "href": "http://www.google.com/foo?bar=baz#", "origin": "http://www.google.com", "protocol": "http:", @@ -2310,7 +2310,7 @@ }, { "input": "http://www.google.com/foo?bar=baz# »", - "base": "about:blank", + "base": null, "href": "http://www.google.com/foo?bar=baz#%20%C2%BB", "origin": "http://www.google.com", "protocol": "http:", @@ -2325,7 +2325,7 @@ }, { "input": "data:test# »", - "base": "about:blank", + "base": null, "href": "data:test#%20%C2%BB", "origin": "null", "protocol": "data:", @@ -2340,7 +2340,7 @@ }, { "input": "http://www.google.com", - "base": "about:blank", + "base": null, "href": "http://www.google.com/", "origin": "http://www.google.com", "protocol": "http:", @@ -2355,7 +2355,7 @@ }, { "input": "http://192.0x00A80001", - "base": "about:blank", + "base": null, "href": "http://192.168.0.1/", "origin": "http://192.168.0.1", "protocol": "http:", @@ -2370,7 +2370,7 @@ }, { "input": "http://www/foo%2Ehtml", - "base": "about:blank", + "base": null, "href": "http://www/foo%2Ehtml", "origin": "http://www", "protocol": "http:", @@ -2385,7 +2385,7 @@ }, { "input": "http://www/foo/%2E/html", - "base": "about:blank", + "base": null, "href": "http://www/foo/html", "origin": "http://www", "protocol": "http:", @@ -2400,12 +2400,12 @@ }, { "input": "http://user:pass@/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://%25DOMAIN:foobar@foodomain.com/", - "base": "about:blank", + "base": null, "href": "http://%25DOMAIN:foobar@foodomain.com/", "origin": "http://foodomain.com", "protocol": "http:", @@ -2420,7 +2420,7 @@ }, { "input": "http:\\\\www.google.com\\foo", - "base": "about:blank", + "base": null, "href": "http://www.google.com/foo", "origin": "http://www.google.com", "protocol": "http:", @@ -2435,7 +2435,7 @@ }, { "input": "http://foo:80/", - "base": "about:blank", + "base": null, "href": "http://foo/", "origin": "http://foo", "protocol": "http:", @@ -2450,7 +2450,7 @@ }, { "input": "http://foo:81/", - "base": "about:blank", + "base": null, "href": "http://foo:81/", "origin": "http://foo:81", "protocol": "http:", @@ -2465,7 +2465,7 @@ }, { "input": "httpa://foo:80/", - "base": "about:blank", + "base": null, "href": "httpa://foo:80/", "origin": "null", "protocol": "httpa:", @@ -2480,12 +2480,12 @@ }, { "input": "http://foo:-80/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://foo:443/", - "base": "about:blank", + "base": null, "href": "https://foo/", "origin": "https://foo", "protocol": "https:", @@ -2500,7 +2500,7 @@ }, { "input": "https://foo:80/", - "base": "about:blank", + "base": null, "href": "https://foo:80/", "origin": "https://foo:80", "protocol": "https:", @@ -2515,7 +2515,7 @@ }, { "input": "ftp://foo:21/", - "base": "about:blank", + "base": null, "href": "ftp://foo/", "origin": "ftp://foo", "protocol": "ftp:", @@ -2530,7 +2530,7 @@ }, { "input": "ftp://foo:80/", - "base": "about:blank", + "base": null, "href": "ftp://foo:80/", "origin": "ftp://foo:80", "protocol": "ftp:", @@ -2545,7 +2545,7 @@ }, { "input": "gopher://foo:70/", - "base": "about:blank", + "base": null, "href": "gopher://foo:70/", "origin": "null", "protocol": "gopher:", @@ -2560,7 +2560,7 @@ }, { "input": "gopher://foo:443/", - "base": "about:blank", + "base": null, "href": "gopher://foo:443/", "origin": "null", "protocol": "gopher:", @@ -2575,7 +2575,7 @@ }, { "input": "ws://foo:80/", - "base": "about:blank", + "base": null, "href": "ws://foo/", "origin": "ws://foo", "protocol": "ws:", @@ -2590,7 +2590,7 @@ }, { "input": "ws://foo:81/", - "base": "about:blank", + "base": null, "href": "ws://foo:81/", "origin": "ws://foo:81", "protocol": "ws:", @@ -2605,7 +2605,7 @@ }, { "input": "ws://foo:443/", - "base": "about:blank", + "base": null, "href": "ws://foo:443/", "origin": "ws://foo:443", "protocol": "ws:", @@ -2620,7 +2620,7 @@ }, { "input": "ws://foo:815/", - "base": "about:blank", + "base": null, "href": "ws://foo:815/", "origin": "ws://foo:815", "protocol": "ws:", @@ -2635,7 +2635,7 @@ }, { "input": "wss://foo:80/", - "base": "about:blank", + "base": null, "href": "wss://foo:80/", "origin": "wss://foo:80", "protocol": "wss:", @@ -2650,7 +2650,7 @@ }, { "input": "wss://foo:81/", - "base": "about:blank", + "base": null, "href": "wss://foo:81/", "origin": "wss://foo:81", "protocol": "wss:", @@ -2665,7 +2665,7 @@ }, { "input": "wss://foo:443/", - "base": "about:blank", + "base": null, "href": "wss://foo/", "origin": "wss://foo", "protocol": "wss:", @@ -2680,7 +2680,7 @@ }, { "input": "wss://foo:815/", - "base": "about:blank", + "base": null, "href": "wss://foo:815/", "origin": "wss://foo:815", "protocol": "wss:", @@ -2695,7 +2695,7 @@ }, { "input": "http:/example.com/", - "base": "about:blank", + "base": null, "href": "http://example.com/", "origin": "http://example.com", "protocol": "http:", @@ -2710,7 +2710,7 @@ }, { "input": "ftp:/example.com/", - "base": "about:blank", + "base": null, "href": "ftp://example.com/", "origin": "ftp://example.com", "protocol": "ftp:", @@ -2725,7 +2725,7 @@ }, { "input": "https:/example.com/", - "base": "about:blank", + "base": null, "href": "https://example.com/", "origin": "https://example.com", "protocol": "https:", @@ -2740,7 +2740,7 @@ }, { "input": "madeupscheme:/example.com/", - "base": "about:blank", + "base": null, "href": "madeupscheme:/example.com/", "origin": "null", "protocol": "madeupscheme:", @@ -2755,7 +2755,7 @@ }, { "input": "file:/example.com/", - "base": "about:blank", + "base": null, "href": "file:///example.com/", "protocol": "file:", "username": "", @@ -2769,7 +2769,7 @@ }, { "input": "ftps:/example.com/", - "base": "about:blank", + "base": null, "href": "ftps:/example.com/", "origin": "null", "protocol": "ftps:", @@ -2784,7 +2784,7 @@ }, { "input": "gopher:/example.com/", - "base": "about:blank", + "base": null, "href": "gopher:/example.com/", "origin": "null", "protocol": "gopher:", @@ -2799,7 +2799,7 @@ }, { "input": "ws:/example.com/", - "base": "about:blank", + "base": null, "href": "ws://example.com/", "origin": "ws://example.com", "protocol": "ws:", @@ -2814,7 +2814,7 @@ }, { "input": "wss:/example.com/", - "base": "about:blank", + "base": null, "href": "wss://example.com/", "origin": "wss://example.com", "protocol": "wss:", @@ -2829,7 +2829,7 @@ }, { "input": "data:/example.com/", - "base": "about:blank", + "base": null, "href": "data:/example.com/", "origin": "null", "protocol": "data:", @@ -2844,7 +2844,7 @@ }, { "input": "javascript:/example.com/", - "base": "about:blank", + "base": null, "href": "javascript:/example.com/", "origin": "null", "protocol": "javascript:", @@ -2859,7 +2859,7 @@ }, { "input": "mailto:/example.com/", - "base": "about:blank", + "base": null, "href": "mailto:/example.com/", "origin": "null", "protocol": "mailto:", @@ -2874,7 +2874,7 @@ }, { "input": "http:example.com/", - "base": "about:blank", + "base": null, "href": "http://example.com/", "origin": "http://example.com", "protocol": "http:", @@ -2889,7 +2889,7 @@ }, { "input": "ftp:example.com/", - "base": "about:blank", + "base": null, "href": "ftp://example.com/", "origin": "ftp://example.com", "protocol": "ftp:", @@ -2904,7 +2904,7 @@ }, { "input": "https:example.com/", - "base": "about:blank", + "base": null, "href": "https://example.com/", "origin": "https://example.com", "protocol": "https:", @@ -2919,7 +2919,7 @@ }, { "input": "madeupscheme:example.com/", - "base": "about:blank", + "base": null, "href": "madeupscheme:example.com/", "origin": "null", "protocol": "madeupscheme:", @@ -2934,7 +2934,7 @@ }, { "input": "ftps:example.com/", - "base": "about:blank", + "base": null, "href": "ftps:example.com/", "origin": "null", "protocol": "ftps:", @@ -2949,7 +2949,7 @@ }, { "input": "gopher:example.com/", - "base": "about:blank", + "base": null, "href": "gopher:example.com/", "origin": "null", "protocol": "gopher:", @@ -2964,7 +2964,7 @@ }, { "input": "ws:example.com/", - "base": "about:blank", + "base": null, "href": "ws://example.com/", "origin": "ws://example.com", "protocol": "ws:", @@ -2979,7 +2979,7 @@ }, { "input": "wss:example.com/", - "base": "about:blank", + "base": null, "href": "wss://example.com/", "origin": "wss://example.com", "protocol": "wss:", @@ -2994,7 +2994,7 @@ }, { "input": "data:example.com/", - "base": "about:blank", + "base": null, "href": "data:example.com/", "origin": "null", "protocol": "data:", @@ -3009,7 +3009,7 @@ }, { "input": "javascript:example.com/", - "base": "about:blank", + "base": null, "href": "javascript:example.com/", "origin": "null", "protocol": "javascript:", @@ -3024,7 +3024,7 @@ }, { "input": "mailto:example.com/", - "base": "about:blank", + "base": null, "href": "mailto:example.com/", "origin": "null", "protocol": "mailto:", @@ -3040,7 +3040,7 @@ "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/segments-userinfo-vs-host.html", { "input": "http:@www.example.com", - "base": "about:blank", + "base": null, "href": "http://www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3055,7 +3055,7 @@ }, { "input": "http:/@www.example.com", - "base": "about:blank", + "base": null, "href": "http://www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3070,7 +3070,7 @@ }, { "input": "http://@www.example.com", - "base": "about:blank", + "base": null, "href": "http://www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3085,7 +3085,7 @@ }, { "input": "http:a:b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3100,7 +3100,7 @@ }, { "input": "http:/a:b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3115,7 +3115,7 @@ }, { "input": "http://a:b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3130,7 +3130,7 @@ }, { "input": "http://@pple.com", - "base": "about:blank", + "base": null, "href": "http://pple.com/", "origin": "http://pple.com", "protocol": "http:", @@ -3145,7 +3145,7 @@ }, { "input": "http::b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3160,7 +3160,7 @@ }, { "input": "http:/:b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3175,7 +3175,7 @@ }, { "input": "http://:b@www.example.com", - "base": "about:blank", + "base": null, "href": "http://:b@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3190,64 +3190,64 @@ }, { "input": "http:/:@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http://user@/www.example.com", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http:@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http:/@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http://@/www.example.com", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https:@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http:a:b@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http:/a:b@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http://a:b@/www.example.com", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http::@/www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http:a:@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3262,7 +3262,7 @@ }, { "input": "http:/a:@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3277,7 +3277,7 @@ }, { "input": "http://a:@www.example.com", - "base": "about:blank", + "base": null, "href": "http://a@www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3292,7 +3292,7 @@ }, { "input": "http://www.@pple.com", - "base": "about:blank", + "base": null, "href": "http://www.@pple.com/", "origin": "http://pple.com", "protocol": "http:", @@ -3307,24 +3307,24 @@ }, { "input": "http:@:www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http:/@:www.example.com", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "http://@:www.example.com", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://:@www.example.com", - "base": "about:blank", + "base": null, "href": "http://www.example.com/", "origin": "http://www.example.com", "protocol": "http:", @@ -3622,7 +3622,7 @@ "Leading and trailing C0 control or space", { "input": "\u0000\u001b\u0004\u0012 http://example.com/\u001f \u000d ", - "base": "about:blank", + "base": null, "href": "http://example.com/", "origin": "http://example.com", "protocol": "http:", @@ -3666,17 +3666,17 @@ "U+FFFD", { "input": "https://\ufffd", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://%EF%BF%BD", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://x/\ufffd?\ufffd#\ufffd", - "base": "about:blank", + "base": null, "href": "https://x/%EF%BF%BD?%EF%BF%BD#%EF%BF%BD", "origin": "https://x", "protocol": "https:", @@ -3692,33 +3692,33 @@ "Domain is ASCII, but a label is invalid IDNA", { "input": "http://a.b.c.xn--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://10.0.0.xn--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, "IDNA labels should be matched case-insensitively", { "input": "http://a.b.c.XN--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a.b.c.Xn--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://10.0.0.XN--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://10.0.0.xN--pokxncvks", - "base": "about:blank", + "base": null, "failure": true }, "Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.", @@ -3777,7 +3777,7 @@ }, { "input": "https://faß.ExAmPlE/", - "base": "about:blank", + "base": null, "href": "https://xn--fa-hia.example/", "origin": "https://xn--fa-hia.example", "protocol": "https:", @@ -3792,7 +3792,7 @@ }, { "input": "sc://faß.ExAmPlE/", - "base": "about:blank", + "base": null, "href": "sc://fa%C3%9F.ExAmPlE/", "origin": "null", "protocol": "sc:", @@ -3872,7 +3872,7 @@ }, { "input": "https://x x:12", - "base": "about:blank", + "base": null, "failure": true }, "Fullwidth and escaped UTF-8 fullwidth should still be treated as IP", @@ -3894,7 +3894,7 @@ "Domains with empty labels", { "input": "http://./", - "base": "about:blank", + "base": null, "href": "http://./", "origin": "http://.", "protocol": "http:", @@ -3909,7 +3909,7 @@ }, { "input": "http://../", - "base": "about:blank", + "base": null, "href": "http://../", "origin": "http://..", "protocol": "http:", @@ -3925,7 +3925,7 @@ "Non-special domains with empty labels", { "input": "h://.", - "base": "about:blank", + "base": null, "href": "h://.", "origin": "null", "protocol": "h:", @@ -3941,7 +3941,7 @@ "Broken IPv6", { "input": "http://[www.google.com]/", - "base": "about:blank", + "base": null, "failure": true }, { @@ -4066,6 +4066,21 @@ "search": "", "hash": "#x" }, + { + "input": "#x:y", + "base": "about:blank", + "href": "about:blank#x:y", + "origin": "null", + "protocol": "about:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "blank", + "search": "", + "hash": "#x:y" + }, { "input": "#", "base": "test:test?test", @@ -4131,7 +4146,7 @@ "byte is ' and url is special", { "input": "http://host/?'", - "base": "about:blank", + "base": null, "href": "http://host/?%27", "origin": "http://host", "protocol": "http:", @@ -4146,7 +4161,7 @@ }, { "input": "notspecial://host/?'", - "base": "about:blank", + "base": null, "href": "notspecial://host/?'", "origin": "null", "protocol": "notspecial:", @@ -4504,7 +4519,7 @@ "# make sure that relative URL logic works on known typically non-relative schemes too", { "input": "about:/../", - "base": "about:blank", + "base": null, "href": "about:/", "origin": "null", "protocol": "about:", @@ -4519,7 +4534,7 @@ }, { "input": "data:/../", - "base": "about:blank", + "base": null, "href": "data:/", "origin": "null", "protocol": "data:", @@ -4534,7 +4549,7 @@ }, { "input": "javascript:/../", - "base": "about:blank", + "base": null, "href": "javascript:/", "origin": "null", "protocol": "javascript:", @@ -4549,7 +4564,7 @@ }, { "input": "mailto:/../", - "base": "about:blank", + "base": null, "href": "mailto:/", "origin": "null", "protocol": "mailto:", @@ -4565,7 +4580,7 @@ "# unknown schemes and their hosts", { "input": "sc://ñ.test/", - "base": "about:blank", + "base": null, "href": "sc://%C3%B1.test/", "origin": "null", "protocol": "sc:", @@ -4580,7 +4595,7 @@ }, { "input": "sc://%/", - "base": "about:blank", + "base": null, "href": "sc://%/", "protocol": "sc:", "username": "", @@ -4594,22 +4609,22 @@ }, { "input": "sc://@/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://te@s:t@/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://:/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://:12/", - "base": "about:blank", + "base": null, "failure": true }, { @@ -4630,7 +4645,7 @@ "# unknown schemes and backslashes", { "input": "sc:\\../", - "base": "about:blank", + "base": null, "href": "sc:\\../", "origin": "null", "protocol": "sc:", @@ -4646,7 +4661,7 @@ "# unknown scheme with path looking like a password", { "input": "sc::a@example.net", - "base": "about:blank", + "base": null, "href": "sc::a@example.net", "origin": "null", "protocol": "sc:", @@ -4662,7 +4677,7 @@ "# unknown scheme with bogus percent-encoding", { "input": "wow:%NBD", - "base": "about:blank", + "base": null, "href": "wow:%NBD", "origin": "null", "protocol": "wow:", @@ -4677,7 +4692,7 @@ }, { "input": "wow:%1G", - "base": "about:blank", + "base": null, "href": "wow:%1G", "origin": "null", "protocol": "wow:", @@ -4693,7 +4708,7 @@ "# unknown scheme with non-URL characters", { "input": "wow:\uFFFF", - "base": "about:blank", + "base": null, "href": "wow:%EF%BF%BF", "origin": "null", "protocol": "wow:", @@ -4709,53 +4724,53 @@ "Forbidden host code points", { "input": "sc://a\u0000b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://ab", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a[b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a\\b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a]b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a^b", - "base": "about:blank", + "base": null, "failure": true }, { "input": "sc://a|b/", - "base": "about:blank", + "base": null, "failure": true }, "Forbidden host codepoints: tabs and newlines are removed during preprocessing", { "input": "foo://ho\u0009st/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -4769,7 +4784,7 @@ }, { "input": "foo://ho\u000Ast/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -4783,7 +4798,7 @@ }, { "input": "foo://ho\u000Dst/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -4798,198 +4813,198 @@ "Forbidden domain code-points", { "input": "http://a\u0000b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0001b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0002b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0003b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0004b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0005b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0006b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0007b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0008b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u000Bb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u000Cb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u000Eb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u000Fb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0010b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0011b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0012b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0013b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0014b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0015b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0016b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0017b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0018b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u0019b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Ab/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Bb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Cb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Db/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Eb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u001Fb/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a%b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ab", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a[b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a]b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a^b", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a|b/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://a\u007Fb/", - "base": "about:blank", + "base": null, "failure": true }, "Forbidden domain codepoints: tabs and newlines are removed during preprocessing", { "input": "http://ho\u0009st/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -5003,7 +5018,7 @@ }, { "input": "http://ho\u000Ast/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -5017,7 +5032,7 @@ }, { "input": "http://ho\u000Dst/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -5032,238 +5047,238 @@ "Encoded forbidden domain codepoints in special URLs", { "input": "http://ho%00st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%01st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%02st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%03st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%04st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%05st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%06st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%07st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%08st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%09st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Ast/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Bst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Cst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Dst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Est/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%0Fst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%10st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%11st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%12st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%13st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%14st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%15st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%16st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%17st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%18st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%19st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Ast/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Bst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Cst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Dst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Est/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%1Fst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%20st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%23st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%25st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%2Fst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%3Ast/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%3Cst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%3Est/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%3Fst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%40st/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%5Bst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%5Cst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%5Dst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%7Cst/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://ho%7Fst/", - "base": "about:blank", + "base": null, "failure": true }, "Allowed host/domain code points", { "input": "http://!\"$&'()*+,-.;=_`{}~/", - "base": "about:blank", + "base": null, "href": "http://!\"$&'()*+,-.;=_`{}~/", "origin": "http://!\"$&'()*+,-.;=_`{}~", "protocol": "http:", @@ -5278,7 +5293,7 @@ }, { "input": "sc://\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\u007F!\"$%&'()*+,-.;=_`{}~/", - "base": "about:blank", + "base": null, "href": "sc://%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~/", "origin": "null", "protocol": "sc:", @@ -5294,27 +5309,27 @@ "# Hosts and percent-encoding", { "input": "ftp://example.com%80/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "ftp://example.com%A0/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://example.com%80/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://example.com%A0/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "ftp://%e2%98%83", - "base": "about:blank", + "base": null, "href": "ftp://xn--n3h/", "origin": "ftp://xn--n3h", "protocol": "ftp:", @@ -5329,7 +5344,7 @@ }, { "input": "https://%e2%98%83", - "base": "about:blank", + "base": null, "href": "https://xn--n3h/", "origin": "https://xn--n3h", "protocol": "https:", @@ -5345,7 +5360,7 @@ "# tests from jsdom/whatwg-url designed for code coverage", { "input": "http://127.0.0.1:10100/relative_import.html", - "base": "about:blank", + "base": null, "href": "http://127.0.0.1:10100/relative_import.html", "origin": "http://127.0.0.1:10100", "protocol": "http:", @@ -5360,7 +5375,7 @@ }, { "input": "http://facebook.com/?foo=%7B%22abc%22", - "base": "about:blank", + "base": null, "href": "http://facebook.com/?foo=%7B%22abc%22", "origin": "http://facebook.com", "protocol": "http:", @@ -5375,7 +5390,7 @@ }, { "input": "https://localhost:3000/jqueryui@1.2.3", - "base": "about:blank", + "base": null, "href": "https://localhost:3000/jqueryui@1.2.3", "origin": "https://localhost:3000", "protocol": "https:", @@ -5391,7 +5406,7 @@ "# tab/LF/CR", { "input": "h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg", - "base": "about:blank", + "base": null, "href": "http://host:9000/path?query#frag", "origin": "http://host:9000", "protocol": "http:", @@ -5478,7 +5493,7 @@ "# Percent encoding of fragments", { "input": "http://foo.bar/baz?qux#foo\bbar", - "base": "about:blank", + "base": null, "href": "http://foo.bar/baz?qux#foo%08bar", "origin": "http://foo.bar", "protocol": "http:", @@ -5494,7 +5509,7 @@ }, { "input": "http://foo.bar/baz?qux#foo\"bar", - "base": "about:blank", + "base": null, "href": "http://foo.bar/baz?qux#foo%22bar", "origin": "http://foo.bar", "protocol": "http:", @@ -5510,7 +5525,7 @@ }, { "input": "http://foo.bar/baz?qux#foobar", - "base": "about:blank", + "base": null, "href": "http://foo.bar/baz?qux#foo%3Ebar", "origin": "http://foo.bar", "protocol": "http:", @@ -5542,7 +5557,7 @@ }, { "input": "http://foo.bar/baz?qux#foo`bar", - "base": "about:blank", + "base": null, "href": "http://foo.bar/baz?qux#foo%60bar", "origin": "http://foo.bar", "protocol": "http:", @@ -5774,7 +5789,7 @@ }, { "input": "https://0x.0x.0", - "base": "about:blank", + "base": null, "href": "https://0.0.0.0/", "origin": "https://0.0.0.0", "protocol": "https:", @@ -5790,18 +5805,18 @@ "More IPv4 parsing (via https://github.com/jsdom/whatwg-url/issues/92)", { "input": "https://0x100000000/test", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://256.0.0.1/test", - "base": "about:blank", + "base": null, "failure": true }, "# file URLs containing percent-encoded Windows drive letters (shouldn't work)", { "input": "file:///C%3A/", - "base": "about:blank", + "base": null, "href": "file:///C%3A/", "protocol": "file:", "username": "", @@ -5815,7 +5830,7 @@ }, { "input": "file:///C%7C/", - "base": "about:blank", + "base": null, "href": "file:///C%7C/", "protocol": "file:", "username": "", @@ -5829,42 +5844,42 @@ }, { "input": "file://%43%3A", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://%43%7C", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://%43|", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://C%7C", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://%43%7C/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://%43%7C/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "asdf://%43|/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "asdf://%43%7C/", - "base": "about:blank", + "base": null, "href": "asdf://%43%7C/", "origin": "null", "protocol": "asdf:", @@ -5935,7 +5950,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/", "base": "file://h/C:/a/b", @@ -6105,10 +6119,9 @@ "hash": "#x" }, "# File URLs and many (back)slashes", - "skip next", { "input": "file:\\\\//", - "base": "about:blank", + "base": null, "href": "file:////", "protocol": "file:", "username": "", @@ -6120,10 +6133,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:\\\\\\\\", - "base": "about:blank", + "base": null, "href": "file:////", "protocol": "file:", "username": "", @@ -6135,10 +6147,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:\\\\\\\\?fox", - "base": "about:blank", + "base": null, "href": "file:////?fox", "protocol": "file:", "username": "", @@ -6150,10 +6161,9 @@ "search": "?fox", "hash": "" }, - "skip next", { "input": "file:\\\\\\\\#guppy", - "base": "about:blank", + "base": null, "href": "file:////#guppy", "protocol": "file:", "username": "", @@ -6165,10 +6175,9 @@ "search": "", "hash": "#guppy" }, - "skip next", { "input": "file://spider///", - "base": "about:blank", + "base": null, "href": "file://spider///", "protocol": "file:", "username": "", @@ -6180,10 +6189,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:\\\\localhost//", - "base": "about:blank", + "base": null, "href": "file:////", "protocol": "file:", "username": "", @@ -6197,7 +6205,7 @@ }, { "input": "file:///localhost//cat", - "base": "about:blank", + "base": null, "href": "file:///localhost//cat", "protocol": "file:", "username": "", @@ -6209,10 +6217,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file://\\/localhost//cat", - "base": "about:blank", + "base": null, "href": "file:////localhost//cat", "protocol": "file:", "username": "", @@ -6224,10 +6231,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file://localhost//a//../..//", - "base": "about:blank", + "base": null, "href": "file://///", "protocol": "file:", "username": "", @@ -6239,7 +6245,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/////mouse", "base": "file:///elephant", @@ -6268,7 +6273,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "\\/localhost//pig", "base": "file://lion/", @@ -6283,7 +6287,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "//localhost//pig", "base": "file://lion/", @@ -6298,7 +6301,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/..//localhost//pig", "base": "file://lion/", @@ -6357,7 +6359,6 @@ "hash": "" }, "# Windows drive letter handling with the 'file:' base URL", - "skip next", { "input": "C|", "base": "file://host/dir/file", @@ -6372,7 +6373,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|", "base": "file://host/D:/dir1/dir2/file", @@ -6387,7 +6387,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|#", "base": "file://host/dir/file", @@ -6402,7 +6401,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|?", "base": "file://host/dir/file", @@ -6417,7 +6415,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|/", "base": "file://host/dir/file", @@ -6432,7 +6429,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|\n/", "base": "file://host/dir/file", @@ -6447,7 +6443,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "C|\\", "base": "file://host/dir/file", @@ -6533,7 +6528,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/c:/foo/bar", "base": "file://host/path", @@ -6549,10 +6543,9 @@ "hash": "" }, "# Do not drop the host in the presence of a drive letter", - "skip next", { "input": "file://example.net/C:/", - "base": "about:blank", + "base": null, "href": "file://example.net/C:/", "protocol": "file:", "username": "", @@ -6564,10 +6557,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file://1.2.3.4/C:/", - "base": "about:blank", + "base": null, "href": "file://1.2.3.4/C:/", "protocol": "file:", "username": "", @@ -6579,10 +6571,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file://[1::8]/C:/", - "base": "about:blank", + "base": null, "href": "file://[1::8]/C:/", "protocol": "file:", "username": "", @@ -6595,7 +6586,6 @@ "hash": "" }, "# Copy the host from the base URL in the following cases", - "skip next", { "input": "C|/", "base": "file://host/", @@ -6610,7 +6600,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/C:/", "base": "file://host/", @@ -6625,7 +6614,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:C:/", "base": "file://host/", @@ -6640,7 +6628,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:/C:/", "base": "file://host/", @@ -6656,7 +6643,6 @@ "hash": "" }, "# Copy the empty host from the input in the following cases", - "skip next", { "input": "//C:/", "base": "file://host/", @@ -6716,7 +6702,7 @@ "# Windows drive letter quirk (no host)", { "input": "file:/C|/", - "base": "about:blank", + "base": null, "href": "file:///C:/", "protocol": "file:", "username": "", @@ -6730,7 +6716,7 @@ }, { "input": "file://C|/", - "base": "about:blank", + "base": null, "href": "file:///C:/", "protocol": "file:", "username": "", @@ -6745,7 +6731,7 @@ "# file URLs without base URL by Rimas Misevičius", { "input": "file:", - "base": "about:blank", + "base": null, "href": "file:///", "protocol": "file:", "username": "", @@ -6759,7 +6745,7 @@ }, { "input": "file:?q=v", - "base": "about:blank", + "base": null, "href": "file:///?q=v", "protocol": "file:", "username": "", @@ -6773,7 +6759,7 @@ }, { "input": "file:#frag", - "base": "about:blank", + "base": null, "href": "file:///#frag", "protocol": "file:", "username": "", @@ -6788,7 +6774,7 @@ "# file: drive letter cases from https://crbug.com/1078698", { "input": "file:///Y:", - "base": "about:blank", + "base": null, "href": "file:///Y:", "protocol": "file:", "username": "", @@ -6802,7 +6788,7 @@ }, { "input": "file:///Y:/", - "base": "about:blank", + "base": null, "href": "file:///Y:/", "protocol": "file:", "username": "", @@ -6816,7 +6802,7 @@ }, { "input": "file:///./Y", - "base": "about:blank", + "base": null, "href": "file:///Y", "protocol": "file:", "username": "", @@ -6830,7 +6816,7 @@ }, { "input": "file:///./Y:", - "base": "about:blank", + "base": null, "href": "file:///Y:", "protocol": "file:", "username": "", @@ -6844,14 +6830,14 @@ }, { "input": "\\\\\\.\\Y:", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, "# file: drive letter cases from https://crbug.com/1078698 but lowercased", { "input": "file:///y:", - "base": "about:blank", + "base": null, "href": "file:///y:", "protocol": "file:", "username": "", @@ -6865,7 +6851,7 @@ }, { "input": "file:///y:/", - "base": "about:blank", + "base": null, "href": "file:///y:/", "protocol": "file:", "username": "", @@ -6879,7 +6865,7 @@ }, { "input": "file:///./y", - "base": "about:blank", + "base": null, "href": "file:///y", "protocol": "file:", "username": "", @@ -6893,7 +6879,7 @@ }, { "input": "file:///./y:", - "base": "about:blank", + "base": null, "href": "file:///y:", "protocol": "file:", "username": "", @@ -6907,15 +6893,14 @@ }, { "input": "\\\\\\.\\y:", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, "# Additional file URL tests for (https://github.com/whatwg/url/issues/405)", - "skip next", { "input": "file://localhost//a//../..//foo", - "base": "about:blank", + "base": null, "href": "file://///foo", "protocol": "file:", "username": "", @@ -6927,10 +6912,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file://localhost////foo", - "base": "about:blank", + "base": null, "href": "file://////foo", "protocol": "file:", "username": "", @@ -6942,10 +6926,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:////foo", - "base": "about:blank", + "base": null, "href": "file:////foo", "protocol": "file:", "username": "", @@ -6971,7 +6954,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:////one/two", "base": "file:///", @@ -7014,7 +6996,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "////one/two", "base": "file:///", @@ -7029,7 +7010,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:///.//", "base": "file:////", @@ -7045,10 +7025,9 @@ "hash": "" }, "File URL tests for https://github.com/whatwg/url/issues/549", - "skip next", { "input": "file:.//p", - "base": "about:blank", + "base": null, "href": "file:////p", "protocol": "file:", "username": "", @@ -7060,10 +7039,9 @@ "search": "", "hash": "" }, - "skip next", { "input": "file:/.//p", - "base": "about:blank", + "base": null, "href": "file:////p", "protocol": "file:", "username": "", @@ -7098,48 +7076,48 @@ }, { "input": "https://[0::0::0]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:.0]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:0:]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:1:2:3:4:5:6:7.0.0.0.1]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:1.00.0.0.0]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:1.290.0.0.0]", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://[0:1.23.23]", - "base": "about:blank", + "base": null, "failure": true }, "# Empty host", { "input": "http://?", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://#", - "base": "about:blank", + "base": null, "failure": true }, "Port overflow (2^32 + 81)", @@ -7163,7 +7141,7 @@ "# Non-special-URL path tests", { "input": "sc://ñ", - "base": "about:blank", + "base": null, "href": "sc://%C3%B1", "origin": "null", "protocol": "sc:", @@ -7178,7 +7156,7 @@ }, { "input": "sc://ñ?x", - "base": "about:blank", + "base": null, "href": "sc://%C3%B1?x", "origin": "null", "protocol": "sc:", @@ -7193,7 +7171,7 @@ }, { "input": "sc://ñ#x", - "base": "about:blank", + "base": null, "href": "sc://%C3%B1#x", "origin": "null", "protocol": "sc:", @@ -7238,7 +7216,7 @@ }, { "input": "sc://?", - "base": "about:blank", + "base": null, "href": "sc://?", "protocol": "sc:", "username": "", @@ -7252,7 +7230,7 @@ }, { "input": "sc://#", - "base": "about:blank", + "base": null, "href": "sc://#", "protocol": "sc:", "username": "", @@ -7308,7 +7286,7 @@ }, { "input": "tftp://foobar.com/someconfig;mode=netascii", - "base": "about:blank", + "base": null, "href": "tftp://foobar.com/someconfig;mode=netascii", "origin": "null", "protocol": "tftp:", @@ -7323,7 +7301,7 @@ }, { "input": "telnet://user:pass@foobar.com:23/", - "base": "about:blank", + "base": null, "href": "telnet://user:pass@foobar.com:23/", "origin": "null", "protocol": "telnet:", @@ -7338,7 +7316,7 @@ }, { "input": "ut2004://10.10.10.10:7777/Index.ut2", - "base": "about:blank", + "base": null, "href": "ut2004://10.10.10.10:7777/Index.ut2", "origin": "null", "protocol": "ut2004:", @@ -7353,7 +7331,7 @@ }, { "input": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz", - "base": "about:blank", + "base": null, "href": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz", "origin": "null", "protocol": "redis:", @@ -7368,7 +7346,7 @@ }, { "input": "rsync://foo@host:911/sup", - "base": "about:blank", + "base": null, "href": "rsync://foo@host:911/sup", "origin": "null", "protocol": "rsync:", @@ -7383,7 +7361,7 @@ }, { "input": "git://github.com/foo/bar.git", - "base": "about:blank", + "base": null, "href": "git://github.com/foo/bar.git", "origin": "null", "protocol": "git:", @@ -7398,7 +7376,7 @@ }, { "input": "irc://myserver.com:6999/channel?passwd", - "base": "about:blank", + "base": null, "href": "irc://myserver.com:6999/channel?passwd", "origin": "null", "protocol": "irc:", @@ -7413,7 +7391,7 @@ }, { "input": "dns://fw.example.org:9999/foo.bar.org?type=TXT", - "base": "about:blank", + "base": null, "href": "dns://fw.example.org:9999/foo.bar.org?type=TXT", "origin": "null", "protocol": "dns:", @@ -7428,7 +7406,7 @@ }, { "input": "ldap://localhost:389/ou=People,o=JNDITutorial", - "base": "about:blank", + "base": null, "href": "ldap://localhost:389/ou=People,o=JNDITutorial", "origin": "null", "protocol": "ldap:", @@ -7443,7 +7421,7 @@ }, { "input": "git+https://github.com/foo/bar", - "base": "about:blank", + "base": null, "href": "git+https://github.com/foo/bar", "origin": "null", "protocol": "git+https:", @@ -7458,7 +7436,7 @@ }, { "input": "urn:ietf:rfc:2648", - "base": "about:blank", + "base": null, "href": "urn:ietf:rfc:2648", "origin": "null", "protocol": "urn:", @@ -7473,7 +7451,7 @@ }, { "input": "tag:joe@example.org,2001:foo/bar", - "base": "about:blank", + "base": null, "href": "tag:joe@example.org,2001:foo/bar", "origin": "null", "protocol": "tag:", @@ -7489,7 +7467,7 @@ "Serialize /. in path", { "input": "non-spec:/.//", - "base": "about:blank", + "base": null, "href": "non-spec:/.//", "protocol": "non-spec:", "username": "", @@ -7503,7 +7481,7 @@ }, { "input": "non-spec:/..//", - "base": "about:blank", + "base": null, "href": "non-spec:/.//", "protocol": "non-spec:", "username": "", @@ -7517,7 +7495,7 @@ }, { "input": "non-spec:/a/..//", - "base": "about:blank", + "base": null, "href": "non-spec:/.//", "protocol": "non-spec:", "username": "", @@ -7531,7 +7509,7 @@ }, { "input": "non-spec:/.//path", - "base": "about:blank", + "base": null, "href": "non-spec:/.//path", "protocol": "non-spec:", "username": "", @@ -7545,7 +7523,7 @@ }, { "input": "non-spec:/..//path", - "base": "about:blank", + "base": null, "href": "non-spec:/.//path", "protocol": "non-spec:", "username": "", @@ -7559,7 +7537,7 @@ }, { "input": "non-spec:/a/..//path", - "base": "about:blank", + "base": null, "href": "non-spec:/.//path", "protocol": "non-spec:", "username": "", @@ -7571,7 +7549,6 @@ "search": "", "hash": "" }, - "skip next", { "input": "/.//path", "base": "non-spec:/p", @@ -7674,7 +7651,7 @@ "# percent encoded hosts in non-special-URLs", { "input": "non-special://%E2%80%A0/", - "base": "about:blank", + "base": null, "href": "non-special://%E2%80%A0/", "protocol": "non-special:", "username": "", @@ -7688,7 +7665,7 @@ }, { "input": "non-special://H%4fSt/path", - "base": "about:blank", + "base": null, "href": "non-special://H%4fSt/path", "protocol": "non-special:", "username": "", @@ -7703,7 +7680,7 @@ "# IPv6 in non-special-URLs", { "input": "non-special://[1:2:0:0:5:0:0:0]/", - "base": "about:blank", + "base": null, "href": "non-special://[1:2:0:0:5::]/", "protocol": "non-special:", "username": "", @@ -7717,7 +7694,7 @@ }, { "input": "non-special://[1:2:0:0:0:0:0:3]/", - "base": "about:blank", + "base": null, "href": "non-special://[1:2::3]/", "protocol": "non-special:", "username": "", @@ -7731,7 +7708,7 @@ }, { "input": "non-special://[1:2::3]:80/", - "base": "about:blank", + "base": null, "href": "non-special://[1:2::3]:80/", "protocol": "non-special:", "username": "", @@ -7745,12 +7722,12 @@ }, { "input": "non-special://[:80/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "blob:https://example.com:443/", - "base": "about:blank", + "base": null, "href": "blob:https://example.com:443/", "origin": "https://example.com", "protocol": "blob:", @@ -7763,9 +7740,24 @@ "search": "", "hash": "" }, + { + "input": "blob:http://example.org:88/", + "base": null, + "href": "blob:http://example.org:88/", + "origin": "http://example.org:88", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "http://example.org:88/", + "search": "", + "hash": "" + }, { "input": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf", - "base": "about:blank", + "base": null, "href": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf", "origin": "null", "protocol": "blob:", @@ -7780,7 +7772,7 @@ }, { "input": "blob:", - "base": "about:blank", + "base": null, "href": "blob:", "origin": "null", "protocol": "blob:", @@ -7793,45 +7785,168 @@ "search": "", "hash": "" }, - "Invalid IPv4 radix digits", + "blob: in blob:", { - "input": "http://0x7f.0.0.0x7g", - "base": "about:blank", - "href": "http://0x7f.0.0.0x7g/", - "protocol": "http:", + "input": "blob:blob:", + "base": null, + "href": "blob:blob:", + "origin": "null", + "protocol": "blob:", "username": "", "password": "", - "host": "0x7f.0.0.0x7g", - "hostname": "0x7f.0.0.0x7g", + "host": "", + "hostname": "", "port": "", - "pathname": "/", + "pathname": "blob:", "search": "", "hash": "" }, { - "input": "http://0X7F.0.0.0X7G", - "base": "about:blank", - "href": "http://0x7f.0.0.0x7g/", - "protocol": "http:", + "input": "blob:blob:https://example.org/", + "base": null, + "href": "blob:blob:https://example.org/", + "origin": "null", + "protocol": "blob:", "username": "", "password": "", - "host": "0x7f.0.0.0x7g", - "hostname": "0x7f.0.0.0x7g", + "host": "", + "hostname": "", "port": "", - "pathname": "/", + "pathname": "blob:https://example.org/", + "search": "", + "hash": "" + }, + "Non-http(s): in blob:", + { + "input": "blob:about:blank", + "base": null, + "href": "blob:about:blank", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "about:blank", + "search": "", + "hash": "" + }, + { + "input": "blob:file://host/path", + "base": null, + "href": "blob:file://host/path", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "file://host/path", + "search": "", + "hash": "" + }, + { + "input": "blob:ftp://host/path", + "base": null, + "href": "blob:ftp://host/path", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "ftp://host/path", + "search": "", + "hash": "" + }, + { + "input": "blob:ws://example.org/", + "base": null, + "href": "blob:ws://example.org/", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "ws://example.org/", + "search": "", + "hash": "" + }, + { + "input": "blob:wss://example.org/", + "base": null, + "href": "blob:wss://example.org/", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "wss://example.org/", + "search": "", + "hash": "" + }, + "Percent-encoded http: in blob:", + { + "input": "blob:http%3a//example.org/", + "base": null, + "href": "blob:http%3a//example.org/", + "origin": "null", + "protocol": "blob:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "http%3a//example.org/", + "search": "", + "hash": "" + }, + "Invalid IPv4 radix digits", + { + "input": "http://0x7f.0.0.0x7g", + "base": null, + "href": "http://0x7f.0.0.0x7g/", + "protocol": "http:", + "username": "", + "password": "", + "host": "0x7f.0.0.0x7g", + "hostname": "0x7f.0.0.0x7g", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "http://0X7F.0.0.0X7G", + "base": null, + "href": "http://0x7f.0.0.0x7g/", + "protocol": "http:", + "username": "", + "password": "", + "host": "0x7f.0.0.0x7g", + "hostname": "0x7f.0.0.0x7g", + "port": "", + "pathname": "/", "search": "", "hash": "" }, "Invalid IPv4 portion of IPv6 address", { "input": "http://[::127.0.0.0.1]", - "base": "about:blank", + "base": null, "failure": true }, "Uncompressed IPv6 addresses with 0", { "input": "http://[0:1:0:1:0:1:0:1]", - "base": "about:blank", + "base": null, "href": "http://[0:1:0:1:0:1:0:1]/", "protocol": "http:", "username": "", @@ -7845,7 +7960,7 @@ }, { "input": "http://[1:0:1:0:1:0:1:0]", - "base": "about:blank", + "base": null, "href": "http://[1:0:1:0:1:0:1:0]/", "protocol": "http:", "username": "", @@ -7860,7 +7975,7 @@ "Percent-encoded query and fragment", { "input": "http://example.org/test?\u0022", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%22", "protocol": "http:", "username": "", @@ -7874,7 +7989,7 @@ }, { "input": "http://example.org/test?\u0023", - "base": "about:blank", + "base": null, "href": "http://example.org/test?#", "protocol": "http:", "username": "", @@ -7888,7 +8003,7 @@ }, { "input": "http://example.org/test?\u003C", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%3C", "protocol": "http:", "username": "", @@ -7902,7 +8017,7 @@ }, { "input": "http://example.org/test?\u003E", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%3E", "protocol": "http:", "username": "", @@ -7916,7 +8031,7 @@ }, { "input": "http://example.org/test?\u2323", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%E2%8C%A3", "protocol": "http:", "username": "", @@ -7930,7 +8045,7 @@ }, { "input": "http://example.org/test?%23%23", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%23%23", "protocol": "http:", "username": "", @@ -7944,7 +8059,7 @@ }, { "input": "http://example.org/test?%GH", - "base": "about:blank", + "base": null, "href": "http://example.org/test?%GH", "protocol": "http:", "username": "", @@ -7958,7 +8073,7 @@ }, { "input": "http://example.org/test?a#%EF", - "base": "about:blank", + "base": null, "href": "http://example.org/test?a#%EF", "protocol": "http:", "username": "", @@ -7972,7 +8087,7 @@ }, { "input": "http://example.org/test?a#%GH", - "base": "about:blank", + "base": null, "href": "http://example.org/test?a#%GH", "protocol": "http:", "username": "", @@ -7987,21 +8102,21 @@ "URLs that require a non-about:blank base. (Also serve as invalid base tests.)", { "input": "a", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "a/", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, { "input": "a//", - "base": "about:blank", + "base": null, "failure": true, - "inputCanBeRelative": true + "relativeTo": "non-opaque-path-base" }, "Bases that don't fail to parse but fail to be bases", { @@ -8074,7 +8189,7 @@ "Null code point in fragment", { "input": "http://example.org/test?a#b\u0000c", - "base": "about:blank", + "base": null, "href": "http://example.org/test?a#b%00c", "protocol": "http:", "username": "", @@ -8088,7 +8203,7 @@ }, { "input": "non-spec://example.org/test?a#b\u0000c", - "base": "about:blank", + "base": null, "href": "non-spec://example.org/test?a#b%00c", "protocol": "non-spec:", "username": "", @@ -8102,7 +8217,7 @@ }, { "input": "non-spec:/test?a#b\u0000c", - "base": "about:blank", + "base": null, "href": "non-spec:/test?a#b%00c", "protocol": "non-spec:", "username": "", @@ -8162,7 +8277,7 @@ "IDNA ignored code points in file URLs hosts", { "input": "file://a\u00ADb/p", - "base": "about:blank", + "base": null, "href": "file://ab/p", "protocol": "file:", "username": "", @@ -8176,7 +8291,7 @@ }, { "input": "file://a%C2%ADb/p", - "base": "about:blank", + "base": null, "href": "file://ab/p", "protocol": "file:", "username": "", @@ -8191,7 +8306,7 @@ "IDNA hostnames which get mapped to 'localhost'", { "input": "file://loC𝐀𝐋𝐇𝐨𝐬𝐭/usr/bin", - "base": "about:blank", + "base": null, "href": "file:///usr/bin", "protocol": "file:", "username": "", @@ -8206,17 +8321,17 @@ "Empty host after the domain to ASCII", { "input": "file://\u00ad/p", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://%C2%AD/p", - "base": "about:blank", + "base": null, "failure": true }, { "input": "file://xn--/p", - "base": "about:blank", + "base": null, "failure": true }, "https://bugzilla.mozilla.org/show_bug.cgi?id=1647058", @@ -8237,7 +8352,7 @@ "UTF-8 percent-encode of C0 control percent-encode set and supersets", { "input": "non-special:cannot-be-a-base-url-\u0000\u0001\u001F\u001E\u007E\u007F\u0080", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8252,7 +8367,7 @@ }, { "input": "https://www.example.com/path{\u007Fpath.html?query'\u007F=query#fragment<\u007Ffragment", - "base": "about:blank", + "base": null, "hash": "#fragment%3C%7Ffragment", "host": "www.example.com", "hostname": "www.example.com", @@ -8283,7 +8398,7 @@ "Tests for the distinct percent-encode sets", { "input": "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8298,7 +8413,7 @@ }, { "input": "wss:// !\"$%&'()*+,-.;<=>@[]^_`{|}~@host/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8313,7 +8428,7 @@ }, { "input": "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8328,7 +8443,7 @@ }, { "input": "wss://joe: !\"$%&'()*+,-.:;<=>@[]^_`{|}~@host/", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8343,7 +8458,7 @@ }, { "input": "foo://!\"$%&'()*+,-.;=_`{}~/", - "base": "about:blank", + "base": null, "hash": "", "host": "!\"$%&'()*+,-.;=_`{}~", "hostname": "!\"$%&'()*+,-.;=_`{}~", @@ -8358,7 +8473,7 @@ }, { "input": "wss://!\"$&'()*+,-.;=_`{}~/", - "base": "about:blank", + "base": null, "hash": "", "host": "!\"$&'()*+,-.;=_`{}~", "hostname": "!\"$&'()*+,-.;=_`{}~", @@ -8373,7 +8488,7 @@ }, { "input": "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8388,7 +8503,7 @@ }, { "input": "wss://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8403,7 +8518,7 @@ }, { "input": "foo://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8418,7 +8533,7 @@ }, { "input": "wss://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "", "host": "host", "hostname": "host", @@ -8433,7 +8548,7 @@ }, { "input": "foo://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~", "host": "host", "hostname": "host", @@ -8448,7 +8563,7 @@ }, { "input": "wss://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "base": "about:blank", + "base": null, "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~", "host": "host", "hostname": "host", @@ -8522,12 +8637,14 @@ { "input": "#", "base": null, - "failure": true + "failure": true, + "relativeTo": "any-base" }, { "input": "?", "base": null, - "failure": true + "failure": true, + "relativeTo": "non-opaque-path-base" }, "Last component looks like a number, but not valid IPv4", { @@ -8542,12 +8659,12 @@ }, { "input": "http://0..0x300/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://0..0x300./", - "base": "about:blank", + "base": null, "failure": true }, { @@ -8562,102 +8679,102 @@ }, { "input": "http://1.2.3.08", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://1.2.3.08.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://1.2.3.09", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://09.2.3.4", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://09.2.3.4.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://01.2.3.4.5", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://01.2.3.4.5.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://0x100.2.3.4", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://0x100.2.3.4.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://0x1.2.3.4.5", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://0x1.2.3.4.5.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.1.2.3.4", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.1.2.3.4.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.2.3.4", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.2.3.4.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.09", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.09.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.0x4", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.0x4.", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.09..", - "base": "about:blank", + "base": null, "hash": "", "host": "foo.09..", "hostname": "foo.09..", @@ -8671,33 +8788,33 @@ }, { "input": "http://0999999999999999999/", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.0x", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://foo.0XFfFfFfFfFfFfFfFfFfAcE123", - "base": "about:blank", + "base": null, "failure": true }, { "input": "http://💩.123/", - "base": "about:blank", + "base": null, "failure": true }, "U+0000 and U+FFFF in various places", { "input": "https://\u0000y", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://x/\u0000y", - "base": "about:blank", + "base": null, "hash": "", "host": "x", "hostname": "x", @@ -8711,7 +8828,7 @@ }, { "input": "https://x/?\u0000y", - "base": "about:blank", + "base": null, "hash": "", "host": "x", "hostname": "x", @@ -8725,7 +8842,7 @@ }, { "input": "https://x/?#\u0000y", - "base": "about:blank", + "base": null, "hash": "#%00y", "host": "x", "hostname": "x", @@ -8739,12 +8856,12 @@ }, { "input": "https://\uFFFFy", - "base": "about:blank", + "base": null, "failure": true }, { "input": "https://x/\uFFFFy", - "base": "about:blank", + "base": null, "hash": "", "host": "x", "hostname": "x", @@ -8758,7 +8875,7 @@ }, { "input": "https://x/?\uFFFFy", - "base": "about:blank", + "base": null, "hash": "", "host": "x", "hostname": "x", @@ -8772,7 +8889,7 @@ }, { "input": "https://x/?#\uFFFFy", - "base": "about:blank", + "base": null, "hash": "#%EF%BF%BFy", "host": "x", "hostname": "x", @@ -8786,7 +8903,7 @@ }, { "input": "non-special:\u0000y", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8800,7 +8917,7 @@ }, { "input": "non-special:x/\u0000y", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8814,7 +8931,7 @@ }, { "input": "non-special:x/?\u0000y", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8828,7 +8945,7 @@ }, { "input": "non-special:x/?#\u0000y", - "base": "about:blank", + "base": null, "hash": "#%00y", "host": "", "hostname": "", @@ -8842,7 +8959,7 @@ }, { "input": "non-special:\uFFFFy", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8856,7 +8973,7 @@ }, { "input": "non-special:x/\uFFFFy", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8870,7 +8987,7 @@ }, { "input": "non-special:x/?\uFFFFy", - "base": "about:blank", + "base": null, "hash": "", "host": "", "hostname": "", @@ -8884,7 +9001,7 @@ }, { "input": "non-special:x/?#\uFFFFy", - "base": "about:blank", + "base": null, "hash": "#%EF%BF%BFy", "host": "", "hostname": "", @@ -8898,12 +9015,13 @@ }, { "input": "", - "base": "about:blank", - "failure": true + "base": null, + "failure": true, + "relativeTo": "non-opaque-path-base" }, { "input": "https://example.com/\"quoted\"", - "base": "about:blank", + "base": null, "hash": "", "host": "example.com", "hostname": "example.com", @@ -8915,5 +9033,487 @@ "protocol": "https:", "search": "", "username": "" + }, + { + "input": "https://a%C2%ADb/", + "base": null, + "hash": "", + "host": "ab", + "hostname": "ab", + "href": "https://ab/", + "origin": "https://ab", + "password": "", + "pathname": "/", + "port": "", + "protocol": "https:", + "search": "", + "username": "" + }, + { + "comment": "Empty host after domain to ASCII", + "input": "https://\u00AD/", + "base": null, + "failure": true + }, + { + "input": "https://%C2%AD/", + "base": null, + "failure": true + }, + { + "input": "https://xn--/", + "base": null, + "failure": true + }, + "Non-special schemes that some implementations might incorrectly treat as special", + { + "input": "data://example.com:8080/pathname?search#hash", + "base": null, + "href": "data://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "data:///test", + "base": null, + "href": "data:///test", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "data://test/a/../b", + "base": null, + "href": "data://test/b", + "origin": "null", + "protocol": "data:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "data://:443", + "base": null, + "failure": true + }, + { + "input": "data://test:test", + "base": null, + "failure": true + }, + { + "input": "data://[:1]", + "base": null, + "failure": true + }, + { + "input": "javascript://example.com:8080/pathname?search#hash", + "base": null, + "href": "javascript://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "javascript:///test", + "base": null, + "href": "javascript:///test", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "javascript://test/a/../b", + "base": null, + "href": "javascript://test/b", + "origin": "null", + "protocol": "javascript:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "javascript://:443", + "base": null, + "failure": true + }, + { + "input": "javascript://test:test", + "base": null, + "failure": true + }, + { + "input": "javascript://[:1]", + "base": null, + "failure": true + }, + { + "input": "mailto://example.com:8080/pathname?search#hash", + "base": null, + "href": "mailto://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "mailto:///test", + "base": null, + "href": "mailto:///test", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "mailto://test/a/../b", + "base": null, + "href": "mailto://test/b", + "origin": "null", + "protocol": "mailto:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "mailto://:443", + "base": null, + "failure": true + }, + { + "input": "mailto://test:test", + "base": null, + "failure": true + }, + { + "input": "mailto://[:1]", + "base": null, + "failure": true + }, + { + "input": "intent://example.com:8080/pathname?search#hash", + "base": null, + "href": "intent://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "intent:///test", + "base": null, + "href": "intent:///test", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "intent://test/a/../b", + "base": null, + "href": "intent://test/b", + "origin": "null", + "protocol": "intent:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "intent://:443", + "base": null, + "failure": true + }, + { + "input": "intent://test:test", + "base": null, + "failure": true + }, + { + "input": "intent://[:1]", + "base": null, + "failure": true + }, + { + "input": "urn://example.com:8080/pathname?search#hash", + "base": null, + "href": "urn://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "urn:///test", + "base": null, + "href": "urn:///test", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "urn://test/a/../b", + "base": null, + "href": "urn://test/b", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "urn://:443", + "base": null, + "failure": true + }, + { + "input": "urn://test:test", + "base": null, + "failure": true + }, + { + "input": "urn://[:1]", + "base": null, + "failure": true + }, + { + "input": "turn://example.com:8080/pathname?search#hash", + "base": null, + "href": "turn://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "turn:///test", + "base": null, + "href": "turn:///test", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "turn://test/a/../b", + "base": null, + "href": "turn://test/b", + "origin": "null", + "protocol": "turn:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "turn://:443", + "base": null, + "failure": true + }, + { + "input": "turn://test:test", + "base": null, + "failure": true + }, + { + "input": "turn://[:1]", + "base": null, + "failure": true + }, + { + "input": "stun://example.com:8080/pathname?search#hash", + "base": null, + "href": "stun://example.com:8080/pathname?search#hash", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "example.com:8080", + "hostname": "example.com", + "port": "8080", + "pathname": "/pathname", + "search": "?search", + "hash": "#hash" + }, + { + "input": "stun:///test", + "base": null, + "href": "stun:///test", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "", + "hash": "" + }, + { + "input": "stun://test/a/../b", + "base": null, + "href": "stun://test/b", + "origin": "null", + "protocol": "stun:", + "username": "", + "password": "", + "host": "test", + "hostname": "test", + "port": "", + "pathname": "/b", + "search": "", + "hash": "" + }, + { + "input": "stun://:443", + "base": null, + "failure": true + }, + { + "input": "stun://test:test", + "base": null, + "failure": true + }, + { + "input": "stun://[:1]", + "base": null, + "failure": true + }, + { + "input": "w://x:0", + "base": null, + "href": "w://x:0", + "origin": "null", + "protocol": "w:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" + }, + { + "input": "west://x:0", + "base": null, + "href": "west://x:0", + "origin": "null", + "protocol": "west:", + "username": "", + "password": "", + "host": "x:0", + "hostname": "x", + "port": "0", + "pathname": "", + "search": "", + "hash": "" } ] diff --git a/vendor/url/tests/wpt.rs b/vendor/url/tests/wpt.rs new file mode 100644 index 000000000..701044d67 --- /dev/null +++ b/vendor/url/tests/wpt.rs @@ -0,0 +1,477 @@ +// Copyright 2013-2014 The rust-url developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Data-driven tests imported from web-platform-tests + +use std::collections::HashMap; +use std::fmt::Write; +use std::panic; + +use serde_json::Value; +use url::Url; + +#[derive(Debug, serde::Deserialize)] +struct UrlTest { + input: String, + base: Option, + #[serde(flatten)] + result: UrlTestResult, +} + +#[derive(Debug, serde::Deserialize)] +#[serde(untagged)] +#[allow(clippy::large_enum_variant)] +enum UrlTestResult { + Ok(UrlTestOk), + Fail(UrlTestFail), +} + +#[derive(Debug, serde::Deserialize)] +struct UrlTestOk { + href: String, + protocol: String, + username: String, + password: String, + host: String, + hostname: String, + port: String, + pathname: String, + search: String, + hash: String, +} + +#[derive(Debug, serde::Deserialize)] +struct UrlTestFail { + failure: bool, +} + +#[derive(Debug, serde::Deserialize)] +struct SetterTest { + href: String, + new_value: String, + expected: SetterTestExpected, +} + +#[derive(Debug, serde::Deserialize)] +struct SetterTestExpected { + href: Option, + protocol: Option, + username: Option, + password: Option, + host: Option, + hostname: Option, + port: Option, + pathname: Option, + search: Option, + hash: Option, +} + +fn main() { + let mut filter = None; + let mut args = std::env::args().skip(1); + while filter.is_none() { + if let Some(arg) = args.next() { + if arg == "--test-threads" { + args.next(); + continue; + } + filter = Some(arg); + } else { + break; + } + } + + let mut expected_failures = include_str!("expected_failures.txt") + .lines() + .collect::>(); + + let mut errors = vec![]; + + // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/ + let url_json: Vec = serde_json::from_str(include_str!("urltestdata.json")) + .expect("JSON parse error in urltestdata.json"); + let url_tests = url_json + .into_iter() + .filter(|val| val.is_object()) + .map(|val| serde_json::from_value::(val).expect("parsing failed")) + .collect::>(); + + let setter_json: HashMap = + serde_json::from_str(include_str!("setters_tests.json")) + .expect("JSON parse error in setters_tests.json"); + let setter_tests = setter_json + .into_iter() + .filter(|(k, _)| k != "comment") + .map(|(k, v)| { + let test = serde_json::from_value::>(v).expect("parsing failed"); + (k, test) + }) + .collect::>(); + + for url_test in url_tests { + let mut name = format!("<{}>", url_test.input.escape_default()); + if let Some(base) = &url_test.base { + write!(&mut name, " against <{}>", base.escape_default()).unwrap(); + } + if should_skip(&name, filter.as_deref()) { + continue; + } + print!("{} ... ", name); + + let res = run_url_test(url_test); + report(name, res, &mut errors, &mut expected_failures); + } + + for (kind, tests) in setter_tests { + for test in tests { + let name = format!( + "<{}> set {} to <{}>", + test.href.escape_default(), + kind, + test.new_value.escape_default() + ); + if should_skip(&name, filter.as_deref()) { + continue; + } + + print!("{} ... ", name); + + let res = run_setter_test(&kind, test); + report(name, res, &mut errors, &mut expected_failures); + } + } + + println!(); + println!("===================="); + println!(); + + if !errors.is_empty() { + println!("errors:"); + println!(); + + for (name, err) in errors { + println!(" name: {}", name); + println!(" err: {}", err); + println!(); + } + + std::process::exit(1); + } else { + println!("all tests passed"); + } + + if !expected_failures.is_empty() && filter.is_none() { + println!(); + println!("===================="); + println!(); + println!("tests were expected to fail but did not run:"); + println!(); + + for name in expected_failures { + println!(" {}", name); + } + + println!(); + println!("if these tests were removed, update expected_failures.txt"); + println!(); + + std::process::exit(1); + } +} + +fn should_skip(name: &str, filter: Option<&str>) -> bool { + match filter { + Some(filter) => !name.contains(filter), + None => false, + } +} + +fn report( + name: String, + res: Result<(), String>, + errors: &mut Vec<(String, String)>, + expected_failures: &mut Vec<&str>, +) { + let expected_failure = expected_failures.contains(&&*name); + expected_failures.retain(|&s| s != &*name); + match res { + Ok(()) => { + if expected_failure { + println!("🟠 (unexpected success)"); + errors.push((name, "unexpected success".to_string())); + } else { + println!("✅"); + } + } + Err(err) => { + if expected_failure { + println!("✅ (expected fail)"); + } else { + println!("❌"); + errors.push((name, err)); + } + } + } +} + +fn run_url_test( + UrlTest { + base, + input, + result, + }: UrlTest, +) -> Result<(), String> { + let base = match base { + Some(base) => { + let base = panic::catch_unwind(|| Url::parse(&base)) + .map_err(|_| "panicked while parsing base".to_string())? + .map_err(|e| format!("errored while parsing base: {}", e))?; + Some(base) + } + None => None, + }; + + let res = panic::catch_unwind(move || Url::options().base_url(base.as_ref()).parse(&input)) + .map_err(|_| "panicked while parsing input".to_string())? + .map_err(|e| format!("errored while parsing input: {}", e)); + + match result { + UrlTestResult::Ok(ok) => check_url_ok(res, ok), + UrlTestResult::Fail(fail) => { + assert!(fail.failure); + if res.is_ok() { + return Err("expected failure, but parsed successfully".to_string()); + } + + Ok(()) + } + } +} + +fn check_url_ok(res: Result, ok: UrlTestOk) -> Result<(), String> { + let url = match res { + Ok(url) => url, + Err(err) => { + return Err(format!("expected success, but errored: {:?}", err)); + } + }; + + let href = url::quirks::href(&url); + if href != ok.href { + return Err(format!("expected href {:?}, but got {:?}", ok.href, href)); + } + + let protocol = url::quirks::protocol(&url); + if protocol != ok.protocol { + return Err(format!( + "expected protocol {:?}, but got {:?}", + ok.protocol, protocol + )); + } + + let username = url::quirks::username(&url); + if username != ok.username { + return Err(format!( + "expected username {:?}, but got {:?}", + ok.username, username + )); + } + + let password = url::quirks::password(&url); + if password != ok.password { + return Err(format!( + "expected password {:?}, but got {:?}", + ok.password, password + )); + } + + let host = url::quirks::host(&url); + if host != ok.host { + return Err(format!("expected host {:?}, but got {:?}", ok.host, host)); + } + + let hostname = url::quirks::hostname(&url); + if hostname != ok.hostname { + return Err(format!( + "expected hostname {:?}, but got {:?}", + ok.hostname, hostname + )); + } + + let port = url::quirks::port(&url); + if port != ok.port { + return Err(format!("expected port {:?}, but got {:?}", ok.port, port)); + } + + let pathname = url::quirks::pathname(&url); + if pathname != ok.pathname { + return Err(format!( + "expected pathname {:?}, but got {:?}", + ok.pathname, pathname + )); + } + + let search = url::quirks::search(&url); + if search != ok.search { + return Err(format!( + "expected search {:?}, but got {:?}", + ok.search, search + )); + } + + let hash = url::quirks::hash(&url); + if hash != ok.hash { + return Err(format!("expected hash {:?}, but got {:?}", ok.hash, hash)); + } + + Ok(()) +} + +fn run_setter_test( + kind: &str, + SetterTest { + href, + new_value, + expected, + }: SetterTest, +) -> Result<(), String> { + let mut url = panic::catch_unwind(|| Url::parse(&href)) + .map_err(|_| "panicked while parsing href".to_string())? + .map_err(|e| format!("errored while parsing href: {}", e))?; + + let url = panic::catch_unwind(move || { + match kind { + "protocol" => { + url::quirks::set_protocol(&mut url, &new_value).ok(); + } + "username" => { + url::quirks::set_username(&mut url, &new_value).ok(); + } + "password" => { + url::quirks::set_password(&mut url, &new_value).ok(); + } + "host" => { + url::quirks::set_host(&mut url, &new_value).ok(); + } + "hostname" => { + url::quirks::set_hostname(&mut url, &new_value).ok(); + } + "port" => { + url::quirks::set_port(&mut url, &new_value).ok(); + } + "pathname" => url::quirks::set_pathname(&mut url, &new_value), + "search" => url::quirks::set_search(&mut url, &new_value), + "hash" => url::quirks::set_hash(&mut url, &new_value), + _ => panic!("unknown setter kind: {:?}", kind), + }; + url + }) + .map_err(|_| "panicked while setting value".to_string())?; + + if let Some(expected_href) = expected.href { + let href = url::quirks::href(&url); + if href != expected_href { + return Err(format!( + "expected href {:?}, but got {:?}", + expected_href, href + )); + } + } + + if let Some(expected_protocol) = expected.protocol { + let protocol = url::quirks::protocol(&url); + if protocol != expected_protocol { + return Err(format!( + "expected protocol {:?}, but got {:?}", + expected_protocol, protocol + )); + } + } + + if let Some(expected_username) = expected.username { + let username = url::quirks::username(&url); + if username != expected_username { + return Err(format!( + "expected username {:?}, but got {:?}", + expected_username, username + )); + } + } + + if let Some(expected_password) = expected.password { + let password = url::quirks::password(&url); + if password != expected_password { + return Err(format!( + "expected password {:?}, but got {:?}", + expected_password, password + )); + } + } + + if let Some(expected_host) = expected.host { + let host = url::quirks::host(&url); + if host != expected_host { + return Err(format!( + "expected host {:?}, but got {:?}", + expected_host, host + )); + } + } + + if let Some(expected_hostname) = expected.hostname { + let hostname = url::quirks::hostname(&url); + if hostname != expected_hostname { + return Err(format!( + "expected hostname {:?}, but got {:?}", + expected_hostname, hostname + )); + } + } + + if let Some(expected_port) = expected.port { + let port = url::quirks::port(&url); + if port != expected_port { + return Err(format!( + "expected port {:?}, but got {:?}", + expected_port, port + )); + } + } + + if let Some(expected_pathname) = expected.pathname { + let pathname = url::quirks::pathname(&url); + if pathname != expected_pathname { + return Err(format!( + "expected pathname {:?}, but got {:?}", + expected_pathname, pathname + )); + } + } + + if let Some(expected_search) = expected.search { + let search = url::quirks::search(&url); + if search != expected_search { + return Err(format!( + "expected search {:?}, but got {:?}", + expected_search, search + )); + } + } + + if let Some(expected_hash) = expected.hash { + let hash = url::quirks::hash(&url); + if hash != expected_hash { + return Err(format!( + "expected hash {:?}, but got {:?}", + expected_hash, hash + )); + } + } + + Ok(()) +} -- cgit v1.2.3