Title: [229818] trunk
Revision
229818
Author
[email protected]
Date
2018-03-21 12:41:26 -0700 (Wed, 21 Mar 2018)

Log Message

[Web Animations] Dispatch DOM events for CSS Transitions and CSS Animations implemented as Web Animations
https://bugs.webkit.org/show_bug.cgi?id=183781

Reviewed by Dean Jackson.

LayoutTests/imported/mozilla:

Some of the Mozilla tests no longer time out and partially pass, marking the progression.

* css-animations/test_animation-starttime-expected.txt:
* css-animations/test_element-get-animations-expected.txt:

Source/WebCore:

Now that we've implemented CSS Animations and CSS Transitions as Web Animations (webkit.org/b/183504) we can dispatch DOM events
for targets of DeclarativeAnimation objects. To do that, we add a new invalidateDOMEvents() method on DeclarativeAnimations which
is called when the timer scheduled after the timing model has been invalidated fires in DocumentTimeline::performInvalidationTask().
When we check for DOM events to dispatch, we look at the last recorded phase and iteration and determine whether the state of the
animation has changed. We use a GenericEventQueue to enqueue the events such that they are dispatched asynchronously at a moment
when it is safe to evaluate script.

* animation/AnimationEffectReadOnly.h: Make currentIteration() public since we now need it in DeclarativeAnimation::invalidateDOMEvents().
* animation/CSSAnimation.cpp:
(WebCore::CSSAnimation::create): Pass the animation target to the constructor instead of its document.
(WebCore::CSSAnimation::CSSAnimation): Pass the animation target to the superclass instead of its document.
* animation/CSSAnimation.h:
* animation/CSSTransition.cpp:
(WebCore::CSSTransition::create): Pass the animation target to the constructor instead of its document.
(WebCore::CSSTransition::CSSTransition): Pass the animation target to the superclass instead of its document.
* animation/CSSTransition.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::DeclarativeAnimation): Expect an Element instead of a Document and use that element as the target of the
GenericEventQueue that we initialize. We also register this element as our m_target.
(WebCore::DeclarativeAnimation::~DeclarativeAnimation): Close the GenericEventQueue member upon destruction.
(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.
(WebCore::DeclarativeAnimation::phaseWithoutEffect const): Because we may need to get an animation's current phase in invalidateDOMEvents()
after an animation's effect has been removed, we provide an alternate way to compute the phase just by looking at the animation's current time.
(WebCore::DeclarativeAnimation::invalidateDOMEvents): Based on the previous and current pending state, iteration and phase, we enqueue animation
and transition DOM events as specified by the CSS Animations Level 2 and CSS Transitions Level 2 specifications.
(WebCore::DeclarativeAnimation::enqueueDOMEvent): Enqueue an event on the GenericEventQueue based on the animation type.
* animation/DeclarativeAnimation.h:
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::performInvalidationTask): We call invalidateDOMEvents() on all declarative animations registered with this timeline
now that the timing model has been invalidated.
* dom/EventNames.h: Add the names of newly-implemented events (animationcancel, transitioncancel, transitionrun and transitionstart).
* dom/GlobalEventHandlers.idl: Add new attribute-based event handlers for the newly-implemented events.
* html/HTMLAttributeNames.in: Add new attribute-based event handlers for the newly-implemented events.
* html/HTMLElement.cpp:
(WebCore::HTMLElement::createEventHandlerNameMap): Add new attribute-based event handlers for the newly-implemented events.

LayoutTests:

New attribute-based event handlers are now exposed, update the expectations for those.

* js/dom/dom-static-property-for-in-iteration-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (229817 => 229818)


--- trunk/LayoutTests/ChangeLog	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/LayoutTests/ChangeLog	2018-03-21 19:41:26 UTC (rev 229818)
@@ -1,5 +1,16 @@
 2018-03-21  Antoine Quint  <[email protected]>
 
+        [Web Animations] Dispatch DOM events for CSS Transitions and CSS Animations implemented as Web Animations
+        https://bugs.webkit.org/show_bug.cgi?id=183781
+
+        Reviewed by Dean Jackson.
+
+        New attribute-based event handlers are now exposed, update the expectations for those.
+
+        * js/dom/dom-static-property-for-in-iteration-expected.txt:
+
+2018-03-21  Antoine Quint  <[email protected]>
+
         [Web Animations] Import CSS Animations and CSS Transitions as Web Animations tests from Mozilla
         https://bugs.webkit.org/show_bug.cgi?id=183851
 

Modified: trunk/LayoutTests/imported/mozilla/ChangeLog (229817 => 229818)


--- trunk/LayoutTests/imported/mozilla/ChangeLog	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/LayoutTests/imported/mozilla/ChangeLog	2018-03-21 19:41:26 UTC (rev 229818)
@@ -1,5 +1,17 @@
 2018-03-21  Antoine Quint  <[email protected]>
 
+        [Web Animations] Dispatch DOM events for CSS Transitions and CSS Animations implemented as Web Animations
+        https://bugs.webkit.org/show_bug.cgi?id=183781
+
+        Reviewed by Dean Jackson.
+
+        Some of the Mozilla tests no longer time out and partially pass, marking the progression.
+
+        * css-animations/test_animation-starttime-expected.txt:
+        * css-animations/test_element-get-animations-expected.txt:
+
+2018-03-21  Antoine Quint  <[email protected]>
+
         [Web Animations] Import CSS Animations and CSS Transitions as Web Animations tests from Mozilla
         https://bugs.webkit.org/show_bug.cgi?id=183851
 

Modified: trunk/LayoutTests/imported/mozilla/css-animations/test_animation-starttime-expected.txt (229817 => 229818)


--- trunk/LayoutTests/imported/mozilla/css-animations/test_animation-starttime-expected.txt	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/LayoutTests/imported/mozilla/css-animations/test_animation-starttime-expected.txt	2018-03-21 19:41:26 UTC (rev 229818)
@@ -1,3 +1,22 @@
-#PID UNRESPONSIVE - com.apple.WebKit.WebContent.Development (pid 13542)
-FAIL: Timed out waiting for notifyDone to be called
 
+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 is resolved when running 
+FAIL startTime is unresolved when paused undefined is not an object (evaluating 'animation.ready')
+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() 
+FAIL Pausing should make the startTime become null assert_true: After the animation has started, startTime is greater than the time when it was started expected true got false
+PASS Sanity test to check round-tripping assigning to a new animation's startTime 
+PASS Skipping forward through animation 
+PASS Skipping backwards through animation 
+PASS Redundant change, before -> active, then back 
+PASS Redundant change, before -> after, then back 
+PASS Redundant change, active -> before, then back 
+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 cancelling 
+

Modified: trunk/LayoutTests/imported/mozilla/css-animations/test_element-get-animations-expected.txt (229817 => 229818)


--- trunk/LayoutTests/imported/mozilla/css-animations/test_element-get-animations-expected.txt	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/LayoutTests/imported/mozilla/css-animations/test_element-get-animations-expected.txt	2018-03-21 19:41:26 UTC (rev 229818)
@@ -1,3 +1,24 @@
-#PID UNRESPONSIVE - com.apple.WebKit.WebContent.Development (pid 13551)
-FAIL: Timed out waiting for notifyDone to be called
 
+PASS getAnimations for non-animated content 
+PASS getAnimations for CSS Animations 
+PASS getAnimations returns CSSAnimation objects for CSS Animations 
+PASS getAnimations for multi-property animations 
+FAIL getAnimations for both CSS Animations and CSS Transitions at once assert_equals: getAnimations returns Animations for both animations and transitions that run simultaneously expected 2 but got 1
+PASS getAnimations for CSS Animations that have finished 
+PASS getAnimations for CSS Animations that have finished but are forwards filling 
+FAIL getAnimations for CSS Animations with animation-name: none assert_equals: getAnimations returns an empty sequence for an element with animation-name: none expected 0 but got 1
+FAIL getAnimations for CSS Animations with animation-name: missing assert_equals: getAnimations returns an empty sequence for an element with animation-name: missing expected 0 but got 1
+FAIL getAnimations for CSS Animations where the @keyframes rule is added later assert_equals: getAnimations initally only returns Animations for CSS Animations whose animation-name is found expected 1 but got 2
+PASS getAnimations for CSS Animations with duplicated animation-name 
+PASS getAnimations for CSS Animations with empty keyframes rule 
+PASS getAnimations for CSS animations in delay phase 
+PASS getAnimations for zero-duration CSS Animations 
+PASS getAnimations returns objects with the same identity 
+PASS getAnimations for CSS Animations that are cancelled 
+FAIL getAnimations for CSS Animations follows animation-name order assert_equals: animation order after prepending to list expected "anim1" but got "anim2"
+PASS Test AnimationFilter{ subtree: false } with single element 
+FAIL Test AnimationFilter{ subtree: true } with single element assert_equals: getAnimations({ subtree: true }) should return animations on pseudo-elements expected 3 but got 1
+PASS Test AnimationFilter{ subtree: false } with element that has a child 
+FAIL Test AnimationFilter{ subtree: true } with element that has a child assert_equals: Should find all elements, pesudo-elements that parent has expected 6 but got 1
+FAIL Test AnimationFilter{ subtree: true } with element that has many descendant assert_equals: Should find all descendants of the element expected 5 but got 1
+

Modified: trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt (229817 => 229818)


--- trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt	2018-03-21 19:41:26 UTC (rev 229818)
@@ -111,9 +111,13 @@
 PASS a["onvolumechange"] is null
 PASS a["onwaiting"] is null
 PASS a["ontransitionend"] is null
+PASS a["ontransitionrun"] is null
+PASS a["ontransitionstart"] is null
+PASS a["ontransitioncancel"] is null
 PASS a["onanimationend"] is null
 PASS a["onanimationiteration"] is null
 PASS a["onanimationstart"] is null
+PASS a["onanimationcancel"] is null
 PASS a["namespaceURI"] is http://www.w3.org/1999/xhtml
 PASS a["prefix"] is null
 PASS a["localName"] is a

Modified: trunk/Source/WebCore/ChangeLog (229817 => 229818)


--- trunk/Source/WebCore/ChangeLog	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/ChangeLog	2018-03-21 19:41:26 UTC (rev 229818)
@@ -1,3 +1,47 @@
+2018-03-21  Antoine Quint  <[email protected]>
+
+        [Web Animations] Dispatch DOM events for CSS Transitions and CSS Animations implemented as Web Animations
+        https://bugs.webkit.org/show_bug.cgi?id=183781
+
+        Reviewed by Dean Jackson.
+
+        Now that we've implemented CSS Animations and CSS Transitions as Web Animations (webkit.org/b/183504) we can dispatch DOM events
+        for targets of DeclarativeAnimation objects. To do that, we add a new invalidateDOMEvents() method on DeclarativeAnimations which
+        is called when the timer scheduled after the timing model has been invalidated fires in DocumentTimeline::performInvalidationTask().
+        When we check for DOM events to dispatch, we look at the last recorded phase and iteration and determine whether the state of the
+        animation has changed. We use a GenericEventQueue to enqueue the events such that they are dispatched asynchronously at a moment
+        when it is safe to evaluate script.
+
+        * animation/AnimationEffectReadOnly.h: Make currentIteration() public since we now need it in DeclarativeAnimation::invalidateDOMEvents().
+        * animation/CSSAnimation.cpp:
+        (WebCore::CSSAnimation::create): Pass the animation target to the constructor instead of its document.
+        (WebCore::CSSAnimation::CSSAnimation): Pass the animation target to the superclass instead of its document.
+        * animation/CSSAnimation.h:
+        * animation/CSSTransition.cpp:
+        (WebCore::CSSTransition::create): Pass the animation target to the constructor instead of its document.
+        (WebCore::CSSTransition::CSSTransition): Pass the animation target to the superclass instead of its document.
+        * animation/CSSTransition.h:
+        * animation/DeclarativeAnimation.cpp:
+        (WebCore::DeclarativeAnimation::DeclarativeAnimation): Expect an Element instead of a Document and use that element as the target of the
+        GenericEventQueue that we initialize. We also register this element as our m_target.
+        (WebCore::DeclarativeAnimation::~DeclarativeAnimation): Close the GenericEventQueue member upon destruction.
+        (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.
+        (WebCore::DeclarativeAnimation::phaseWithoutEffect const): Because we may need to get an animation's current phase in invalidateDOMEvents()
+        after an animation's effect has been removed, we provide an alternate way to compute the phase just by looking at the animation's current time.
+        (WebCore::DeclarativeAnimation::invalidateDOMEvents): Based on the previous and current pending state, iteration and phase, we enqueue animation
+        and transition DOM events as specified by the CSS Animations Level 2 and CSS Transitions Level 2 specifications.
+        (WebCore::DeclarativeAnimation::enqueueDOMEvent): Enqueue an event on the GenericEventQueue based on the animation type.
+        * animation/DeclarativeAnimation.h:
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::performInvalidationTask): We call invalidateDOMEvents() on all declarative animations registered with this timeline
+        now that the timing model has been invalidated.
+        * dom/EventNames.h: Add the names of newly-implemented events (animationcancel, transitioncancel, transitionrun and transitionstart).
+        * dom/GlobalEventHandlers.idl: Add new attribute-based event handlers for the newly-implemented events.
+        * html/HTMLAttributeNames.in: Add new attribute-based event handlers for the newly-implemented events.
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::createEventHandlerNameMap): Add new attribute-based event handlers for the newly-implemented events.
+
 2018-03-21  Per Arne Vollan  <[email protected]>
 
         Compile error when not using IOSurface canvas backing store.

Modified: trunk/Source/WebCore/animation/AnimationEffectReadOnly.h (229817 => 229818)


--- trunk/Source/WebCore/animation/AnimationEffectReadOnly.h	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/AnimationEffectReadOnly.h	2018-03-21 19:41:26 UTC (rev 229818)
@@ -53,6 +53,7 @@
     std::optional<Seconds> localTime() const;
     std::optional<Seconds> activeTime() const;
     std::optional<double> iterationProgress() const;
+    std::optional<double> currentIteration() const;
 
     enum class Phase { Before, Active, After, Idle };
     Phase phase() const;
@@ -76,7 +77,6 @@
 
     std::optional<double> overallProgress() const;
     std::optional<double> simpleIterationProgress() const;
-    std::optional<double> currentIteration() const;
     AnimationEffectReadOnly::ComputedDirection currentDirection() const;
     std::optional<double> directedProgress() const;
     std::optional<double> transformedProgress() const;

Modified: trunk/Source/WebCore/animation/CSSAnimation.cpp (229817 => 229818)


--- trunk/Source/WebCore/animation/CSSAnimation.cpp	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/CSSAnimation.cpp	2018-03-21 19:41:26 UTC (rev 229818)
@@ -33,14 +33,14 @@
 
 Ref<CSSAnimation> CSSAnimation::create(Element& target, const Animation& backingAnimation)
 {
-    auto result = adoptRef(*new CSSAnimation(target.document(), backingAnimation));
+    auto result = adoptRef(*new CSSAnimation(target, backingAnimation));
     result->m_animationName = backingAnimation.name();
     result->initialize(target);
     return result;
 }
 
-CSSAnimation::CSSAnimation(Document& document, const Animation& backingAnimation)
-    : DeclarativeAnimation(document, backingAnimation)
+CSSAnimation::CSSAnimation(Element& element, const Animation& backingAnimation)
+    : DeclarativeAnimation(element, backingAnimation)
 {
 }
 

Modified: trunk/Source/WebCore/animation/CSSAnimation.h (229817 => 229818)


--- trunk/Source/WebCore/animation/CSSAnimation.h	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/CSSAnimation.h	2018-03-21 19:41:26 UTC (rev 229818)
@@ -46,7 +46,7 @@
     void syncPropertiesWithBackingAnimation() final;
 
 private:
-    CSSAnimation(Document&, const Animation&);
+    CSSAnimation(Element&, const Animation&);
 
     String m_animationName;
 

Modified: trunk/Source/WebCore/animation/CSSTransition.cpp (229817 => 229818)


--- trunk/Source/WebCore/animation/CSSTransition.cpp	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/CSSTransition.cpp	2018-03-21 19:41:26 UTC (rev 229818)
@@ -34,7 +34,7 @@
 
 Ref<CSSTransition> CSSTransition::create(Element& target, const Animation& backingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle)
 {
-    auto result = adoptRef(*new CSSTransition(target.document(), backingAnimation));
+    auto result = adoptRef(*new CSSTransition(target, backingAnimation));
     result->m_transitionProperty = backingAnimation.property();
     result->initialize(target);
     downcast<KeyframeEffectReadOnly>(result->effect())->computeCSSTransitionBlendingKeyframes(oldStyle, newStyle);
@@ -41,8 +41,8 @@
     return result;
 }
 
-CSSTransition::CSSTransition(Document& document, const Animation& backingAnimation)
-    : DeclarativeAnimation(document, backingAnimation)
+CSSTransition::CSSTransition(Element& element, const Animation& backingAnimation)
+    : DeclarativeAnimation(element, backingAnimation)
 {
 }
 

Modified: trunk/Source/WebCore/animation/CSSTransition.h (229817 => 229818)


--- trunk/Source/WebCore/animation/CSSTransition.h	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/CSSTransition.h	2018-03-21 19:41:26 UTC (rev 229818)
@@ -47,7 +47,7 @@
     bool canBeListed() const final;
 
 private:
-    CSSTransition(Document&, const Animation&);
+    CSSTransition(Element&, const Animation&);
 
     CSSPropertyID m_transitionProperty;
 

Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.cpp (229817 => 229818)


--- trunk/Source/WebCore/animation/DeclarativeAnimation.cpp	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.cpp	2018-03-21 19:41:26 UTC (rev 229818)
@@ -28,17 +28,28 @@
 
 #include "Animation.h"
 #include "AnimationEffectTimingReadOnly.h"
+#include "AnimationEvent.h"
 #include "Element.h"
+#include "EventNames.h"
 #include "KeyframeEffectReadOnly.h"
+#include "PseudoElement.h"
+#include "TransitionEvent.h"
 
 namespace WebCore {
 
-DeclarativeAnimation::DeclarativeAnimation(Document& document, const Animation& backingAnimation)
-    : WebAnimation(document)
+DeclarativeAnimation::DeclarativeAnimation(Element& target, const Animation& backingAnimation)
+    : WebAnimation(target.document())
+    , m_target(target)
     , m_backingAnimation(const_cast<Animation&>(backingAnimation))
+    , m_eventQueue(target)
 {
 }
 
+DeclarativeAnimation::~DeclarativeAnimation()
+{
+    m_eventQueue.close();
+}
+
 void DeclarativeAnimation::setBackingAnimation(const Animation& backingAnimation)
 {
     m_backingAnimation = const_cast<Animation&>(backingAnimation);
@@ -73,4 +84,106 @@
     unsuspendEffectInvalidation();
 }
 
+AnimationEffectReadOnly::Phase DeclarativeAnimation::phaseWithoutEffect() const
+{
+    // This shouldn't be called if we actually have an effect.
+    ASSERT(!effect());
+
+    auto animationCurrentTime = currentTime();
+    if (!animationCurrentTime)
+        return AnimationEffectReadOnly::Phase::Idle;
+
+    // Since we don't have an effect, the duration will be zero so the phase is 'before' if the current time is less than zero.
+    return animationCurrentTime.value() < 0_s ? AnimationEffectReadOnly::Phase::Before : AnimationEffectReadOnly::Phase::After;
+}
+
+void DeclarativeAnimation::invalidateDOMEvents()
+{
+    auto* animationEffect = effect();
+
+    auto isPending = pending();
+    auto iteration = animationEffect ? animationEffect->currentIteration().value() : 0;
+    auto currentPhase = animationEffect ? animationEffect->phase() : phaseWithoutEffect();
+
+    bool wasActive = m_previousPhase == AnimationEffectReadOnly::Phase::Active;
+    bool wasAfter = m_previousPhase == AnimationEffectReadOnly::Phase::After;
+    bool wasBefore = m_previousPhase == AnimationEffectReadOnly::Phase::Before;
+    bool wasIdle = m_previousPhase == AnimationEffectReadOnly::Phase::Idle;
+
+    bool isActive = currentPhase == AnimationEffectReadOnly::Phase::Active;
+    bool isAfter = currentPhase == AnimationEffectReadOnly::Phase::After;
+    bool isBefore = currentPhase == AnimationEffectReadOnly::Phase::Before;
+    bool isIdle = currentPhase == AnimationEffectReadOnly::Phase::Idle;
+
+    auto* effectTiming = animationEffect ? animationEffect->timing() : nullptr;
+    auto intervalStart = effectTiming ? std::max(0_s, std::min(-effectTiming->delay(), effectTiming->activeDuration())) : 0_s;
+    auto intervalEnd = effectTiming ? std::max(0_s, std::min(effectTiming->endTime() - effectTiming->delay(), effectTiming->activeDuration())) : 0_s;
+
+    if (is<CSSAnimation>(this)) {
+        // https://drafts.csswg.org/css-animations-2/#events
+        if ((wasIdle || wasBefore) && isActive)
+            enqueueDOMEvent(eventNames().animationstartEvent, intervalStart);
+        else if ((wasIdle || wasBefore) && isAfter) {
+            enqueueDOMEvent(eventNames().animationstartEvent, intervalStart);
+            enqueueDOMEvent(eventNames().animationendEvent, intervalEnd);
+        } else if (wasActive && isBefore)
+            enqueueDOMEvent(eventNames().animationendEvent, intervalStart);
+        else if (wasActive && isActive && m_previousIteration != iteration) {
+            auto iterationBoundary = iteration;
+            if (m_previousIteration > iteration)
+                iterationBoundary++;
+            auto elapsedTime = effectTiming ? effectTiming->iterationDuration() * (iterationBoundary - effectTiming->iterationStart()) : 0_s;
+            enqueueDOMEvent(eventNames().animationiterationEvent, elapsedTime);
+        } else if (wasActive && isAfter)
+            enqueueDOMEvent(eventNames().animationendEvent, intervalEnd);
+        else if (wasAfter && isActive)
+            enqueueDOMEvent(eventNames().animationstartEvent, intervalEnd);
+        else if (wasAfter && isBefore) {
+            enqueueDOMEvent(eventNames().animationstartEvent, intervalEnd);
+            enqueueDOMEvent(eventNames().animationendEvent, intervalStart);
+        } else if ((!wasIdle && !wasAfter) && isIdle)
+            enqueueDOMEvent(eventNames().animationcancelEvent, 0_s);
+    } else if (is<CSSTransition>(this)) {
+        // https://drafts.csswg.org/css-transitions-2/#transition-events
+        if (wasIdle && (isPending || isBefore))
+            enqueueDOMEvent(eventNames().transitionrunEvent, intervalStart);
+        else if (wasIdle && isActive) {
+            enqueueDOMEvent(eventNames().transitionrunEvent, intervalStart);
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalStart);
+        } else if (wasIdle && isAfter) {
+            enqueueDOMEvent(eventNames().transitionrunEvent, intervalStart);
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalStart);
+            enqueueDOMEvent(eventNames().transitionendEvent, intervalEnd);
+        } else if ((m_wasPending || wasBefore) && isActive)
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalStart);
+        else if ((m_wasPending || wasBefore) && isAfter) {
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalStart);
+            enqueueDOMEvent(eventNames().transitionendEvent, intervalEnd);
+        } else if (wasActive && isAfter)
+            enqueueDOMEvent(eventNames().transitionendEvent, intervalEnd);
+        else if (wasActive && isBefore)
+            enqueueDOMEvent(eventNames().transitionendEvent, intervalStart);
+        else if (wasAfter && isActive)
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalEnd);
+        else if (wasAfter && isBefore) {
+            enqueueDOMEvent(eventNames().transitionstartEvent, intervalEnd);
+            enqueueDOMEvent(eventNames().transitionendEvent, intervalStart);
+        } else if ((!wasIdle && !wasAfter) && isIdle)
+            enqueueDOMEvent(eventNames().transitioncancelEvent, 0_s);
+    }
+
+    m_wasPending = isPending;
+    m_previousPhase = currentPhase;
+    m_previousIteration = iteration;
+}
+
+void DeclarativeAnimation::enqueueDOMEvent(const AtomicString& eventType, Seconds elapsedTime)
+{
+    auto time = secondsToWebAnimationsAPITime(elapsedTime) / 1000;
+    if (is<CSSAnimation>(this))
+        m_eventQueue.enqueueEvent(AnimationEvent::create(eventType, downcast<CSSAnimation>(this)->animationName(), time));
+    else if (is<CSSTransition>(this))
+        m_eventQueue.enqueueEvent(TransitionEvent::create(eventType, downcast<CSSTransition>(this)->transitionProperty(), time, PseudoElement::pseudoElementNameForEvents(m_target.pseudoId())));
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.h (229817 => 229818)


--- trunk/Source/WebCore/animation/DeclarativeAnimation.h	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.h	2018-03-21 19:41:26 UTC (rev 229818)
@@ -25,6 +25,8 @@
 
 #pragma once
 
+#include "AnimationEffectReadOnly.h"
+#include "GenericEventQueue.h"
 #include "WebAnimation.h"
 #include <wtf/Ref.h>
 
@@ -35,22 +37,30 @@
 
 class DeclarativeAnimation : public WebAnimation {
 public:
-    ~DeclarativeAnimation() = default;
+    ~DeclarativeAnimation();
 
     bool isDeclarativeAnimation() const final { return true; }
 
     const Animation& backingAnimation() const { return m_backingAnimation; }
     void setBackingAnimation(const Animation&);
+    void invalidateDOMEvents();
 
 protected:
-    DeclarativeAnimation(Document&, const Animation&);
+    DeclarativeAnimation(Element&, const Animation&);
 
     virtual void initialize(const Element&);
     virtual void syncPropertiesWithBackingAnimation();
 
 private:
+    AnimationEffectReadOnly::Phase phaseWithoutEffect() const;
+    void enqueueDOMEvent(const AtomicString&, Seconds);
+
+    Element& m_target;
     Ref<Animation> m_backingAnimation;
-
+    bool m_wasPending { false };
+    AnimationEffectReadOnly::Phase m_previousPhase { AnimationEffectReadOnly::Phase::Idle };
+    double m_previousIteration;
+    GenericEventQueue m_eventQueue;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (229817 => 229818)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2018-03-21 19:41:26 UTC (rev 229818)
@@ -30,6 +30,7 @@
 #include "Chrome.h"
 #include "ChromeClient.h"
 #include "DOMWindow.h"
+#include "DeclarativeAnimation.h"
 #include "DisplayRefreshMonitor.h"
 #include "DisplayRefreshMonitorManager.h"
 #include "Document.h"
@@ -109,6 +110,12 @@
 
 void DocumentTimeline::performInvalidationTask()
 {
+    // Now that the timing model has changed we can see if there are DOM events to dispatch for declarative animations.
+    for (auto& animation : animations()) {
+        if (is<DeclarativeAnimation>(animation))
+            downcast<DeclarativeAnimation>(*animation).invalidateDOMEvents();
+    }
+
     updateAnimationSchedule();
     m_cachedCurrentTime = std::nullopt;
 }

Modified: trunk/Source/WebCore/dom/EventNames.h (229817 => 229818)


--- trunk/Source/WebCore/dom/EventNames.h	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/dom/EventNames.h	2018-03-21 19:41:26 UTC (rev 229818)
@@ -59,6 +59,7 @@
     macro(addsourcebuffer) \
     macro(addstream) \
     macro(addtrack) \
+    macro(animationcancel) \
     macro(animationend) \
     macro(animationiteration) \
     macro(animationstart) \
@@ -249,7 +250,10 @@
     macro(touchmove) \
     macro(touchstart) \
     macro(track) \
+    macro(transitioncancel) \
     macro(transitionend) \
+    macro(transitionrun) \
+    macro(transitionstart) \
     macro(unhandledrejection) \
     macro(unload) \
     macro(unmute) \

Modified: trunk/Source/WebCore/dom/GlobalEventHandlers.idl (229817 => 229818)


--- trunk/Source/WebCore/dom/GlobalEventHandlers.idl	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/dom/GlobalEventHandlers.idl	2018-03-21 19:41:26 UTC (rev 229818)
@@ -97,15 +97,15 @@
 
     // Extensions from CSS Transitions API (https://drafts.csswg.org/css-transitions/#interface-globaleventhandlers-idl).
     attribute EventHandler ontransitionend;
-    // attribute EventHandler ontransitionrun;
-    // attribute EventHandler ontransitionstart;
-    // attribute EventHandler ontransitioncancel;
+    attribute EventHandler ontransitionrun;
+    attribute EventHandler ontransitionstart;
+    attribute EventHandler ontransitioncancel;
 
     // Event handlers from CSS Animations API (https://drafts.csswg.org/css-animations/#interface-globaleventhandlers-idl).
     attribute EventHandler onanimationend;
     attribute EventHandler onanimationiteration;
     attribute EventHandler onanimationstart;
-    // attribute EventHandler onanimationcancel;
+    attribute EventHandler onanimationcancel;
 
     // Additions that are not yet part of the standard.
 

Modified: trunk/Source/WebCore/html/HTMLAttributeNames.in (229817 => 229818)


--- trunk/Source/WebCore/html/HTMLAttributeNames.in	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/html/HTMLAttributeNames.in	2018-03-21 19:41:26 UTC (rev 229818)
@@ -193,6 +193,7 @@
 onanimationstart
 onanimationiteration
 onanimationend
+onanimationcancel
 onautocomplete
 onautocompleteerror
 onbeforecopy
@@ -282,7 +283,10 @@
 ontouchmove
 ontouchend
 ontouchcancel
+ontransitioncancel
 ontransitionend
+ontransitionrun
+ontransitionstart
 onunload
 onvolumechange
 onwaiting

Modified: trunk/Source/WebCore/html/HTMLElement.cpp (229817 => 229818)


--- trunk/Source/WebCore/html/HTMLElement.cpp	2018-03-21 19:33:01 UTC (rev 229817)
+++ trunk/Source/WebCore/html/HTMLElement.cpp	2018-03-21 19:41:26 UTC (rev 229818)
@@ -229,6 +229,7 @@
         &onanimationendAttr.get(),
         &onanimationiterationAttr.get(),
         &onanimationstartAttr.get(),
+        &onanimationcancelAttr.get(),
         &onautocompleteAttr.get(),
         &onautocompleteerrorAttr.get(),
         &onbeforecopyAttr.get(),
@@ -303,7 +304,10 @@
         &ontouchforcechangeAttr.get(),
         &ontouchmoveAttr.get(),
         &ontouchstartAttr.get(),
+        &ontransitioncancelAttr.get(),
         &ontransitionendAttr.get(),
+        &ontransitionrunAttr.get(),
+        &ontransitionstartAttr.get(),
         &onvolumechangeAttr.get(),
         &onwaitingAttr.get(),
         &onwebkitbeginfullscreenAttr.get(),
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to