Bug 1202333 part 1 - Remove excessive animationiteration event. r=birtles

The Firefox fired excessive animationiteration event.
But We fixed specification in order to prevent firing the animationiteration when animation is start.

For detail, See https://github.com/w3c/csswg-drafts/issues/68

MozReview-Commit-ID: 391DRxSpq86

--HG--
extra : rebase_source : 38e6710da4d9ad7422d6313eeae2803402a51b24
This commit is contained in:
Mantaroh Yoshinaga 2016-12-20 15:57:13 +09:00
parent bb2c4d0096
commit 90c5d3d372
6 changed files with 24 additions and 34 deletions

View File

@ -73,22 +73,15 @@ function triggerShortAnimation(node) {
node.style.animation = "anim1 1ms linear";
}
// This function triggers a long animation with two iterations, which is
// *nearly* at the end of its first iteration. It will hit the end of that
// iteration (firing an event) almost immediately, 1ms in the future.
// This function triggers a very short (10ms long) animation with many
// iterations, which will cause a start event followed by an iteration event
// on each subsequent tick, to fire.
//
// NOTE: It's important that this animation have a *long* duration. If it were
// short (e.g. 1ms duration), then we might jump past all its iterations in
// a single refresh-driver tick. And if that were to happens, we'd *never* fire
// any animationiteration events -- the CSS Animations spec says this event
// must not be fired "...when an animationend event would fire at the same time"
// (which would be the case in this example with a 1ms duration). So, to make
// sure our event does fire, we use a long duration and a nearly-as-long
// negative delay. This ensures we hit the end of the first iteration right
// away, and that we don't risk hitting the end of the second iteration at the
// same time.
// NOTE: We need the many iterations since if an animation frame coincides
// with the animation starting or ending we dispatch only the start or end
// event and not the iteration event.
function triggerAnimationIteration(node) {
node.style.animation = "anim1 300s -299.999s linear 2";
node.style.animation = "anim1 10ms linear 20000";
}
// GENERAL UTILITY FUNCTIONS

View File

@ -17,7 +17,7 @@ body { padding: 50px }
height: 200px; width: 200px;
backface-visibility: hidden;
/* use a -99.9s delay to start at 99.9% and then move to 0% */
animation: flip 100s -99.9s linear 2;
animation: flip 100s -99.9s linear 2 paused;
}
</style>
@ -27,7 +27,13 @@ body { padding: 50px }
<script>
document.getElementById("test").addEventListener("animationiteration", IterationListener, false);
document.getElementById("test").addEventListener("animationstart", StartListener, false);
function StartListener(event) {
var test = document.getElementById("test");
test.style.animationPlayState = 'running';
test.addEventListener("animationiteration", IterationListener, false);
}
function IterationListener(event) {
setTimeout(RemoveReftestWait, 0);

View File

@ -18,7 +18,7 @@ body { padding: 50px }
border: 1px solid black;
transform-style: preserve-3d;
/* use a -99.9s delay to start at 99.9% and then move to 0% */
animation: spin 100s -99.9s linear 2;
animation: spin 100s -99.9s linear 2 paused;
}
#child {
@ -39,7 +39,13 @@ body { padding: 50px }
<script>
document.getElementById("parent").addEventListener("animationiteration", IterationListener, false);
document.getElementById("parent").addEventListener("animationstart", StartListener, false);
function StartListener(event) {
var test = document.getElementById("parent");
test.style.animationPlayState = 'running';
test.addEventListener("animationiteration", IterationListener, false);
}
function IterationListener(event) {
setTimeout(RemoveReftestWait, 0);

View File

@ -218,10 +218,6 @@ CSSAnimation::QueueEvents()
computedTiming.mPhase == ComputedTiming::AnimationPhase::After) ||
(mPreviousPhaseOrIteration == PREVIOUS_PHASE_AFTER &&
computedTiming.mPhase == ComputedTiming::AnimationPhase::Before);
bool skippedFirstIteration =
isActive &&
mPreviousPhaseOrIteration == PREVIOUS_PHASE_BEFORE &&
computedTiming.mCurrentIteration > 0;
MOZ_ASSERT(!skippedActivePhase || (!isActive && !wasActive),
"skippedActivePhase only makes sense if we were & are inactive");
@ -240,12 +236,7 @@ CSSAnimation::QueueEvents()
computedTiming.mCurrentIteration;
const StickyTimeDuration& activeDuration = computedTiming.mActiveDuration;
if (skippedFirstIteration) {
// Notify animationstart and animationiteration in same tick.
events.AppendElement(EventPair(eAnimationStart, initialAdvance));
events.AppendElement(EventPair(eAnimationIteration,
std::max(iterationStart, initialAdvance)));
} else if (!wasActive && isActive) {
if (!wasActive && isActive) {
events.AppendElement(EventPair(eAnimationStart, initialAdvance));
} else if (wasActive && !isActive) {
events.AppendElement(EventPair(eAnimationEnd, activeDuration));

View File

@ -1226,9 +1226,6 @@ advance_clock(0); // complete pending animation start
is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.4), 0.01,
"large negative delay test at 0ms");
check_events([{ type: 'animationstart', target: div,
animationName: 'anim2', elapsedTime: 3.6,
pseudoElement: "" },
{ type: 'animationiteration', target: div,
animationName: 'anim2', elapsedTime: 3.6,
pseudoElement: "" }],
"right after start in large negative delay test");

View File

@ -1407,9 +1407,6 @@ addAsyncAnimTest(function *() {
omta_is_approx("opacity", gTF.ease_in(0.4), 0.01, RunningOn.Compositor,
"large negative delay test at 0ms");
check_events([{ type: 'animationstart', target: gDiv,
animationName: 'anim2', elapsedTime: 3.6,
pseudoElement: "" },
{ type: 'animationiteration', target: gDiv,
animationName: 'anim2', elapsedTime: 3.6,
pseudoElement: "" }],
"right after start in large negative delay test");