diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 9063cad57bce..0afa78885d97 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -233,9 +233,6 @@ ElementAnimations::GetEventsAt(TimeStamp aRefreshTime, ComputedTiming computedTiming = ElementAnimation::GetComputedTimingAt(elapsedDuration, anim->mTiming); - // FIXME: Bug 1004361: If our active duration is sufficiently short and our - // samples are sufficiently infrequent we will end up skipping the start - // event and jumping straight to the end event. switch (computedTiming.mPhase) { case ComputedTiming::AnimationPhase_Before: // Do nothing @@ -262,6 +259,18 @@ ElementAnimations::GetEventsAt(TimeStamp aRefreshTime, break; case ComputedTiming::AnimationPhase_After: + // If we skipped the animation interval entirely, dispatch + // 'animationstart' first + if (anim->mLastNotification == + ElementAnimation::LAST_NOTIFICATION_NONE) { + // Notifying for start of 0th iteration. + // (This is overwritten below but we set it here to maintain + // internal consistency.) + anim->mLastNotification = 0; + AnimationEventInfo ei(mElement, anim->mName, NS_ANIMATION_START, + elapsedDuration, PseudoElement()); + aEventsToDispatch.AppendElement(ei); + } // Dispatch 'animationend' when needed. if (anim->mLastNotification != ElementAnimation::LAST_NOTIFICATION_END) { diff --git a/layout/style/test/test_animations.html b/layout/style/test/test_animations.html index 8c98d47142ae..9c44d2338210 100644 --- a/layout/style/test/test_animations.html +++ b/layout/style/test/test_animations.html @@ -1539,6 +1539,25 @@ dyn_sheet_elt.parentNode.removeChild(dyn_sheet_elt); dyn_sheet_elt = null; dyn_sheet = null; +/* + * Bug 1004361 - CSS animations with short duration sometimes don't dispatch + * a start event + */ +new_div("animation: anim2 1s 0.1s"); +listen(); +advance_clock(0); // Trigger animation +advance_clock(1200); // Skip past end of animation's entire active duration +check_events([{ type: 'animationstart', target: div, + // Bug 1007513 - elapsedTime should be 0 below + animationName: 'anim2', elapsedTime: 1.1, + pseudoElement: "" }, + { type: 'animationend', target: div, + // Bug 1007513 - elapsedTime should be 1 below + animationName: 'anim2', elapsedTime: 1.1, + pseudoElement: "" }], + "events after skipping over animation interval"); +done_div(); + SpecialPowers.DOMWindowUtils.restoreNormalRefresh(); diff --git a/layout/style/test/test_animations_omta.html b/layout/style/test/test_animations_omta.html index 398405fab32d..e4facc193c09 100644 --- a/layout/style/test/test_animations_omta.html +++ b/layout/style/test/test_animations_omta.html @@ -1845,6 +1845,28 @@ addAsyncTest(function *() { dyn_sheet = null; }); +/* + * Bug 1004361 - CSS animations with short duration sometimes don't dispatch + * a start event + */ +addAsyncTest(function *() { + new_div("animation: anim2 1s 0.1s"); + listen(); + yield waitForPaints(); + advance_clock(0); // Trigger animation + advance_clock(1200); // Skip past end of animation's entire active duration + check_events([{ type: 'animationstart', target: gDiv, + // Bug 1007513 - elapsedTime should be 0 below + animationName: 'anim2', elapsedTime: 1.1, + pseudoElement: "" }, + { type: 'animationend', target: gDiv, + // Bug 1007513 - elapsedTime should be 1 below + animationName: 'anim2', elapsedTime: 1.1, + pseudoElement: "" }], + "events after skipping over animation interval"); + done_div(); +}); + //---------------------------------------------------------------------- // // Helper functions from test_animations.html