From 7f2c833a39e150c7372299dcfe4d2d5590ae779f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 14 Jun 2024 17:04:56 +0200 Subject: [PATCH] LibWeb: Implement CSSKeyframesRule.cssRuleList To make this straightforward, CSSKeyframesRule now uses a CSSRuleList for internal storage. --- .../Text/expected/css/keyframes-css-rules.txt | 5 +++++ .../Text/input/css/keyframes-css-rules.html | 17 +++++++++++++++++ Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h | 1 + .../Libraries/LibWeb/CSS/CSSKeyframesRule.cpp | 17 ++++++++++++----- .../Libraries/LibWeb/CSS/CSSKeyframesRule.h | 14 ++++++++------ .../Libraries/LibWeb/CSS/CSSKeyframesRule.idl | 2 +- Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 4 ++-- Userland/Libraries/LibWeb/CSS/StyleComputer.cpp | 12 ++++-------- 8 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt create mode 100644 Tests/LibWeb/Text/input/css/keyframes-css-rules.html diff --git a/Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt b/Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt new file mode 100644 index 00000000000..3af11a131fc --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt @@ -0,0 +1,5 @@ +fooRule: [object CSSKeyframesRule] ~ @keyframes "foo" { 0% { color: rgb(0, 0, 0); } 100% { color: rgb(255, 255, 255); } } +fooRule.cssRules: [object CSSRuleList] +fooRule.cssRules[0]: [object CSSKeyframeRule] ~ 0% { color: rgb(0, 0, 0); } +fooRule.cssRules[0].style.parentRule: [object CSSKeyframeRule] ~ 0% { color: rgb(0, 0, 0); } +fooRule.cssRules[0].style.parentRule === fooRule.cssRules[0]: true diff --git a/Tests/LibWeb/Text/input/css/keyframes-css-rules.html b/Tests/LibWeb/Text/input/css/keyframes-css-rules.html new file mode 100644 index 00000000000..249cace53fb --- /dev/null +++ b/Tests/LibWeb/Text/input/css/keyframes-css-rules.html @@ -0,0 +1,17 @@ + + + diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h index bac207ead9d..74958a9284b 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframeRule.h @@ -29,6 +29,7 @@ public: CSS::Percentage key() const { return m_key; } JS::NonnullGCPtr style() const { return m_declarations; } + JS::NonnullGCPtr style_as_property_owning_style_declaration() const { return m_declarations; } String key_text() const { diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.cpp index 74ce66884f6..3fff7ffc8c8 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.cpp @@ -1,26 +1,28 @@ /* * Copyright (c) 2023, Ali Mohammad Pur + * Copyright (c) 2024, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ -#include "CSSKeyframesRule.h" #include #include +#include +#include namespace Web::CSS { JS_DEFINE_ALLOCATOR(CSSKeyframesRule); -JS::NonnullGCPtr CSSKeyframesRule::create(JS::Realm& realm, FlyString name, JS::MarkedVector> keyframes) +JS::NonnullGCPtr CSSKeyframesRule::create(JS::Realm& realm, FlyString name, JS::NonnullGCPtr css_rules) { - return realm.heap().allocate(realm, realm, move(name), move(keyframes)); + return realm.heap().allocate(realm, realm, move(name), move(css_rules)); } void CSSKeyframesRule::visit_edges(Visitor& visitor) { Base::visit_edges(visitor); - visitor.visit(m_keyframes); + visitor.visit(m_rules); } void CSSKeyframesRule::initialize(JS::Realm& realm) @@ -34,7 +36,7 @@ String CSSKeyframesRule::serialized() const StringBuilder builder; builder.appendff("@keyframes \"{}\"", name()); builder.append(" { "sv); - for (auto const& keyframe : keyframes()) { + for (auto const& keyframe : *m_rules) { builder.append(keyframe->css_text()); builder.append(' '); } @@ -42,4 +44,9 @@ String CSSKeyframesRule::serialized() const return MUST(builder.to_string()); } +WebIDL::UnsignedLong CSSKeyframesRule::length() const +{ + return m_rules->length(); +} + } diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.h b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.h index b95a53c5bbb..f1863d11549 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Ali Mohammad Pur + * Copyright (c) 2024, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,6 +14,7 @@ #include #include #include +#include namespace Web::CSS { @@ -22,23 +24,23 @@ class CSSKeyframesRule final : public CSSRule { JS_DECLARE_ALLOCATOR(CSSKeyframesRule); public: - [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString name, JS::MarkedVector>); + [[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&, FlyString name, JS::NonnullGCPtr); virtual ~CSSKeyframesRule() = default; virtual Type type() const override { return Type::Keyframes; } - Vector> const& keyframes() const { return m_keyframes; } + auto const& css_rules() const { return m_rules; } FlyString const& name() const { return m_name; } - size_t length() { return m_keyframes.size(); } + [[nodiscard]] WebIDL::UnsignedLong length() const; void set_name(String const& name) { m_name = name; } private: - CSSKeyframesRule(JS::Realm& realm, FlyString name, JS::MarkedVector> keyframes) + CSSKeyframesRule(JS::Realm& realm, FlyString name, JS::NonnullGCPtr keyframes) : CSSRule(realm) , m_name(move(name)) - , m_keyframes(move(keyframes)) + , m_rules(move(keyframes)) { } @@ -48,7 +50,7 @@ private: virtual String serialized() const override; FlyString m_name; - Vector> m_keyframes; + JS::NonnullGCPtr m_rules; }; template<> diff --git a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.idl b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.idl index f1aab1c311b..c6aea702c96 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.idl +++ b/Userland/Libraries/LibWeb/CSS/CSSKeyframesRule.idl @@ -5,7 +5,7 @@ [Exposed=Window] interface CSSKeyframesRule : CSSRule { attribute CSSOMString name; - [FIXME] readonly attribute CSSRuleList cssRules; + readonly attribute CSSRuleList cssRules; readonly attribute unsigned long length; getter CSSKeyframeRule (unsigned long index); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 71a256c25a2..04978565260 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -1349,7 +1349,7 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr rule) auto child_tokens = TokenStream { rule->block()->values() }; - JS::MarkedVector> keyframes(m_context.realm().heap()); + JS::MarkedVector keyframes(m_context.realm().heap()); while (child_tokens.has_next_token()) { child_tokens.skip_whitespace(); // keyframe-selector = | @@ -1415,7 +1415,7 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr rule) } } - return CSSKeyframesRule::create(m_context.realm(), name, move(keyframes)); + return CSSKeyframesRule::create(m_context.realm(), name, CSSRuleList::create(m_context.realm(), move(keyframes))); } if (rule->at_rule_name().equals_ignoring_ascii_case("namespace"sv)) { // https://drafts.csswg.org/css-namespaces/#syntax diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index abba7c9506b..d0feffa7cdd 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -2553,16 +2553,12 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca HashTable animated_properties; // Forwards pass, resolve all the user-specified keyframe properties. - for (auto const& keyframe : rule.keyframes()) { + for (auto const& keyframe_rule : *rule.css_rules()) { + auto const& keyframe = verify_cast(*keyframe_rule); Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame resolved_keyframe; - auto key = static_cast(keyframe->key().value() * Animations::KeyframeEffect::AnimationKeyFrameKeyScaleFactor); - auto keyframe_rule = keyframe->style(); - - if (!is(*keyframe_rule)) - continue; - - auto const& keyframe_style = static_cast(*keyframe_rule); + auto key = static_cast(keyframe.key().value() * Animations::KeyframeEffect::AnimationKeyFrameKeyScaleFactor); + auto const& keyframe_style = *keyframe.style_as_property_owning_style_declaration(); for (auto const& it : keyframe_style.properties()) { // Unresolved properties will be resolved in collect_animation_into() for_each_property_expanding_shorthands(it.property_id, it.value, AllowUnresolved::Yes, [&](PropertyID shorthand_id, StyleValue const& shorthand_value) {