diff --git a/Libraries/LibHTTP/HttpRequest.cpp b/Libraries/LibHTTP/HttpRequest.cpp index e2d0b5a9163..acf13073fb1 100644 --- a/Libraries/LibHTTP/HttpRequest.cpp +++ b/Libraries/LibHTTP/HttpRequest.cpp @@ -243,7 +243,7 @@ ErrorOr HttpRequest::from_raw_request(Read return ParseError::InvalidURL; }; - request.m_url.set_cannot_be_a_base_url(true); + request.m_url.set_has_an_opaque_path(true); if (url_parts.size() == 2) { request.m_resource = url_parts[0]; request.m_url.set_paths({ url_parts[0] }); diff --git a/Libraries/LibURL/Parser.cpp b/Libraries/LibURL/Parser.cpp index 4594238410a..92534b423fb 100644 --- a/Libraries/LibURL/Parser.cpp +++ b/Libraries/LibURL/Parser.cpp @@ -646,7 +646,7 @@ constexpr bool is_double_dot_path_segment(StringView input) void Parser::shorten_urls_path(URL& url) { // 1. Assert: url does not have an opaque path. - VERIFY(!url.cannot_be_a_base_url()); + VERIFY(!url.has_an_opaque_path()); // 2. Let path be url’s path. auto& path = url.m_data->paths; @@ -892,7 +892,7 @@ Optional Parser::basic_parse(StringView raw_input, Optional bas } // 9. Otherwise, set url’s path to the empty string and set state to opaque path state. else { - url->m_data->cannot_be_a_base_url = true; + url->m_data->has_an_opaque_path = true; url->append_slash(); state = State::OpaquePath; } @@ -912,18 +912,18 @@ Optional Parser::basic_parse(StringView raw_input, Optional bas // -> no scheme state, https://url.spec.whatwg.org/#no-scheme-state case State::NoScheme: // 1. If base is null, or base has an opaque path and c is not U+0023 (#), missing-scheme-non-relative-URL validation error, return failure. - if (!base_url.has_value() || (base_url->m_data->cannot_be_a_base_url && code_point != '#')) { + if (!base_url.has_value() || (base_url->has_an_opaque_path() && code_point != '#')) { report_validation_error(); return {}; } // 2. Otherwise, if base has an opaque path and c is U+0023 (#), set url’s scheme to base’s scheme, url’s path to base’s path, url’s query // to base’s query,url’s fragment to the empty string, and set state to fragment state. - else if (base_url->m_data->cannot_be_a_base_url && code_point == '#') { + else if (base_url->has_an_opaque_path() && code_point == '#') { url->m_data->scheme = base_url->m_data->scheme; url->m_data->paths = base_url->m_data->paths; url->m_data->query = base_url->m_data->query; url->m_data->fragment = String {}; - url->m_data->cannot_be_a_base_url = true; + url->m_data->has_an_opaque_path = true; state = State::Fragment; } // 3. Otherwise, if base’s scheme is not "file", set state to relative state and decrease pointer by 1. diff --git a/Libraries/LibURL/URL.cpp b/Libraries/LibURL/URL.cpp index c57ae3e6b14..c9d3bc20e07 100644 --- a/Libraries/LibURL/URL.cpp +++ b/Libraries/LibURL/URL.cpp @@ -119,7 +119,7 @@ bool URL::compute_validity() const if (m_data->scheme.is_empty()) return false; - if (m_data->cannot_be_a_base_url) { + if (m_data->has_an_opaque_path) { if (m_data->paths.size() != 1) return false; if (m_data->paths[0].is_empty()) @@ -193,7 +193,7 @@ URL create_with_url_or_path(ByteString const& url_or_path) URL create_with_data(StringView mime_type, StringView payload, bool is_base64) { URL url; - url.set_cannot_be_a_base_url(true); + url.set_has_an_opaque_path(true); url.set_scheme("data"_string); StringBuilder builder; @@ -216,8 +216,7 @@ bool is_special_scheme(StringView scheme) String URL::serialize_path() const { // 1. If url has an opaque path, then return url’s path. - // FIXME: Reimplement this step once we modernize the URL implementation to meet the spec. - if (cannot_be_a_base_url()) + if (has_an_opaque_path()) return m_data->paths[0]; // 2. Let output be the empty string. @@ -272,7 +271,7 @@ String URL::serialize(ExcludeFragment exclude_fragment) const // 3. If url’s host is null, url does not have an opaque path, url’s path’s size is greater than 1, and url’s path[0] is the empty string, then append U+002F (/) followed by U+002E (.) to output. // 4. Append the result of URL path serializing url to output. // FIXME: Implement this closer to spec steps. - if (cannot_be_a_base_url()) { + if (has_an_opaque_path()) { output.append(m_data->paths[0]); } else { if (!m_data->host.has_value() && m_data->paths.size() > 1 && m_data->paths[0].is_empty()) @@ -318,7 +317,7 @@ ByteString URL::serialize_for_display() const builder.appendff(":{}", *m_data->port); } - if (cannot_be_a_base_url()) { + if (has_an_opaque_path()) { builder.append(m_data->paths[0]); } else { if (!m_data->host.has_value() && m_data->paths.size() > 1 && m_data->paths[0].is_empty()) @@ -470,7 +469,7 @@ URL URL::about(String path) url.m_data->valid = true; url.m_data->scheme = "about"_string; url.m_data->paths = { move(path) }; - url.m_data->cannot_be_a_base_url = true; + url.m_data->has_an_opaque_path = true; return url; } diff --git a/Libraries/LibURL/URL.h b/Libraries/LibURL/URL.h index ffda3acccc2..f5f334c0efa 100644 --- a/Libraries/LibURL/URL.h +++ b/Libraries/LibURL/URL.h @@ -93,7 +93,11 @@ public: size_t path_segment_count() const { return m_data->paths.size(); } u16 port_or_default() const { return m_data->port.value_or(default_port_for_scheme(m_data->scheme).value_or(0)); } - bool cannot_be_a_base_url() const { return m_data->cannot_be_a_base_url; } + + // https://url.spec.whatwg.org/#url-opaque-path + // A URL has an opaque path if its path is a URL path segment. + bool has_an_opaque_path() const { return m_data->has_an_opaque_path; } + bool cannot_have_a_username_or_password_or_port() const; bool includes_credentials() const { return !m_data->username.is_empty() || !m_data->password.is_empty(); } @@ -108,7 +112,7 @@ public: Vector const& paths() const { return m_data->paths; } void set_query(Optional query) { m_data->query = move(query); } void set_fragment(Optional fragment) { m_data->fragment = move(fragment); } - void set_cannot_be_a_base_url(bool value) { m_data->cannot_be_a_base_url = value; } + void set_has_an_opaque_path(bool value) { m_data->has_an_opaque_path = value; } void append_path(StringView); void append_slash() { @@ -156,7 +160,7 @@ private: clone->paths = paths; clone->query = query; clone->fragment = fragment; - clone->cannot_be_a_base_url = cannot_be_a_base_url; + clone->has_an_opaque_path = has_an_opaque_path; clone->blob_url_entry = blob_url_entry; return clone; } @@ -188,7 +192,7 @@ private: // A URL’s fragment is either null or an ASCII string that can be used for further processing on the resource the URL’s other components identify. It is initially null. Optional fragment; - bool cannot_be_a_base_url { false }; + bool has_an_opaque_path { false }; // https://url.spec.whatwg.org/#concept-url-blob-entry // A URL also has an associated blob URL entry that is either null or a blob URL entry. It is initially null. diff --git a/Libraries/LibWeb/DOMURL/DOMURL.cpp b/Libraries/LibWeb/DOMURL/DOMURL.cpp index f30b6fdc0e1..7b6d3aaae71 100644 --- a/Libraries/LibWeb/DOMURL/DOMURL.cpp +++ b/Libraries/LibWeb/DOMURL/DOMURL.cpp @@ -288,11 +288,11 @@ String DOMURL::host() const return MUST(String::formatted("{}:{}", url.serialized_host(), *url.port())); } -// https://url.spec.whatwg.org/#dom-url-hostref-for-dom-url-host%E2%91%A0 +// https://url.spec.whatwg.org/#dom-url-host void DOMURL::set_host(String const& host) { - // 1. If this’s URL’s cannot-be-a-base-URL is true, then return. - if (m_url.cannot_be_a_base_url()) + // 1. If this’s URL has an opaque path, then return. + if (m_url.has_an_opaque_path()) return; // 2. Basic URL parse the given value with this’s URL as url and host state as state override. @@ -313,8 +313,8 @@ String DOMURL::hostname() const // https://url.spec.whatwg.org/#ref-for-dom-url-hostname① void DOMURL::set_hostname(String const& hostname) { - // 1. If this’s URL’s cannot-be-a-base-URL is true, then return. - if (m_url.cannot_be_a_base_url()) + // 1. If this’s URL has an opaque path, then return. + if (m_url.has_an_opaque_path()) return; // 2. Basic URL parse the given value with this’s URL as url and hostname state as state override. @@ -359,9 +359,8 @@ String DOMURL::pathname() const // https://url.spec.whatwg.org/#ref-for-dom-url-pathname%E2%91%A0 void DOMURL::set_pathname(String const& pathname) { - // FIXME: These steps no longer match the speci. - // 1. If this’s URL’s cannot-be-a-base-URL is true, then return. - if (m_url.cannot_be_a_base_url()) + // 1. If this’s URL has an opaque path, then return. + if (m_url.has_an_opaque_path()) return; // 2. Empty this’s URL’s path. diff --git a/Libraries/LibWeb/DOMURL/DOMURL.h b/Libraries/LibWeb/DOMURL/DOMURL.h index 66e0d958fdd..5869263caac 100644 --- a/Libraries/LibWeb/DOMURL/DOMURL.h +++ b/Libraries/LibWeb/DOMURL/DOMURL.h @@ -64,8 +64,7 @@ public: void set_paths(Vector const& paths) { return m_url.set_paths(paths); } - // FIXME: Reimplement this to meet the definition in https://url.spec.whatwg.org/#url-opaque-path once we modernize URL to meet the spec. - bool cannot_be_a_base_url() const { return m_url.cannot_be_a_base_url(); } + bool has_an_opaque_path() const { return m_url.has_an_opaque_path(); } String search() const; void set_search(String const&); diff --git a/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp b/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp index a493f6b03ea..ccf884d88b2 100644 --- a/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp +++ b/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp @@ -17,8 +17,8 @@ HTMLHyperlinkElementUtils::~HTMLHyperlinkElementUtils() = default; // https://html.spec.whatwg.org/multipage/links.html#reinitialise-url void HTMLHyperlinkElementUtils::reinitialize_url() const { - // 1. If element's url is non-null, its scheme is "blob", and its cannot-be-a-basFe-URL is true, terminate these steps. - if (m_url.has_value() && m_url->scheme() == "blob"sv && m_url->cannot_be_a_base_url()) + // 1. If the element's url is non-null, its scheme is "blob", and it has an opaque path, then terminate these steps. + if (m_url.has_value() && m_url->scheme() == "blob"sv && m_url->has_an_opaque_path()) return; // 2. Set the url. @@ -204,8 +204,8 @@ void HTMLHyperlinkElementUtils::set_host(StringView host) // 2. Let url be this element's url. auto& url = m_url; - // 3. If url is null or url's cannot-be-a-base-URL is true, then return. - if (!url.has_value() || url->cannot_be_a_base_url()) + // 3. If url is null or url has an opaque path, then return. + if (!url.has_value() || url->has_an_opaque_path()) return; // 4. Basic URL parse the given value, with url as url and host state as state override. @@ -241,8 +241,8 @@ void HTMLHyperlinkElementUtils::set_hostname(StringView hostname) // 2. Let url be this element's url. auto& url = m_url; - // 3. If url is null or url's cannot-be-a-base-URL is true, then return. - if (!url.has_value() || url->cannot_be_a_base_url()) + // 3. If url is null or url has an opaque path, then return. + if (!url.has_value() || url->has_an_opaque_path()) return; // 4. Basic URL parse the given value, with url as url and hostname state as state override. @@ -317,16 +317,17 @@ void HTMLHyperlinkElementUtils::set_pathname(StringView pathname) reinitialize_url(); // 2. Let url be this element's url. + auto& url = m_url; - // 3. If url is null or url's cannot-be-a-base-URL is true, then return. - if (!m_url.has_value() || m_url->cannot_be_a_base_url()) + // 3. If url is null or url has an opaque path, then return. + if (!url.has_value() || url->has_an_opaque_path()) return; // 4. Set url's path to the empty list. - m_url->set_paths({}); + url->set_paths({}); // 5. Basic URL parse the given value, with url as url and path start state as state override. - (void)URL::Parser::basic_parse(pathname, {}, &m_url.value(), URL::Parser::State::PathStart); + (void)URL::Parser::basic_parse(pathname, {}, &url.value(), URL::Parser::State::PathStart); // 6. Update href. update_href(); diff --git a/Tests/LibURL/TestURL.cpp b/Tests/LibURL/TestURL.cpp index 815fb07952a..c0178c15098 100644 --- a/Tests/LibURL/TestURL.cpp +++ b/Tests/LibURL/TestURL.cpp @@ -303,7 +303,7 @@ TEST_CASE(complete_url) EXPECT_EQ(url->serialized_host(), "serenityos.org"); EXPECT_EQ(url->serialize_path(), "/test.html"); EXPECT(!url->query().has_value()); - EXPECT_EQ(url->cannot_be_a_base_url(), false); + EXPECT_EQ(url->has_an_opaque_path(), false); EXPECT(base_url->complete_url("../index.html#fragment"sv)->equals(*base_url)); }