[Web Animations] Make all animation event types inherit from the same base class
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Feb 2020 16:34:52 +0000 (16:34 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Feb 2020 16:34:52 +0000 (16:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=207629

Reviewed by Simon Fraser.

Currently we dispatch events CSS Transitions and CSS Animations events using a dedicated event queue on DeclarativeAnimation, while the events
added by the Web Animations specification (of type AnimationPlaybackEvent) are dispatched using a shared queue on the DocumentTimeline that is
processed during the "update animations and send events procedure". The Web Animations specification dictates that all events should be dispatched
during that procedure, which includes sorting of such events based on their timeline time and associated animation relative composite order.

In this patch, we prepare the work towards spec compliance for animation events dispatch by making all event types (AnimationPlaybackEvent,
TransitionEvent and AnimationEvent) inherit from a single AnimationEventBase interface. This will allow DocumentTimeline to enqueue, sort and
dispatch all such events with a single queue in a future patch.

Due to CSSAnimationController, we must make the "timeline time" and "animation" parameters optional. When we drop support for CSSAnimationController
we'll be able to enforce stronger requirements for these.

No new test since this should not introduce any behavior change.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEventBase.cpp: Added.
(WebCore::AnimationEventBase::AnimationEventBase):
* animation/AnimationEventBase.h: Added.
(WebCore::AnimationEventBase::create):
(WebCore::AnimationEventBase::isAnimationPlaybackEvent const):
(WebCore::AnimationEventBase::isAnimationEvent const):
(WebCore::AnimationEventBase::isTransitionEvent const):
(WebCore::AnimationEventBase::timelineTime const):
(WebCore::AnimationEventBase::animation const):
* animation/AnimationPlaybackEvent.cpp:
(WebCore::AnimationPlaybackEvent::AnimationPlaybackEvent):
(WebCore::AnimationPlaybackEvent::bindingsTimelineTime const):
* animation/AnimationPlaybackEvent.h:
* animation/CSSAnimation.cpp:
(WebCore::CSSAnimation::createEvent):
* animation/CSSAnimation.h:
* animation/CSSTransition.cpp:
(WebCore::CSSTransition::createEvent):
* animation/CSSTransition.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::enqueueDOMEvent):
* animation/DeclarativeAnimation.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::enqueueAnimationPlaybackEvent):
* dom/AnimationEvent.cpp:
(WebCore::AnimationEvent::AnimationEvent):
* dom/AnimationEvent.h:
* dom/TransitionEvent.cpp:
(WebCore::TransitionEvent::TransitionEvent):
* dom/TransitionEvent.h:
* page/animation/CSSAnimationController.cpp:
(WebCore::CSSAnimationControllerPrivate::fireEventsAndUpdateStyle):

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/animation/AnimationEventBase.cpp [new file with mode: 0644]
Source/WebCore/animation/AnimationEventBase.h [new file with mode: 0644]
Source/WebCore/animation/AnimationPlaybackEvent.cpp
Source/WebCore/animation/AnimationPlaybackEvent.h
Source/WebCore/animation/CSSAnimation.cpp
Source/WebCore/animation/CSSAnimation.h
Source/WebCore/animation/CSSTransition.cpp
Source/WebCore/animation/CSSTransition.h
Source/WebCore/animation/DeclarativeAnimation.cpp
Source/WebCore/animation/DeclarativeAnimation.h
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/dom/AnimationEvent.cpp
Source/WebCore/dom/AnimationEvent.h
Source/WebCore/dom/TransitionEvent.cpp
Source/WebCore/dom/TransitionEvent.h
Source/WebCore/page/animation/CSSAnimationController.cpp

index b0f402d..9934ebf 100644 (file)
@@ -1,3 +1,59 @@
+2020-02-14  Antoine Quint  <graouts@webkit.org>
+
+        [Web Animations] Make all animation event types inherit from the same base class
+        https://bugs.webkit.org/show_bug.cgi?id=207629
+
+        Reviewed by Simon Fraser.
+
+        Currently we dispatch events CSS Transitions and CSS Animations events using a dedicated event queue on DeclarativeAnimation, while the events
+        added by the Web Animations specification (of type AnimationPlaybackEvent) are dispatched using a shared queue on the DocumentTimeline that is
+        processed during the "update animations and send events procedure". The Web Animations specification dictates that all events should be dispatched
+        during that procedure, which includes sorting of such events based on their timeline time and associated animation relative composite order.
+
+        In this patch, we prepare the work towards spec compliance for animation events dispatch by making all event types (AnimationPlaybackEvent,
+        TransitionEvent and AnimationEvent) inherit from a single AnimationEventBase interface. This will allow DocumentTimeline to enqueue, sort and
+        dispatch all such events with a single queue in a future patch.
+
+        Due to CSSAnimationController, we must make the "timeline time" and "animation" parameters optional. When we drop support for CSSAnimationController
+        we'll be able to enforce stronger requirements for these.
+
+        No new test since this should not introduce any behavior change.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * animation/AnimationEventBase.cpp: Added.
+        (WebCore::AnimationEventBase::AnimationEventBase):
+        * animation/AnimationEventBase.h: Added.
+        (WebCore::AnimationEventBase::create):
+        (WebCore::AnimationEventBase::isAnimationPlaybackEvent const):
+        (WebCore::AnimationEventBase::isAnimationEvent const):
+        (WebCore::AnimationEventBase::isTransitionEvent const):
+        (WebCore::AnimationEventBase::timelineTime const):
+        (WebCore::AnimationEventBase::animation const):
+        * animation/AnimationPlaybackEvent.cpp:
+        (WebCore::AnimationPlaybackEvent::AnimationPlaybackEvent):
+        (WebCore::AnimationPlaybackEvent::bindingsTimelineTime const):
+        * animation/AnimationPlaybackEvent.h:
+        * animation/CSSAnimation.cpp:
+        (WebCore::CSSAnimation::createEvent):
+        * animation/CSSAnimation.h:
+        * animation/CSSTransition.cpp:
+        (WebCore::CSSTransition::createEvent):
+        * animation/CSSTransition.h:
+        * animation/DeclarativeAnimation.cpp:
+        (WebCore::DeclarativeAnimation::enqueueDOMEvent):
+        * animation/DeclarativeAnimation.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::enqueueAnimationPlaybackEvent):
+        * dom/AnimationEvent.cpp:
+        (WebCore::AnimationEvent::AnimationEvent):
+        * dom/AnimationEvent.h:
+        * dom/TransitionEvent.cpp:
+        (WebCore::TransitionEvent::TransitionEvent):
+        * dom/TransitionEvent.h:
+        * page/animation/CSSAnimationController.cpp:
+        (WebCore::CSSAnimationControllerPrivate::fireEventsAndUpdateStyle):
+
 2020-02-14  Don Olmstead  <don.olmstead@sony.com>
 
         [CMake] Add Fontconfig::Fontconfig target
index 3976134..1a04916 100644 (file)
@@ -447,7 +447,7 @@ accessibility/isolatedtree/AXIsolatedObject.cpp
 accessibility/isolatedtree/AXIsolatedTree.cpp
 
 animation/AnimationEffect.cpp
-animation/KeyframeEffectStack.cpp
+animation/AnimationEventBase.cpp
 animation/AnimationPlaybackEvent.cpp
 animation/AnimationTimeline.cpp
 animation/CSSAnimation.cpp
@@ -455,6 +455,7 @@ animation/CSSTransition.cpp
 animation/DeclarativeAnimation.cpp
 animation/DocumentTimeline.cpp
 animation/KeyframeEffect.cpp
+animation/KeyframeEffectStack.cpp
 animation/WebAnimation.cpp
 animation/WebAnimationUtilities.cpp
 
index 08d5a2d..3d021ce 100644 (file)
                7116E2CF1FED765B00C06FDE /* JSComputedEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7116E2CE1FED765200C06FDE /* JSComputedEffectTiming.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7117445914BC34EC00EE5FC8 /* SVGTextMetricsBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7117445714BC34E200EE5FC8 /* SVGTextMetricsBuilder.h */; };
                7118FED515685CC60030B79A /* JSSVGViewSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 7118FED315685CC60030B79A /* JSSVGViewSpec.h */; };
+               711AD126236D86E5006FF37C /* AnimationEventBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 711AD123236D86D3006FF37C /* AnimationEventBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71207340216DFB0000C78329 /* OptionalEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7120733D216DFAF100C78329 /* OptionalEffectTiming.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71207343216DFB4100C78329 /* JSOptionalEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 71207341216DFB3100C78329 /* JSOptionalEffectTiming.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71247E371FEA5F86008C08CE /* CompositeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 71247E351FEA5F81008C08CE /* CompositeOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7117445714BC34E200EE5FC8 /* SVGTextMetricsBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTextMetricsBuilder.h; sourceTree = "<group>"; };
                7118FED215685CC60030B79A /* JSSVGViewSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGViewSpec.cpp; sourceTree = "<group>"; };
                7118FED315685CC60030B79A /* JSSVGViewSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSVGViewSpec.h; sourceTree = "<group>"; };
+               711AD123236D86D3006FF37C /* AnimationEventBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationEventBase.h; sourceTree = "<group>"; };
+               711AD125236D86D4006FF37C /* AnimationEventBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationEventBase.cpp; sourceTree = "<group>"; };
                711FB0751DC7688F00C4C708 /* placard-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "placard-support.js"; sourceTree = "<group>"; };
                7120733D216DFAF100C78329 /* OptionalEffectTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionalEffectTiming.h; sourceTree = "<group>"; };
                7120733F216DFAF200C78329 /* OptionalEffectTiming.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OptionalEffectTiming.idl; sourceTree = "<group>"; };
                                71EFCED7202B388D00D7C411 /* AnimationEffect.h */,
                                71EFCED6202B388C00D7C411 /* AnimationEffect.idl */,
                                71E2C42421C9351D0024F8C8 /* AnimationEffectPhase.h */,
+                               711AD125236D86D4006FF37C /* AnimationEventBase.cpp */,
+                               711AD123236D86D3006FF37C /* AnimationEventBase.h */,
                                714C7C601FDAD27900F2BEE1 /* AnimationPlaybackEvent.cpp */,
                                714C7C651FDAD27B00F2BEE1 /* AnimationPlaybackEvent.h */,
                                714C7C641FDAD27B00F2BEE1 /* AnimationPlaybackEvent.idl */,
                                71EFCEDC202B38A900D7C411 /* AnimationEffect.h in Headers */,
                                71E2C42621C935280024F8C8 /* AnimationEffectPhase.h in Headers */,
                                319848011A1D817B00A13318 /* AnimationEvent.h in Headers */,
+                               711AD126236D86E5006FF37C /* AnimationEventBase.h in Headers */,
                                49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */,
                                714C7C661FDAD2A100F2BEE1 /* AnimationPlaybackEvent.h in Headers */,
                                714C7C671FDAD2A900F2BEE1 /* AnimationPlaybackEventInit.h in Headers */,
diff --git a/Source/WebCore/animation/AnimationEventBase.cpp b/Source/WebCore/animation/AnimationEventBase.cpp
new file mode 100644 (file)
index 0000000..0dbf4c5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AnimationEventBase.h"
+
+#include "WebAnimationUtilities.h"
+#include <wtf/IsoMallocInlines.h>
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(AnimationEventBase);
+
+AnimationEventBase::AnimationEventBase(const AtomString& type, WebAnimation* animation, Optional<Seconds> timelineTime)
+    : Event(type, CanBubble::Yes, IsCancelable::No)
+    , m_animation(animation)
+    , m_timelineTime(timelineTime)
+{
+}
+
+AnimationEventBase::AnimationEventBase(const AtomString& type, const EventInit& initializer, IsTrusted isTrusted)
+    : Event(type, initializer, isTrusted)
+{
+}
+
+AnimationEventBase::~AnimationEventBase() = default;
+
+} // namespace WebCore
diff --git a/Source/WebCore/animation/AnimationEventBase.h b/Source/WebCore/animation/AnimationEventBase.h
new file mode 100644 (file)
index 0000000..c778148
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Event.h"
+#include <wtf/Markable.h>
+
+namespace WebCore {
+
+class WebAnimation;
+
+class AnimationEventBase : public Event {
+    WTF_MAKE_ISO_ALLOCATED(AnimationEventBase);
+public:
+    static Ref<AnimationEventBase> create(const AtomString& type, WebAnimation* animation, Optional<Seconds> timelineTime)
+    {
+        return adoptRef(*new AnimationEventBase(type, animation, timelineTime));
+    }
+
+    virtual ~AnimationEventBase();
+
+    virtual bool isAnimationPlaybackEvent() const { return false; }
+    virtual bool isAnimationEvent() const { return false; }
+    virtual bool isTransitionEvent() const { return false; }
+
+    Optional<Seconds> timelineTime() const { return m_timelineTime; }
+    WebAnimation* animation() const { return m_animation.get(); }
+
+protected:
+    AnimationEventBase(const AtomString&, WebAnimation*, Optional<Seconds>);
+    AnimationEventBase(const AtomString&, const EventInit&, IsTrusted);
+
+    RefPtr<WebAnimation> m_animation;
+    Markable<Seconds, Seconds::MarkableTraits> m_timelineTime;
+};
+
+}
+
+#define SPECIALIZE_TYPE_TRAITS_ANIMATION_EVENT_BASE(ToValueTypeName, predicate) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
+static bool isType(const WebCore::AnimationEventBase& value) { return value.predicate; } \
+SPECIALIZE_TYPE_TRAITS_END()
+
index 847e594..829a3bd 100644 (file)
@@ -34,7 +34,7 @@ namespace WebCore {
 WTF_MAKE_ISO_ALLOCATED_IMPL(AnimationPlaybackEvent);
 
 AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomString& type, const AnimationPlaybackEventInit& initializer, IsTrusted isTrusted)
-    : Event(type, initializer, isTrusted)
+    : AnimationEventBase(type, initializer, isTrusted)
 {
     if (initializer.currentTime)
         m_currentTime = Seconds::fromMilliseconds(*initializer.currentTime);
@@ -47,10 +47,9 @@ AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomString& type, const Ani
         m_timelineTime = WTF::nullopt;
 }
 
-AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime)
-    : Event(type, CanBubble::Yes, IsCancelable::No)
+AnimationPlaybackEvent::AnimationPlaybackEvent(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime, WebAnimation* animation)
+    : AnimationEventBase(type, animation, timelineTime)
     , m_currentTime(currentTime)
-    , m_timelineTime(timelineTime)
 {
 }
 
@@ -65,9 +64,9 @@ Optional<double> AnimationPlaybackEvent::bindingsCurrentTime() const
 
 Optional<double> AnimationPlaybackEvent::bindingsTimelineTime() const
 {
-    if (!m_timelineTime)
+    if (!timelineTime())
         return WTF::nullopt;
-    return secondsToWebAnimationsAPITime(m_timelineTime.value());
+    return secondsToWebAnimationsAPITime(timelineTime().value());
 }
 
 } // namespace WebCore
index b2285b0..35ff97c 100644 (file)
 
 #pragma once
 
+#include "AnimationEventBase.h"
 #include "AnimationPlaybackEventInit.h"
-#include "Event.h"
 #include <wtf/Markable.h>
 
 namespace WebCore {
 
-class AnimationPlaybackEvent final : public Event {
+class AnimationPlaybackEvent final : public AnimationEventBase {
     WTF_MAKE_ISO_ALLOCATED(AnimationPlaybackEvent);
 public:
-    static Ref<AnimationPlaybackEvent> create(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime)
+    static Ref<AnimationPlaybackEvent> create(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime, WebAnimation* animation)
     {
-        return adoptRef(*new AnimationPlaybackEvent(type, currentTime, timelineTime));
+        return adoptRef(*new AnimationPlaybackEvent(type, currentTime, timelineTime, animation));
     }
 
     static Ref<AnimationPlaybackEvent> create(const AtomString& type, const AnimationPlaybackEventInit& initializer, IsTrusted isTrusted = IsTrusted::No)
@@ -46,19 +46,21 @@ public:
 
     virtual ~AnimationPlaybackEvent();
 
+    bool isAnimationPlaybackEvent() const final { return true; }
+
     Optional<double> bindingsCurrentTime() const;
     Optional<Seconds> currentTime() const { return m_currentTime; }
     Optional<double> bindingsTimelineTime() const;
-    Optional<Seconds> timelineTime() const { return m_timelineTime; }
 
     EventInterface eventInterface() const override { return AnimationPlaybackEventInterfaceType; }
 
 private:
-    AnimationPlaybackEvent(const AtomString&, Optional<Seconds>, Optional<Seconds>);
+    AnimationPlaybackEvent(const AtomString&, Optional<Seconds>, Optional<Seconds>, WebAnimation*);
     AnimationPlaybackEvent(const AtomString&, const AnimationPlaybackEventInit&, IsTrusted);
 
     Markable<Seconds, Seconds::MarkableTraits> m_currentTime;
-    Markable<Seconds, Seconds::MarkableTraits> m_timelineTime;
 };
 
 }
+
+SPECIALIZE_TYPE_TRAITS_ANIMATION_EVENT_BASE(AnimationPlaybackEvent, isAnimationPlaybackEvent())
index 58ada03..fecf02a 100644 (file)
@@ -27,6 +27,7 @@
 #include "CSSAnimation.h"
 
 #include "Animation.h"
+#include "AnimationEvent.h"
 #include "Element.h"
 #include "InspectorInstrumentation.h"
 #include "RenderStyle.h"
@@ -127,4 +128,9 @@ ExceptionOr<void> CSSAnimation::bindingsPause()
     return DeclarativeAnimation::bindingsPause();
 }
 
+Ref<AnimationEventBase> CSSAnimation::createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime)
+{
+    return AnimationEvent::create(eventType, m_animationName, elapsedTime, pseudoId, timelineTime, this);
+}
+
 } // namespace WebCore
index 8a806aa..22e8d15 100644 (file)
@@ -49,6 +49,7 @@ public:
 
 protected:
     void syncPropertiesWithBackingAnimation() final;
+    Ref<AnimationEventBase> createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime) final;
 
 private:
     CSSAnimation(Element&, const Animation&, const RenderStyle&);
index 6a66b87..5859b2e 100644 (file)
@@ -30,6 +30,7 @@
 #include "Element.h"
 #include "InspectorInstrumentation.h"
 #include "KeyframeEffect.h"
+#include "TransitionEvent.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
@@ -85,4 +86,9 @@ void CSSTransition::setTimingProperties(Seconds delay, Seconds duration)
     unsuspendEffectInvalidation();
 }
 
+Ref<AnimationEventBase> CSSTransition::createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime)
+{
+    return TransitionEvent::create(eventType, getPropertyNameString(m_property), elapsedTime, pseudoId, timelineTime, this);
+}
+
 } // namespace WebCore
index 4224ab5..23317ed 100644 (file)
@@ -55,6 +55,7 @@ public:
 private:
     CSSTransition(Element&, CSSPropertyID, MonotonicTime generationTime, const Animation&, const RenderStyle& oldStyle, const RenderStyle& targetStyle, const RenderStyle& reversingAdjustedStartStyle, double);
     void setTimingProperties(Seconds delay, Seconds duration);
+    Ref<AnimationEventBase> createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime) final;
 
     CSSPropertyID m_property;
     MonotonicTime m_generationTime;
index bbe4c37..e31d2f7 100644 (file)
@@ -27,7 +27,6 @@
 #include "DeclarativeAnimation.h"
 
 #include "Animation.h"
-#include "AnimationEvent.h"
 #include "CSSAnimation.h"
 #include "CSSTransition.h"
 #include "DocumentTimeline.h"
@@ -35,7 +34,6 @@
 #include "EventNames.h"
 #include "KeyframeEffect.h"
 #include "PseudoElement.h"
-#include "TransitionEvent.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
@@ -351,10 +349,9 @@ void DeclarativeAnimation::enqueueDOMEvent(const AtomString& eventType, Seconds
 {
     ASSERT(m_owningElement);
     auto time = secondsToWebAnimationsAPITime(elapsedTime) / 1000;
-    if (is<CSSAnimation>(this))
-        m_eventQueue->enqueueEvent(AnimationEvent::create(eventType, downcast<CSSAnimation>(this)->animationName(), time, PseudoElement::pseudoElementNameForEvents(m_owningElement->pseudoId())));
-    else if (is<CSSTransition>(this))
-        m_eventQueue->enqueueEvent(TransitionEvent::create(eventType, downcast<CSSTransition>(this)->transitionProperty(), time, PseudoElement::pseudoElementNameForEvents(m_owningElement->pseudoId())));
+    const auto& pseudoId = PseudoElement::pseudoElementNameForEvents(m_owningElement->pseudoId());
+    auto timelineTime = timeline() ? timeline()->currentTime() : WTF::nullopt;
+    m_eventQueue->enqueueEvent(createEvent(eventType, time, pseudoId, timelineTime));
 }
 
 } // namespace WebCore
index 363e98c..27e52d9 100644 (file)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class Animation;
+class AnimationEventBase;
 class Element;
 class RenderStyle;
 
@@ -74,6 +75,9 @@ protected:
 
     virtual void initialize(const RenderStyle* oldStyle, const RenderStyle& newStyle);
     virtual void syncPropertiesWithBackingAnimation();
+    // elapsedTime is the animation's current time at the time the event is added and is exposed through the DOM API, timelineTime is the animations'
+    // timeline current time and is not exposed through the DOM API but used by the DocumentTimeline for sorting events before dispatch. 
+    virtual Ref<AnimationEventBase> createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime) = 0;
     void invalidateDOMEvents(Seconds elapsedTime = 0_s);
 
 private:
index d4211cc..d0896fb 100644 (file)
@@ -683,7 +683,7 @@ void WebAnimation::willChangeRenderer()
 
 void WebAnimation::enqueueAnimationPlaybackEvent(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime)
 {
-    auto event = AnimationPlaybackEvent::create(type, currentTime, timelineTime);
+    auto event = AnimationPlaybackEvent::create(type, currentTime, timelineTime, this);
     event->setTarget(this);
 
     if (is<DocumentTimeline>(m_timeline)) {
index dc89864..8fb19d5 100644 (file)
@@ -33,15 +33,15 @@ namespace WebCore {
 WTF_MAKE_ISO_ALLOCATED_IMPL(AnimationEvent);
 
 AnimationEvent::AnimationEvent(const AtomString& type, const Init& initializer, IsTrusted isTrusted)
-    : Event(type, initializer, isTrusted)
+    : AnimationEventBase(type, initializer, isTrusted)
     , m_animationName(initializer.animationName)
     , m_elapsedTime(initializer.elapsedTime)
     , m_pseudoElement(initializer.pseudoElement)
 {
 }
 
-AnimationEvent::AnimationEvent(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement)
-    : Event(type, CanBubble::Yes, IsCancelable::No)
+AnimationEvent::AnimationEvent(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation* animation)
+    : AnimationEventBase(type, animation, timelineTime)
     , m_animationName(animationName)
     , m_elapsedTime(elapsedTime)
     , m_pseudoElement(pseudoElement)
index 01eae37..7955d71 100644 (file)
 
 #pragma once
 
-#include "Event.h"
+#include "AnimationEventBase.h"
 
 namespace WebCore {
 
-class AnimationEvent final : public Event {
+class AnimationEvent final : public AnimationEventBase {
     WTF_MAKE_ISO_ALLOCATED(AnimationEvent);
 public:
-    static Ref<AnimationEvent> create(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement)
+    static Ref<AnimationEvent> create(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation* animation)
     {
-        return adoptRef(*new AnimationEvent(type, animationName, elapsedTime, pseudoElement));
+        return adoptRef(*new AnimationEvent(type, animationName, elapsedTime, pseudoElement, timelineTime, animation));
     }
 
     struct Init : EventInit {
@@ -50,6 +50,8 @@ public:
 
     virtual ~AnimationEvent();
 
+    bool isAnimationEvent() const final { return true; }
+
     const String& animationName() const;
     double elapsedTime() const;
     const String& pseudoElement() const;
@@ -57,7 +59,7 @@ public:
     EventInterface eventInterface() const override;
 
 private:
-    AnimationEvent(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement);
+    AnimationEvent(const AtomString& type, const String& animationName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation*);
     AnimationEvent(const AtomString&, const Init&, IsTrusted);
 
     String m_animationName;
@@ -66,3 +68,5 @@ private:
 };
 
 } // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_ANIMATION_EVENT_BASE(AnimationEvent, isAnimationEvent())
index 6961ef3..3d59265 100644 (file)
@@ -33,8 +33,8 @@ namespace WebCore {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(TransitionEvent);
 
-TransitionEvent::TransitionEvent(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement)
-    : Event(type, CanBubble::Yes, IsCancelable::Yes)
+TransitionEvent::TransitionEvent(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation* animation)
+    : AnimationEventBase(type, animation, timelineTime)
     , m_propertyName(propertyName)
     , m_elapsedTime(elapsedTime)
     , m_pseudoElement(pseudoElement)
@@ -42,7 +42,7 @@ TransitionEvent::TransitionEvent(const AtomString& type, const String& propertyN
 }
 
 TransitionEvent::TransitionEvent(const AtomString& type, const Init& initializer, IsTrusted isTrusted)
-    : Event(type, initializer, isTrusted)
+    : AnimationEventBase(type, initializer, isTrusted)
     , m_propertyName(initializer.propertyName)
     , m_elapsedTime(initializer.elapsedTime)
     , m_pseudoElement(initializer.pseudoElement)
index 494f9a4..23136d7 100644 (file)
 
 #pragma once
 
-#include "Event.h"
+#include "AnimationEventBase.h"
 
 namespace WebCore {
 
-class TransitionEvent final : public Event {
+class TransitionEvent final : public AnimationEventBase {
     WTF_MAKE_ISO_ALLOCATED(TransitionEvent);
 public:
-    static Ref<TransitionEvent> create(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement)
+    static Ref<TransitionEvent> create(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation* animation)
     {
-        return adoptRef(*new TransitionEvent(type, propertyName, elapsedTime, pseudoElement));
+        return adoptRef(*new TransitionEvent(type, propertyName, elapsedTime, pseudoElement, timelineTime, animation));
     }
 
     struct Init : EventInit {
@@ -51,6 +51,8 @@ public:
 
     virtual ~TransitionEvent();
 
+    bool isTransitionEvent() const final { return true; }
+
     const String& propertyName() const;
     double elapsedTime() const;
     const String& pseudoElement() const;
@@ -58,7 +60,7 @@ public:
     EventInterface eventInterface() const override;
 
 private:
-    TransitionEvent(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement);
+    TransitionEvent(const AtomString& type, const String& propertyName, double elapsedTime, const String& pseudoElement, Optional<Seconds> timelineTime, WebAnimation*);
     TransitionEvent(const AtomString& type, const Init& initializer, IsTrusted);
 
     String m_propertyName;
@@ -67,3 +69,5 @@ private:
 };
 
 } // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_ANIMATION_EVENT_BASE(TransitionEvent, isTransitionEvent())
index b145360..11db060 100644 (file)
@@ -225,9 +225,9 @@ void CSSAnimationControllerPrivate::fireEventsAndUpdateStyle()
     for (auto& event : eventsToDispatch) {
         Element& element = event.element;
         if (event.eventType == eventNames().transitionendEvent)
-            element.dispatchEvent(TransitionEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId())));
+            element.dispatchEvent(TransitionEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId()), WTF::nullopt, nullptr));
         else
-            element.dispatchEvent(AnimationEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId())));
+            element.dispatchEvent(AnimationEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId()), WTF::nullopt, nullptr));
     }
 
     for (auto& change : m_elementChangesToDispatch)