mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
LibWeb: Implement CSSKeyframesRule.cssRuleList
To make this straightforward, CSSKeyframesRule now uses a CSSRuleList for internal storage.
This commit is contained in:
parent
a12d28fd30
commit
7f2c833a39
Notes:
sideshowbarker
2024-07-17 05:01:20 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/7f2c833a39 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/168
8 changed files with 50 additions and 22 deletions
5
Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt
Normal file
5
Tests/LibWeb/Text/expected/css/keyframes-css-rules.txt
Normal file
|
@ -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
|
17
Tests/LibWeb/Text/input/css/keyframes-css-rules.html
Normal file
17
Tests/LibWeb/Text/input/css/keyframes-css-rules.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<style>
|
||||||
|
@keyframes foo {
|
||||||
|
from { color: black; }
|
||||||
|
to { color: white; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const fooRule = document.styleSheets[0].cssRules[0];
|
||||||
|
println("fooRule: " + fooRule + " ~ " + fooRule.cssText);
|
||||||
|
println("fooRule.cssRules: " + fooRule.cssRules);
|
||||||
|
println("fooRule.cssRules[0]: " + fooRule.cssRules[0] + " ~ " + fooRule.cssRules[0].cssText);
|
||||||
|
println("fooRule.cssRules[0].style.parentRule: " + fooRule.cssRules[0].style.parentRule + " ~ " + fooRule.cssRules[0].style.parentRule.cssText);
|
||||||
|
println("fooRule.cssRules[0].style.parentRule === fooRule.cssRules[0]: " + (fooRule.cssRules[0].style.parentRule === fooRule.cssRules[0]));
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -29,6 +29,7 @@ public:
|
||||||
|
|
||||||
CSS::Percentage key() const { return m_key; }
|
CSS::Percentage key() const { return m_key; }
|
||||||
JS::NonnullGCPtr<CSSStyleDeclaration> style() const { return m_declarations; }
|
JS::NonnullGCPtr<CSSStyleDeclaration> style() const { return m_declarations; }
|
||||||
|
JS::NonnullGCPtr<PropertyOwningCSSStyleDeclaration> style_as_property_owning_style_declaration() const { return m_declarations; }
|
||||||
|
|
||||||
String key_text() const
|
String key_text() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
|
* Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||||
|
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CSSKeyframesRule.h"
|
|
||||||
#include <LibWeb/Bindings/CSSKeyframesRulePrototype.h>
|
#include <LibWeb/Bindings/CSSKeyframesRulePrototype.h>
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
|
#include <LibWeb/CSS/CSSKeyframesRule.h>
|
||||||
|
#include <LibWeb/CSS/CSSRuleList.h>
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
JS_DEFINE_ALLOCATOR(CSSKeyframesRule);
|
JS_DEFINE_ALLOCATOR(CSSKeyframesRule);
|
||||||
|
|
||||||
JS::NonnullGCPtr<CSSKeyframesRule> CSSKeyframesRule::create(JS::Realm& realm, FlyString name, JS::MarkedVector<JS::NonnullGCPtr<CSSKeyframeRule>> keyframes)
|
JS::NonnullGCPtr<CSSKeyframesRule> CSSKeyframesRule::create(JS::Realm& realm, FlyString name, JS::NonnullGCPtr<CSSRuleList> css_rules)
|
||||||
{
|
{
|
||||||
return realm.heap().allocate<CSSKeyframesRule>(realm, realm, move(name), move(keyframes));
|
return realm.heap().allocate<CSSKeyframesRule>(realm, realm, move(name), move(css_rules));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSSKeyframesRule::visit_edges(Visitor& visitor)
|
void CSSKeyframesRule::visit_edges(Visitor& visitor)
|
||||||
{
|
{
|
||||||
Base::visit_edges(visitor);
|
Base::visit_edges(visitor);
|
||||||
visitor.visit(m_keyframes);
|
visitor.visit(m_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSSKeyframesRule::initialize(JS::Realm& realm)
|
void CSSKeyframesRule::initialize(JS::Realm& realm)
|
||||||
|
@ -34,7 +36,7 @@ String CSSKeyframesRule::serialized() const
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
builder.appendff("@keyframes \"{}\"", name());
|
builder.appendff("@keyframes \"{}\"", name());
|
||||||
builder.append(" { "sv);
|
builder.append(" { "sv);
|
||||||
for (auto const& keyframe : keyframes()) {
|
for (auto const& keyframe : *m_rules) {
|
||||||
builder.append(keyframe->css_text());
|
builder.append(keyframe->css_text());
|
||||||
builder.append(' ');
|
builder.append(' ');
|
||||||
}
|
}
|
||||||
|
@ -42,4 +44,9 @@ String CSSKeyframesRule::serialized() const
|
||||||
return MUST(builder.to_string());
|
return MUST(builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebIDL::UnsignedLong CSSKeyframesRule::length() const
|
||||||
|
{
|
||||||
|
return m_rules->length();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
|
* Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||||
|
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include <LibWeb/CSS/CSSRule.h>
|
#include <LibWeb/CSS/CSSRule.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||||
|
#include <LibWeb/WebIDL/Types.h>
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
@ -22,23 +24,23 @@ class CSSKeyframesRule final : public CSSRule {
|
||||||
JS_DECLARE_ALLOCATOR(CSSKeyframesRule);
|
JS_DECLARE_ALLOCATOR(CSSKeyframesRule);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static JS::NonnullGCPtr<CSSKeyframesRule> create(JS::Realm&, FlyString name, JS::MarkedVector<JS::NonnullGCPtr<CSSKeyframeRule>>);
|
[[nodiscard]] static JS::NonnullGCPtr<CSSKeyframesRule> create(JS::Realm&, FlyString name, JS::NonnullGCPtr<CSSRuleList>);
|
||||||
|
|
||||||
virtual ~CSSKeyframesRule() = default;
|
virtual ~CSSKeyframesRule() = default;
|
||||||
|
|
||||||
virtual Type type() const override { return Type::Keyframes; }
|
virtual Type type() const override { return Type::Keyframes; }
|
||||||
|
|
||||||
Vector<JS::NonnullGCPtr<CSSKeyframeRule>> const& keyframes() const { return m_keyframes; }
|
auto const& css_rules() const { return m_rules; }
|
||||||
FlyString const& name() const { return m_name; }
|
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; }
|
void set_name(String const& name) { m_name = name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CSSKeyframesRule(JS::Realm& realm, FlyString name, JS::MarkedVector<JS::NonnullGCPtr<CSSKeyframeRule>> keyframes)
|
CSSKeyframesRule(JS::Realm& realm, FlyString name, JS::NonnullGCPtr<CSSRuleList> keyframes)
|
||||||
: CSSRule(realm)
|
: CSSRule(realm)
|
||||||
, m_name(move(name))
|
, m_name(move(name))
|
||||||
, m_keyframes(move(keyframes))
|
, m_rules(move(keyframes))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ private:
|
||||||
virtual String serialized() const override;
|
virtual String serialized() const override;
|
||||||
|
|
||||||
FlyString m_name;
|
FlyString m_name;
|
||||||
Vector<JS::NonnullGCPtr<CSSKeyframeRule>> m_keyframes;
|
JS::NonnullGCPtr<CSSRuleList> m_rules;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
[Exposed=Window]
|
[Exposed=Window]
|
||||||
interface CSSKeyframesRule : CSSRule {
|
interface CSSKeyframesRule : CSSRule {
|
||||||
attribute CSSOMString name;
|
attribute CSSOMString name;
|
||||||
[FIXME] readonly attribute CSSRuleList cssRules;
|
readonly attribute CSSRuleList cssRules;
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
|
|
||||||
getter CSSKeyframeRule (unsigned long index);
|
getter CSSKeyframeRule (unsigned long index);
|
||||||
|
|
|
@ -1349,7 +1349,7 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr<Rule> rule)
|
||||||
|
|
||||||
auto child_tokens = TokenStream { rule->block()->values() };
|
auto child_tokens = TokenStream { rule->block()->values() };
|
||||||
|
|
||||||
JS::MarkedVector<JS::NonnullGCPtr<CSSKeyframeRule>> keyframes(m_context.realm().heap());
|
JS::MarkedVector<CSSRule*> keyframes(m_context.realm().heap());
|
||||||
while (child_tokens.has_next_token()) {
|
while (child_tokens.has_next_token()) {
|
||||||
child_tokens.skip_whitespace();
|
child_tokens.skip_whitespace();
|
||||||
// keyframe-selector = <keyframe-keyword> | <percentage>
|
// keyframe-selector = <keyframe-keyword> | <percentage>
|
||||||
|
@ -1415,7 +1415,7 @@ CSSRule* Parser::convert_to_rule(NonnullRefPtr<Rule> 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)) {
|
if (rule->at_rule_name().equals_ignoring_ascii_case("namespace"sv)) {
|
||||||
// https://drafts.csswg.org/css-namespaces/#syntax
|
// https://drafts.csswg.org/css-namespaces/#syntax
|
||||||
|
|
|
@ -2553,16 +2553,12 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
|
||||||
HashTable<PropertyID> animated_properties;
|
HashTable<PropertyID> animated_properties;
|
||||||
|
|
||||||
// Forwards pass, resolve all the user-specified keyframe 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<CSSKeyframeRule>(*keyframe_rule);
|
||||||
Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame resolved_keyframe;
|
Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame resolved_keyframe;
|
||||||
|
|
||||||
auto key = static_cast<u64>(keyframe->key().value() * Animations::KeyframeEffect::AnimationKeyFrameKeyScaleFactor);
|
auto key = static_cast<u64>(keyframe.key().value() * Animations::KeyframeEffect::AnimationKeyFrameKeyScaleFactor);
|
||||||
auto keyframe_rule = keyframe->style();
|
auto const& keyframe_style = *keyframe.style_as_property_owning_style_declaration();
|
||||||
|
|
||||||
if (!is<PropertyOwningCSSStyleDeclaration>(*keyframe_rule))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto const& keyframe_style = static_cast<PropertyOwningCSSStyleDeclaration const&>(*keyframe_rule);
|
|
||||||
for (auto const& it : keyframe_style.properties()) {
|
for (auto const& it : keyframe_style.properties()) {
|
||||||
// Unresolved properties will be resolved in collect_animation_into()
|
// 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) {
|
for_each_property_expanding_shorthands(it.property_id, it.value, AllowUnresolved::Yes, [&](PropertyID shorthand_id, StyleValue const& shorthand_value) {
|
||||||
|
|
Loading…
Reference in a new issue