Bug 1474247 - Reset pending tasks in KeyframeEffect::SetTarget if no new target sets. r?birtles
MozReview-Commit-ID: 5vn8ruP3PtY
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -385,16 +385,22 @@ public:
* If we have a pending animation, it will either be registered
* in the pending animation tracker and have a null pending ready time,
* or, after it has been painted, it will be removed from the tracker
* and assigned a pending ready time.
*/
void ReschedulePendingTasks();
/**
+ * Performs the same steps as CancelPendingTasks and also rejects and
+ * recreates the ready promise if the animation was pending.
+ */
+ void ResetPendingTasks();
+
+ /**
* Used by subclasses to synchronously queue a cancel event in situations
* where the Animation may have been cancelled.
*
* We need to do this synchronously because after a CSS animation/transition
* is canceled, it will be released by its owning element and may not still
* exist when we would normally go to queue events on the next tick.
*/
virtual void MaybeQueueCancelEvent(const StickyTimeDuration& aActiveTime) {};
@@ -467,22 +473,16 @@ protected:
* Remove this animation from the pending animation tracker and reset
* mPendingReadyTime.
* Unlike the above CancelPendingTasks() this function preserves
* mPendingState.
*/
void RemovePendingTasksFromTracker();
/**
- * Performs the same steps as CancelPendingTasks and also rejects and
- * recreates the ready promise if the animation was pending.
- */
- void ResetPendingTasks();
-
- /**
* Returns true if this animation is not only play-pending, but has
* yet to be given a pending ready time. This roughly corresponds to
* animations that are waiting to be painted (since we set the pending
* ready time at the end of painting). Identifying such animations is
* useful because in some cases animations that are painted together
* may need to be synchronized.
*
* We don't, however, want to include animations with a fixed start time such
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -944,16 +944,19 @@ KeyframeEffect::SetTarget(const Nullable
if (mTarget) {
UnregisterTarget();
ResetIsRunningOnCompositor();
RequestRestyle(EffectCompositor::RestyleType::Layer);
nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc());
if (mAnimation) {
+ if (!newTarget) {
+ mAnimation->ResetPendingTasks();
+ }
nsNodeUtils::AnimationRemoved(mAnimation);
}
}
mTarget = newTarget;
if (mTarget) {
UpdateTargetRegistration();
--- a/dom/animation/test/mozilla/test_pending_animation_tracker.html
+++ b/dom/animation/test/mozilla/test_pending_animation_tracker.html
@@ -142,10 +142,24 @@ test(t => {
anim.effect.target = anotherTarget;
assert_true(anim.pending, 'The animation should be pending');
assert_true(SpecialPowers.DOMWindowUtils.isAnimationPending(anim),
'The animation should be still tracked by tracker');
}, 'Setting another target keeps the pending animation in the tracker');
+test(t => {
+ const target = addDiv(t);
+ const anim = target.animate(null, 100 * MS_PER_SEC);
+ assert_true(anim.pending, 'The animation should be pending');
+ assert_true(SpecialPowers.DOMWindowUtils.isAnimationPending(anim),
+ 'The animation should be tracked by the tracker');
+
+ anim.effect.target = null;
+
+ assert_false(anim.pending, 'The animation should not be pending');
+ assert_false(SpecialPowers.DOMWindowUtils.isAnimationPending(anim),
+ 'The animation should NOT be tracked by the tracker');
+}, 'Setting null target removes the animation from the tracker');
+
</script>
</body>