From b4f581b39f1c6f2f1ef35728913e355303b0fa60 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Thu, 22 Oct 2015 15:16:18 +0900 Subject: [PATCH] Bug 1194639 part 8 - Report changes from calling pause() to animation mutation observers; r=heycam --- dom/animation/Animation.cpp | 5 + .../test/chrome/test_animation_observers.html | 141 +++++++++++++++++- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index af9238e291a6..95d4dc7c4ff2 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -852,6 +852,8 @@ Animation::DoPause(ErrorResult& aRv) return; } + AutoMutationBatchForAnimation mb(*this); + // If we are transitioning from idle, fill in the current time if (GetCurrentTime().IsNull()) { if (mPlaybackRate >= 0.0) { @@ -888,6 +890,9 @@ Animation::DoPause(ErrorResult& aRv) } UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async); + if (IsRelevant()) { + nsNodeUtils::AnimationChanged(this); + } } void diff --git a/dom/animation/test/chrome/test_animation_observers.html b/dom/animation/test/chrome/test_animation_observers.html index 3885a3e2238f..21c77a2873bc 100644 --- a/dom/animation/test/chrome/test_animation_observers.html +++ b/dom/animation/test/chrome/test_animation_observers.html @@ -792,10 +792,11 @@ function assert_records(expected, desc) { // currentTime while pause-pending has the effect of cancelling a pause. animations[0].currentTime = animations[0].currentTime; - // Wait for the MutationRecord from updating the currentTime to be - // delivered. + // Wait for the two MutationRecords for the Animation changes to + // be delivered: one for pausing, one for aborting the pause. yield await_frame(); - assert_records([{ added: [], changed: animations, removed: [] }], + assert_records([{ added: [], changed: animations, removed: [] }, + { added: [], changed: animations, removed: [] }], "records after pausing then seeking"); // Cancel the animation. @@ -985,8 +986,10 @@ function assert_records(expected, desc) { is(animations[0].playState, "paused", "playState after finishing and pausing"); - // We should have one MutationRecord for the finish() operation. - assert_records([{ added: [], changed: animations, removed: [] }], + // We should have two MutationRecords for the Animation changes: + // one for the finish, one for the pause. + assert_records([{ added: [], changed: animations, removed: [] }, + { added: [], changed: animations, removed: [] }], "records after finish() and pause()"); // Call finish() again. @@ -1040,10 +1043,11 @@ function assert_records(expected, desc) { is(animations[0].playState, "finished", "playState after finishing and calling pause()"); - // Wait for the two MutationRecords for the Animation changes to - // be delivered: one for each finish() operation. + // Wait for three MutationRecords for the Animation changes to + // be delivered: one for each finish(), pause(), finish() operation. yield await_frame(); assert_records([{ added: [], changed: animations, removed: [] }, + { added: [], changed: animations, removed: [] }, { added: [], changed: animations, removed: [] }], "records after finish(), pause(), finish()"); @@ -1194,6 +1198,129 @@ function assert_records(expected, desc) { "records after animation end"); }); + // Test that calling pause() on an Animation dispatches a changed + // notification. + addAsyncAnimTest("pause", 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(); + 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"); + + // Wait until the animation is ready + yield animations[0].ready; + + // Pause + animations[0].pause(); + + // Wait for the single MutationRecord for the Animation change to + // be delivered. + yield animations[0].ready; + assert_records([{ added: [], changed: animations, removed: [] }], + "records after pause()"); + + // Redundant pause + animations[0].pause(); + + // Wait to ensure no change is dispatched + yield animations[0].ready; + assert_records([], "records after redundant pause()"); + + // 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 pause() on an Animation that is pause-pending + // does not dispatch an additional changed notification. + addAsyncAnimTest("pause_while_pause_pending", 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(); + 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"); + + // Wait until the animation is ready + yield animations[0].ready; + + // Pause + animations[0].pause(); + + // We are now pause-pending, but pause again + animations[0].pause(); + + // We should only get a single change record + yield animations[0].ready; + assert_records([{ added: [], changed: animations, removed: [] }], + "records after pause()"); + + // 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 play() on an Animation that is pause-pending + // dispatches a changed notification. + addAsyncAnimTest("aborted_pause", 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(); + 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"); + + // Wait until the animation is ready + yield animations[0].ready; + + // Pause + animations[0].pause(); + + // We are now pause-pending. If we play() now, we will abort the pause + animations[0].play(); + + // We should get two change records + yield animations[0].ready; + assert_records([{ added: [], changed: animations, removed: [] }, + { added: [], changed: animations, removed: [] }], + "records after aborting a pause()"); + + // 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*() {