Browse Source

LibWeb: Add slots for pseudo-elements animation cache in Animatable

Fixes the bug when animation does not run at all if an element has a
pseudo-element, because both of them use the same cache.
Aliaksandr Kalenik 11 tháng trước cách đây
mục cha
commit
4049cce40c

+ 36 - 2
Userland/Libraries/LibWeb/Animations/Animatable.cpp

@@ -102,8 +102,42 @@ void Animatable::disassociate_with_animation(JS::NonnullGCPtr<Animation> animati
 void Animatable::visit_edges(JS::Cell::Visitor& visitor)
 void Animatable::visit_edges(JS::Cell::Visitor& visitor)
 {
 {
     visitor.visit(m_associated_animations);
     visitor.visit(m_associated_animations);
-    visitor.visit(m_cached_animation_name_source);
-    visitor.visit(m_cached_animation_name_animation);
+    for (auto const& cached_animation_source : m_cached_animation_name_source)
+        visitor.visit(cached_animation_source);
+    for (auto const& cached_animation_name : m_cached_animation_name_animation)
+        visitor.visit(cached_animation_name);
+}
+
+JS::GCPtr<CSS::CSSStyleDeclaration const> Animatable::cached_animation_name_source(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const
+{
+    if (pseudo_element.has_value())
+        return m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1];
+    return m_cached_animation_name_source[0];
+}
+
+void Animatable::set_cached_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element)
+{
+    if (pseudo_element.has_value()) {
+        m_cached_animation_name_source[to_underlying(pseudo_element.value()) + 1] = value;
+    } else {
+        m_cached_animation_name_source[0] = value;
+    }
+}
+
+JS::GCPtr<Animations::Animation> Animatable::cached_animation_name_animation(Optional<CSS::Selector::PseudoElement::Type> pseudo_element) const
+{
+    if (pseudo_element.has_value())
+        return m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1];
+    return m_cached_animation_name_animation[0];
+}
+
+void Animatable::set_cached_animation_name_animation(JS::GCPtr<Animations::Animation> value, Optional<CSS::Selector::PseudoElement::Type> pseudo_element)
+{
+    if (pseudo_element.has_value()) {
+        m_cached_animation_name_animation[to_underlying(pseudo_element.value()) + 1] = value;
+    } else {
+        m_cached_animation_name_animation[0] = value;
+    }
 }
 }
 
 
 }
 }

+ 7 - 6
Userland/Libraries/LibWeb/Animations/Animatable.h

@@ -33,11 +33,11 @@ public:
     void associate_with_animation(JS::NonnullGCPtr<Animation>);
     void associate_with_animation(JS::NonnullGCPtr<Animation>);
     void disassociate_with_animation(JS::NonnullGCPtr<Animation>);
     void disassociate_with_animation(JS::NonnullGCPtr<Animation>);
 
 
-    JS::GCPtr<CSS::CSSStyleDeclaration const> cached_animation_name_source() const { return m_cached_animation_name_source; }
-    void set_cached_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> value) { m_cached_animation_name_source = value; }
+    JS::GCPtr<CSS::CSSStyleDeclaration const> cached_animation_name_source(Optional<CSS::Selector::PseudoElement::Type>) const;
+    void set_cached_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> value, Optional<CSS::Selector::PseudoElement::Type>);
 
 
-    JS::GCPtr<Animations::Animation> cached_animation_name_animation() const { return m_cached_animation_name_animation; }
-    void set_cached_animation_name_animation(JS::GCPtr<Animations::Animation> value) { m_cached_animation_name_animation = value; }
+    JS::GCPtr<Animations::Animation> cached_animation_name_animation(Optional<CSS::Selector::PseudoElement::Type>) const;
+    void set_cached_animation_name_animation(JS::GCPtr<Animations::Animation> value, Optional<CSS::Selector::PseudoElement::Type>);
 
 
 protected:
 protected:
     void visit_edges(JS::Cell::Visitor&);
     void visit_edges(JS::Cell::Visitor&);
@@ -45,8 +45,9 @@ protected:
 private:
 private:
     Vector<JS::NonnullGCPtr<Animation>> m_associated_animations;
     Vector<JS::NonnullGCPtr<Animation>> m_associated_animations;
     bool m_is_sorted_by_composite_order { true };
     bool m_is_sorted_by_composite_order { true };
-    JS::GCPtr<CSS::CSSStyleDeclaration const> m_cached_animation_name_source;
-    JS::GCPtr<Animations::Animation> m_cached_animation_name_animation;
+
+    Array<JS::GCPtr<CSS::CSSStyleDeclaration const>, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount) + 1> m_cached_animation_name_source;
+    Array<JS::GCPtr<Animations::Animation>, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount) + 1> m_cached_animation_name_animation;
 };
 };
 
 
 }
 }

+ 8 - 8
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -1774,11 +1774,11 @@ void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element
         if (auto source_declaration = style.property_source_declaration(PropertyID::AnimationName); source_declaration) {
         if (auto source_declaration = style.property_source_declaration(PropertyID::AnimationName); source_declaration) {
             auto& realm = element.realm();
             auto& realm = element.realm();
 
 
-            if (source_declaration != element.cached_animation_name_source()) {
+            if (source_declaration != element.cached_animation_name_source(pseudo_element)) {
                 // This animation name is new, so we need to create a new animation for it.
                 // This animation name is new, so we need to create a new animation for it.
-                if (auto existing_animation = element.cached_animation_name_animation())
+                if (auto existing_animation = element.cached_animation_name_animation(pseudo_element))
                     existing_animation->cancel(Animations::Animation::ShouldInvalidate::No);
                     existing_animation->cancel(Animations::Animation::ShouldInvalidate::No);
-                element.set_cached_animation_name_source(source_declaration);
+                element.set_cached_animation_name_source(source_declaration, pseudo_element);
 
 
                 auto effect = Animations::KeyframeEffect::create(realm);
                 auto effect = Animations::KeyframeEffect::create(realm);
                 auto animation = CSSAnimation::create(realm);
                 auto animation = CSSAnimation::create(realm);
@@ -1795,21 +1795,21 @@ void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element
                     effect->set_key_frame_set(keyframe_set.value());
                     effect->set_key_frame_set(keyframe_set.value());
 
 
                 effect->set_target(&element);
                 effect->set_target(&element);
-                element.set_cached_animation_name_animation(animation);
+                element.set_cached_animation_name_animation(animation, pseudo_element);
 
 
                 HTML::TemporaryExecutionContext context(m_document->relevant_settings_object());
                 HTML::TemporaryExecutionContext context(m_document->relevant_settings_object());
                 animation->play().release_value_but_fixme_should_propagate_errors();
                 animation->play().release_value_but_fixme_should_propagate_errors();
             } else {
             } else {
                 // The animation hasn't changed, but some properties of the animation may have
                 // The animation hasn't changed, but some properties of the animation may have
-                apply_animation_properties(m_document, style, *element.cached_animation_name_animation());
+                apply_animation_properties(m_document, style, *element.cached_animation_name_animation(pseudo_element));
             }
             }
         }
         }
     } else {
     } else {
         // If the element had an existing animation, cancel it
         // If the element had an existing animation, cancel it
-        if (auto existing_animation = element.cached_animation_name_animation()) {
+        if (auto existing_animation = element.cached_animation_name_animation(pseudo_element)) {
             existing_animation->cancel(Animations::Animation::ShouldInvalidate::No);
             existing_animation->cancel(Animations::Animation::ShouldInvalidate::No);
-            element.set_cached_animation_name_animation({});
-            element.set_cached_animation_name_source({});
+            element.set_cached_animation_name_animation({}, pseudo_element);
+            element.set_cached_animation_name_source({}, pseudo_element);
         }
         }
     }
     }