mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 03:25:13 +00:00
LibURL+LibWeb: Port URL::complete_url to Optional
Removing one more source of the URL::is_valid API.
This commit is contained in:
parent
356728b1e0
commit
53826995f6
Notes:
github-actions[bot]
2025-02-15 17:07:12 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/53826995f61 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3586 Reviewed-by: https://github.com/tcl3 ✅
14 changed files with 57 additions and 52 deletions
|
@ -33,16 +33,12 @@ URL::URL(StringView string)
|
|||
}
|
||||
}
|
||||
|
||||
URL URL::complete_url(StringView relative_url) const
|
||||
Optional<URL> URL::complete_url(StringView relative_url) const
|
||||
{
|
||||
if (!is_valid())
|
||||
return {};
|
||||
|
||||
auto result = Parser::basic_parse(relative_url, *this);
|
||||
if (!result.has_value())
|
||||
return {};
|
||||
|
||||
return result.release_value();
|
||||
return Parser::basic_parse(relative_url, *this);
|
||||
}
|
||||
|
||||
ByteString URL::path_segment_at_index(size_t index) const
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
|
||||
bool equals(URL const& other, ExcludeFragment = ExcludeFragment::No) const;
|
||||
|
||||
URL complete_url(StringView) const;
|
||||
Optional<URL> complete_url(StringView) const;
|
||||
|
||||
[[nodiscard]] bool operator==(URL const& other) const
|
||||
{
|
||||
|
|
|
@ -45,8 +45,8 @@ WebIDL::ExceptionOr<GC::Ref<CSSStyleSheet>> CSSStyleSheet::construct_impl(JS::Re
|
|||
sheet_location_url = sheet->location().release_value();
|
||||
|
||||
// AD-HOC: This isn't explicitly mentioned in the specification, but multiple modern browsers do this.
|
||||
URL::URL url = sheet->location().has_value() ? sheet_location_url->complete_url(options->base_url.value()) : options->base_url.value();
|
||||
if (!url.is_valid())
|
||||
Optional<URL::URL> url = sheet->location().has_value() ? sheet_location_url->complete_url(options->base_url.value()) : options->base_url.value();
|
||||
if (!url.has_value())
|
||||
return WebIDL::NotAllowedError::create(realm, "Constructed style sheets must have a valid base URL"_string);
|
||||
|
||||
sheet->set_base_url(url);
|
||||
|
|
|
@ -1761,7 +1761,7 @@ bool Parser::is_parsing_svg_presentation_attribute() const
|
|||
|
||||
// https://www.w3.org/TR/css-values-4/#relative-urls
|
||||
// FIXME: URLs shouldn't be completed during parsing, but when used.
|
||||
URL::URL Parser::complete_url(StringView relative_url) const
|
||||
Optional<URL::URL> Parser::complete_url(StringView relative_url) const
|
||||
{
|
||||
return m_url.complete_url(relative_url);
|
||||
}
|
||||
|
|
|
@ -460,7 +460,7 @@ private:
|
|||
JS::Realm& realm() const;
|
||||
bool in_quirks_mode() const;
|
||||
bool is_parsing_svg_presentation_attribute() const;
|
||||
URL::URL complete_url(StringView) const;
|
||||
Optional<URL::URL> complete_url(StringView) const;
|
||||
|
||||
GC::Ptr<DOM::Document const> m_document;
|
||||
GC::Ptr<JS::Realm> m_realm;
|
||||
|
|
|
@ -2470,7 +2470,7 @@ Optional<URL::URL> Parser::parse_url_function(TokenStream<ComponentValue>& token
|
|||
|
||||
auto convert_string_to_url = [&](StringView url_string) -> Optional<URL::URL> {
|
||||
auto url = complete_url(url_string);
|
||||
if (url.is_valid()) {
|
||||
if (url.has_value()) {
|
||||
transaction.commit();
|
||||
return url;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,9 @@ String FormAssociatedElement::form_action() const
|
|||
}
|
||||
|
||||
auto document_base_url = html_element.document().base_url();
|
||||
return document_base_url.complete_url(form_action_attribute.value()).to_string();
|
||||
if (auto maybe_url = document_base_url.complete_url(form_action_attribute.value()); maybe_url.has_value())
|
||||
return maybe_url->to_string();
|
||||
return {};
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<void> FormAssociatedElement::set_form_action(String const& value)
|
||||
|
|
|
@ -74,12 +74,12 @@ void HTMLBaseElement::set_the_frozen_base_url()
|
|||
|
||||
// 3. Set element's frozen base URL to document's fallback base URL, if urlRecord is failure or running Is base allowed for Document? on the resulting URL record and document returns "Blocked", and to urlRecord otherwise.
|
||||
// FIXME: Apply "Is base allowed for Document?" CSP
|
||||
if (!url_record.is_valid()) {
|
||||
if (!url_record.has_value()) {
|
||||
m_frozen_base_url = document.fallback_base_url();
|
||||
return;
|
||||
}
|
||||
|
||||
m_frozen_base_url = move(url_record);
|
||||
m_frozen_base_url = url_record.release_value();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/semantics.html#dom-base-href
|
||||
|
@ -96,11 +96,11 @@ String HTMLBaseElement::href() const
|
|||
auto url_record = document.fallback_base_url().complete_url(url);
|
||||
|
||||
// 4. If urlRecord is failure, return url.
|
||||
if (!url_record.is_valid())
|
||||
if (!url_record.has_value())
|
||||
return url;
|
||||
|
||||
// 5. Return the serialization of urlRecord.
|
||||
return url_record.to_string();
|
||||
return url_record->to_string();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/semantics.html#dom-base-href
|
||||
|
|
|
@ -619,7 +619,9 @@ String HTMLFormElement::action() const
|
|||
return document().url_string();
|
||||
}
|
||||
|
||||
return document().base_url().complete_url(form_action_attribute.value()).to_string();
|
||||
if (auto maybe_url = document().base_url().complete_url(form_action_attribute.value()); maybe_url.has_value())
|
||||
return maybe_url->to_string();
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-fs-action
|
||||
|
|
|
@ -25,7 +25,9 @@ GC::Ptr<SVGGeometryElement const> SVGTextPathElement::path_or_shape() const
|
|||
if (!href.has_value())
|
||||
return {};
|
||||
auto url = document().url().complete_url(*href);
|
||||
return try_resolve_url_to<SVGGeometryElement const>(url);
|
||||
if (!url.has_value())
|
||||
return {};
|
||||
return try_resolve_url_to<SVGGeometryElement const>(*url);
|
||||
}
|
||||
|
||||
void SVGTextPathElement::initialize(JS::Realm& realm)
|
||||
|
|
|
@ -79,19 +79,19 @@ void SVGUseElement::process_the_url(Optional<String> const& href)
|
|||
// a same-document URL reference, and processing the URL must continue as indicated in Identifying
|
||||
// the target element with the current document as the referenced document.
|
||||
m_href = document().url().complete_url(href.value_or(String {}));
|
||||
if (!m_href.is_valid())
|
||||
if (!m_href.has_value())
|
||||
return;
|
||||
|
||||
if (is_referrenced_element_same_document()) {
|
||||
clone_element_tree_as_our_shadow_tree(referenced_element());
|
||||
} else {
|
||||
fetch_the_document(m_href);
|
||||
fetch_the_document(*m_href);
|
||||
}
|
||||
}
|
||||
|
||||
bool SVGUseElement::is_referrenced_element_same_document() const
|
||||
{
|
||||
return m_href.equals(document().url(), URL::ExcludeFragment::Yes);
|
||||
return m_href->equals(document().url(), URL::ExcludeFragment::Yes);
|
||||
}
|
||||
|
||||
Gfx::AffineTransform SVGUseElement::element_transform() const
|
||||
|
@ -121,11 +121,11 @@ void SVGUseElement::svg_element_changed(SVGElement& svg_element)
|
|||
|
||||
void SVGUseElement::svg_element_removed(SVGElement& svg_element)
|
||||
{
|
||||
if (!m_href.fragment().has_value() || !is_referrenced_element_same_document()) {
|
||||
if (!m_href.has_value() || !m_href->fragment().has_value() || !is_referrenced_element_same_document()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AK::StringUtils::matches(svg_element.get_attribute_value("id"_fly_string), m_href.fragment().value())) {
|
||||
if (AK::StringUtils::matches(svg_element.get_attribute_value("id"_fly_string), m_href->fragment().value())) {
|
||||
shadow_root()->remove_all_children();
|
||||
}
|
||||
}
|
||||
|
@ -133,14 +133,17 @@ void SVGUseElement::svg_element_removed(SVGElement& svg_element)
|
|||
// https://svgwg.org/svg2-draft/linking.html#processingURL-target
|
||||
GC::Ptr<DOM::Element> SVGUseElement::referenced_element()
|
||||
{
|
||||
if (!m_href.is_valid())
|
||||
if (!m_href.has_value())
|
||||
return nullptr;
|
||||
|
||||
if (!m_href.fragment().has_value())
|
||||
if (!m_href->is_valid())
|
||||
return nullptr;
|
||||
|
||||
if (!m_href->fragment().has_value())
|
||||
return nullptr;
|
||||
|
||||
if (is_referrenced_element_same_document())
|
||||
return document().get_element_by_id(*m_href.fragment());
|
||||
return document().get_element_by_id(*m_href->fragment());
|
||||
|
||||
if (!m_resource_request)
|
||||
return nullptr;
|
||||
|
@ -149,7 +152,7 @@ GC::Ptr<DOM::Element> SVGUseElement::referenced_element()
|
|||
if (!data || !is<SVG::SVGDecodedImageData>(*data))
|
||||
return nullptr;
|
||||
|
||||
return as<SVG::SVGDecodedImageData>(*data).svg_document().get_element_by_id(*m_href.fragment());
|
||||
return as<SVG::SVGDecodedImageData>(*data).svg_document().get_element_by_id(*m_href->fragment());
|
||||
}
|
||||
|
||||
// https://svgwg.org/svg2-draft/linking.html#processingURL-fetch
|
||||
|
|
|
@ -65,7 +65,7 @@ private:
|
|||
Optional<float> m_x;
|
||||
Optional<float> m_y;
|
||||
|
||||
URL::URL m_href;
|
||||
Optional<URL::URL> m_href;
|
||||
|
||||
GC::Ptr<DOM::DocumentObserver> m_document_observer;
|
||||
GC::Ptr<HTML::SharedResourceRequest> m_resource_request;
|
||||
|
|
|
@ -195,10 +195,10 @@ TEST_CASE(file_url_serialization)
|
|||
|
||||
TEST_CASE(file_url_relative)
|
||||
{
|
||||
EXPECT_EQ(URL::URL("https://vkoskiv.com/index.html"sv).complete_url("/static/foo.js"sv).serialize(), "https://vkoskiv.com/static/foo.js");
|
||||
EXPECT_EQ(URL::URL("file:///home/vkoskiv/test/index.html"sv).complete_url("/static/foo.js"sv).serialize(), "file:///static/foo.js");
|
||||
EXPECT_EQ(URL::URL("https://vkoskiv.com/index.html"sv).complete_url("static/foo.js"sv).serialize(), "https://vkoskiv.com/static/foo.js");
|
||||
EXPECT_EQ(URL::URL("file:///home/vkoskiv/test/index.html"sv).complete_url("static/foo.js"sv).serialize(), "file:///home/vkoskiv/test/static/foo.js");
|
||||
EXPECT_EQ(URL::URL("https://vkoskiv.com/index.html"sv).complete_url("/static/foo.js"sv)->serialize(), "https://vkoskiv.com/static/foo.js");
|
||||
EXPECT_EQ(URL::URL("file:///home/vkoskiv/test/index.html"sv).complete_url("/static/foo.js"sv)->serialize(), "file:///static/foo.js");
|
||||
EXPECT_EQ(URL::URL("https://vkoskiv.com/index.html"sv).complete_url("static/foo.js"sv)->serialize(), "https://vkoskiv.com/static/foo.js");
|
||||
EXPECT_EQ(URL::URL("file:///home/vkoskiv/test/index.html"sv).complete_url("static/foo.js"sv)->serialize(), "file:///home/vkoskiv/test/static/foo.js");
|
||||
}
|
||||
|
||||
TEST_CASE(about_url)
|
||||
|
@ -243,10 +243,10 @@ TEST_CASE(mailto_url_with_subject)
|
|||
|
||||
TEST_CASE(trailing_slash_with_complete_url)
|
||||
{
|
||||
EXPECT_EQ(URL::URL("http://a/b/"sv).complete_url("c/"sv).serialize(), "http://a/b/c/");
|
||||
EXPECT_EQ(URL::URL("http://a/b/"sv).complete_url("c"sv).serialize(), "http://a/b/c");
|
||||
EXPECT_EQ(URL::URL("http://a/b"sv).complete_url("c/"sv).serialize(), "http://a/c/");
|
||||
EXPECT_EQ(URL::URL("http://a/b"sv).complete_url("c"sv).serialize(), "http://a/c");
|
||||
EXPECT_EQ(URL::URL("http://a/b/"sv).complete_url("c/"sv)->serialize(), "http://a/b/c/");
|
||||
EXPECT_EQ(URL::URL("http://a/b/"sv).complete_url("c"sv)->serialize(), "http://a/b/c");
|
||||
EXPECT_EQ(URL::URL("http://a/b"sv).complete_url("c/"sv)->serialize(), "http://a/c/");
|
||||
EXPECT_EQ(URL::URL("http://a/b"sv).complete_url("c"sv)->serialize(), "http://a/c");
|
||||
}
|
||||
|
||||
TEST_CASE(trailing_port)
|
||||
|
@ -297,15 +297,15 @@ TEST_CASE(create_with_file_scheme)
|
|||
TEST_CASE(complete_url)
|
||||
{
|
||||
URL::URL base_url("http://serenityos.org/index.html#fragment"sv);
|
||||
URL::URL url = base_url.complete_url("test.html"sv);
|
||||
EXPECT(url.is_valid());
|
||||
EXPECT_EQ(url.scheme(), "http");
|
||||
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);
|
||||
auto url = base_url.complete_url("test.html"sv);
|
||||
EXPECT(url.has_value());
|
||||
EXPECT_EQ(url->scheme(), "http");
|
||||
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(base_url.complete_url("../index.html#fragment"sv).equals(base_url));
|
||||
EXPECT(base_url.complete_url("../index.html#fragment"sv)->equals(base_url));
|
||||
}
|
||||
|
||||
TEST_CASE(leading_whitespace)
|
||||
|
@ -385,8 +385,8 @@ TEST_CASE(complete_file_url_with_base)
|
|||
EXPECT_EQ(url.path_segment_at_index(1), "index.html");
|
||||
|
||||
auto sub_url = url.complete_url("js/app.js"sv);
|
||||
EXPECT(sub_url.is_valid());
|
||||
EXPECT_EQ(sub_url.serialize_path(), "/home/js/app.js");
|
||||
EXPECT(sub_url.has_value());
|
||||
EXPECT_EQ(sub_url->serialize_path(), "/home/js/app.js");
|
||||
}
|
||||
|
||||
TEST_CASE(empty_url_with_base_url)
|
||||
|
|
|
@ -102,12 +102,12 @@ TEST_CASE(data_url_base64_encoded_with_inline_whitespace)
|
|||
TEST_CASE(data_url_completed_with_fragment)
|
||||
{
|
||||
auto url = URL::URL("data:text/plain,test"sv).complete_url("#a"sv);
|
||||
EXPECT(url.is_valid());
|
||||
EXPECT_EQ(url.scheme(), "data");
|
||||
EXPECT_EQ(url.fragment(), "a");
|
||||
EXPECT(!url.host().has_value());
|
||||
EXPECT(url.has_value());
|
||||
EXPECT_EQ(url->scheme(), "data");
|
||||
EXPECT_EQ(url->fragment(), "a");
|
||||
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(StringView(data_url.body.bytes()), "test"sv);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue