From 43950c73428a4de9661ace9fe4f7ea561df4518e Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Thu, 10 Apr 2025 12:09:39 +0100 Subject: [PATCH] LibWeb/CSS: Make fetch_a_style_resource() work with no CSSStyleSheet See the spec issue in the comments for details. There are situations where we will need to call this but don't have a CSSStyleSheet to pass in, but we always have a Document, so use that where possible. --- Libraries/LibWeb/CSS/CSSImportRule.cpp | 2 +- Libraries/LibWeb/CSS/Fetch.cpp | 24 +++++++++++++++++------- Libraries/LibWeb/CSS/Fetch.h | 5 ++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Libraries/LibWeb/CSS/CSSImportRule.cpp b/Libraries/LibWeb/CSS/CSSImportRule.cpp index 13cdf57750f..cfc23407446 100644 --- a/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -116,7 +116,7 @@ void CSSImportRule::fetch() m_document_load_event_delayer.emplace(*m_document); // 4. Fetch a style resource from parsedUrl, with stylesheet parentStylesheet, destination "style", CORS mode "no-cors", and processResponse being the following steps given response response and byte stream, null or failure byteStream: - fetch_a_style_resource(parsed_url.value(), parent_style_sheet, Fetch::Infrastructure::Request::Destination::Style, CorsMode::NoCors, + fetch_a_style_resource(parsed_url.value(), { parent_style_sheet }, Fetch::Infrastructure::Request::Destination::Style, CorsMode::NoCors, [strong_this = GC::Ref { *this }, parent_style_sheet = GC::Ref { parent_style_sheet }, parsed_url = parsed_url.value()](auto response, auto maybe_byte_stream) { // AD-HOC: Stop delaying the load event. ScopeGuard guard = [strong_this] { diff --git a/Libraries/LibWeb/CSS/Fetch.cpp b/Libraries/LibWeb/CSS/Fetch.cpp index b11db422bb1..e8cf9ecdf8d 100644 --- a/Libraries/LibWeb/CSS/Fetch.cpp +++ b/Libraries/LibWeb/CSS/Fetch.cpp @@ -7,20 +7,26 @@ #include #include #include +#include #include namespace Web::CSS { // https://drafts.csswg.org/css-values-4/#fetch-a-style-resource -void fetch_a_style_resource(StyleResourceURL const& url_value, CSSStyleSheet const& sheet, Fetch::Infrastructure::Request::Destination destination, CorsMode cors_mode, Fetch::Infrastructure::FetchAlgorithms::ProcessResponseConsumeBodyFunction process_response) +void fetch_a_style_resource(StyleResourceURL const& url_value, StyleSheetOrDocument sheet_or_document, Fetch::Infrastructure::Request::Destination destination, CorsMode cors_mode, Fetch::Infrastructure::FetchAlgorithms::ProcessResponseConsumeBodyFunction process_response) { - auto& vm = sheet.vm(); + // AD-HOC: Not every caller has a CSSStyleSheet, so allow passing a Document in instead for URL completion. + // Spec issue: https://github.com/w3c/csswg-drafts/issues/12065 + + auto& vm = sheet_or_document.visit([](auto& it) -> JS::VM& { return it->vm(); }); // 1. Let environmentSettings be sheet’s relevant settings object. - auto& environment_settings = HTML::relevant_settings_object(sheet); + auto& environment_settings = HTML::relevant_settings_object(sheet_or_document.visit([](auto& it) -> JS::Object& { return it; })); // 2. Let base be sheet’s stylesheet base URL if it is not null, otherwise environmentSettings’s API base URL. [CSSOM] - auto base = sheet.base_url().value_or(environment_settings.api_base_url()); + auto base = sheet_or_document.visit( + [&](GC::Ref const& sheet) { return sheet->base_url().value_or(environment_settings.api_base_url()); }, + [](GC::Ref const& document) { return document->base_url(); }); // 3. Let parsedUrl be the result of the URL parser steps with urlValue’s url and base. If the algorithm returns an error, return. auto url_string = url_value.visit( @@ -47,11 +53,15 @@ void fetch_a_style_resource(StyleResourceURL const& url_value, CSSStyleSheet con // FIXME: No specs seem to define these yet. When they do, implement them. // 6. If req’s mode is "cors", set req’s referrer to sheet’s location. [CSSOM] - if (request->mode() == Fetch::Infrastructure::Request::Mode::CORS) - request->set_referrer(sheet.location().value()); + if (request->mode() == Fetch::Infrastructure::Request::Mode::CORS) { + auto location = sheet_or_document.visit( + [](GC::Ref const& sheet) { return sheet->location().value(); }, + [](GC::Ref const& document) { return document->url(); }); + request->set_referrer(move(location)); + } // 7. If sheet’s origin-clean flag is set, set req’s initiator type to "css". [CSSOM] - if (sheet.is_origin_clean()) + if (auto* sheet = sheet_or_document.get_pointer>(); sheet && (*sheet)->is_origin_clean()) request->set_initiator_type(Fetch::Infrastructure::Request::InitiatorType::CSS); // 8. Fetch req, with processresponseconsumebody set to processResponse. diff --git a/Libraries/LibWeb/CSS/Fetch.h b/Libraries/LibWeb/CSS/Fetch.h index f39d5b2d8b5..4e0c648b5ea 100644 --- a/Libraries/LibWeb/CSS/Fetch.h +++ b/Libraries/LibWeb/CSS/Fetch.h @@ -20,7 +20,10 @@ enum class CorsMode { using StyleResourceURL = Variant<::URL::URL, CSS::URL>; +// AD-HOC: See comment inside fetch_a_style_resource() implementation. +using StyleSheetOrDocument = Variant, GC::Ref>; + // https://drafts.csswg.org/css-values-4/#fetch-a-style-resource -void fetch_a_style_resource(StyleResourceURL const& url, CSSStyleSheet const&, Fetch::Infrastructure::Request::Destination, CorsMode, Fetch::Infrastructure::FetchAlgorithms::ProcessResponseConsumeBodyFunction process_response); +void fetch_a_style_resource(StyleResourceURL const& url, StyleSheetOrDocument, Fetch::Infrastructure::Request::Destination, CorsMode, Fetch::Infrastructure::FetchAlgorithms::ProcessResponseConsumeBodyFunction process_response); }