From 84a695c958d82bf32dfc4db83676f3a07215ee31 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Thu, 13 Mar 2025 16:04:48 +0000 Subject: [PATCH] LibWeb/CSS: Evaluate Supports query components during parsing Instead of parsing the parts of a `@supports` query, then only evaluating them when constructing the Supports itself, we can instead evaluate them as we parse them. This simplifies things as we no longer need to pass a Realm around, and don't have to re-parse the conditions again with a new Parser instance. --- Libraries/LibWeb/CSS/Parser/Helpers.cpp | 7 ----- Libraries/LibWeb/CSS/Parser/Parser.cpp | 11 +++++-- Libraries/LibWeb/CSS/Parser/Parser.h | 1 - Libraries/LibWeb/CSS/Supports.cpp | 39 +++++++++---------------- Libraries/LibWeb/CSS/Supports.h | 22 +++++++------- 5 files changed, 32 insertions(+), 48 deletions(-) diff --git a/Libraries/LibWeb/CSS/Parser/Helpers.cpp b/Libraries/LibWeb/CSS/Parser/Helpers.cpp index 9478d33139a..c503f65ba7d 100644 --- a/Libraries/LibWeb/CSS/Parser/Helpers.cpp +++ b/Libraries/LibWeb/CSS/Parser/Helpers.cpp @@ -87,11 +87,4 @@ RefPtr parse_css_supports(CSS::Parser::ParsingParams const& conte return CSS::Parser::Parser::create(context, string).parse_as_supports(); } -Optional parse_css_supports_condition(CSS::Parser::ParsingParams const& context, StringView string) -{ - if (string.is_empty()) - return {}; - return CSS::Parser::Parser::create(context, string).parse_as_supports_condition(); -} - } diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index c606f8aefbc..aee37269670 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -154,7 +154,7 @@ RefPtr Parser::parse_a_supports(TokenStream& tokens) m_rule_context.take_last(); token_stream.discard_whitespace(); if (maybe_condition && !token_stream.has_next_token()) - return Supports::create(realm(), maybe_condition.release_nonnull()); + return Supports::create(maybe_condition.release_nonnull()); return {}; } @@ -279,7 +279,9 @@ Optional Parser::parse_supports_feature(TokenStreamto_string() } + Supports::Declaration { + declaration->to_string(), + convert_to_style_property(*declaration).has_value() } }; } } @@ -291,8 +293,11 @@ Optional Parser::parse_supports_feature(TokenStream parse_media_query(CSS::Parser::ParsingParams const&, StringView); Vector> parse_media_query_list(CSS::Parser::ParsingParams const&, StringView); RefPtr parse_css_supports(CSS::Parser::ParsingParams const&, StringView); -Optional parse_css_supports_condition(CSS::Parser::ParsingParams const&, StringView); } diff --git a/Libraries/LibWeb/CSS/Supports.cpp b/Libraries/LibWeb/CSS/Supports.cpp index 5f97ada429a..2106524c40e 100644 --- a/Libraries/LibWeb/CSS/Supports.cpp +++ b/Libraries/LibWeb/CSS/Supports.cpp @@ -1,11 +1,10 @@ /* - * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #include -#include #include namespace Web::CSS { @@ -16,26 +15,26 @@ static void indent(StringBuilder& builder, int levels) builder.append(" "sv); } -Supports::Supports(JS::Realm& realm, NonnullOwnPtr&& condition) +Supports::Supports(NonnullOwnPtr&& condition) : m_condition(move(condition)) { - m_matches = m_condition->evaluate(realm); + m_matches = m_condition->evaluate(); } -bool Supports::Condition::evaluate(JS::Realm& realm) const +bool Supports::Condition::evaluate() const { switch (type) { case Type::Not: - return !children.first().evaluate(realm); + return !children.first().evaluate(); case Type::And: for (auto& child : children) { - if (!child.evaluate(realm)) + if (!child.evaluate()) return false; } return true; case Type::Or: for (auto& child : children) { - if (child.evaluate(realm)) + if (child.evaluate()) return true; } return false; @@ -43,40 +42,28 @@ bool Supports::Condition::evaluate(JS::Realm& realm) const VERIFY_NOT_REACHED(); } -bool Supports::InParens::evaluate(JS::Realm& realm) const +bool Supports::InParens::evaluate() const { return value.visit( [&](NonnullOwnPtr const& condition) { - return condition->evaluate(realm); + return condition->evaluate(); }, [&](Feature const& feature) { - return feature.evaluate(realm); + return feature.evaluate(); }, [&](GeneralEnclosed const&) { return false; }); } -bool Supports::Declaration::evaluate(JS::Realm& realm) const -{ - auto style_property = parse_css_supports_condition(Parser::ParsingParams { realm }, declaration); - return style_property.has_value(); -} - -bool Supports::Selector::evaluate(JS::Realm& realm) const -{ - auto style_property = parse_selector(Parser::ParsingParams { realm }, selector); - return style_property.has_value(); -} - -bool Supports::Feature::evaluate(JS::Realm& realm) const +bool Supports::Feature::evaluate() const { return value.visit( [&](Declaration const& declaration) { - return declaration.evaluate(realm); + return declaration.evaluate(); }, [&](Selector const& selector) { - return selector.evaluate(realm); + return selector.evaluate(); }); } diff --git a/Libraries/LibWeb/CSS/Supports.h b/Libraries/LibWeb/CSS/Supports.h index 2bd3cb8e098..913ceb24c4b 100644 --- a/Libraries/LibWeb/CSS/Supports.h +++ b/Libraries/LibWeb/CSS/Supports.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2021-2025, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -17,26 +17,26 @@ namespace Web::CSS { // https://www.w3.org/TR/css-conditional-3/#at-supports class Supports final : public RefCounted { - friend class Parser::Parser; - public: struct Declaration { String declaration; - [[nodiscard]] bool evaluate(JS::Realm&) const; + bool matches; + [[nodiscard]] bool evaluate() const { return matches; } String to_string() const; void dump(StringBuilder&, int indent_levels = 0) const; }; struct Selector { String selector; - [[nodiscard]] bool evaluate(JS::Realm&) const; + bool matches; + [[nodiscard]] bool evaluate() const { return matches; } String to_string() const; void dump(StringBuilder&, int indent_levels = 0) const; }; struct Feature { Variant value; - [[nodiscard]] bool evaluate(JS::Realm&) const; + [[nodiscard]] bool evaluate() const; String to_string() const; void dump(StringBuilder&, int indent_levels = 0) const; }; @@ -45,7 +45,7 @@ public: struct InParens { Variant, Feature, GeneralEnclosed> value; - [[nodiscard]] bool evaluate(JS::Realm&) const; + [[nodiscard]] bool evaluate() const; String to_string() const; void dump(StringBuilder&, int indent_levels = 0) const; }; @@ -59,14 +59,14 @@ public: Type type; Vector children; - [[nodiscard]] bool evaluate(JS::Realm&) const; + [[nodiscard]] bool evaluate() const; String to_string() const; void dump(StringBuilder&, int indent_levels = 0) const; }; - static NonnullRefPtr create(JS::Realm& realm, NonnullOwnPtr&& condition) + static NonnullRefPtr create(NonnullOwnPtr&& condition) { - return adopt_ref(*new Supports(realm, move(condition))); + return adopt_ref(*new Supports(move(condition))); } bool matches() const { return m_matches; } @@ -75,7 +75,7 @@ public: void dump(StringBuilder&, int indent_levels = 0) const; private: - Supports(JS::Realm&, NonnullOwnPtr&&); + Supports(NonnullOwnPtr&&); NonnullOwnPtr m_condition; bool m_matches { false };