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.
This commit is contained in:
Aliaksandr Kalenik 2025-07-19 03:34:13 +02:00 committed by Alexander Kalenik
commit c8b574e9b4
Notes: github-actions[bot] 2025-07-23 21:51:20 +00:00
3 changed files with 12 additions and 0 deletions

View file

@ -235,6 +235,15 @@ void Animatable::clear_transitions(Optional<CSS::PseudoElement> pseudo_element)
transition.transition_attributes.clear(); 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) void Animatable::visit_edges(JS::Cell::Visitor& visitor)
{ {
auto& impl = ensure_impl(); auto& impl = ensure_impl();

View file

@ -67,6 +67,8 @@ public:
GC::Ptr<CSS::CSSTransition> property_transition(Optional<CSS::PseudoElement>, CSS::PropertyID) const; GC::Ptr<CSS::CSSTransition> property_transition(Optional<CSS::PseudoElement>, CSS::PropertyID) const;
void clear_transitions(Optional<CSS::PseudoElement>); void clear_transitions(Optional<CSS::PseudoElement>);
void remove_animations_from_timeline();
protected: protected:
void visit_edges(JS::Cell::Visitor&); void visit_edges(JS::Cell::Visitor&);

View file

@ -1356,6 +1356,7 @@ void Element::removed_from(Node* old_parent, Node& old_root)
} }
play_or_cancel_animations_after_display_property_change(); play_or_cancel_animations_after_display_property_change();
remove_animations_from_timeline();
} }
void Element::moved_from(GC::Ptr<Node> old_parent) void Element::moved_from(GC::Ptr<Node> old_parent)