diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index b91a5484da8..9e34ce28264 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -183,7 +183,9 @@ 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); auto maybe_condition = parse_supports_condition(token_stream); + m_rule_context.take_last(); token_stream.discard_whitespace(); if (maybe_condition && !token_stream.has_next_token()) return Supports::create(m_context.realm(), maybe_condition.release_nonnull()); @@ -458,7 +460,9 @@ 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)); rule.child_rules_and_lists_of_declarations = consume_a_block(input); + m_rule_context.take_last(); // If rule is valid in the current context, return it. Otherwise, return nothing. if (is_valid_in_the_current_context(rule)) @@ -487,6 +491,12 @@ Variant Parser::consume_a_qualif .child_rules = {}, }; + // 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; + // Process input: for (;;) { auto& token = input.next_token(); @@ -532,7 +542,9 @@ Variant Parser::consume_a_qualif } // Otherwise, consume a block from input, and let child rules be the result. + m_rule_context.append(type_of_qualified_rule); rule.child_rules = consume_a_block(input); + m_rule_context.take_last(); // If the first item of child rules is a list of declarations, remove it from child rules and assign it to rule’s declarations. if (!rule.child_rules.is_empty() && rule.child_rules.first().has>()) { @@ -1077,7 +1089,9 @@ Vector Parser::parse_a_blocks_contents(TokenStream& Optional Parser::parse_as_supports_condition() { + m_rule_context.append(ContextType::SupportsCondition); auto maybe_declaration = parse_a_declaration(m_token_stream); + m_rule_context.take_last(); if (maybe_declaration.has_value()) return convert_to_style_property(maybe_declaration.release_value()); return {}; @@ -1198,7 +1212,10 @@ ElementInlineCSSStyleDeclaration* Parser::parse_as_style_attribute(DOM::Element& return expanded_properties; }; + m_rule_context.append(ContextType::Style); auto declarations_and_at_rules = parse_a_blocks_contents(m_token_stream); + m_rule_context.take_last(); + auto [properties, custom_properties] = extract_properties(declarations_and_at_rules); auto expanded_properties = expand_shorthands(properties); return ElementInlineCSSStyleDeclaration::create(element, move(expanded_properties), move(custom_properties)); @@ -1521,22 +1538,122 @@ RefPtr Parser::parse_basic_shape_value(TokenStream const& rules_and_lists_of_declarations) @@ -8987,4 +9104,21 @@ RefPtr Parser::parse_opentype_tag_value(TokenStream parse_layer_name(TokenStream&, AllowBlankLayerName); - bool is_valid_in_the_current_context(Declaration&); - bool is_valid_in_the_current_context(AtRule&); - bool is_valid_in_the_current_context(QualifiedRule&); + bool is_valid_in_the_current_context(Declaration const&) const; + bool is_valid_in_the_current_context(AtRule const&) const; + bool is_valid_in_the_current_context(QualifiedRule const&) const; JS::GCPtr convert_to_rule(Rule const&, Nested); JS::GCPtr convert_to_style_rule(QualifiedRule const&, Nested); JS::GCPtr convert_to_font_face_rule(AtRule const&); @@ -398,6 +398,21 @@ private: Vector m_tokens; TokenStream m_token_stream; + + 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; }; }