diff --git a/url/src/lib.rs b/url/src/lib.rs index bf944741..ad9c0853 100644 --- a/url/src/lib.rs +++ b/url/src/lib.rs @@ -2129,7 +2129,7 @@ impl Url { } else { self.host_end }; - let suffix = self.slice(old_suffix_pos..).to_owned(); + let mut suffix = self.slice(old_suffix_pos..).to_owned(); self.serialization.truncate(self.host_start as usize); if !self.has_authority() { debug_assert!(self.slice(self.scheme_end..self.host_start) == ":"); @@ -2143,6 +2143,23 @@ impl Url { self.host_end = to_u32(self.serialization.len()).unwrap(); self.host = host.into(); + // Adjust serialization to switch between host and empty segment + if suffix.starts_with("/.//") { + suffix = suffix["/.".len()..].to_string(); + // pathname should be "//p" not "p" given that the first segment was empty + self.path_start -= "//".len() as u32; + } else if self.host == HostInternal::None && suffix.starts_with("//") { + if let Some(index) = self.serialization.find(":") { + if self.serialization.len() == index + "://".len() + && self.serialization.as_bytes().get(index + 1) == Some(&b'/') + && self.serialization.as_bytes().get(index + 2) == Some(&b'/') + { + self.serialization + .replace_range(index..index + "://".len(), ":/."); + } + } + } + if let Some(new_port) = opt_new_port { self.port = new_port; if let Some(port) = new_port { diff --git a/url/tests/expected_failures.txt b/url/tests/expected_failures.txt index d1ed726c..9bf60b34 100644 --- a/url/tests/expected_failures.txt +++ b/url/tests/expected_failures.txt @@ -36,8 +36,6 @@ set hostname to set hostname to - set hostname to - set hostname to <> set pathname to <> set href to set pathname to <\\\\> diff --git a/url/tests/unit.rs b/url/tests/unit.rs index d8bd3fc5..6febdeb2 100644 --- a/url/tests/unit.rs +++ b/url/tests/unit.rs @@ -1382,6 +1382,7 @@ fn serde_error_message() { #[test] fn test_can_be_a_base_with_set_path() { + use url::quirks; let mut url = Url::parse("web+demo:/").unwrap(); assert!(!url.cannot_be_a_base()); @@ -1396,6 +1397,10 @@ fn test_can_be_a_base_with_set_path() { assert_eq!(segments, vec!["", "not-a-host"]); assert_eq!(url.as_str(), "web+demo:/.//not-a-host"); + quirks::set_hostname(&mut url, "test").unwrap(); + assert_eq!(url.as_str(), "web+demo://test//not-a-host"); + quirks::set_hostname(&mut url, "").unwrap(); + assert_eq!(url.as_str(), "web+demo:/.//not-a-host"); } #[test]