Bug 1437272 - Don't throttle transform animations in out-of-view element if the animations are not infinite. r?
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Sun, 11 Feb 2018 07:26:14 +0900
changeset 1424411 0f0f9354d50f571f73d5411aa643632dd4fd25ca
parent 1424029 c2cddb0cbb20f02b839a6b7bfdbc1f766bf2feb0
child 1424412 be131da4ff0d4818ba65452c8fd8686669250d8b
push id251717
push userhikezoe@mozilla.com
push dateSat, 10 Feb 2018 22:26:56 +0000
treeherdertry@be131da4ff0d [default view] [failures only]
bugs1437272
milestone60.0a1
Bug 1437272 - Don't throttle transform animations in out-of-view element if the animations are not infinite. r? MozReview-Commit-ID: HaMjmxqXPIK
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/test/mozilla/file_restyles.html
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -1452,22 +1452,26 @@ KeyframeEffectReadOnly::CanThrottle() co
   // Unless we are newly in-effect, we can throttle the animation if the
   // animation is paint only and the target frame is out of view or the document
   // is in background tabs.
   if (mInEffectOnLastAnimationTimingUpdate && CanIgnoreIfNotVisible()) {
     nsIPresShell* presShell = GetPresShell();
     if (presShell && !presShell->IsActive()) {
       return true;
     }
+
     if (frame->IsScrolledOutOfView()) {
       // If there are transform change hints, unthrottle the animation
       // periodically since it might affect the overflow region.
       if (mCumulativeChangeHint & (nsChangeHint_UpdatePostTransformOverflow |
                                    nsChangeHint_AddOrRemoveTransform |
                                    nsChangeHint_UpdateTransformLayer)) {
+        if (SpecifiedTiming().ActiveDuration() != TimeDuration::Forever()) {
+          return false;
+        }
         return CanThrottleTransformChanges(*frame);
       }
       return true;
     }
   }
 
   // First we need to check layer generation and transform overflow
   // prior to the property.mIsRunningOnCompositor check because we should
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -409,17 +409,17 @@ waitForAllPaints(() => {
         return;
       }
 
       await SpecialPowers.pushPrefEnv({ set: [["ui.showHideScrollbars", 1]] });
 
       var parentElement = addDiv(null,
         { style: 'overflow-y: scroll; height: 20px;' });
       var div = addDiv(null,
-        { style: 'animation: rotate 100s; position: relative; top: 100px;' });
+        { style: 'animation: rotate 100s infinite; position: relative; top: 100px;' });
       parentElement.appendChild(div);
       var animation = div.getAnimations()[0];
       var timeAtStart = document.timeline.currentTime;
 
       ok(!animation.isRunningOnCompositor,
          'The transform animation is not running on the compositor');
 
       var markers;
@@ -455,17 +455,17 @@ waitForAllPaints(() => {
       await SpecialPowers.pushPrefEnv({ set: [["ui.showHideScrollbars", 1]] });
 
       // Make sure we start from the state right after requestAnimationFrame.
       await waitForFrame();
 
       var parentElement = addDiv(null,
         { style: 'overflow-y: scroll; height: 20px;' });
       var div = addDiv(null,
-        { style: 'animation: rotate 100s; position: relative; top: 100px;' });
+        { style: 'animation: rotate 100s infinite; position: relative; top: 100px;' });
       parentElement.appendChild(div);
       var animation = div.getAnimations()[0];
       var timeAtStart = document.timeline.currentTime;
 
       ok(!animation.isRunningOnCompositor,
          'The transform animation is not running on the compositor');
 
       var markers;
@@ -511,41 +511,25 @@ waitForAllPaints(() => {
       }
 
       var parentElement = addDiv(null,
         { style: 'overflow: hidden;' });
       var div = addDiv(null,
         { style: 'animation: move-in 100s;' });
       parentElement.appendChild(div);
       var animation = div.getAnimations()[0];
-      var timeAtStart = document.timeline.currentTime;
 
-      ok(!animation.isRunningOnCompositor,
-         'The transform animation on out of view element ' +
-         'is not running on the compositor');
+      await animation.ready;
+      ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
 
-      var markers;
-      var now;
-      while (true) {
-        markers = await observeStyling(1);
-        // Check restyle markers until 200ms is elapsed.
-        now = document.timeline.currentTime;
-        if ((now - timeAtStart) >= 200) {
-          break;
-        }
-
-        is(markers.length, 0,
-           'Transform animation running on out of view element ' +
-           'should be throttled until 200ms is elapsed');
-      }
-
-      is(markers.length, 1,
-         'Transform animation running on out of view element ' +
-         'should be unthrottled after around 200ms have elapsed. now: ' +
-         now + ' start time: ' + timeAtStart);
+      const expectedRestyleCount = tweakExpectedRestyleCount(animation, 5);
+      var markers = await observeStyling(5);
+      is(markers.length, expectedRestyleCount,
+         'Finite transform animation running on out of view element ' +
+         'should never be throttled');
 
       await ensureElementRemoval(parentElement);
     }
   );
 
   add_task(
     async function restyling_out_of_view_transform_animations_in_another_element() {
       if (!hasConformantPromiseHandling) {
@@ -556,45 +540,25 @@ waitForAllPaints(() => {
       await waitForFrame();
 
       var parentElement = addDiv(null,
         { style: 'overflow: hidden;' });
       var div = addDiv(null,
         { style: 'animation: move-in 100s;' });
       parentElement.appendChild(div);
       var animation = div.getAnimations()[0];
-      var timeAtStart = document.timeline.currentTime;
 
-      ok(!animation.isRunningOnCompositor,
-         'The transform animation on out of view element ' +
-         'is not running on the compositor');
+      await animation.ready;
+      ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
 
-      var markers;
-      var now;
-      while (true) {
-        now = document.timeline.currentTime;
-        if ((now - timeAtStart) >= 200) {
-          // If the current time has elapsed over 200ms since the animation was
-          // created, it means that the animation should have already
-          // unthrottled in this tick, let's see what we observe in this tick's
-          // restyling process.
-          markers = await observeStyling(1);
-          break;
-        }
-
-        markers = await observeStyling(1);
-        is(markers.length, 0,
-           'Transform animation running on out of view element ' +
-           'should be throttled until 200ms is elapsed');
-      }
-
-      is(markers.length, 1,
-         'Transform animation running on out of view element ' +
-         'should be unthrottled after around 200ms have elapsed. now: ' +
-         now + ' start time: ' + timeAtStart);
+      const expectedRestyleCount = tweakExpectedRestyleCount(animation, 5);
+      var markers = await observeStyling(5);
+      is(markers.length, expectedRestyleCount,
+         'Finite transform animation running on out of view element ' +
+         'should never be throttled');
 
       await ensureElementRemoval(parentElement);
     }
   );
 
   add_task(async function restyling_main_thread_animations_in_scrolled_out_element() {
     var parentElement = addDiv(null,
       { style: 'overflow-y: scroll; height: 20px;' });