diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 0eb87ff6b1f4..c3f592118c8a 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -374,6 +374,11 @@ Animation::UpdatePlaybackRate(double aPlaybackRate) return; } + // Calculate the play state using the existing playback rate since below we + // want to know if the animation is _currently_ finished or not, not whether + // it _will_ be finished. + AnimationPlayState playState = PlayState(); + mPendingPlaybackRate = Some(aPlaybackRate); // If we already have a pending task, there is nothing more to do since the @@ -384,7 +389,6 @@ Animation::UpdatePlaybackRate(double aPlaybackRate) AutoMutationBatchForAnimation mb(*this); - AnimationPlayState playState = PlayState(); if (playState == AnimationPlayState::Idle || playState == AnimationPlayState::Paused) { // We are either idle or paused. In either case we can apply the pending @@ -457,9 +461,10 @@ Animation::PlayState() const return AnimationPlayState::Paused; } + double playbackRate = CurrentOrPendingPlaybackRate(); if (!currentTime.IsNull() && - ((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) || - (mPlaybackRate < 0.0 && currentTime.Value() <= TimeDuration()))) { + ((playbackRate > 0.0 && currentTime.Value() >= EffectEnd()) || + (playbackRate < 0.0 && currentTime.Value() <= TimeDuration()))) { return AnimationPlayState::Finished; } diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html b/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html index 82b707c52c0b..ec7d8c842fc9 100644 --- a/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html +++ b/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html @@ -150,5 +150,36 @@ test(t => { }, 'reports \'running\' when playback rate > 0 and' + ' current time < target effect end and there is a pending play task'); +test(t => { + const animation = createDiv(t).animate({}, 100 * MS_PER_SEC); + assert_equals(animation.playState, 'running'); + assert_true(animation.pending); +}, 'reports \'running\' for a play-pending animation'); + +test(t => { + const animation = createDiv(t).animate({}, 100 * MS_PER_SEC); + animation.pause(); + assert_equals(animation.playState, 'paused'); + assert_true(animation.pending); +}, 'reports \'paused\' for a pause-pending animation'); + +test(t => { + const animation = createDiv(t).animate({}, 0); + assert_equals(animation.playState, 'finished'); + assert_true(animation.pending); +}, 'reports \'finished\' for a finished-pending animation'); + +test(t => { + const animation = createDiv(t).animate({}, 100 * MS_PER_SEC); + // Set up the pending playback rate + animation.updatePlaybackRate(-1); + // Call play again so that we seek to the end while remaining play-pending + animation.play(); + // For a pending animation, the play state should always report what the + // play state _will_ be once we finish pending. + assert_equals(animation.playState, 'running'); + assert_true(animation.pending); +}, 'reports the play state based on the pending playback rate'); +