From c8b574e9b4f7d771277507520592b2084fa42ce9 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 19 Jul 2025 03:34:13 +0200 Subject: [PATCH] LibWeb: Remove animations from timeline in `Element::removed_from()` `AnimationTimeline` visits pointers of all registered animations, so if element is removed from DOM tree but its animations remain registered in timeline, then `Animation` and owner `Element` will be kept alive until `AnimationTimeline` is destroyed. --- Libraries/LibWeb/Animations/Animatable.cpp | 9 +++++++++ Libraries/LibWeb/Animations/Animatable.h | 2 ++ Libraries/LibWeb/DOM/Element.cpp | 1 + 3 files changed, 12 insertions(+) diff --git a/Libraries/LibWeb/Animations/Animatable.cpp b/Libraries/LibWeb/Animations/Animatable.cpp index 8ed2c17d1ca..c0371dd1b76 100644 --- a/Libraries/LibWeb/Animations/Animatable.cpp +++ b/Libraries/LibWeb/Animations/Animatable.cpp @@ -235,6 +235,15 @@ void Animatable::clear_transitions(Optional pseudo_element) transition.transition_attributes.clear(); } +void Animatable::remove_animations_from_timeline() +{ + // This is needed to avoid leaking Animation objects + auto& impl = ensure_impl(); + for (auto animation : impl.associated_animations) { + animation->set_timeline({}); + } +} + void Animatable::visit_edges(JS::Cell::Visitor& visitor) { auto& impl = ensure_impl(); diff --git a/Libraries/LibWeb/Animations/Animatable.h b/Libraries/LibWeb/Animations/Animatable.h index 09afeb8f4d7..1efb3446d4c 100644 --- a/Libraries/LibWeb/Animations/Animatable.h +++ b/Libraries/LibWeb/Animations/Animatable.h @@ -67,6 +67,8 @@ public: GC::Ptr property_transition(Optional, CSS::PropertyID) const; void clear_transitions(Optional); + void remove_animations_from_timeline(); + protected: void visit_edges(JS::Cell::Visitor&); diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index c375df3be16..9557d992a28 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -1356,6 +1356,7 @@ void Element::removed_from(Node* old_parent, Node& old_root) } play_or_cancel_animations_after_display_property_change(); + remove_animations_from_timeline(); } void Element::moved_from(GC::Ptr old_parent)