LibWeb: Correctly sort animations returned by getAnimations()

This commit is contained in:
Psychpsyo 2025-11-10 16:27:00 +01:00 committed by Jelle Raaijmakers
parent 2c389ae96c
commit b7a71ca950
Notes: github-actions[bot] 2025-11-10 17:30:34 +00:00
6 changed files with 284 additions and 14 deletions

View file

@ -627,11 +627,12 @@ void KeyframeEffect::generate_initial_and_final_frames(RefPtr<KeyFrameSet> keyfr
// https://www.w3.org/TR/web-animations-1/#animation-composite-order
int KeyframeEffect::composite_order(GC::Ref<KeyframeEffect> a, GC::Ref<KeyframeEffect> b)
{
// 1. Let the associated animation of an animation effect be the animation associated with the animation effect.
// The relative composite order of any two keyframe effects A and B within an effect stack is established by
// comparing their properties as follows:
auto a_animation = a->associated_animation();
auto b_animation = b->associated_animation();
// 2. Sort A and B by applying the following conditions in turn until the order is resolved,
// 1. Sort A and B by applying the following conditions in turn until the order is resolved,
// 1. If A and Bs associated animations differ by class, sort by any inter-class composite order defined for
// the corresponding classes.

View file

@ -5472,12 +5472,7 @@ void Document::remove_replaced_animations()
WebIDL::ExceptionOr<Vector<GC::Ref<Animations::Animation>>> Document::get_animations()
{
Vector<GC::Ref<Animations::Animation>> relevant_animations;
TRY(for_each_child_of_type_fallible<Element>([&](auto& child) -> WebIDL::ExceptionOr<IterationDecision> {
relevant_animations.extend(TRY(child.get_animations(Animations::GetAnimationsOptions { .subtree = true })));
return IterationDecision::Continue;
}));
return relevant_animations;
return calculate_get_animations(*this);
}
// https://html.spec.whatwg.org/multipage/dom.html#dom-document-nameditem-filter

View file

@ -7,6 +7,7 @@
#pragma once
#include <LibWeb/Animations/Animation.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Utils.h>
@ -47,4 +48,32 @@ GC::Ptr<Element> calculate_active_element(T& self)
return nullptr;
}
// https://drafts.csswg.org/web-animations-1/#dom-documentorshadowroot-getanimations
template<DocumentOrShadowRoot T>
WebIDL::ExceptionOr<Vector<GC::Ref<Animations::Animation>>> calculate_get_animations(T& self)
{
// Returns the set of relevant animations for a subtree for the document or shadow root on which this
// method is called.
Vector<GC::Ref<Animations::Animation>> relevant_animations;
TRY(self.template for_each_child_of_type_fallible<Element>([&](auto& child) -> WebIDL::ExceptionOr<IterationDecision> {
relevant_animations.extend(TRY(child.get_animations(Animations::GetAnimationsOptions { .subtree = true })));
return IterationDecision::Continue;
}));
// The returned list is sorted using the composite order described for the associated animations of
// effects in §5.4.2 The effect stack.
quick_sort(relevant_animations, [](GC::Ref<Animations::Animation>& a, GC::Ref<Animations::Animation>& b) {
auto& a_effect = as<Animations::KeyframeEffect>(*a->effect());
auto& b_effect = as<Animations::KeyframeEffect>(*b->effect());
return Animations::KeyframeEffect::composite_order(a_effect, b_effect) < 0;
});
// Calling this method triggers a style change event for the document. As a result, the returned list
// reflects the state after applying any pending style changes to animation such as changes to
// animation-related style properties that have yet to be processed.
// FIXME: Implement this.
return relevant_animations;
}
}

View file

@ -198,12 +198,7 @@ void ShadowRoot::for_each_css_style_sheet(Function<void(CSS::CSSStyleSheet&)>&&
WebIDL::ExceptionOr<Vector<GC::Ref<Animations::Animation>>> ShadowRoot::get_animations()
{
Vector<GC::Ref<Animations::Animation>> relevant_animations;
TRY(for_each_child_of_type_fallible<Element>([&](auto& child) -> WebIDL::ExceptionOr<IterationDecision> {
relevant_animations.extend(TRY(child.get_animations(Animations::GetAnimationsOptions { .subtree = true })));
return IterationDecision::Continue;
}));
return relevant_animations;
return calculate_get_animations(*this);
}
ElementByIdMap& ShadowRoot::element_by_id() const