[Web Animations] Make imported/mozilla/css-animations/test_event-dispatch.html pass...
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2018 21:33:53 +0000 (21:33 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2018 21:33:53 +0000 (21:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=183845

Reviewed by Dean Jackson.

LayoutTests/imported/mozilla:

Add test expectations for previously crashing tests, update other expectations with progressions, including
the two event dispatch tests which now pass all assertions.

* css-animations/test_animation-finish-expected.txt:
* css-animations/test_animation-pausing-expected.txt:
* css-animations/test_animation-playstate-expected.txt:
* css-animations/test_animation-ready-expected.txt:
* css-animations/test_animation-starttime-expected.txt:
* css-animations/test_event-dispatch-expected.txt:
* css-animations/test_event-order-expected.txt:
* css-animations/test_setting-effect-expected.txt: Added.
* css-transitions/test_animation-cancel-expected.txt:
* css-transitions/test_animation-computed-timing-expected.txt:
* css-transitions/test_animation-currenttime-expected.txt:
* css-transitions/test_animation-pausing-expected.txt:
* css-transitions/test_animation-starttime-expected.txt:
* css-transitions/test_event-dispatch-expected.txt:
* css-transitions/test_setting-effect-expected.txt: Added.

Source/WebCore:

Finish the work to get DOM events for CSS Animations and CSS Transitions dispatching as specified.

* animation/AnimationEffectReadOnly.cpp: Move timeEpsilon to be shared as part of WebAnimationUtilities.h since we now need it in
WebAnimation::timeToNextRequiredTick().
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::updateCSSAnimationsForElement): We add a pre-emptive return clause when we know that the AnimationList
for previous and current styles are a match.
* animation/CSSTransition.cpp:
(WebCore::CSSTransition::matchesBackingAnimationAndStyles const): Ensure we have a valid effect before downcasting it.
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::initialize): We need to call pause() for declarative animations that aren't playing so that the animation's
playState is set correctly and the animation is not idle.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::updateAnimationSchedule): We no longer need to pass the current time to timeToNextRequiredTick() since the method has
been reworked to use the animation's current time, which is based on the timeline's current time.
(WebCore::DocumentTimeline::updateAnimations): Avoid creating a copy when iterating over pending hardware animations.
* animation/KeyframeEffectReadOnly.cpp:
(WebCore::KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes const): We should never generate new blending keyframes if the
old and new styles contain the same value, since there would be no transition between two equal values, and we should only look at whether the new
style value and the recorded target value differ to determine if new blending keyframes are necessary.
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::timeToNextRequiredTick const): We correct our scheduling code which was shown to be broken in several of the newly-imported
Mozilla tests. Any running animation is now scheduled to invalidate again on the next tick, and we use timeEpsilon from WebAnimationUtilities.h to
correctly check if we're right at the active threshold, when we also invalidate on the next tick. If our current time is negative, in other words
when the animation has not yet started, we schedule this animation's next tick to be the negative of that value. In all other cases, no invalidation
needs to be scheduled.
* animation/WebAnimation.h: We move updateFinishedState() to private since this method is not actually used outside of WebAnimation.cpp.
* animation/WebAnimationUtilities.h: Move timeEpsilon to be shared as part of WebAnimationUtilities.h.

LayoutTests:

A couple of crashing tests no longer crash and a couple are now reliably passing.

* TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@229864 268f45cc-cd09-0410-ab3c-d52691b4dbfc

28 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/imported/mozilla/ChangeLog
LayoutTests/imported/mozilla/css-animations/test_animation-finish-expected.txt
LayoutTests/imported/mozilla/css-animations/test_animation-pausing-expected.txt
LayoutTests/imported/mozilla/css-animations/test_animation-playstate-expected.txt
LayoutTests/imported/mozilla/css-animations/test_animation-ready-expected.txt
LayoutTests/imported/mozilla/css-animations/test_animation-starttime-expected.txt
LayoutTests/imported/mozilla/css-animations/test_event-dispatch-expected.txt
LayoutTests/imported/mozilla/css-animations/test_event-order-expected.txt
LayoutTests/imported/mozilla/css-animations/test_setting-effect-expected.txt [new file with mode: 0644]
LayoutTests/imported/mozilla/css-transitions/test_animation-cancel-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_animation-computed-timing-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_animation-currenttime-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_animation-pausing-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_animation-starttime-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_event-dispatch-expected.txt
LayoutTests/imported/mozilla/css-transitions/test_setting-effect-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/animation/AnimationEffectReadOnly.cpp
Source/WebCore/animation/AnimationTimeline.cpp
Source/WebCore/animation/CSSTransition.cpp
Source/WebCore/animation/DeclarativeAnimation.cpp
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/KeyframeEffectReadOnly.cpp
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/animation/WebAnimation.h
Source/WebCore/animation/WebAnimationUtilities.h

index 3750744..939203e 100644 (file)
@@ -1,3 +1,14 @@
+2018-03-21  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Make imported/mozilla/css-animations/test_event-dispatch.html pass reliably
+        https://bugs.webkit.org/show_bug.cgi?id=183845
+
+        Reviewed by Dean Jackson.
+
+        A couple of crashing tests no longer crash and a couple are now reliably passing.
+
+        * TestExpectations:
+
 2018-03-22  Ross Kirsling  <ross.kirsling@sony.com>
 
         Unreviewed gardening. Update WinCairo TestExpectations and drop the unnecessary suffix.
index da708d5..51e62c8 100644 (file)
@@ -1733,15 +1733,13 @@ webkit.org/b/183839 imported/mozilla/css-transitions/test_effect-target.html [ P
 webkit.org/b/183840 imported/mozilla/css-animations/test_document-get-animations.html [ Pass Failure Timeout ]
 webkit.org/b/183841 imported/mozilla/css-transitions/test_element-get-animations.html [ Pass Failure Timeout ]
 webkit.org/b/183842 imported/mozilla/css-animations/test_effect-target.html [ Pass Failure Timeout ]
-webkit.org/b/183843 imported/mozilla/css-transitions/test_event-dispatch.html [ Pass Failure Timeout ]
 webkit.org/b/183844 imported/mozilla/css-animations/test_element-get-animations.html [ Pass Failure Timeout ]
-webkit.org/b/183845 imported/mozilla/css-animations/test_event-dispatch.html [ Pass Failure Timeout ]
 webkit.org/b/183846 imported/mozilla/css-transitions/test_pseudoElement-get-animations.html [ Pass Failure Timeout ]
 webkit.org/b/183847 imported/mozilla/css-animations/test_event-order.html [ Pass Failure Timeout ]
+webkit.org/b/183849 imported/mozilla/css-animations/test_setting-effect.html [ Pass Failure Timeout ]
+webkit.org/b/183850 imported/mozilla/css-transitions/test_setting-effect.html [ Pass Failure Timeout ]
 
 webkit.org/b/183848 imported/mozilla/css-animations/test_keyframeeffect-getkeyframes.html [ Crash ]
-webkit.org/b/183849 imported/mozilla/css-animations/test_setting-effect.html [ Crash ]
-webkit.org/b/183850 imported/mozilla/css-transitions/test_setting-effect.html [ Crash ]
 
 webkit.org/b/177440 imported/w3c/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_null.tentative.html [ Pass Failure ]
 
index cd80978..9fdecc1 100644 (file)
@@ -1,5 +1,31 @@
 2018-03-21  Antoine Quint  <graouts@apple.com>
 
+        [Web Animations] Make imported/mozilla/css-animations/test_event-dispatch.html pass reliably
+        https://bugs.webkit.org/show_bug.cgi?id=183845
+
+        Reviewed by Dean Jackson.
+
+        Add test expectations for previously crashing tests, update other expectations with progressions, including
+        the two event dispatch tests which now pass all assertions.
+
+        * css-animations/test_animation-finish-expected.txt:
+        * css-animations/test_animation-pausing-expected.txt:
+        * css-animations/test_animation-playstate-expected.txt:
+        * css-animations/test_animation-ready-expected.txt:
+        * css-animations/test_animation-starttime-expected.txt:
+        * css-animations/test_event-dispatch-expected.txt:
+        * css-animations/test_event-order-expected.txt:
+        * css-animations/test_setting-effect-expected.txt: Added.
+        * css-transitions/test_animation-cancel-expected.txt:
+        * css-transitions/test_animation-computed-timing-expected.txt:
+        * css-transitions/test_animation-currenttime-expected.txt:
+        * css-transitions/test_animation-pausing-expected.txt:
+        * css-transitions/test_animation-starttime-expected.txt:
+        * css-transitions/test_event-dispatch-expected.txt:
+        * css-transitions/test_setting-effect-expected.txt: Added.
+
+2018-03-21  Antoine Quint  <graouts@apple.com>
+
         [Web Animations] Ensure animationcancel and transitioncancel events are dispatched
         https://bugs.webkit.org/show_bug.cgi?id=183864
 
index a678010..71029af 100644 (file)
@@ -1,6 +1,6 @@
 
 FAIL Test exceptions when finishing infinite animation assert_true: Expect InvalidStateError exception trying to finish an infinite animation expected true got false
-FAIL Test finish() while paused undefined is not an object (evaluating 'animation.ready')
-FAIL Test finish() while pause-pending with positive playbackRate undefined is not an object (evaluating 'animation.playbackRate = 2')
-FAIL Test finish() while pause-pending with negative playbackRate undefined is not an object (evaluating 'animation.playbackRate = -2')
+PASS Test finish() while paused 
+PASS Test finish() while pause-pending with positive playbackRate 
+PASS Test finish() while pause-pending with negative playbackRate 
 
index 4f6fa5b..da2838c 100644 (file)
@@ -1,5 +1,5 @@
 
-FAIL play() overrides animation-play-state undefined is not an object (evaluating 'animation.play')
+PASS play() overrides animation-play-state 
 FAIL pause() overrides animation-play-state undefined is not an object (evaluating 'animation.pause')
 FAIL play() is overridden by later setting "animation-play-state: paused" undefined is not an object (evaluating 'animation.play')
 FAIL play() flushes pending changes to animation-play-state first assert_greater_than: Playing value of margin-left is increasing expected a number greater than 0 but got 0
index 76903c0..47d7af8 100644 (file)
@@ -1,7 +1,7 @@
 
 PASS Animation returns correct playState when running 
-FAIL Animation returns correct playState when paused undefined is not an object (evaluating 'animation.playState')
+PASS Animation returns correct playState when paused 
 PASS Animation.playState updates when paused by script 
-FAIL Animation.playState updates when resumed by setting style undefined is not an object (evaluating 'animation.playState')
+FAIL Animation.playState updates when resumed by setting style assert_equals: Animation.playState reports running after updating animation-play-state (got: paused) expected "running" but got "paused"
 PASS Animation returns correct playState when cancelled 
 
index 02a277f..437a7b1 100644 (file)
@@ -1,5 +1,5 @@
 
-FAIL A new ready promise is created when setting animation-play-state: running undefined is not an object (evaluating 'animation.ready')
+FAIL A new ready promise is created when setting animation-play-state: running assert_not_equals: After updating animation-play-state a new ready promise object is created got disallowed value object "[object Promise]"
 PASS ready promise is rejected when an animation is canceled by resetting the animation property 
 PASS ready promise is rejected when an animation is cancelled by updating the animation property 
 FAIL A new ready promise is created when setting animation-play-state: paused assert_not_equals: A new Promise object is generated when setting animation-play-state: paused got disallowed value object "[object Promise]"
index 6f4f803..ea77245 100644 (file)
@@ -1,8 +1,8 @@
 
 PASS startTime of a newly created (play-pending) animation is unresolved 
-FAIL startTime of a newly created (pause-pending) animation is unresolved undefined is not an object (evaluating 'animation.startTime')
+PASS startTime of a newly created (pause-pending) animation is unresolved 
 PASS startTime is resolved when running 
-FAIL startTime is unresolved when paused undefined is not an object (evaluating 'animation.ready')
+PASS startTime is unresolved when paused 
 PASS startTime while pause-pending and play-pending 
 PASS startTime while play-pending from finished state 
 PASS startTime while play-pending from finished state using finish() 
@@ -17,6 +17,6 @@ PASS Redundant change, active -> after, then back
 PASS Redundant change, after -> before, then back 
 PASS Redundant change, after -> active, then back 
 PASS Setting startTime to null 
-FAIL Animation.startTime after pausing assert_equals: Animation.playState is "paused" after pause() call expected "paused" but got "running"
+PASS Animation.startTime after pausing 
 PASS Animation.startTime after cancelling 
 
index c06f80d..5220817 100644 (file)
@@ -1,3 +1,23 @@
-#PID UNRESPONSIVE - com.apple.WebKit.WebContent.Development (pid 13559)
-FAIL: Timed out waiting for notifyDone to be called
+
+PASS Idle -> Active 
+PASS Idle -> After 
+PASS Before -> Active 
+PASS Before -> After 
+PASS Active -> Idle, display: none 
+PASS Active -> Idle, setting Animation.timeline = null 
+PASS Active -> Idle, calling Animation.cancel() 
+PASS Active -> Before 
+PASS Active -> After 
+PASS After -> Before 
+PASS After -> Active 
+PASS Active -> Active (forwards) 
+PASS Active -> Active (backwards) 
+PASS Active -> Idle -> Active: animationstart is fired by restarting animation 
+PASS Negative playbackRate sanity test(Before -> Active -> Before) 
+PASS Call Animation.cancel after cancelling animation. 
+PASS Restart animation after cancelling animation immediately. 
+PASS Call Animation.cancel after restarting animation immediately. 
+PASS Set timeline and play transition after clearing the timeline. 
+PASS Set null target effect after cancelling the animation. 
+PASS Cancel the animation after clearing the target effect. 
 
index d6d7311..bfd3031 100644 (file)
@@ -1,3 +1,6 @@
-#PID UNRESPONSIVE - com.apple.WebKit.WebContent.Development (pid 13563)
-FAIL: Timed out waiting for notifyDone to be called
+
+PASS Test same events are ordered by elements. 
+FAIL Test start and iteration events are ordered by time. assert_equals: Event type should match expected "animationstart" but got "animationiteration"
+FAIL Test iteration and end events are ordered by time. assert_equals: Event type should match expected "animationend" but got "animationiteration"
+FAIL Test start and end events are sorted correctly when fired simultaneously assert_equals: Event target should match expected Element node <div style="animation: anim 100s 100s"></div> but got Element node <div style="animation: anim 100s 2"></div>
 
diff --git a/LayoutTests/imported/mozilla/css-animations/test_setting-effect-expected.txt b/LayoutTests/imported/mozilla/css-animations/test_setting-effect-expected.txt
new file mode 100644 (file)
index 0000000..f0009b3
--- /dev/null
@@ -0,0 +1,8 @@
+
+PASS Setting a null effect on a running animation fires an animationend event 
+PASS Replacing an animation's effect with an effect that targets a different property should update both properties 
+PASS Replacing an animation's effect with a shorter one that should have already finished, the animation finishes immediately 
+PASS A play-pending animation's effect whose effect is replaced still exits the pending state 
+PASS The event is dispatched at the original element even after setting an effect with a different target element 
+PASS After replacing a finished animation's effect with a longer one it fires an animationstart event 
+
index 560d877..77cb3e4 100644 (file)
@@ -1,13 +1,13 @@
 
-FAIL Animated style is cleared after cancelling a running CSS transition assert_equals: transform style is no longer animated after cancelling expected "1000px" but got "0.0030002400744706392px"
-FAIL After canceling a transition, it can still be re-used assert_equals: margin-left style is animated after re-starting transition expected "0px" but got "1000px"
-FAIL After cancelling a finished transition, it can still be re-used assert_equals: margin-left style is not animated after cancelling expected "1000px" but got "0.044057685881853104px"
+PASS Animated style is cleared after cancelling a running CSS transition 
+PASS After canceling a transition, it can still be re-used 
+PASS After cancelling a finished transition, it can still be re-used 
 PASS After cancelling a transition, updating transition properties doesn't make it live again 
 PASS Setting display:none on an element cancels its transitions 
 FAIL Setting display:none cancels transitions on a child element assert_equals: expected "idle" but got "running"
 PASS Removing a property from transition-property cancels transitions on that property 
 PASS Setting zero combined duration 
 FAIL Changing style to another interpolable value cancels the original transition assert_equals: expected "idle" but got "finished"
-FAIL An after-change style value can't be interpolated assert_equals: expected "idle" but got "finished"
-FAIL Reversing a running transition cancels the original transition assert_equals: expected "idle" but got "finished"
+FAIL An after-change style value can't be interpolated assert_equals: There should be no transitions expected 0 but got 1
+FAIL Reversing a running transition cancels the original transition assert_equals: expected "idle" but got "running"
 
index 7034ba8..8e496f7 100644 (file)
@@ -13,7 +13,7 @@ PASS endTime of a new transition
 PASS activeDuration of a new transition 
 PASS localTime of a new transition 
 PASS localTime is always equal to currentTime 
-FAIL localTime reflects playbackRate immediately null is not an object (evaluating 'anim.effect.getComputedTiming')
+PASS localTime reflects playbackRate immediately 
 PASS progress of a new transition 
 FAIL progress of a new transition with positive delay in before phase assert_equals: Initial value of progress expected (number) 0 but got (object) null
 PASS progress of a finished transition 
index 8f4b1ee..90e6d26 100644 (file)
@@ -1,7 +1,7 @@
 
 PASS currentTime of a newly created transition is zero 
 PASS Sanity test to check round-tripping assigning to new animation's currentTime 
-FAIL Skipping forward through transition assert_equals: Animation.playState should be "running" on the first paint tick after animation creation expected "running" but got "finished"
+FAIL Skipping forward through transition assert_equals: the computed value of margin-left should be unaffected by an animation with a delay on ready Promise resolve expected 100 but got 200
 PASS Skipping backwards through transition 
 PASS Setting currentTime to null 
 PASS Animation.currentTime after pausing 
index fa4d26d..8ab6d2d 100644 (file)
@@ -1,3 +1,3 @@
 
-FAIL pause() and play() a transition null is not an object (evaluating 'animation.effect.getComputedTiming')
+PASS pause() and play() a transition 
 
index 6dddb06..53f0be4 100644 (file)
@@ -1,8 +1,8 @@
 
 PASS startTime of a newly created transition is unresolved 
 PASS Sanity test to check round-tripping assigning to new animation's startTime 
-FAIL Skipping forward through animation assert_equals: Animation.playState should be "running" on the first paint tick after animation creation expected "running" but got "finished"
-FAIL Skipping backwards through transition assert_equals: the computed value of margin-left should be half way through the animation at the midpoint of the active interval expected 150 but got 200
+FAIL Skipping forward through animation assert_equals: the computed value of margin-left should be unaffected by an animation with a delay on ready Promise resolve expected 100 but got 200
+PASS Skipping backwards through transition 
 PASS Setting startTime to null 
 PASS Animation.startTime after paused 
 
index 19db10f..e5c32e5 100644 (file)
@@ -1,3 +1,28 @@
-#PID UNRESPONSIVE - com.apple.WebKit.WebContent.Development (pid 13546)
-FAIL: Timed out waiting for notifyDone to be called
+
+PASS Idle -> Pending or Before 
+PASS Idle -> Before 
+PASS Idle or Pending -> Active 
+PASS Idle or Pending -> After 
+PASS Before -> Idle (display: none) 
+PASS Before -> Idle (Animation.timeline = null) 
+PASS Before -> Active 
+PASS Before -> After 
+PASS Active -> Idle, no delay (display: none) 
+PASS Active -> Idle, no delay (Animation.timeline = null) 
+PASS Active -> Idle, with positive delay (display: none) 
+PASS Active -> Idle, with positive delay (Animation.timeline = null) 
+PASS Active -> Idle, with negative delay (display: none) 
+PASS Active -> Idle, with negative delay (Animation.timeline = null) 
+PASS Active -> Before 
+PASS Active -> After 
+PASS After -> Before 
+PASS After -> Active 
+PASS Calculating the interval start and end time with negative start delay. 
+PASS Calculating the interval start and end time with negative end delay. 
+PASS Call Animation.cancel after cancelling transition. 
+PASS Restart transition after cancelling transition immediately 
+PASS Call Animation.cancel after restarting transition immediately 
+PASS Set timeline and play transition after clear the timeline 
+PASS Set null target effect after cancel the transition 
+PASS Cancel the transition after clearing the target effect 
 
diff --git a/LayoutTests/imported/mozilla/css-transitions/test_setting-effect-expected.txt b/LayoutTests/imported/mozilla/css-transitions/test_setting-effect-expected.txt
new file mode 100644 (file)
index 0000000..2386f0e
--- /dev/null
@@ -0,0 +1,6 @@
+
+PASS Test for removing a transition effect 
+FAIL Test for replacing the transition effect by a new keyframe effect assert_equals: expected "100px" but got "0px"
+PASS Test for setting a new keyframe effect with a shorter duration 
+PASS Test for setting a new keyframe effect to a pending transition 
+
index 837cf52..195beca 100644 (file)
@@ -1,3 +1,39 @@
+2018-03-21  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Make imported/mozilla/css-animations/test_event-dispatch.html pass reliably
+        https://bugs.webkit.org/show_bug.cgi?id=183845
+
+        Reviewed by Dean Jackson.
+
+        Finish the work to get DOM events for CSS Animations and CSS Transitions dispatching as specified.
+
+        * animation/AnimationEffectReadOnly.cpp: Move timeEpsilon to be shared as part of WebAnimationUtilities.h since we now need it in
+        WebAnimation::timeToNextRequiredTick().
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::updateCSSAnimationsForElement): We add a pre-emptive return clause when we know that the AnimationList
+        for previous and current styles are a match.
+        * animation/CSSTransition.cpp:
+        (WebCore::CSSTransition::matchesBackingAnimationAndStyles const): Ensure we have a valid effect before downcasting it.
+        * animation/DeclarativeAnimation.cpp:
+        (WebCore::DeclarativeAnimation::initialize): We need to call pause() for declarative animations that aren't playing so that the animation's
+        playState is set correctly and the animation is not idle.
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::updateAnimationSchedule): We no longer need to pass the current time to timeToNextRequiredTick() since the method has
+        been reworked to use the animation's current time, which is based on the timeline's current time.
+        (WebCore::DocumentTimeline::updateAnimations): Avoid creating a copy when iterating over pending hardware animations.
+        * animation/KeyframeEffectReadOnly.cpp:
+        (WebCore::KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes const): We should never generate new blending keyframes if the
+        old and new styles contain the same value, since there would be no transition between two equal values, and we should only look at whether the new
+        style value and the recorded target value differ to determine if new blending keyframes are necessary.
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::timeToNextRequiredTick const): We correct our scheduling code which was shown to be broken in several of the newly-imported
+        Mozilla tests. Any running animation is now scheduled to invalidate again on the next tick, and we use timeEpsilon from WebAnimationUtilities.h to
+        correctly check if we're right at the active threshold, when we also invalidate on the next tick. If our current time is negative, in other words
+        when the animation has not yet started, we schedule this animation's next tick to be the negative of that value. In all other cases, no invalidation
+        needs to be scheduled.
+        * animation/WebAnimation.h: We move updateFinishedState() to private since this method is not actually used outside of WebAnimation.cpp.
+        * animation/WebAnimationUtilities.h: Move timeEpsilon to be shared as part of WebAnimationUtilities.h.
+
 2018-03-22  Tim Horton  <timothy_horton@apple.com>
 
         Improve readability of WebCore's OTHER_LDFLAGS
index 8c7f27f..682a34a 100644 (file)
@@ -33,8 +33,6 @@
 
 namespace WebCore {
 
-const auto timeEpsilon = Seconds::fromMilliseconds(0.001);
-
 AnimationEffectReadOnly::AnimationEffectReadOnly(ClassType classType, Ref<AnimationEffectTimingReadOnly>&& timing)
     : m_classType(classType)
     , m_timing(WTFMove(timing))
index 98ab1d9..844e4be 100644 (file)
@@ -144,6 +144,9 @@ void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const Re
         return;
     }
 
+    if (oldStyle && oldStyle->hasAnimations() && newStyle.hasAnimations() && *(oldStyle->animations()) == *(newStyle.animations()))
+        return;
+
     // First, compile the list of animation names that were applied to this element up to this point.
     HashSet<String> namesOfPreviousAnimations;
     if (oldStyle && oldStyle->hasAnimations()) {
index 2de2ebc..7fd1b73 100644 (file)
@@ -49,7 +49,7 @@ CSSTransition::CSSTransition(Element& element, const Animation& backingAnimation
 bool CSSTransition::matchesBackingAnimationAndStyles(const Animation& newBackingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle) const
 {
     bool backingAnimationsMatch = backingAnimation() == newBackingAnimation;
-    if (!oldStyle)
+    if (!oldStyle || !effect())
         return backingAnimationsMatch;
     return backingAnimationsMatch && !downcast<KeyframeEffectReadOnly>(effect())->stylesWouldYieldNewCSSTransitionsBlendingKeyframes(*oldStyle, newStyle);
 }
index 227ca64..db4a968 100644 (file)
@@ -68,6 +68,8 @@ void DeclarativeAnimation::initialize(const Element& target)
     syncPropertiesWithBackingAnimation();
     if (backingAnimation().playState() == AnimPlayStatePlaying)
         play();
+    else
+        pause();
 
     unsuspendEffectInvalidation();
 }
index 411ef3c..632fc63 100644 (file)
@@ -127,11 +127,10 @@ void DocumentTimeline::updateAnimationSchedule()
 
     m_needsUpdateAnimationSchedule = false;
 
-    Seconds now = currentTime().value();
     Seconds scheduleDelay = Seconds::infinity();
 
     for (const auto& animation : animations()) {
-        auto animationTimeToNextRequiredTick = animation->timeToNextRequiredTick(now);
+        auto animationTimeToNextRequiredTick = animation->timeToNextRequiredTick();
         if (animationTimeToNextRequiredTick < animationInterval) {
             scheduleAnimationResolution();
             return;
@@ -180,7 +179,7 @@ void DocumentTimeline::updateAnimations()
         m_document->updateStyleIfNeeded();
     }
 
-    for (auto animation : m_acceleratedAnimationsPendingRunningStateChange)
+    for (auto& animation : m_acceleratedAnimationsPendingRunningStateChange)
         animation->startOrStopAccelerated();
     m_acceleratedAnimationsPendingRunningStateChange.clear();
 
index f4fb976..2a7a881 100644 (file)
@@ -748,15 +748,13 @@ bool KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes(
     ASSERT(is<CSSTransition>(animation()));
     auto property = downcast<CSSTransition>(animation())->backingAnimation().property();
 
-    // If we didn't have blending keyframes yet, we would create new blending keyframes provided
-    // the start and end styles hold different values for this property.
-    if (!hasBlendingKeyframes())
-        return !CSSPropertyAnimation::propertiesEqual(property, &oldStyle, &newStyle);
-
-    // Otherwise, we would create new blending keyframes provided the current start keyframe holds
-    // a different value than the new start style or the current end keyframe holds a different value
-    // than the new end style for this property.
-    return !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[0].style(), &oldStyle) || !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[1].style(), &newStyle);
+    // There cannot be new keyframes if the start and to values are the same.
+    if (CSSPropertyAnimation::propertiesEqual(property, &oldStyle, &newStyle))
+        return false;
+
+    // Otherwise, we would create new blending keyframes provided the current end keyframe holds a different
+    // value than the new end style for this property.
+    return !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[1].style(), &newStyle);
 }
 
 void KeyframeEffectReadOnly::computeStackingContextImpact()
index 407aea7..3df014f 100644 (file)
@@ -974,26 +974,31 @@ void WebAnimation::updatePendingTasks()
     timingModelDidChange();
 }
 
-Seconds WebAnimation::timeToNextRequiredTick(Seconds timelineTime) const
+Seconds WebAnimation::timeToNextRequiredTick() const
 {
-    if (!m_timeline || !m_startTime || !m_effect || !m_playbackRate)
+    // If we don't have a timeline, an effect, a start time or a playback rate other than 0,
+    // there is no value to apply so we don't need to schedule invalidation.
+    if (!m_timeline || !m_effect || !m_startTime || !m_playbackRate)
         return Seconds::infinity();
 
-    auto startTime = m_startTime.value();
-    auto endTime = startTime + (m_effect->timing()->iterationDuration() / m_playbackRate);
+    // If we're in the running state, we need to schedule invalidation as soon as possible.
+    if (playState() == PlayState::Running)
+        return 0_s;
 
-    // If we haven't started yet, return the interval until our active start time.
-    auto activeStartTime = std::min(startTime, endTime);
-    if (timelineTime <= activeStartTime)
-        return activeStartTime - timelineTime;
+    // If our current time is negative, we need to be scheduled to be resolved at the inverse
+    // of our current time, unless we fill backwards, in which case we want to invalidate as
+    // soon as possible.
+    auto localTime = currentTime().value();
+    if (localTime < 0_s)
+        return -localTime;
 
-    // If we're in the middle of our active duration, we want to be called as soon as possible.
-    auto activeEndTime = std::max(startTime, endTime);
-    if (timelineTime <= activeEndTime)
-        return 0_ms;
+    // If our current time is just at the acthive duration threshold we want to invalidate as
+    // soon as possible to restore a non-animated value.
+    if (std::abs(localTime.microseconds() - m_effect->timing()->activeDuration().microseconds()) < timeEpsilon.microseconds())
+        return 0_s;
 
-    // If none of the previous cases match, then we're already past our active duration
-    // and do not need scheduling.
+    // In any other case, we're idle or already outside our active duration and have no need
+    // to schedule an invalidation.
     return Seconds::infinity();
 }
 
index f6ad91f..1485294 100644 (file)
@@ -97,16 +97,12 @@ public:
     ExceptionOr<void> pause();
     ExceptionOr<void> reverse();
 
-    Seconds timeToNextRequiredTick(Seconds) const;
+    Seconds timeToNextRequiredTick() const;
     void resolve(RenderStyle&);
     void effectTargetDidChange(Element* previousTarget, Element* newTarget);
     void acceleratedRunningStateDidChange();
     void startOrStopAccelerated();
 
-    enum class DidSeek { Yes, No };
-    enum class SynchronouslyNotify { Yes, No };
-    void updateFinishedState(DidSeek, SynchronouslyNotify);
-
     void timingModelDidChange();
     void suspendEffectInvalidation();
     void unsuspendEffectInvalidation();
@@ -122,10 +118,13 @@ protected:
     bool isEffectInvalidationSuspended() { return m_suspendCount; }
 
 private:
+    enum class DidSeek { Yes, No };
+    enum class SynchronouslyNotify { Yes, No };
     enum class RespectHoldTime { Yes, No };
     enum class AutoRewind { Yes, No };
     enum class TimeToRunPendingTask { NotScheduled, ASAP, WhenReady };
 
+    void updateFinishedState(DidSeek, SynchronouslyNotify);
     void enqueueAnimationPlaybackEvent(const AtomicString&, std::optional<Seconds>, std::optional<Seconds>);
     Seconds effectEndTime() const;
     WebAnimation& readyPromiseResolve();
index f4365a8..a7abdac 100644 (file)
@@ -40,5 +40,7 @@ inline double secondsToWebAnimationsAPITime(const Seconds time)
     return std::round(time.microseconds()) / 1000;
 }
 
+const auto timeEpsilon = Seconds::fromMilliseconds(0.001);
+
 } // namespace WebCore