From cf4482199c5b92c5029b79c086cf9f831a87f895 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 08:52:52 +0100 Subject: Bug 1264125: Fire transitioncancel event when a transition is canceled - part 1 (in the description) Issue #55 part 1 - Add transitioncancel event handler part 2 - Add ontransitioncancel EventHandler to WebIDL part 3 - Add member of active time to ComputedTiming --- dom/animation/AnimationEffectReadOnly.cpp | 18 ++++++++---------- dom/animation/ComputedTiming.h | 2 ++ dom/base/nsGkAtomList.h | 1 + dom/events/EventNameList.h | 4 ++++ dom/webidl/EventHandler.webidl | 1 + 5 files changed, 16 insertions(+), 10 deletions(-) (limited to 'dom') diff --git a/dom/animation/AnimationEffectReadOnly.cpp b/dom/animation/AnimationEffectReadOnly.cpp index aff28a37b..bf2e2197d 100644 --- a/dom/animation/AnimationEffectReadOnly.cpp +++ b/dom/animation/AnimationEffectReadOnly.cpp @@ -127,10 +127,6 @@ AnimationEffectReadOnly::GetComputedTimingAt( } const TimeDuration& localTime = aLocalTime.Value(); - // Calculate the time within the active interval. - // https://w3c.github.io/web-animations/#active-time - StickyTimeDuration activeTime; - StickyTimeDuration beforeActiveBoundary = std::max(std::min(StickyTimeDuration(aTiming.mDelay), result.mEndTime), zeroDuration); @@ -148,7 +144,7 @@ AnimationEffectReadOnly::GetComputedTimingAt( // The animation isn't active or filling at this time. return result; } - activeTime = + result.mActiveTime = std::max(std::min(StickyTimeDuration(localTime - aTiming.mDelay), result.mActiveDuration), zeroDuration); @@ -159,13 +155,14 @@ AnimationEffectReadOnly::GetComputedTimingAt( // The animation isn't active or filling at this time. return result; } - activeTime = std::max(StickyTimeDuration(localTime - aTiming.mDelay), - zeroDuration); + result.mActiveTime + = std::max(StickyTimeDuration(localTime - aTiming.mDelay), + zeroDuration); } else { MOZ_ASSERT(result.mActiveDuration != zeroDuration, "How can we be in the middle of a zero-duration interval?"); result.mPhase = ComputedTiming::AnimationPhase::Active; - activeTime = localTime - aTiming.mDelay; + result.mActiveTime = localTime - aTiming.mDelay; } // Convert active time to a multiple of iterations. @@ -176,7 +173,7 @@ AnimationEffectReadOnly::GetComputedTimingAt( ? 0.0 : result.mIterations; } else { - overallProgress = activeTime / result.mDuration; + overallProgress = result.mActiveTime / result.mDuration; } // Factor in iteration start offset. @@ -208,7 +205,8 @@ AnimationEffectReadOnly::GetComputedTimingAt( if (result.mPhase == ComputedTiming::AnimationPhase::After && progress == 0.0 && result.mIterations != 0.0 && - (activeTime != zeroDuration || result.mDuration == zeroDuration)) { + (result.mActiveTime != zeroDuration || + result.mDuration == zeroDuration)) { // The only way we can be in the after phase with a progress of zero and // a current iteration of zero, is if we have a zero iteration count or // were clipped using a negative end delay--both of which we should have diff --git a/dom/animation/ComputedTiming.h b/dom/animation/ComputedTiming.h index 4a98e3933..addf15865 100644 --- a/dom/animation/ComputedTiming.h +++ b/dom/animation/ComputedTiming.h @@ -29,6 +29,8 @@ struct ComputedTiming // Will equal StickyTimeDuration::Forever() if the animation repeats // indefinitely. StickyTimeDuration mActiveDuration; + // The time within the active interval. + StickyTimeDuration mActiveTime; // The effect end time in local time (i.e. an offset from the effect's // start time). Will equal StickyTimeDuration::Forever() if the animation // plays indefinitely. diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index e4ae7ede8..09d73e617 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -941,6 +941,7 @@ GK_ATOM(ontouchstart, "ontouchstart") GK_ATOM(ontouchend, "ontouchend") GK_ATOM(ontouchmove, "ontouchmove") GK_ATOM(ontouchcancel, "ontouchcancel") +GK_ATOM(ontransitioncancel, "ontransitioncancel") GK_ATOM(ontransitionend, "ontransitionend") GK_ATOM(ontransitionrun, "ontransitionrun") GK_ATOM(ontransitionstart, "ontransitionstart") diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h index ba2427623..61942b251 100644 --- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -1003,6 +1003,10 @@ EVENT(transitionend, eTransitionEnd, EventNameType_All, eTransitionEventClass) +EVENT(transitioncancel, + eTransitionCancel, + EventNameType_All, + eTransitionEventClass) EVENT(animationstart, eAnimationStart, EventNameType_All, diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl index e65a75787..c76dfe211 100644 --- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -131,6 +131,7 @@ interface GlobalEventHandlers { attribute EventHandler onanimationend; attribute EventHandler onanimationiteration; attribute EventHandler onanimationstart; + attribute EventHandler ontransitioncancel; attribute EventHandler ontransitionend; // We will ship transitionrun and transitionstart events // on Firefox 53. (For detail, see bug 1324985) -- cgit v1.2.3 From 3a9cafda4dcbf860862347241515e730707f3581 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 09:04:22 +0100 Subject: Revert - Bug 1324985: Disable firing the transitionrun and transitionstart on Aurora 52 Issue #55 --- dom/animation/test/mochitest.ini | 2 ++ dom/webidl/EventHandler.webidl | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'dom') diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index feb424518..c694e4d25 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -28,6 +28,7 @@ support-files = css-transitions/file_animation-pausing.html css-transitions/file_animation-ready.html css-transitions/file_animation-starttime.html + css-transitions/file_csstransition-events.html css-transitions/file_csstransition-transitionproperty.html css-transitions/file_document-get-animations.html css-transitions/file_effect-target.html @@ -81,6 +82,7 @@ support-files = [css-transitions/test_animation-pausing.html] [css-transitions/test_animation-ready.html] [css-transitions/test_animation-starttime.html] +[css-transitions/test_csstransition-events.html] [css-transitions/test_csstransition-transitionproperty.html] [css-transitions/test_document-get-animations.html] [css-transitions/test_effect-target.html] diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl index c76dfe211..6691ca224 100644 --- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -133,10 +133,8 @@ interface GlobalEventHandlers { attribute EventHandler onanimationstart; attribute EventHandler ontransitioncancel; attribute EventHandler ontransitionend; - // We will ship transitionrun and transitionstart events - // on Firefox 53. (For detail, see bug 1324985) -// attribute EventHandler ontransitionrun; -// attribute EventHandler ontransitionstart; + attribute EventHandler ontransitionrun; + attribute EventHandler ontransitionstart; // CSS-Animation and CSS-Transition legacy handlers. // This handler isn't standard. -- cgit v1.2.3 From 34ef9d4683b3e81b8df1be1a9c38eae331e8c398 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 09:16:03 +0100 Subject: Bug 1264125: Call the queueing events when canceling transition via Style or Script Issue #55 --- dom/animation/Animation.cpp | 23 +++++++++++++++++++++++ dom/animation/Animation.h | 10 ++++++++++ 2 files changed, 33 insertions(+) (limited to 'dom') diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 6dd583ed1..cefdbb76d 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -230,6 +230,10 @@ Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline) return; } + StickyTimeDuration activeTime = mEffect + ? mEffect->GetComputedTiming().mActiveTime + : StickyTimeDuration(); + RefPtr oldTimeline = mTimeline; if (oldTimeline) { oldTimeline->RemoveAnimation(this); @@ -240,6 +244,9 @@ Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline) mHoldTime.SetNull(); } + if (!aTimeline) { + MaybeQueueCancelEvent(activeTime); + } UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async); } @@ -771,6 +778,10 @@ Animation::CancelNoUpdate() DispatchPlaybackEvent(NS_LITERAL_STRING("cancel")); + StickyTimeDuration activeTime = mEffect + ? mEffect->GetComputedTiming().mActiveTime + : StickyTimeDuration(); + mHoldTime.SetNull(); mStartTime.SetNull(); @@ -779,6 +790,7 @@ Animation::CancelNoUpdate() if (mTimeline) { mTimeline->RemoveAnimation(this); } + MaybeQueueCancelEvent(activeTime); } void @@ -819,6 +831,17 @@ Animation::HasLowerCompositeOrderThan(const Animation& aOther) const return thisTransition->HasLowerCompositeOrderThan(*otherTransition); } if (thisTransition || otherTransition) { + // Cancelled transitions no longer have an owning element. To be strictly + // correct we should store a strong reference to the owning element + // so that if we arrive here while sorting cancel events, we can sort + // them in the correct order. + // + // However, given that cancel events are almost always queued + // synchronously in some deterministic manner, we can be fairly sure + // that cancel events will be dispatched in a deterministic order + // (which is our only hard requirement until specs say otherwise). + // Furthermore, we only reach here when we have events with equal + // timestamps so this is an edge case we can probably ignore for now. return thisTransition; } } diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index c59d7d6ce..3263b30c4 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -326,6 +326,16 @@ public: void NotifyEffectTimingUpdated(); + /** + * Used by subclasses to synchronously queue a cancel event in situations + * where the Animation may have been cancelled. + * + * We need to do this synchronously because after a CSS animation/transition + * is canceled, it will be released by its owning element and may not still + * exist when we would normally go to queue events on the next tick. + */ + virtual void MaybeQueueCancelEvent(StickyTimeDuration aActiveTime) {}; + protected: void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime); void SilentlySetPlaybackRate(double aPlaybackRate); -- cgit v1.2.3 From dcc00ffadf64270b0ae82431f5b71c527590e91b Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 09:18:49 +0100 Subject: Bug 1264125: Queue CSS related event when setting null target effect Issue #55 --- dom/animation/Animation.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'dom') diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index cefdbb76d..242a0c6d6 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -729,8 +729,10 @@ TimeStamp Animation::ElapsedTimeToTimeStamp( const StickyTimeDuration& aElapsedTime) const { - return AnimationTimeToTimeStamp(aElapsedTime + - mEffect->SpecifiedTiming().mDelay); + TimeDuration delay = mEffect + ? mEffect->SpecifiedTiming().mDelay + : TimeDuration(); + return AnimationTimeToTimeStamp(aElapsedTime + delay); } -- cgit v1.2.3 From aade91b13a50ee4f246016fa8d8d1561f58f80ee Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 11:45:38 +0100 Subject: moebius#89: DOM - implement animationcancel event Issue #55 --- dom/animation/Animation.cpp | 13 +++++++++++-- dom/animation/ComputedTiming.h | 4 ++-- dom/base/nsGkAtomList.h | 1 + dom/events/EventNameList.h | 4 ++++ dom/webidl/EventHandler.webidl | 1 + 5 files changed, 19 insertions(+), 4 deletions(-) (limited to 'dom') diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 242a0c6d6..bd318f79e 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -787,12 +787,21 @@ Animation::CancelNoUpdate() mHoldTime.SetNull(); mStartTime.SetNull(); - UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async); - if (mTimeline) { mTimeline->RemoveAnimation(this); } MaybeQueueCancelEvent(activeTime); + + // When an animation is cancelled it no longer needs further ticks from the + // timeline. However, if we queued a cancel event and this was the last + // animation attached to the timeline, the timeline will stop observing the + // refresh driver and there may be no subsequent refresh driver tick for + // dispatching the queued event. + // + // By calling UpdateTiming *after* removing ourselves from our timeline, we + // ensure the timeline will register with the refresh driver for at least one + // more tick. + UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async); } void diff --git a/dom/animation/ComputedTiming.h b/dom/animation/ComputedTiming.h index addf15865..525d59d23 100644 --- a/dom/animation/ComputedTiming.h +++ b/dom/animation/ComputedTiming.h @@ -64,12 +64,12 @@ struct ComputedTiming } enum class AnimationPhase { - Null, // Not sampled (null sample time) + Idle, // Not sampled (null sample time) Before, // Sampled prior to the start of the active interval Active, // Sampled within the active interval After // Sampled after (or at) the end of the active interval }; - AnimationPhase mPhase = AnimationPhase::Null; + AnimationPhase mPhase = AnimationPhase::Idle; ComputedTimingFunction::BeforeFlag mBeforeFlag = ComputedTimingFunction::BeforeFlag::Unset; diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 09d73e617..948487083 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -694,6 +694,7 @@ GK_ATOM(onadapterremoved, "onadapterremoved") GK_ATOM(onafterprint, "onafterprint") GK_ATOM(onafterscriptexecute, "onafterscriptexecute") GK_ATOM(onalerting, "onalerting") +GK_ATOM(onanimationcancel, "onanimationcancel") GK_ATOM(onanimationend, "onanimationend") GK_ATOM(onanimationiteration, "onanimationiteration") GK_ATOM(onanimationstart, "onanimationstart") diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h index 61942b251..00478c87b 100644 --- a/dom/events/EventNameList.h +++ b/dom/events/EventNameList.h @@ -1019,6 +1019,10 @@ EVENT(animationiteration, eAnimationIteration, EventNameType_All, eAnimationEventClass) +EVENT(animationcancel, + eAnimationCancel, + EventNameType_All, + eAnimationEventClass) // Webkit-prefixed versions of Transition & Animation events, for web compat: EVENT(webkitAnimationEnd, diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl index 6691ca224..306372ff1 100644 --- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -128,6 +128,7 @@ interface GlobalEventHandlers { attribute EventHandler onmozpointerlockerror; // CSS-Animation and CSS-Transition handlers. + attribute EventHandler onanimationcancel; attribute EventHandler onanimationend; attribute EventHandler onanimationiteration; attribute EventHandler onanimationstart; -- cgit v1.2.3 From c58cec26c73da9a5c48f7d75555c6a2409965693 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 11:55:23 +0100 Subject: Bug 1202333: AnimationEvent elapsedTime should reflect playbackRate (added tests) Issue #55 --- .../test/css-animations/file_event-dispatch.html | 252 +++++++++++++++++++++ .../test/css-animations/file_event-order.html | 160 +++++++++++++ .../test/css-animations/test_event-dispatch.html | 15 ++ .../test/css-animations/test_event-order.html | 15 ++ dom/animation/test/mochitest.ini | 4 + dom/events/test/test_legacy_event.html | 21 +- 6 files changed, 453 insertions(+), 14 deletions(-) create mode 100644 dom/animation/test/css-animations/file_event-dispatch.html create mode 100644 dom/animation/test/css-animations/file_event-order.html create mode 100644 dom/animation/test/css-animations/test_event-dispatch.html create mode 100644 dom/animation/test/css-animations/test_event-order.html (limited to 'dom') diff --git a/dom/animation/test/css-animations/file_event-dispatch.html b/dom/animation/test/css-animations/file_event-dispatch.html new file mode 100644 index 000000000..266205bc3 --- /dev/null +++ b/dom/animation/test/css-animations/file_event-dispatch.html @@ -0,0 +1,252 @@ + + +Tests for CSS animation event dispatch + + + + + + + diff --git a/dom/animation/test/css-animations/file_event-order.html b/dom/animation/test/css-animations/file_event-order.html new file mode 100644 index 000000000..da78b6541 --- /dev/null +++ b/dom/animation/test/css-animations/file_event-order.html @@ -0,0 +1,160 @@ + + +Tests for CSS animation event order + + + + + + + diff --git a/dom/animation/test/css-animations/test_event-dispatch.html b/dom/animation/test/css-animations/test_event-dispatch.html new file mode 100644 index 000000000..de3be0301 --- /dev/null +++ b/dom/animation/test/css-animations/test_event-dispatch.html @@ -0,0 +1,15 @@ + + + + +
+ + diff --git a/dom/animation/test/css-animations/test_event-order.html b/dom/animation/test/css-animations/test_event-order.html new file mode 100644 index 000000000..57f1f3876 --- /dev/null +++ b/dom/animation/test/css-animations/test_event-order.html @@ -0,0 +1,15 @@ + + + + +
+ + diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index c694e4d25..07e04d4d6 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -19,6 +19,8 @@ support-files = css-animations/file_document-get-animations.html css-animations/file_effect-target.html css-animations/file_element-get-animations.html + css-animations/file_event-dispatch.html + css-animations/file_event-order.html css-animations/file_keyframeeffect-getkeyframes.html css-animations/file_pseudoElement-get-animations.html css-transitions/file_animation-cancel.html @@ -73,6 +75,8 @@ support-files = [css-animations/test_document-get-animations.html] [css-animations/test_effect-target.html] [css-animations/test_element-get-animations.html] +[css-animations/test_event-dispatch.html] +[css-animations/test_event-order.html] [css-animations/test_keyframeeffect-getkeyframes.html] [css-animations/test_pseudoElement-get-animations.html] [css-transitions/test_animation-cancel.html] diff --git a/dom/events/test/test_legacy_event.html b/dom/events/test/test_legacy_event.html index d772be106..b2105a6df 100644 --- a/dom/events/test/test_legacy_event.html +++ b/dom/events/test/test_legacy_event.html @@ -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 -- cgit v1.2.3 From 35c61a027dc6f4d58ca9d33e06da79adf2503ebd Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Wed, 14 Mar 2018 12:13:01 +0100 Subject: Bug 1264125: Fire transitioncancel event when a transition is canceled (added tests + style clean up) Issue #55 --- dom/animation/ComputedTiming.h | 2 +- .../css-transitions/file_animation-cancel.html | 182 +++++--- .../css-transitions/file_csstransition-events.html | 223 ---------- .../test/css-transitions/file_event-dispatch.html | 474 +++++++++++++++++++++ .../test/css-transitions/file_setting-effect.html | 9 + .../css-transitions/test_csstransition-events.html | 14 - .../test/css-transitions/test_event-dispatch.html | 14 + dom/animation/test/mochitest.ini | 4 +- 8 files changed, 625 insertions(+), 297 deletions(-) delete mode 100644 dom/animation/test/css-transitions/file_csstransition-events.html create mode 100644 dom/animation/test/css-transitions/file_event-dispatch.html delete mode 100644 dom/animation/test/css-transitions/test_csstransition-events.html create mode 100644 dom/animation/test/css-transitions/test_event-dispatch.html (limited to 'dom') diff --git a/dom/animation/ComputedTiming.h b/dom/animation/ComputedTiming.h index 525d59d23..b1c6674a5 100644 --- a/dom/animation/ComputedTiming.h +++ b/dom/animation/ComputedTiming.h @@ -30,7 +30,7 @@ struct ComputedTiming // indefinitely. StickyTimeDuration mActiveDuration; // The time within the active interval. - StickyTimeDuration mActiveTime; + StickyTimeDuration mActiveTime; // The effect end time in local time (i.e. an offset from the effect's // start time). Will equal StickyTimeDuration::Forever() if the animation // plays indefinitely. diff --git a/dom/animation/test/css-transitions/file_animation-cancel.html b/dom/animation/test/css-transitions/file_animation-cancel.html index 6094b383f..71f02fb11 100644 --- a/dom/animation/test/css-transitions/file_animation-cancel.html +++ b/dom/animation/test/css-transitions/file_animation-cancel.html @@ -11,13 +11,12 @@ promise_test(function(t) { div.style.transition = 'margin-left 100s'; div.style.marginLeft = '1000px'; - flushComputedStyle(div); - var animation = div.getAnimations()[0]; - return animation.ready.then(waitForFrame).then(function() { + var transition = div.getAnimations()[0]; + return transition.ready.then(waitForFrame).then(function() { assert_not_equals(getComputedStyle(div).marginLeft, '1000px', 'transform style is animated before cancelling'); - animation.cancel(); + transition.cancel(); assert_equals(getComputedStyle(div).marginLeft, div.style.marginLeft, 'transform style is no longer animated after cancelling'); }); @@ -29,45 +28,21 @@ promise_test(function(t) { div.style.transition = 'margin-left 100s'; div.style.marginLeft = '1000px'; - flushComputedStyle(div); - - div.addEventListener('transitionend', function() { - assert_unreached('Got unexpected end event on cancelled transition'); - }); - - var animation = div.getAnimations()[0]; - return animation.ready.then(function() { - // Seek to just before the end then cancel - animation.currentTime = 99.9 * 1000; - animation.cancel(); - // Then wait a couple of frames and check that no event was dispatched - return waitForAnimationFrames(2); - }); -}, 'Cancelled CSS transitions do not dispatch events'); - -promise_test(function(t) { - var div = addDiv(t, { style: 'margin-left: 0px' }); - flushComputedStyle(div); - - div.style.transition = 'margin-left 100s'; - div.style.marginLeft = '1000px'; - flushComputedStyle(div); - - var animation = div.getAnimations()[0]; - return animation.ready.then(function() { - animation.cancel(); + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + transition.cancel(); assert_equals(getComputedStyle(div).marginLeft, '1000px', 'margin-left style is not animated after cancelling'); - animation.play(); + transition.play(); assert_equals(getComputedStyle(div).marginLeft, '0px', 'margin-left style is animated after re-starting transition'); - return animation.ready; + return transition.ready; }).then(function() { - assert_equals(animation.playState, 'running', + assert_equals(transition.playState, 'running', 'Transition succeeds in running after being re-started'); }); -}, 'After cancelling a transition, it can still be re-used'); +}, 'After canceling a transition, it can still be re-used'); promise_test(function(t) { var div = addDiv(t, { style: 'margin-left: 0px' }); @@ -75,20 +50,19 @@ promise_test(function(t) { div.style.transition = 'margin-left 100s'; div.style.marginLeft = '1000px'; - flushComputedStyle(div); - var animation = div.getAnimations()[0]; - return animation.ready.then(function() { - animation.finish(); - animation.cancel(); + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + transition.finish(); + transition.cancel(); assert_equals(getComputedStyle(div).marginLeft, '1000px', 'margin-left style is not animated after cancelling'); - animation.play(); + transition.play(); assert_equals(getComputedStyle(div).marginLeft, '0px', 'margin-left style is animated after re-starting transition'); - return animation.ready; + return transition.ready; }).then(function() { - assert_equals(animation.playState, 'running', + assert_equals(transition.playState, 'running', 'Transition succeeds in running after being re-started'); }); }, 'After cancelling a finished transition, it can still be re-used'); @@ -99,10 +73,9 @@ test(function(t) { div.style.transition = 'margin-left 100s'; div.style.marginLeft = '1000px'; - flushComputedStyle(div); - var animation = div.getAnimations()[0]; - animation.cancel(); + var transition = div.getAnimations()[0]; + transition.cancel(); assert_equals(getComputedStyle(div).marginLeft, '1000px', 'margin-left style is not animated after cancelling'); @@ -113,7 +86,7 @@ test(function(t) { assert_equals(getComputedStyle(div).marginLeft, '1000px', 'margin-left style is still not animated after updating' + ' transition-duration'); - assert_equals(animation.playState, 'idle', + assert_equals(transition.playState, 'idle', 'Transition is still idle after updating transition-duration'); }, 'After cancelling a transition, updating transition properties doesn\'t make' + ' it live again'); @@ -124,15 +97,14 @@ promise_test(function(t) { div.style.transition = 'margin-left 100s'; div.style.marginLeft = '1000px'; - flushComputedStyle(div); - var animation = div.getAnimations()[0]; - return animation.ready.then(function() { - assert_equals(animation.playState, 'running'); + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); div.style.display = 'none'; return waitForFrame(); }).then(function() { - assert_equals(animation.playState, 'idle'); + assert_equals(transition.playState, 'idle'); assert_equals(getComputedStyle(div).marginLeft, '1000px'); }); }, 'Setting display:none on an element cancels its transitions'); @@ -147,19 +119,115 @@ promise_test(function(t) { childDiv.style.transition = 'margin-left 100s'; childDiv.style.marginLeft = '1000px'; - flushComputedStyle(childDiv); - var animation = childDiv.getAnimations()[0]; - return animation.ready.then(function() { - assert_equals(animation.playState, 'running'); + var transition = childDiv.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); parentDiv.style.display = 'none'; return waitForFrame(); }).then(function() { - assert_equals(animation.playState, 'idle'); + assert_equals(transition.playState, 'idle'); assert_equals(getComputedStyle(childDiv).marginLeft, '1000px'); }); }, 'Setting display:none cancels transitions on a child element'); +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + // Set an unrecognized property value + div.style.transitionProperty = 'none'; + flushComputedStyle(div); + return waitForFrame(); + }).then(function() { + assert_equals(transition.playState, 'idle'); + assert_equals(getComputedStyle(div).marginLeft, '1000px'); + }); +}, 'Removing a property from transition-property cancels transitions on that '+ + 'property'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + div.style.transition = 'margin-top 10s -10s'; // combined duration is zero + flushComputedStyle(div); + return waitForFrame(); + }).then(function() { + assert_equals(transition.playState, 'idle'); + assert_equals(getComputedStyle(div).marginLeft, '1000px'); + }); +}, 'Setting zero combined duration'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + div.style.marginLeft = '2000px'; + flushComputedStyle(div); + return waitForFrame(); + }).then(function() { + assert_equals(transition.playState, 'idle'); + }); +}, 'Changing style to another interpolable value cancels the original ' + + 'transition'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + div.style.marginLeft = 'auto'; + flushComputedStyle(div); + return waitForFrame(); + }).then(function() { + assert_equals(div.getAnimations().length, 0, + 'There should be no transitions'); + assert_equals(transition.playState, 'idle'); + }); +}, 'An after-change style value can\'t be interpolated'); + +promise_test(function(t) { + var div = addDiv(t, { style: 'margin-left: 0px' }); + flushComputedStyle(div); + + div.style.transition = 'margin-left 100s'; + div.style.marginLeft = '1000px'; + + var transition = div.getAnimations()[0]; + return transition.ready.then(function() { + assert_equals(transition.playState, 'running'); + div.style.marginLeft = '0px'; + flushComputedStyle(div); + return waitForFrame(); + }).then(function() { + assert_equals(transition.playState, 'idle'); + }); +}, 'Reversing a running transition cancels the original transition'); + done(); diff --git a/dom/animation/test/css-transitions/file_csstransition-events.html b/dom/animation/test/css-transitions/file_csstransition-events.html deleted file mode 100644 index 5011bc130..000000000 --- a/dom/animation/test/css-transitions/file_csstransition-events.html +++ /dev/null @@ -1,223 +0,0 @@ - - -Tests for CSS-Transition events - - - - - - diff --git a/dom/animation/test/css-transitions/file_event-dispatch.html b/dom/animation/test/css-transitions/file_event-dispatch.html new file mode 100644 index 000000000..7140cda36 --- /dev/null +++ b/dom/animation/test/css-transitions/file_event-dispatch.html @@ -0,0 +1,474 @@ + + +Tests for CSS-Transition events + + + + + + diff --git a/dom/animation/test/css-transitions/file_setting-effect.html b/dom/animation/test/css-transitions/file_setting-effect.html index c61877194..81279ea55 100644 --- a/dom/animation/test/css-transitions/file_setting-effect.html +++ b/dom/animation/test/css-transitions/file_setting-effect.html @@ -7,6 +7,8 @@ promise_test(function(t) { var div = addDiv(t); + var watcher = new EventWatcher(t, div, [ 'transitionend', + 'transitioncancel' ]); div.style.left = '0px'; div.style.transition = 'left 100s'; @@ -20,11 +22,14 @@ promise_test(function(t) { assert_equals(transition.transitionProperty, 'left'); assert_equals(transition.playState, 'finished'); assert_equals(window.getComputedStyle(div).left, '100px'); + return watcher.wait_for('transitionend'); }); }, 'Test for removing a transition effect'); promise_test(function(t) { var div = addDiv(t); + var watcher = new EventWatcher(t, div, [ 'transitionend', + 'transitioncancel' ]); div.style.left = '0px'; div.style.transition = 'left 100s'; @@ -46,6 +51,8 @@ promise_test(function(t) { promise_test(function(t) { var div = addDiv(t); + var watcher = new EventWatcher(t, div, [ 'transitionend', + 'transitioncancel' ]); div.style.left = '0px'; div.style.width = '0px'; @@ -65,6 +72,8 @@ promise_test(function(t) { promise_test(function(t) { var div = addDiv(t); + var watcher = new EventWatcher(t, div, [ 'transitionend', + 'transitioncancel' ]); div.style.left = '0px'; div.style.width = '0px'; diff --git a/dom/animation/test/css-transitions/test_csstransition-events.html b/dom/animation/test/css-transitions/test_csstransition-events.html deleted file mode 100644 index 92559ad67..000000000 --- a/dom/animation/test/css-transitions/test_csstransition-events.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -
- diff --git a/dom/animation/test/css-transitions/test_event-dispatch.html b/dom/animation/test/css-transitions/test_event-dispatch.html new file mode 100644 index 000000000..c90431cd1 --- /dev/null +++ b/dom/animation/test/css-transitions/test_event-dispatch.html @@ -0,0 +1,14 @@ + + + + +
+ diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index 07e04d4d6..db6dffada 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -30,11 +30,11 @@ support-files = css-transitions/file_animation-pausing.html css-transitions/file_animation-ready.html css-transitions/file_animation-starttime.html - css-transitions/file_csstransition-events.html css-transitions/file_csstransition-transitionproperty.html css-transitions/file_document-get-animations.html css-transitions/file_effect-target.html css-transitions/file_element-get-animations.html + css-transitions/file_event-dispatch.html css-transitions/file_keyframeeffect-getkeyframes.html css-transitions/file_pseudoElement-get-animations.html css-transitions/file_setting-effect.html @@ -86,11 +86,11 @@ support-files = [css-transitions/test_animation-pausing.html] [css-transitions/test_animation-ready.html] [css-transitions/test_animation-starttime.html] -[css-transitions/test_csstransition-events.html] [css-transitions/test_csstransition-transitionproperty.html] [css-transitions/test_document-get-animations.html] [css-transitions/test_effect-target.html] [css-transitions/test_element-get-animations.html] +[css-transitions/test_event-dispatch.html] [css-transitions/test_keyframeeffect-getkeyframes.html] [css-transitions/test_pseudoElement-get-animations.html] [css-transitions/test_setting-effect.html] -- cgit v1.2.3