Pārlūkot izejas kodu

LibWeb/CSS: Split out `@supports` parsing code

Sam Atkins 11 mēneši atpakaļ
vecāks
revīzija
e5737232c0

+ 42 - 24
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -1262,30 +1262,6 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr<Rule> 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<CSSRule*> 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> 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<CSSNamespaceRule> Parser::convert_to_namespace_rule(Rule& rule)
     return CSSNamespaceRule::create(m_context.realm(), prefix, namespace_uri);
 }
 
+JS::GCPtr<CSSSupportsRule> Parser::convert_to_supports_rule(Rule& rule)
+{
+    // https://drafts.csswg.org/css-conditional-3/#at-supports
+    // @supports <supports-condition> {
+    //   <rule-list>
+    // }
+
+    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<CSSRule*> 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<DeclarationOrAtRule> const& declarations_and_at_rules) -> PropertiesAndCustomProperties
 {
     PropertiesAndCustomProperties result;

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -224,6 +224,7 @@ private:
     CSSMediaRule* convert_to_media_rule(NonnullRefPtr<Rule>);
     JS::GCPtr<CSSImportRule> convert_to_import_rule(Rule&);
     JS::GCPtr<CSSNamespaceRule> convert_to_namespace_rule(Rule&);
+    JS::GCPtr<CSSSupportsRule> convert_to_supports_rule(Rule&);
 
     PropertyOwningCSSStyleDeclaration* convert_to_style_declaration(Vector<DeclarationOrAtRule> const& declarations);
     Optional<StyleProperty> convert_to_style_property(Declaration const&);