From 763b1b0ee29014dcc2d674944f4d6b1b2e905794 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 14 Apr 2025 17:10:20 +0100 Subject: [PATCH] LibWeb/CSS: Move RuleContext type out of Parser.h This was previously internal to the Parser, but we'd like to pass it in from outside. --- Libraries/LibWeb/CMakeLists.txt | 1 + Libraries/LibWeb/CSS/Parser/Parser.cpp | 100 ++++++++------------ Libraries/LibWeb/CSS/Parser/Parser.h | 18 +--- Libraries/LibWeb/CSS/Parser/RuleContext.cpp | 58 ++++++++++++ Libraries/LibWeb/CSS/Parser/RuleContext.h | 29 ++++++ Libraries/LibWeb/CSS/Parser/RuleParsing.cpp | 2 +- 6 files changed, 135 insertions(+), 73 deletions(-) create mode 100644 Libraries/LibWeb/CSS/Parser/RuleContext.cpp create mode 100644 Libraries/LibWeb/CSS/Parser/RuleContext.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index dc51681e714..ceebbbe3312 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -116,6 +116,7 @@ set(SOURCES CSS/Parser/MediaParsing.cpp CSS/Parser/Parser.cpp CSS/Parser/PropertyParsing.cpp + CSS/Parser/RuleContext.cpp CSS/Parser/RuleParsing.cpp CSS/Parser/SelectorParsing.cpp CSS/Parser/Token.cpp diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index b7d0f0c3077..5340242a9c2 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -81,6 +81,7 @@ Parser::Parser(ParsingParams const& context, Vector tokens) , m_parsing_mode(context.mode) , m_tokens(move(tokens)) , m_token_stream(m_tokens) + , m_rule_context(move(context.rule_context)) { } @@ -168,7 +169,7 @@ RefPtr Parser::parse_a_supports(TokenStream& tokens) { auto component_values = parse_a_list_of_component_values(tokens); TokenStream token_stream { component_values }; - m_rule_context.append(ContextType::SupportsCondition); + m_rule_context.append(RuleContext::SupportsCondition); auto maybe_condition = parse_boolean_expression(token_stream, MatchResult::False, [this](auto& tokens) { return parse_supports_feature(tokens); }); m_rule_context.take_last(); token_stream.discard_whitespace(); @@ -492,7 +493,7 @@ Optional Parser::consume_an_at_rule(TokenStream& input, Nested nested // <{-token> if (token.is(Token::Type::OpenCurly)) { // Consume a block from input, and assign the result to rule’s child rules. - m_rule_context.append(context_type_for_at_rule(rule.name)); + m_rule_context.append(rule_context_type_for_at_rule(rule.name)); rule.child_rules_and_lists_of_declarations = consume_a_block(input); m_rule_context.take_last(); @@ -525,9 +526,9 @@ Variant Parser::consume_a_qualif // NOTE: Qualified rules inside @keyframes are a keyframe rule. // We'll assume all others are style rules. - auto type_of_qualified_rule = (!m_rule_context.is_empty() && m_rule_context.last() == ContextType::AtKeyframes) - ? ContextType::Keyframe - : ContextType::Style; + auto type_of_qualified_rule = (!m_rule_context.is_empty() && m_rule_context.last() == RuleContext::AtKeyframes) + ? RuleContext::Keyframe + : RuleContext::Style; // Process input: for (;;) { @@ -1236,7 +1237,7 @@ Vector Parser::parse_a_blocks_contents(TokenStream& Optional Parser::parse_as_supports_condition() { - m_rule_context.append(ContextType::SupportsCondition); + m_rule_context.append(RuleContext::SupportsCondition); auto maybe_declaration = parse_a_declaration(m_token_stream); m_rule_context.take_last(); if (maybe_declaration.has_value()) @@ -1359,7 +1360,7 @@ Parser::PropertiesAndCustomProperties Parser::parse_as_property_declaration_bloc }; // 1. Let declarations be the returned declarations from invoking parse a block’s contents with string. - m_rule_context.append(ContextType::Style); + m_rule_context.append(RuleContext::Style); auto declarations_and_at_rules = parse_a_blocks_contents(m_token_stream); m_rule_context.take_last(); @@ -1392,9 +1393,9 @@ Vector Parser::parse_as_descriptor_declaration_block(AtRuleID at_rul auto context_type = [at_rule_id] { switch (at_rule_id) { case AtRuleID::FontFace: - return ContextType::AtFontFace; + return RuleContext::AtFontFace; case AtRuleID::Property: - return ContextType::AtProperty; + return RuleContext::AtProperty; } VERIFY_NOT_REACHED(); }(); @@ -1436,31 +1437,31 @@ bool Parser::is_valid_in_the_current_context(Declaration const&) const return false; switch (m_rule_context.last()) { - case ContextType::Unknown: + case RuleContext::Unknown: // If the context is an unknown type, we don't accept anything. return false; - case ContextType::Style: - case ContextType::Keyframe: + case RuleContext::Style: + case RuleContext::Keyframe: // Style and keyframe rules contain property declarations return true; - case ContextType::AtLayer: - case ContextType::AtMedia: - case ContextType::AtSupports: + case RuleContext::AtLayer: + case RuleContext::AtMedia: + case RuleContext::AtSupports: // Grouping rules can contain declarations if they are themselves inside a style rule - return m_rule_context.contains_slow(ContextType::Style); + return m_rule_context.contains_slow(RuleContext::Style); - case ContextType::AtFontFace: - case ContextType::AtProperty: + case RuleContext::AtFontFace: + case RuleContext::AtProperty: // @font-face and @property have descriptor declarations return true; - case ContextType::AtKeyframes: + case RuleContext::AtKeyframes: // @keyframes can only contain keyframe rules return false; - case ContextType::SupportsCondition: + case RuleContext::SupportsCondition: // @supports conditions accept all declarations return true; } @@ -1475,32 +1476,32 @@ bool Parser::is_valid_in_the_current_context(AtRule const& at_rule) const return true; // Only grouping rules can be nested within style rules - if (m_rule_context.contains_slow(ContextType::Style)) + if (m_rule_context.contains_slow(RuleContext::Style)) return first_is_one_of(at_rule.name, "layer", "media", "supports"); switch (m_rule_context.last()) { - case ContextType::Unknown: + case RuleContext::Unknown: // If the context is an unknown type, we don't accept anything. return false; - case ContextType::Style: + case RuleContext::Style: // Already handled above VERIFY_NOT_REACHED(); - case ContextType::AtLayer: - case ContextType::AtMedia: - case ContextType::AtSupports: + case RuleContext::AtLayer: + case RuleContext::AtMedia: + case RuleContext::AtSupports: // Grouping rules can contain anything except @import or @namespace return !first_is_one_of(at_rule.name, "import", "namespace"); - case ContextType::SupportsCondition: + case RuleContext::SupportsCondition: // @supports cannot check for at-rules return false; - case ContextType::AtFontFace: - case ContextType::AtKeyframes: - case ContextType::Keyframe: - case ContextType::AtProperty: + case RuleContext::AtFontFace: + case RuleContext::AtKeyframes: + case RuleContext::Keyframe: + case RuleContext::AtProperty: // These can't contain any at-rules return false; } @@ -1517,31 +1518,31 @@ bool Parser::is_valid_in_the_current_context(QualifiedRule const&) const return true; switch (m_rule_context.last()) { - case ContextType::Unknown: + case RuleContext::Unknown: // If the context is an unknown type, we don't accept anything. return false; - case ContextType::Style: + case RuleContext::Style: // Style rules can contain style rules return true; - case ContextType::AtLayer: - case ContextType::AtMedia: - case ContextType::AtSupports: + case RuleContext::AtLayer: + case RuleContext::AtMedia: + case RuleContext::AtSupports: // Grouping rules can contain style rules return true; - case ContextType::AtKeyframes: + case RuleContext::AtKeyframes: // @keyframes can contain keyframe rules return true; - case ContextType::SupportsCondition: + case RuleContext::SupportsCondition: // @supports cannot check qualified rules return false; - case ContextType::AtFontFace: - case ContextType::AtProperty: - case ContextType::Keyframe: + case RuleContext::AtFontFace: + case RuleContext::AtProperty: + case RuleContext::Keyframe: // These can't contain qualified rules return false; } @@ -1786,23 +1787,6 @@ bool Parser::has_ignored_vendor_prefix(StringView string) return true; } -Parser::ContextType Parser::context_type_for_at_rule(FlyString const& name) -{ - if (name == "media") - return ContextType::AtMedia; - if (name == "font-face") - return ContextType::AtFontFace; - if (name == "keyframes") - return ContextType::AtKeyframes; - if (name == "supports") - return ContextType::AtSupports; - if (name == "layer") - return ContextType::AtLayer; - if (name == "property") - return ContextType::AtProperty; - return ContextType::Unknown; -} - template Parser::ParsedStyleSheet Parser::parse_a_stylesheet(TokenStream&, Optional<::URL::URL>); template Parser::ParsedStyleSheet Parser::parse_a_stylesheet(TokenStream&, Optional<::URL::URL>); diff --git a/Libraries/LibWeb/CSS/Parser/Parser.h b/Libraries/LibWeb/CSS/Parser/Parser.h index a37c4ed2a2a..71a630edbd6 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Libraries/LibWeb/CSS/Parser/Parser.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,8 @@ struct ParsingParams { GC::Ptr document; ::URL::URL url; ParsingMode mode { ParsingMode::Normal }; + + Vector rule_context; }; // The very large CSS Parser implementation code is broken up among several .cpp files: @@ -499,20 +502,7 @@ private: } bool context_allows_quirky_length() const; - enum class ContextType { - Unknown, - Style, - AtMedia, - AtFontFace, - AtKeyframes, - Keyframe, - AtSupports, - SupportsCondition, - AtLayer, - AtProperty, - }; - static ContextType context_type_for_at_rule(FlyString const&); - Vector m_rule_context; + Vector m_rule_context; Vector m_pseudo_class_context; // Stack of pseudo-class functions we're currently inside }; diff --git a/Libraries/LibWeb/CSS/Parser/RuleContext.cpp b/Libraries/LibWeb/CSS/Parser/RuleContext.cpp new file mode 100644 index 00000000000..330bfaada8c --- /dev/null +++ b/Libraries/LibWeb/CSS/Parser/RuleContext.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::CSS::Parser { + +RuleContext rule_context_type_for_rule(CSSRule::Type rule_type) +{ + switch (rule_type) { + case CSSRule::Type::Style: + return RuleContext::Style; + case CSSRule::Type::Media: + return RuleContext::AtMedia; + case CSSRule::Type::FontFace: + return RuleContext::AtFontFace; + case CSSRule::Type::Keyframes: + return RuleContext::AtKeyframes; + case CSSRule::Type::Keyframe: + return RuleContext::Keyframe; + case CSSRule::Type::Supports: + return RuleContext::AtSupports; + case CSSRule::Type::LayerBlock: + return RuleContext::AtLayer; + case CSSRule::Type::NestedDeclarations: + return RuleContext::Style; + case CSSRule::Type::Property: + return RuleContext::AtProperty; + // Other types shouldn't be trying to create a context. + case CSSRule::Type::Import: + case CSSRule::Type::LayerStatement: + case CSSRule::Type::Namespace: + break; + } + VERIFY_NOT_REACHED(); +} + +RuleContext rule_context_type_for_at_rule(FlyString const& name) +{ + if (name == "media") + return RuleContext::AtMedia; + if (name == "font-face") + return RuleContext::AtFontFace; + if (name == "keyframes") + return RuleContext::AtKeyframes; + if (name == "supports") + return RuleContext::AtSupports; + if (name == "layer") + return RuleContext::AtLayer; + if (name == "property") + return RuleContext::AtProperty; + return RuleContext::Unknown; +} + +} diff --git a/Libraries/LibWeb/CSS/Parser/RuleContext.h b/Libraries/LibWeb/CSS/Parser/RuleContext.h new file mode 100644 index 00000000000..db402b07aed --- /dev/null +++ b/Libraries/LibWeb/CSS/Parser/RuleContext.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS::Parser { + +enum class RuleContext : u8 { + Unknown, + Style, + AtMedia, + AtFontFace, + AtKeyframes, + Keyframe, + AtSupports, + SupportsCondition, + AtLayer, + AtProperty, +}; +RuleContext rule_context_type_for_rule(CSSRule::Type); +RuleContext rule_context_type_for_at_rule(FlyString const&); + +} diff --git a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp index 50c4b8253ae..b3e85ae81e2 100644 --- a/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/RuleParsing.cpp @@ -171,7 +171,7 @@ GC::Ptr Parser::convert_to_import_rule(AtRule const& rule) if (supports_tokens.next_token().is_block()) { supports = parse_a_supports(supports_tokens); } else { - m_rule_context.append(ContextType::SupportsCondition); + m_rule_context.append(RuleContext::SupportsCondition); auto declaration = consume_a_declaration(supports_tokens); m_rule_context.take_last(); if (declaration.has_value()) {