diff --git a/Libraries/LibWeb/CSS/CSSImportRule.cpp b/Libraries/LibWeb/CSS/CSSImportRule.cpp index f0cc8d7fa8d..ec99bdfe1f3 100644 --- a/Libraries/LibWeb/CSS/CSSImportRule.cpp +++ b/Libraries/LibWeb/CSS/CSSImportRule.cpp @@ -23,17 +23,18 @@ namespace Web::CSS { GC_DEFINE_ALLOCATOR(CSSImportRule); -GC::Ref CSSImportRule::create(URL::URL url, DOM::Document& document, RefPtr supports) +GC::Ref CSSImportRule::create(URL::URL url, DOM::Document& document, RefPtr supports, Vector> media_query_list) { auto& realm = document.realm(); - return realm.create(move(url), document, supports); + return realm.create(move(url), document, supports, move(media_query_list)); } -CSSImportRule::CSSImportRule(URL::URL url, DOM::Document& document, RefPtr supports) +CSSImportRule::CSSImportRule(URL::URL url, DOM::Document& document, RefPtr supports, Vector> media_query_list) : CSSRule(document.realm(), Type::Import) , m_url(move(url)) , m_document(document) , m_supports(supports) + , m_media_query_list(move(media_query_list)) { } @@ -76,7 +77,9 @@ String CSSImportRule::serialized() const if (m_supports) builder.appendff(" supports({})", m_supports->to_string()); - // FIXME: 3. If the rule’s associated media list is not empty, a single SPACE (U+0020) followed by the result of performing serialize a media query list on the media list. + // 3. If the rule’s associated media list is not empty, a single SPACE (U+0020) followed by the result of performing serialize a media query list on the media list. + if (!m_media_query_list.is_empty()) + builder.appendff(" {}", serialize_a_media_query_list(m_media_query_list)); // 4. The string ";", i.e., SEMICOLON (U+003B). builder.append(';'); @@ -148,7 +151,7 @@ void CSSImportRule::fetch() } auto decoded = decoded_or_error.release_value(); - auto* imported_style_sheet = parse_css_stylesheet(Parser::ParsingParams(*strong_this->m_document, strong_this->url()), decoded, strong_this->url()); + auto* imported_style_sheet = parse_css_stylesheet(Parser::ParsingParams(*strong_this->m_document, strong_this->url()), decoded, strong_this->url(), strong_this->m_media_query_list); // 5. Set importedStylesheet’s origin-clean flag to parentStylesheet’s origin-clean flag. imported_style_sheet->set_origin_clean(parent_style_sheet->is_origin_clean()); diff --git a/Libraries/LibWeb/CSS/CSSImportRule.h b/Libraries/LibWeb/CSS/CSSImportRule.h index e6989188074..8b51b5a11e5 100644 --- a/Libraries/LibWeb/CSS/CSSImportRule.h +++ b/Libraries/LibWeb/CSS/CSSImportRule.h @@ -21,7 +21,7 @@ class CSSImportRule final GC_DECLARE_ALLOCATOR(CSSImportRule); public: - [[nodiscard]] static GC::Ref create(URL::URL, DOM::Document&, RefPtr); + [[nodiscard]] static GC::Ref create(URL::URL, DOM::Document&, RefPtr, Vector>); virtual ~CSSImportRule() = default; @@ -36,7 +36,7 @@ public: Optional supports_text() const; private: - CSSImportRule(URL::URL, DOM::Document&, RefPtr); + CSSImportRule(URL::URL, DOM::Document&, RefPtr, Vector>); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; @@ -51,6 +51,7 @@ private: URL::URL m_url; GC::Ptr m_document; RefPtr m_supports; + Vector> m_media_query_list; GC::Ptr m_style_sheet; Optional m_document_load_event_delayer; }; diff --git a/Libraries/LibWeb/CSS/Parser/Helpers.cpp b/Libraries/LibWeb/CSS/Parser/Helpers.cpp index c24ecf70bba..6d11fb205b5 100644 --- a/Libraries/LibWeb/CSS/Parser/Helpers.cpp +++ b/Libraries/LibWeb/CSS/Parser/Helpers.cpp @@ -42,7 +42,7 @@ GC::Ref internal_css_realm() return *realm; } -CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingParams const& context, StringView css, Optional location) +CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingParams const& context, StringView css, Optional location, Vector> media_query_list) { if (css.is_empty()) { auto rule_list = CSS::CSSRuleList::create_empty(*context.realm); @@ -51,7 +51,7 @@ CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingParams const& conte style_sheet->set_source_text({}); return style_sheet; } - auto* style_sheet = CSS::Parser::Parser::create(context, css).parse_as_css_stylesheet(location); + auto* style_sheet = CSS::Parser::Parser::create(context, css).parse_as_css_stylesheet(location, move(media_query_list)); // FIXME: Avoid this copy style_sheet->set_source_text(MUST(String::from_utf8(css))); return style_sheet; diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index a5a6d121204..77451073a78 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -119,7 +119,7 @@ Vector Parser::parse_a_stylesheets_contents(TokenStream& input) } // https://drafts.csswg.org/css-syntax/#parse-a-css-stylesheet -CSSStyleSheet* Parser::parse_as_css_stylesheet(Optional location) +CSSStyleSheet* Parser::parse_as_css_stylesheet(Optional location, Vector> media_query_list) { // To parse a CSS stylesheet, first parse a stylesheet. auto const& style_sheet = parse_a_stylesheet(m_token_stream, {}); @@ -138,7 +138,7 @@ CSSStyleSheet* Parser::parse_as_css_stylesheet(Optional location) } auto rule_list = CSSRuleList::create(realm(), rules); - auto media_list = MediaList::create(realm(), {}); + auto media_list = MediaList::create(realm(), move(media_query_list)); return CSSStyleSheet::create(realm(), rule_list, media_list, move(location)); } diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index 21ef0446c0c..73b4e1cbf6a 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -87,7 +87,7 @@ class Parser { public: static Parser create(ParsingParams const&, StringView input, StringView encoding = "utf-8"sv); - CSSStyleSheet* parse_as_css_stylesheet(Optional location); + CSSStyleSheet* parse_as_css_stylesheet(Optional location, Vector> media_query_list = {}); struct PropertiesAndCustomProperties { Vector properties; @@ -512,7 +512,7 @@ private: namespace Web { -CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingParams const&, StringView, Optional location = {}); +CSS::CSSStyleSheet* parse_css_stylesheet(CSS::Parser::ParsingParams const&, StringView, Optional location = {}, Vector> = {}); CSS::Parser::Parser::PropertiesAndCustomProperties parse_css_style_attribute(CSS::Parser::ParsingParams const&, StringView); RefPtr parse_css_value(CSS::Parser::ParsingParams const&, StringView, CSS::PropertyID property_id = CSS::PropertyID::Invalid); Optional parse_selector(CSS::Parser::ParsingParams const&, StringView); diff --git a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp index 153b5085ccc..a18455ad8f9 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp @@ -180,7 +180,7 @@ GC::Ptr Parser::convert_to_import_rule(AtRule const& rule) } } - // FIXME: Implement media query support. + auto media_query_list = parse_a_media_query_list(tokens); if (tokens.has_next_token()) { if constexpr (CSS_PARSER_DEBUG) { @@ -190,7 +190,7 @@ GC::Ptr Parser::convert_to_import_rule(AtRule const& rule) return {}; } - return CSSImportRule::create(url.value(), const_cast(*document()), supports); + return CSSImportRule::create(url.value(), const_cast(*document()), supports, move(media_query_list)); } Optional Parser::parse_layer_name(TokenStream& tokens, AllowBlankLayerName allow_blank_layer_name) diff --git a/Tests/LibWeb/Ref/input/wpt-import/css/css-cascade/import-conditional-001.html b/Tests/LibWeb/Ref/input/wpt-import/css/css-cascade/import-conditional-001.html new file mode 100644 index 00000000000..21eb2c56b0c --- /dev/null +++ b/Tests/LibWeb/Ref/input/wpt-import/css/css-cascade/import-conditional-001.html @@ -0,0 +1,32 @@ + + + + + CSS Cascade: @import with basic media query + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
FAIL
+ +