Bug 1474247 - Reset pending tasks in KeyframeEffect::SetTarget if no new target sets. r?birtles draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 11 Jul 2018 11:39:10 +0900
changeset 816368 2217664e292d51d266dc9b0a8397977246f75cbb
parent 816367 71ad5d3c4c42b45ab45726f98d93b7f6f5d0e215
child 816369 fadf38c85f1b9305890c6af597c12a11de10178b
push id115815
push userhikezoe@mozilla.com
push dateWed, 11 Jul 2018 02:48:59 +0000
reviewersbirtles
bugs1474247
milestone63.0a1
Bug 1474247 - Reset pending tasks in KeyframeEffect::SetTarget if no new target sets. r?birtles MozReview-Commit-ID: 5vn8ruP3PtY
dom/animation/Animation.h
dom/animation/KeyframeEffect.cpp
dom/animation/test/mozilla/test_pending_animation_tracker.html
--- 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>