From e5737232c059c1a1d6eabaf2560832599343a6fb Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 9 Aug 2024 12:47:24 +0100 Subject: [PATCH] LibWeb/CSS: Split out `@supports` parsing code --- .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 66 ++++++++++++------- Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 1 + 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index d68b96a29a9..2256f80f94c 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1262,30 +1262,6 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr rule) if (rule->at_rule_name().equals_ignoring_ascii_case("media"sv)) return convert_to_media_rule(rule); - if (rule->at_rule_name().equals_ignoring_ascii_case("supports"sv)) { - auto supports_tokens = TokenStream { rule->prelude() }; - auto supports = parse_a_supports(supports_tokens); - if (!supports) { - if constexpr (CSS_PARSER_DEBUG) { - dbgln_if(CSS_PARSER_DEBUG, "CSSParser: @supports rule invalid; discarding."); - supports_tokens.dump_all_tokens(); - } - return {}; - } - - if (!rule->block()) - return {}; - auto child_tokens = TokenStream { rule->block()->values() }; - auto parser_rules = parse_a_list_of_rules(child_tokens); - JS::MarkedVector child_rules(m_context.realm().heap()); - for (auto& raw_rule : parser_rules) { - if (auto* child_rule = convert_to_rule(raw_rule)) - child_rules.append(child_rule); - } - - auto rule_list = CSSRuleList::create(m_context.realm(), child_rules); - return CSSSupportsRule::create(m_context.realm(), supports.release_nonnull(), rule_list); - } if (rule->at_rule_name().equals_ignoring_ascii_case("keyframes"sv)) { auto prelude_stream = TokenStream { rule->prelude() }; prelude_stream.skip_whitespace(); @@ -1392,6 +1368,9 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr rule) if (rule->at_rule_name().equals_ignoring_ascii_case("namespace"sv)) return convert_to_namespace_rule(rule); + if (rule->at_rule_name().equals_ignoring_ascii_case("supports"sv)) + return convert_to_supports_rule(rule); + // FIXME: More at rules! dbgln_if(CSS_PARSER_DEBUG, "Unrecognized CSS at-rule: @{}", rule->at_rule_name()); return {}; @@ -1527,6 +1506,45 @@ JS::GCPtr Parser::convert_to_namespace_rule(Rule& rule) return CSSNamespaceRule::create(m_context.realm(), prefix, namespace_uri); } +JS::GCPtr Parser::convert_to_supports_rule(Rule& rule) +{ + // https://drafts.csswg.org/css-conditional-3/#at-supports + // @supports { + // + // } + + if (rule.prelude().is_empty()) { + dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @supports rule: Empty prelude."); + return {}; + } + + if (!rule.block()) { + dbgln_if(CSS_PARSER_DEBUG, "Failed to parse @supports rule: No block."); + return {}; + } + + auto supports_tokens = TokenStream { rule.prelude() }; + auto supports = parse_a_supports(supports_tokens); + if (!supports) { + if constexpr (CSS_PARSER_DEBUG) { + dbgln("Failed to parse @supports rule: supports clause invalid."); + supports_tokens.dump_all_tokens(); + } + return {}; + } + + auto child_tokens = TokenStream { rule.block()->values() }; + auto parser_rules = parse_a_list_of_rules(child_tokens); + JS::MarkedVector child_rules { m_context.realm().heap() }; + for (auto& raw_rule : parser_rules) { + if (auto* child_rule = convert_to_rule(raw_rule)) + child_rules.append(child_rule); + } + + auto rule_list = CSSRuleList::create(m_context.realm(), child_rules); + return CSSSupportsRule::create(m_context.realm(), supports.release_nonnull(), rule_list); +} + auto Parser::extract_properties(Vector const& declarations_and_at_rules) -> PropertiesAndCustomProperties { PropertiesAndCustomProperties result; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index a1011b25792..2b2ab3a44e2 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -224,6 +224,7 @@ private: CSSMediaRule* convert_to_media_rule(NonnullRefPtr); JS::GCPtr convert_to_import_rule(Rule&); JS::GCPtr convert_to_namespace_rule(Rule&); + JS::GCPtr convert_to_supports_rule(Rule&); PropertyOwningCSSStyleDeclaration* convert_to_style_declaration(Vector const& declarations); Optional convert_to_style_property(Declaration const&);