Bug 1194639 part 5 - Report changes from calling reverse() to animation mutation observers; r=heycam
authorBrian Birtles <birtles@gmail.com>
Thu, 22 Oct 2015 15:16:18 +0900
changeset 304107 af2e781dc33d698244c77634ee695f4ce2aa8b46
parent 304106 96a15f93f1f44d030f39fa997ce0485fe24af412
child 304108 3b618ef232d16c01306ad2fe3177541be42a7607
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1194639
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1194639 part 5 - Report changes from calling reverse() to animation mutation observers; r=heycam
dom/animation/Animation.cpp
dom/animation/test/chrome/test_animation_observers.html
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -387,18 +387,24 @@ Animation::Reverse(ErrorResult& aRv)
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   if (mPlaybackRate == 0.0) {
     return;
   }
 
+  AutoMutationBatchForAnimation mb(*this);
+
   SilentlySetPlaybackRate(-mPlaybackRate);
   Play(aRv, LimitBehavior::AutoRewind);
+
+  if (IsRelevant()) {
+    nsNodeUtils::AnimationChanged(this);
+  }
 }
 
 // ---------------------------------------------------------------------------
 //
 // JS wrappers for Animation interface:
 //
 // ---------------------------------------------------------------------------
 
--- a/dom/animation/test/chrome/test_animation_observers.html
+++ b/dom/animation/test/chrome/test_animation_observers.html
@@ -802,16 +802,90 @@ function assert_records(expected, desc) 
     e.style = "";
 
     // Wait for the single removal notification.
     yield await_frame();
     assert_records([{ added: [], changed: [], removed: animations }],
                     "records after animation end");
   });
 
+  // Test that calling reverse() dispatches a changed notification.
+  addAsyncAnimTest("reverse", aOptions, function*() {
+    // Start a long animation
+    e.style = "animation: anim 100s both";
+
+    // The animation should cause the creation of a single Animation.
+    var animations = e.getAnimations();
+    is(animations.length, 1, "getAnimations().length after animation start");
+
+    // Wait for the single MutationRecord for the Animation addition to
+    // be delivered.
+    yield await_frame();
+    assert_records([{ added: animations, changed: [], removed: [] }],
+                    "records after animation start");
+
+    // Reverse
+    animations[0].reverse();
+
+    // Wait for the single MutationRecord for the Animation change to
+    // be delivered.
+    yield await_frame();
+    assert_records([{ added: [], changed: animations, removed: [] }],
+                    "records after calling reverse()");
+
+    // Cancel the animation.
+    e.style = "";
+
+    // Wait for the single removal notification.
+    yield await_frame();
+    assert_records([{ added: [], changed: [], removed: animations }],
+                    "records after animation end");
+  });
+
+  // Test that calling reverse() does *not* dispatch a changed notification
+  // when playbackRate == 0.
+  addAsyncAnimTest("reverse_with_zero_playbackRate", aOptions, function*() {
+    // Start a long animation
+    e.style = "animation: anim 100s both";
+
+    // The animation should cause the creation of a single Animation.
+    var animations = e.getAnimations();
+    is(animations.length, 1, "getAnimations().length after animation start");
+
+    // Wait for the single MutationRecord for the Animation addition to
+    // be delivered.
+    yield await_frame();
+    assert_records([{ added: animations, changed: [], removed: [] }],
+                    "records after animation start");
+
+    // Seek to the middle and set playbackRate to zero.
+    animations[0].currentTime = 50000;
+    animations[0].playbackRate = 0;
+
+    // Wait for the MutationRecords, one for each change, to be delivered.
+    yield await_frame();
+    assert_records([{ added: [], changed: animations, removed: [] },
+                    { added: [], changed: animations, removed: [] }],
+                    "records after seeking and setting playbackRate");
+
+    // Reverse
+    animations[0].reverse();
+
+    // We should get no notifications.
+    assert_records([], "records after calling reverse()");
+
+    // Cancel the animation.
+    e.style = "";
+
+    // Wait for the single removal notification.
+    yield await_frame();
+    assert_records([{ added: [], changed: [], removed: animations }],
+                    "records after animation end");
+  });
+
   // Test that a non-cancelling change to an animation followed immediately by a
   // cancelling change will only send an animation removal notification.
   addAsyncAnimTest("coalesce_change_cancel", aOptions, function*() {
     // Start a long animation.
     e.style = "animation: anim 100s;";
 
     // The animation should cause the creation of a single Animation.
     var animations = e.getAnimations();