LibWeb: Avoid unnecessary sorting work when getting animations

This way, the list is not re-sorted on every recursive call.
This commit is contained in:
Psychpsyo 2025-11-20 16:18:15 +01:00 committed by Jelle Raaijmakers
parent 1abc91ccc6
commit 693dd7b6f6
Notes: github-actions[bot] 2025-11-26 21:20:28 +00:00
6 changed files with 26 additions and 11 deletions

View file

@ -72,10 +72,10 @@ WebIDL::ExceptionOr<GC::Ref<Animation>> Animatable::animate(Optional<GC::Root<JS
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> Animatable::get_animations(Optional<GetAnimationsOptions> options)
{
as<DOM::Element>(*this).document().update_style();
return get_animations_internal(options);
return get_animations_internal(GetAnimationsSorted::Yes, options);
}
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> Animatable::get_animations_internal(Optional<GetAnimationsOptions> options)
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> Animatable::get_animations_internal(GetAnimationsSorted sorted, Optional<GetAnimationsOptions> options)
{
// 1. Let object be the object on which this method was called.
@ -107,18 +107,20 @@ WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> Animatable::get_animations_inter
if (options.has_value() && options->subtree) {
Optional<WebIDL::Exception> exception;
TRY(target->for_each_child_of_type_fallible<DOM::Element>([&](auto& child) -> WebIDL::ExceptionOr<IterationDecision> {
relevant_animations.extend(TRY(child.get_animations(options)));
relevant_animations.extend(TRY(child.get_animations_internal(GetAnimationsSorted::No, options)));
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<Animation>& a, GC::Ref<Animation>& b) {
auto& a_effect = as<KeyframeEffect>(*a->effect());
auto& b_effect = as<KeyframeEffect>(*b->effect());
return KeyframeEffect::composite_order(a_effect, b_effect) < 0;
});
if (sorted == GetAnimationsSorted::Yes) {
quick_sort(relevant_animations, [](GC::Ref<Animation>& a, GC::Ref<Animation>& b) {
auto& a_effect = as<KeyframeEffect>(*a->effect());
auto& b_effect = as<KeyframeEffect>(*b->effect());
return KeyframeEffect::composite_order(a_effect, b_effect) < 0;
});
}
return relevant_animations;
}

View file

@ -45,9 +45,14 @@ public:
virtual ~Animatable() = default;
enum class GetAnimationsSorted {
No,
Yes
};
WebIDL::ExceptionOr<GC::Ref<Animation>> animate(Optional<GC::Root<JS::Object>> keyframes, Variant<Empty, double, KeyframeAnimationOptions> options = {});
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> get_animations(Optional<GetAnimationsOptions> options = {});
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> get_animations_internal(Optional<GetAnimationsOptions> options = {});
WebIDL::ExceptionOr<Vector<GC::Ref<Animation>>> get_animations_internal(GetAnimationsSorted sorted, Optional<GetAnimationsOptions> options = {});
void associate_with_animation(GC::Ref<Animation>);
void disassociate_with_animation(GC::Ref<Animation>);