LibURL: Replace Host's Empty state with making Url's Host optional

A couple of reasons:
- Origin's Host (when in the tuple state) can't be null
- There's an "empty host" concept in the spec which is NOT the same as a
  null Host, and that was confusing me.
This commit is contained in:
Sam Atkins 2024-11-27 12:48:28 +00:00 committed by Andreas Kling
commit 90e763de4c
Notes: github-actions[bot] 2024-11-30 11:24:09 +00:00
17 changed files with 44 additions and 42 deletions

View file

@ -36,9 +36,9 @@ struct ProxyData {
proxy_data.type = ProxyData::Type::SOCKS5; proxy_data.type = ProxyData::Type::SOCKS5;
if (!url.host().has<URL::IPv4Address>()) if (!url.host().has_value() || !url.host()->has<URL::IPv4Address>())
return Error::from_string_literal("Invalid proxy host, must be an IPv4 address"); return Error::from_string_literal("Invalid proxy host, must be an IPv4 address");
proxy_data.host_ipv4 = url.host().get<URL::IPv4Address>(); proxy_data.host_ipv4 = url.host()->get<URL::IPv4Address>();
auto port = url.port(); auto port = url.port();
if (!port.has_value()) if (!port.has_value())

View file

@ -26,6 +26,6 @@ using IPv6Address = Array<u16, 8>;
// https://url.spec.whatwg.org/#concept-host // https://url.spec.whatwg.org/#concept-host
// A host is a domain, an IP address, an opaque host, or an empty host. Typically a host serves as a network address, // A host is a domain, an IP address, an opaque host, or an empty host. Typically a host serves as a network address,
// but it is sometimes used as opaque identifier in URLs where a network address is not necessary. // but it is sometimes used as opaque identifier in URLs where a network address is not necessary.
using Host = Variant<IPv4Address, IPv6Address, String, Empty>; using Host = Variant<IPv4Address, IPv6Address, String>;
} }

View file

@ -1574,7 +1574,7 @@ URL Parser::basic_parse(StringView raw_input, Optional<URL> const& base_url, URL
continue; continue;
} }
// 5. Otherwise, if state override is given and urls host is null, append the empty string to urls path. // 5. Otherwise, if state override is given and urls host is null, append the empty string to urls path.
else if (state_override.has_value() && url->host().has<Empty>()) { else if (state_override.has_value() && !url->host().has_value()) {
url->append_slash(); url->append_slash();
} }
break; break;

View file

@ -88,7 +88,7 @@ void URL::set_host(Host host)
// https://url.spec.whatwg.org/#concept-host-serializer // https://url.spec.whatwg.org/#concept-host-serializer
ErrorOr<String> URL::serialized_host() const ErrorOr<String> URL::serialized_host() const
{ {
return Parser::serialize_host(m_data->host); return Parser::serialize_host(m_data->host.value());
} }
void URL::set_port(Optional<u16> port) void URL::set_port(Optional<u16> port)
@ -119,7 +119,7 @@ void URL::append_path(StringView path)
bool URL::cannot_have_a_username_or_password_or_port() const bool URL::cannot_have_a_username_or_password_or_port() const
{ {
// A URL cannot have a username/password/port if its host is null or the empty string, or its scheme is "file". // A URL cannot have a username/password/port if its host is null or the empty string, or its scheme is "file".
return m_data->host.has<Empty>() || m_data->host == String {} || m_data->scheme == "file"sv; return !m_data->host.has_value() || m_data->host == String {} || m_data->scheme == "file"sv;
} }
// FIXME: This is by no means complete. // FIXME: This is by no means complete.
@ -142,8 +142,8 @@ bool URL::compute_validity() const
return false; return false;
} }
// NOTE: A file URL's host should be the empty string for localhost, not null. // FIXME: A file URL's host should be the empty string for localhost, not null.
if (m_data->scheme == "file" && m_data->host.has<Empty>()) if (m_data->scheme == "file" && !m_data->host.has_value())
return false; return false;
return true; return true;
@ -252,7 +252,7 @@ ByteString URL::serialize(ExcludeFragment exclude_fragment) const
output.append(':'); output.append(':');
// 2. If urls host is non-null: // 2. If urls host is non-null:
if (!m_data->host.has<Empty>()) { if (m_data->host.has_value()) {
// 1. Append "//" to output. // 1. Append "//" to output.
output.append("//"sv); output.append("//"sv);
@ -285,7 +285,7 @@ ByteString URL::serialize(ExcludeFragment exclude_fragment) const
if (cannot_be_a_base_url()) { if (cannot_be_a_base_url()) {
output.append(m_data->paths[0]); output.append(m_data->paths[0]);
} else { } else {
if (m_data->host.has<Empty>() && m_data->paths.size() > 1 && m_data->paths[0].is_empty()) if (!m_data->host.has_value() && m_data->paths.size() > 1 && m_data->paths[0].is_empty())
output.append("/."sv); output.append("/."sv);
for (auto& segment : m_data->paths) { for (auto& segment : m_data->paths) {
output.append('/'); output.append('/');
@ -321,7 +321,7 @@ ByteString URL::serialize_for_display() const
builder.append(m_data->scheme); builder.append(m_data->scheme);
builder.append(':'); builder.append(':');
if (!m_data->host.has<Empty>()) { if (m_data->host.has_value()) {
builder.append("//"sv); builder.append("//"sv);
builder.append(serialized_host().release_value_but_fixme_should_propagate_errors()); builder.append(serialized_host().release_value_but_fixme_should_propagate_errors());
if (m_data->port.has_value()) if (m_data->port.has_value())
@ -331,7 +331,7 @@ ByteString URL::serialize_for_display() const
if (cannot_be_a_base_url()) { if (cannot_be_a_base_url()) {
builder.append(m_data->paths[0]); builder.append(m_data->paths[0]);
} else { } else {
if (m_data->host.has<Empty>() && m_data->paths.size() > 1 && m_data->paths[0].is_empty()) if (!m_data->host.has_value() && m_data->paths.size() > 1 && m_data->paths[0].is_empty())
builder.append("/."sv); builder.append("/."sv);
for (auto& segment : m_data->paths) { for (auto& segment : m_data->paths) {
builder.append('/'); builder.append('/');
@ -391,7 +391,7 @@ Origin URL::origin() const
// -> "wss" // -> "wss"
if (scheme().is_one_of("ftp"sv, "http"sv, "https"sv, "ws"sv, "wss"sv)) { if (scheme().is_one_of("ftp"sv, "http"sv, "https"sv, "ws"sv, "wss"sv)) {
// Return the tuple origin (urls scheme, urls host, urls port, null). // Return the tuple origin (urls scheme, urls host, urls port, null).
return Origin(scheme().to_byte_string(), host(), port()); return Origin(scheme().to_byte_string(), host().value(), port());
} }
// -> "file" // -> "file"

View file

@ -83,7 +83,7 @@ public:
String const& scheme() const { return m_data->scheme; } String const& scheme() const { return m_data->scheme; }
String const& username() const { return m_data->username; } String const& username() const { return m_data->username; }
String const& password() const { return m_data->password; } String const& password() const { return m_data->password; }
Host const& host() const { return m_data->host; } Optional<Host> const& host() const { return m_data->host; }
ErrorOr<String> serialized_host() const; ErrorOr<String> serialized_host() const;
ByteString basename() const; ByteString basename() const;
Optional<String> const& query() const { return m_data->query; } Optional<String> const& query() const { return m_data->query; }
@ -171,7 +171,7 @@ private:
String password; String password;
// A URLs host is null or a host. It is initially null. // A URLs host is null or a host. It is initially null.
Host host; Optional<Host> host;
// A URLs port is either null or a 16-bit unsigned integer that identifies a networking port. It is initially null. // A URLs port is either null or a 16-bit unsigned integer that identifies a networking port. It is initially null.
Optional<u16> port; Optional<u16> port;

View file

@ -284,7 +284,7 @@ WebIDL::ExceptionOr<String> DOMURL::host() const
auto& url = m_url; auto& url = m_url;
// 2. If urls host is null, then return the empty string. // 2. If urls host is null, then return the empty string.
if (url.host().has<Empty>()) if (!url.host().has_value())
return String {}; return String {};
// 3. If urls port is null, return urls host, serialized. // 3. If urls port is null, return urls host, serialized.
@ -312,7 +312,7 @@ WebIDL::ExceptionOr<String> DOMURL::hostname() const
auto& vm = realm().vm(); auto& vm = realm().vm();
// 1. If thiss URLs host is null, then return the empty string. // 1. If thiss URLs host is null, then return the empty string.
if (m_url.host().has<Empty>()) if (!m_url.host().has_value())
return String {}; return String {};
// 2. Return thiss URLs host, serialized. // 2. Return thiss URLs host, serialized.
@ -477,6 +477,7 @@ void DOMURL::set_hash(String const& hash)
} }
// https://url.spec.whatwg.org/#concept-domain // https://url.spec.whatwg.org/#concept-domain
// FIXME: Move into URL::Host
bool host_is_domain(URL::Host const& host) bool host_is_domain(URL::Host const& host)
{ {
// A domain is a non-empty ASCII string that identifies a realm within a network. // A domain is a non-empty ASCII string that identifies a realm within a network.

View file

@ -322,7 +322,7 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
// - requests current URLs scheme is "http" // - requests current URLs scheme is "http"
request->current_url().scheme() == "http"sv request->current_url().scheme() == "http"sv
// - requests current URLs host is a domain // - requests current URLs host is a domain
&& DOMURL::host_is_domain(request->current_url().host()) && request->current_url().host().has_value() && DOMURL::host_is_domain(request->current_url().host().value())
// FIXME: - Matching requests current URLs host per Known HSTS Host Domain Name Matching results in either a // FIXME: - Matching requests current URLs host per Known HSTS Host Domain Name Matching results in either a
// superdomain match with an asserted includeSubDomains directive or a congruent match (with or without an // superdomain match with an asserted includeSubDomains directive or a congruent match (with or without an
// asserted includeSubDomains directive) [HSTS]; or DNS resolution for the request finds a matching HTTPS RR // asserted includeSubDomains directive) [HSTS]; or DNS resolution for the request finds a matching HTTPS RR

View file

@ -44,7 +44,7 @@ bool url_matches_about_blank(URL::URL const& url)
&& url.paths().size() == 1 && url.paths()[0] == "blank"sv && url.paths().size() == 1 && url.paths()[0] == "blank"sv
&& url.username().is_empty() && url.username().is_empty()
&& url.password().is_empty() && url.password().is_empty()
&& url.host().has<Empty>(); && !url.host().has_value();
} }
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#matches-about:srcdoc // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#matches-about:srcdoc
@ -56,7 +56,7 @@ bool url_matches_about_srcdoc(URL::URL const& url)
&& !url.query().has_value() && !url.query().has_value()
&& url.username().is_empty() && url.username().is_empty()
&& url.password().is_empty() && url.password().is_empty()
&& url.host().has<Empty>(); && !url.host().has_value();
} }
// https://html.spec.whatwg.org/multipage/document-sequences.html#determining-the-origin // https://html.spec.whatwg.org/multipage/document-sequences.html#determining-the-origin

View file

@ -167,7 +167,7 @@ String HTMLHyperlinkElementUtils::host() const
auto const& url = m_url; auto const& url = m_url;
// 3. If url or url's host is null, return the empty string. // 3. If url or url's host is null, return the empty string.
if (!url.has_value() || url->host().has<Empty>()) if (!url.has_value() || !url->host().has_value())
return String {}; return String {};
// 4. If url's port is null, return url's host, serialized. // 4. If url's port is null, return url's host, serialized.
@ -206,7 +206,8 @@ String HTMLHyperlinkElementUtils::hostname() const
URL::URL url(href()); URL::URL url(href());
// 3. If url or url's host is null, return the empty string. // 3. If url or url's host is null, return the empty string.
if (url.host().has<Empty>()) // FIXME: How can url be null here?
if (!url.host().has_value())
return String {}; return String {};
// 4. Return url's host, serialized. // 4. Return url's host, serialized.

View file

@ -203,7 +203,7 @@ WebIDL::ExceptionOr<String> Location::host() const
auto url = this->url(); auto url = this->url();
// 3. If url's host is null, return the empty string. // 3. If url's host is null, return the empty string.
if (url.host().has<Empty>()) if (!url.host().has_value())
return String {}; return String {};
// 4. If url's port is null, return url's host, serialized. // 4. If url's port is null, return url's host, serialized.
@ -233,7 +233,7 @@ WebIDL::ExceptionOr<String> Location::hostname() const
auto url = this->url(); auto url = this->url();
// 2. If this's url's host is null, return the empty string. // 2. If this's url's host is null, return the empty string.
if (url.host().has<Empty>()) if (!url.host().has_value())
return String {}; return String {};
// 3. Return this's url's host, serialized. // 3. Return this's url's host, serialized.

View file

@ -46,7 +46,7 @@ WebIDL::ExceptionOr<String> WorkerLocation::host() const
auto const& url = m_global_scope->url(); auto const& url = m_global_scope->url();
// 2. If url's host is null, return the empty string. // 2. If url's host is null, return the empty string.
if (url.host().has<Empty>()) if (!url.host().has_value())
return String {}; return String {};
// 3. If url's port is null, return url's host, serialized. // 3. If url's port is null, return url's host, serialized.
@ -67,11 +67,11 @@ WebIDL::ExceptionOr<String> WorkerLocation::hostname() const
auto const& host = m_global_scope->url().host(); auto const& host = m_global_scope->url().host();
// 2. If host is null, return the empty string. // 2. If host is null, return the empty string.
if (host.has<Empty>()) if (!host.has_value())
return String {}; return String {};
// 3. Return host, serialized. // 3. Return host, serialized.
return TRY_OR_THROW_OOM(vm, URL::Parser::serialize_host(host)); return TRY_OR_THROW_OOM(vm, URL::Parser::serialize_host(host.value()));
} }
// https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-port // https://html.spec.whatwg.org/multipage/workers.html#dom-workerlocation-port

View file

@ -20,7 +20,7 @@ void upgrade_a_mixed_content_request_to_a_potentially_trustworthy_url_if_appropr
SecureContexts::is_url_potentially_trustworthy(request.url()) == SecureContexts::Trustworthiness::PotentiallyTrustworthy SecureContexts::is_url_potentially_trustworthy(request.url()) == SecureContexts::Trustworthiness::PotentiallyTrustworthy
// 2. requests URLs host is an IP address. // 2. requests URLs host is an IP address.
|| request.url().host().has<URL::IPv4Address>() || request.url().host().has<URL::IPv6Address>() || (request.url().host().has_value() && (request.url().host()->has<URL::IPv4Address>() || request.url().host()->has<URL::IPv6Address>()))
// 3. §4.3 Does settings prohibit mixed security contexts? returns "Does Not Restrict Mixed Security Contents" when applied to requests client. // 3. §4.3 Does settings prohibit mixed security contexts? returns "Does Not Restrict Mixed Security Contents" when applied to requests client.
|| does_settings_prohibit_mixed_security_contexts(request.client()) == ProhibitsMixedSecurityContexts::DoesNotRestrictMixedSecurityContexts || does_settings_prohibit_mixed_security_contexts(request.client()) == ProhibitsMixedSecurityContexts::DoesNotRestrictMixedSecurityContexts

View file

@ -494,7 +494,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::open(String const& method_string, Stri
// NOTE: This is handled in the overload lacking the async argument. // NOTE: This is handled in the overload lacking the async argument.
// 8. If parsedURLs host is non-null, then: // 8. If parsedURLs host is non-null, then:
if (!parsed_url.host().has<Empty>()) { if (parsed_url.host().has_value()) {
// 1. If the username argument is not null, set the username given parsedURL and username. // 1. If the username argument is not null, set the username given parsedURL and username.
if (username.has_value()) if (username.has_value())
parsed_url.set_username(username.value()); parsed_url.set_username(username.value());

View file

@ -220,7 +220,7 @@ void CookieJar::expire_cookies_with_time_offset(AK::Duration offset)
// https://www.ietf.org/archive/id/draft-ietf-httpbis-rfc6265bis-15.html#section-5.1.2 // https://www.ietf.org/archive/id/draft-ietf-httpbis-rfc6265bis-15.html#section-5.1.2
Optional<String> CookieJar::canonicalize_domain(const URL::URL& url) Optional<String> CookieJar::canonicalize_domain(const URL::URL& url)
{ {
if (!url.is_valid() || url.host().has<Empty>()) if (!url.is_valid() || !url.host().has_value())
return {}; return {};
// 1. Convert the host name to a sequence of individual domain name labels. // 1. Convert the host name to a sequence of individual domain name labels.

View file

@ -570,7 +570,7 @@ void ViewImplementation::handle_web_content_process_crash(LoadErrorPage load_err
builder.append(escape_html_entities(m_url.to_byte_string())); builder.append(escape_html_entities(m_url.to_byte_string()));
builder.append("</title></head><body>"sv); builder.append("</title></head><body>"sv);
builder.append("<h1>Web page crashed"sv); builder.append("<h1>Web page crashed"sv);
if (!m_url.host().has<Empty>()) { if (m_url.host().has_value()) {
builder.appendff(" on {}", escape_html_entities(m_url.serialized_host().release_value_but_fixme_should_propagate_errors())); builder.appendff(" on {}", escape_html_entities(m_url.serialized_host().release_value_but_fixme_should_propagate_errors()));
} }
builder.append("</h1>"sv); builder.append("</h1>"sv);

View file

@ -206,7 +206,7 @@ TEST_CASE(about_url)
URL::URL url("about:blank"sv); URL::URL url("about:blank"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "about"); EXPECT_EQ(url.scheme(), "about");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize_path(), "blank"); EXPECT_EQ(url.serialize_path(), "blank");
EXPECT(!url.query().has_value()); EXPECT(!url.query().has_value());
EXPECT(!url.fragment().has_value()); EXPECT(!url.fragment().has_value());
@ -218,7 +218,7 @@ TEST_CASE(mailto_url)
URL::URL url("mailto:mail@example.com"sv); URL::URL url("mailto:mail@example.com"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "mailto"); EXPECT_EQ(url.scheme(), "mailto");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.port_or_default(), 0); EXPECT_EQ(url.port_or_default(), 0);
EXPECT_EQ(url.path_segment_count(), 1u); EXPECT_EQ(url.path_segment_count(), 1u);
EXPECT_EQ(url.path_segment_at_index(0), "mail@example.com"); EXPECT_EQ(url.path_segment_at_index(0), "mail@example.com");
@ -232,7 +232,7 @@ TEST_CASE(mailto_url_with_subject)
URL::URL url("mailto:mail@example.com?subject=test"sv); URL::URL url("mailto:mail@example.com?subject=test"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "mailto"); EXPECT_EQ(url.scheme(), "mailto");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.port_or_default(), 0); EXPECT_EQ(url.port_or_default(), 0);
EXPECT_EQ(url.path_segment_count(), 1u); EXPECT_EQ(url.path_segment_count(), 1u);
EXPECT_EQ(url.path_segment_at_index(0), "mail@example.com"); EXPECT_EQ(url.path_segment_at_index(0), "mail@example.com");

View file

@ -14,7 +14,7 @@ TEST_CASE(data_url)
URL::URL url("data:text/html,test"sv); URL::URL url("data:text/html,test"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data:text/html,test"); EXPECT_EQ(url.serialize(), "data:text/html,test");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -27,7 +27,7 @@ TEST_CASE(data_url_default_mime_type)
URL::URL url("data:,test"sv); URL::URL url("data:,test"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data:,test"); EXPECT_EQ(url.serialize(), "data:,test");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -40,7 +40,7 @@ TEST_CASE(data_url_encoded)
URL::URL url("data:text/html,Hello%20friends%2C%0X%X0"sv); URL::URL url("data:text/html,Hello%20friends%2C%0X%X0"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data:text/html,Hello%20friends%2C%0X%X0"); EXPECT_EQ(url.serialize(), "data:text/html,Hello%20friends%2C%0X%X0");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -53,7 +53,7 @@ TEST_CASE(data_url_base64_encoded)
URL::URL url("data:text/html;base64,dGVzdA=="sv); URL::URL url("data:text/html;base64,dGVzdA=="sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data:text/html;base64,dGVzdA=="); EXPECT_EQ(url.serialize(), "data:text/html;base64,dGVzdA==");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -66,7 +66,7 @@ TEST_CASE(data_url_base64_encoded_default_mime_type)
URL::URL url("data:;base64,dGVzdA=="sv); URL::URL url("data:;base64,dGVzdA=="sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data:;base64,dGVzdA=="); EXPECT_EQ(url.serialize(), "data:;base64,dGVzdA==");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -79,7 +79,7 @@ TEST_CASE(data_url_base64_encoded_with_whitespace)
URL::URL url("data: text/html ; bAsE64 , dGVz dA== "sv); URL::URL url("data: text/html ; bAsE64 , dGVz dA== "sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
EXPECT_EQ(url.serialize(), "data: text/html ; bAsE64 , dGVz dA=="); EXPECT_EQ(url.serialize(), "data: text/html ; bAsE64 , dGVz dA==");
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
@ -92,7 +92,7 @@ TEST_CASE(data_url_base64_encoded_with_inline_whitespace)
URL::URL url("data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207%20"sv); URL::URL url("data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207%20"sv);
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
EXPECT_EQ(data_url.mime_type.serialized(), "text/javascript"); EXPECT_EQ(data_url.mime_type.serialized(), "text/javascript");
@ -105,7 +105,7 @@ TEST_CASE(data_url_completed_with_fragment)
EXPECT(url.is_valid()); EXPECT(url.is_valid());
EXPECT_EQ(url.scheme(), "data"); EXPECT_EQ(url.scheme(), "data");
EXPECT_EQ(url.fragment(), "a"); EXPECT_EQ(url.fragment(), "a");
EXPECT(url.host().has<Empty>()); EXPECT(!url.host().has_value());
auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url)); auto data_url = TRY_OR_FAIL(Web::Fetch::Infrastructure::process_data_url(url));
EXPECT_EQ(data_url.mime_type.serialized(), "text/plain"); EXPECT_EQ(data_url.mime_type.serialized(), "text/plain");