Title: [224760] trunk
Revision
224760
Author
[email protected]
Date
2017-11-13 11:14:47 -0800 (Mon, 13 Nov 2017)

Log Message

[Web Animations] Implement getAnimations()
https://bugs.webkit.org/show_bug.cgi?id=179535
<rdar://problem/34932475>

Reviewed by Simon Fraser.

Source/WebCore:

We now allow a list of animations for a document, with Document.getAnimations(), or for an
element, with Animatable.getAnimations(), to be returned. In order to support this, we maintain
a map on AnimationTimeline of all animations for a given element. This map is invalidated
when an animation's timeline changes and when an animation's effect changes. Note that the
Web Animations spec mandates that an AnimationEffect can only be a single animation's effect.

Tests: http/wpt/wk-web-animations/interfaces/document-get-animations.html
       http/wpt/wk-web-animations/interfaces/element-get-animations.html
       http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html

* CMakeLists.txt: Add Animatable.idl.
* DerivedSources.make: Add Animatable.idl.
* WebCore.xcodeproj/project.pbxproj: Add Animatable.idl.
* animation/Animatable.idl: A new interface that Element implements and which currently only exposes
getAnimations(), the animate() method will be added later.
* animation/AnimationEffect.h: Add a new m_animation member to reference the animation using this
effect. This relationship is required so we guarantee that an effect is associated with a single
animation at most.
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement): New method to notify the timeline that an
animation registered with this timeline has been associated with a new element through its effect.
(WebCore::AnimationTimeline::animationWasRemovedFromElement): New method to notify the timeline that an
animation registered with this timeline has been disassociated with an element through its effect.
(WebCore::AnimationTimeline::animationsForElement): New method returning all animations registered with
this timeline for a given element.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const): All animations registered with this timeline.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument): Clear the reference between this timeline and its document.
(WebCore::DocumentTimeline::currentTime): Protect against a null Document reference.
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Protect against a null Document reference.
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect): As an animation's effect changes, we need to ensure that the old
effect no longer has an associated animation, and that the new effect is associated with this animation.
Additionally, we update the element-to-animations map on the animation's timeline.
(WebCore::WebAnimation::setTimeline): Update the element-to-animations map on the former and new timeline.
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction): Clear the relationship between this document and its timeline.
(WebCore::Document::getAnimations): Obtain all animations associated with this document's timeline.
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations): Obtain all animations associated with this element.
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:

* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* animation/Animatable.idl:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement):
(WebCore::AnimationTimeline::animationWasRemovedFromElement):
(WebCore::AnimationTimeline::animationsForElement):
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const):
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect):
(WebCore::WebAnimation::setTimeline):
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction):
(WebCore::Document::getAnimations):
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations):
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:

LayoutTests:

Update WPT expectations per new progressions and add three new tests that check the behavior of
Document.getAnimations(), Element.getAnimations() and the unique relationship between an Animation
and an AnimationEffect.

* http/wpt/web-animations/interfaces/Animatable/animate-expected.txt:
* http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt:
* http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt:
* http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/document-get-animations.html: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations.html: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (224759 => 224760)


--- trunk/LayoutTests/ChangeLog	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/LayoutTests/ChangeLog	2017-11-13 19:14:47 UTC (rev 224760)
@@ -1,3 +1,25 @@
+2017-11-13  Antoine Quint  <[email protected]>
+
+        [Web Animations] Implement getAnimations()
+        https://bugs.webkit.org/show_bug.cgi?id=179535
+        <rdar://problem/34932475>
+
+        Reviewed by Simon Fraser.
+
+        Update WPT expectations per new progressions and add three new tests that check the behavior of
+        Document.getAnimations(), Element.getAnimations() and the unique relationship between an Animation
+        and an AnimationEffect.
+
+        * http/wpt/web-animations/interfaces/Animatable/animate-expected.txt:
+        * http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt:
+        * http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt:
+        * http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt: Added.
+        * http/wpt/wk-web-animations/interfaces/document-get-animations.html: Added.
+        * http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt: Added.
+        * http/wpt/wk-web-animations/interfaces/element-get-animations.html: Added.
+        * http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt: Added.
+        * http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html: Added.
+
 2017-11-13  Per Arne Vollan  <[email protected]>
 
         Mark editing/execCommand/underline-selection-containing-image.html as failing on Windows.

Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/animate-expected.txt (224759 => 224760)


--- trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/animate-expected.txt	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/animate-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -91,6 +91,6 @@
 FAIL Element.animate() correctly sets the Animation's timeline div.animate is not a function. (In 'div.animate({ opacity: [ 0, 1 ] }, 2000)', 'div.animate' is undefined)
 FAIL Element.animate() correctly sets the Animation's timeline when triggered on an element in a different document div.animate is not a function. (In 'div.animate({ opacity: [ 0, 1 ] }, 2000)', 'div.animate' is undefined)
 FAIL Element.animate() calls play on the Animation div.animate is not a function. (In 'div.animate({ opacity: [ 0, 1 ] }, 2000)', 'div.animate' is undefined)
-FAIL CSSPseudoElement.animate() creates an Animation object document.getAnimations is not a function. (In 'document.getAnimations()', 'document.getAnimations' is undefined)
-FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object document.getAnimations is not a function. (In 'document.getAnimations()', 'document.getAnimations' is undefined)
+FAIL CSSPseudoElement.animate() creates an Animation object assert_true: expected true got false
+FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object assert_true: expected true got false
  

Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt (224759 => 224760)


--- trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -1,5 +1,5 @@
 
-FAIL Test getAnimations on element with no animations div.getAnimations is not a function. (In 'div.getAnimations()', 'div.getAnimations' is undefined)
+PASS Test getAnimations on element with no animations 
 FAIL Test getAnimations on element with two animations div.animate is not a function. (In 'div.animate(null, 100 * MS_PER_SEC)', 'div.animate' is undefined)
 FAIL Test getAnimations on separate elements with separate animations divA.animate is not a function. (In 'divA.animate(null, 100 * MS_PER_SEC)', 'divA.animate' is undefined)
 FAIL Test getAnimations on parent and child elements with separate animations divParent.animate is not a function. (In 'divParent.animate(null, 100 * MS_PER_SEC)', 'divParent.animate' is undefined)

Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt (224759 => 224760)


--- trunk/LayoutTests/http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/LayoutTests/http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -1,5 +1,5 @@
 
-FAIL Test document.getAnimations for non-animated content document.getAnimations is not a function. (In 'document.getAnimations()', 'document.getAnimations' is undefined)
+PASS Test document.getAnimations for non-animated content 
 FAIL Test document.getAnimations for script-generated animations div.animate is not a function. (In 'div.animate(gKeyFrames, 100 * MS_PER_SEC)', 'div.animate' is undefined)
 FAIL Test the order of document.getAnimations with script generated animations div.animate is not a function. (In 'div.animate(gKeyFrames, 100 * MS_PER_SEC)', 'div.animate' is undefined)
 FAIL Test document.getAnimations with null target Can't find variable: KeyframeEffectReadOnly

Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,7 @@
+
+PASS Document exposes the getAnimations method. 
+PASS Document.getAnimations() returns an empty array when no animations were added. 
+PASS Document.getAnimations() returns an array with the new animations contained. 
+PASS Setting timeline = null on an animation removes it from the array returned by Document.getAnimations(). 
+PASS Setting timeline = document.timeline on an animation adds it to the array returned by Document.getAnimations(). 
+

Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations.html (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations.html	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getAnimations()</title>
+<script src=""
+<script src=""
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+let a, b, c;
+
+test(t => {
+    assert_true(typeof document.getAnimations === "function");
+}, "Document exposes the getAnimations method.");
+
+test(t => {
+    assert_array_equals(document.getAnimations(), []);
+}, "Document.getAnimations() returns an empty array when no animations were added.");
+
+test(t => {
+    a = new Animation;
+    b = new Animation;
+    c = new Animation;
+    const animations = document.getAnimations();
+    assert_equals(animations.length, 3);
+    assert_in_array(a, animations);
+    assert_in_array(b, animations);
+    assert_in_array(c, animations);
+}, "Document.getAnimations() returns an array with the new animations contained.");
+
+test(t => {
+    b.timeline = null;
+    const animations = document.getAnimations();
+    assert_equals(animations.length, 2);
+    assert_in_array(a, animations);
+    assert_in_array(c, animations);
+}, "Setting timeline = null on an animation removes it from the array returned by Document.getAnimations().");
+
+test(t => {
+    b.timeline = document.timeline;
+    const animations = document.getAnimations();
+    assert_equals(animations.length, 3);
+    assert_in_array(a, animations);
+    assert_in_array(b, animations);
+    assert_in_array(c, animations);
+}, "Setting timeline = document.timeline on an animation adds it to the array returned by Document.getAnimations().");
+
+</script>
+</body>

Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,7 @@
+
+PASS Element exposes the getAnimations method. 
+PASS Element.getAnimations() returns an empty array when no animations were added. 
+PASS Element.getAnimations() returns an array with animations targetting that element. 
+PASS An effect can only be applied to a single animation and changing it changes the animations returned by Element.getAnimations(). 
+PASS Setting an animation's effect to null changes the animations returned by Element.getAnimations(). 
+

Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations.html (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations.html	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getAnimations()</title>
+<script src=""
+<script src=""
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+let a, b, c;
+
+const targetA = document.createElement("a");
+const targetB = document.createElement("b");
+
+const effectAa = new KeyframeEffect(targetA);
+const effectAb = new KeyframeEffect(targetA);
+const effectB = new KeyframeEffect(targetB);
+
+test(t => {
+    assert_true(typeof targetA.getAnimations === "function");
+}, "Element exposes the getAnimations method.");
+
+test(t => {
+    assert_array_equals(targetA.getAnimations(), []);
+    assert_array_equals(targetB.getAnimations(), []);
+}, "Element.getAnimations() returns an empty array when no animations were added.");
+
+test(t => {
+    a = new Animation(effectAa);
+    b = new Animation(effectAb);
+    c = new Animation(effectB);
+    assert_array_equals(targetA.getAnimations(), [a, b]);
+    assert_array_equals(targetB.getAnimations(), [c]);
+}, "Element.getAnimations() returns an array with animations targetting that element.");
+
+test(t => {
+    b.effect = effectB;
+    assert_array_equals(targetA.getAnimations(), [a]);
+    assert_array_equals(targetB.getAnimations(), [b]);
+}, "An effect can only be applied to a single animation and changing it changes the animations returned by Element.getAnimations().");
+
+test(t => {
+    a.effect = null;
+    b.effect = null;
+    c.effect = null;
+    assert_array_equals(targetA.getAnimations(), []);
+    assert_array_equals(targetB.getAnimations(), []);
+}, "Setting an animation's effect to null changes the animations returned by Element.getAnimations().");
+
+</script>
+</body>

Added: trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,3 @@
+
+PASS Check that setting an animation's effect onto another animation sets effect to null. 
+

Added: trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html (0 => 224760)


--- trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Check an AnimationEffect can only be used for one Animation</title>
+<script src=""
+<script src=""
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+    const effectA = new KeyframeEffect(document.createElement("div"));
+    const effectB = new KeyframeEffect(document.createElement("div"));
+
+    const a = new Animation(effectA);
+    const b = new Animation(effectB);
+
+    assert_equals(a.effect, effectA);
+    assert_equals(b.effect, effectB);
+
+    b.effect = effectA;
+    assert_equals(a.effect, null);
+    assert_equals(b.effect, effectA);
+}, "Check that setting an animation's effect onto another animation sets effect to null.");
+
+</script>
+</body>

Modified: trunk/Source/WebCore/CMakeLists.txt (224759 => 224760)


--- trunk/Source/WebCore/CMakeLists.txt	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/CMakeLists.txt	2017-11-13 19:14:47 UTC (rev 224760)
@@ -419,6 +419,7 @@
     Modules/webvr/VRPose.idl
     Modules/webvr/VRStageParameters.idl
 
+    animation/Animatable.idl
     animation/AnimationEffect.idl
     animation/AnimationEffectTiming.idl
     animation/AnimationTimeline.idl

Modified: trunk/Source/WebCore/ChangeLog (224759 => 224760)


--- trunk/Source/WebCore/ChangeLog	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/ChangeLog	2017-11-13 19:14:47 UTC (rev 224760)
@@ -1,3 +1,97 @@
+2017-11-13  Antoine Quint  <[email protected]>
+
+        [Web Animations] Implement getAnimations()
+        https://bugs.webkit.org/show_bug.cgi?id=179535
+        <rdar://problem/34932475>
+
+        Reviewed by Simon Fraser.
+
+        We now allow a list of animations for a document, with Document.getAnimations(), or for an
+        element, with Animatable.getAnimations(), to be returned. In order to support this, we maintain
+        a map on AnimationTimeline of all animations for a given element. This map is invalidated
+        when an animation's timeline changes and when an animation's effect changes. Note that the
+        Web Animations spec mandates that an AnimationEffect can only be a single animation's effect.
+
+        Tests: http/wpt/wk-web-animations/interfaces/document-get-animations.html
+               http/wpt/wk-web-animations/interfaces/element-get-animations.html
+               http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html
+
+        * CMakeLists.txt: Add Animatable.idl.
+        * DerivedSources.make: Add Animatable.idl.
+        * WebCore.xcodeproj/project.pbxproj: Add Animatable.idl.
+        * animation/Animatable.idl: A new interface that Element implements and which currently only exposes
+        getAnimations(), the animate() method will be added later.
+        * animation/AnimationEffect.h: Add a new m_animation member to reference the animation using this
+        effect. This relationship is required so we guarantee that an effect is associated with a single
+        animation at most.
+        (WebCore::AnimationEffect::animation const):
+        (WebCore::AnimationEffect::setAnimation):
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::animationWasAddedToElement): New method to notify the timeline that an
+        animation registered with this timeline has been associated with a new element through its effect.
+        (WebCore::AnimationTimeline::animationWasRemovedFromElement): New method to notify the timeline that an
+        animation registered with this timeline has been disassociated with an element through its effect.
+        (WebCore::AnimationTimeline::animationsForElement): New method returning all animations registered with
+        this timeline for a given element.
+        * animation/AnimationTimeline.h:
+        (WebCore::AnimationTimeline::animations const): All animations registered with this timeline.
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::DocumentTimeline):
+        (WebCore::DocumentTimeline::detachFromDocument): Clear the reference between this timeline and its document.
+        (WebCore::DocumentTimeline::currentTime): Protect against a null Document reference.
+        (WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Protect against a null Document reference.
+        * animation/DocumentTimeline.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::create):
+        (WebCore::WebAnimation::setEffect): As an animation's effect changes, we need to ensure that the old
+        effect no longer has an associated animation, and that the new effect is associated with this animation.
+        Additionally, we update the element-to-animations map on the animation's timeline.
+        (WebCore::WebAnimation::setTimeline): Update the element-to-animations map on the former and new timeline.
+        * dom/Document.cpp:
+        (WebCore::Document::prepareForDestruction): Clear the relationship between this document and its timeline.
+        (WebCore::Document::getAnimations): Obtain all animations associated with this document's timeline.
+        * dom/Document.h:
+        * dom/Document.idl:
+        * dom/Element.cpp:
+        (WebCore::Element::getAnimations): Obtain all animations associated with this element.
+        * dom/Element.h:
+        * dom/Element.idl:
+        * testing/Internals.cpp:
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * WebCore.xcodeproj/project.pbxproj:
+        * animation/Animatable.idl: 
+        * animation/AnimationEffect.h:
+        (WebCore::AnimationEffect::animation const):
+        (WebCore::AnimationEffect::setAnimation):
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::animationWasAddedToElement):
+        (WebCore::AnimationTimeline::animationWasRemovedFromElement):
+        (WebCore::AnimationTimeline::animationsForElement):
+        * animation/AnimationTimeline.h:
+        (WebCore::AnimationTimeline::animations const):
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::DocumentTimeline):
+        (WebCore::DocumentTimeline::detachFromDocument):
+        (WebCore::DocumentTimeline::currentTime):
+        (WebCore::DocumentTimeline::createDisplayRefreshMonitor const):
+        * animation/DocumentTimeline.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::create):
+        (WebCore::WebAnimation::setEffect):
+        (WebCore::WebAnimation::setTimeline):
+        * dom/Document.cpp:
+        (WebCore::Document::prepareForDestruction):
+        (WebCore::Document::getAnimations):
+        * dom/Document.h:
+        * dom/Document.idl:
+        * dom/Element.cpp:
+        (WebCore::Element::getAnimations):
+        * dom/Element.h:
+        * dom/Element.idl:
+        * testing/Internals.cpp:
+
 2017-11-13  Alex Christensen  <[email protected]>
 
         Make DocumentLoader::willSendRequest asynchronous

Modified: trunk/Source/WebCore/DerivedSources.make (224759 => 224760)


--- trunk/Source/WebCore/DerivedSources.make	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/DerivedSources.make	2017-11-13 19:14:47 UTC (rev 224760)
@@ -343,6 +343,7 @@
     $(WebCore)/Modules/webvr/VRLayerInit.idl \
     $(WebCore)/Modules/webvr/VRPose.idl \
     $(WebCore)/Modules/webvr/VRStageParameters.idl \
+    $(WebCore)/animation/Animatable.idl \
     $(WebCore)/animation/AnimationEffect.idl \
     $(WebCore)/animation/AnimationEffectTiming.idl \
     $(WebCore)/animation/AnimationTimeline.idl \

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (224759 => 224760)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-11-13 19:14:47 UTC (rev 224760)
@@ -8684,6 +8684,7 @@
 		71A57DEF154BE25C0009D120 /* SVGPathUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPathUtilities.cpp; sourceTree = "<group>"; };
 		71A57DF0154BE25C0009D120 /* SVGPathUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPathUtilities.h; sourceTree = "<group>"; };
 		71B0460A1DD3C2EE00EE19CF /* status-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "status-support.js"; sourceTree = "<group>"; };
+		71C5BB1B1FB611EA0007A2AE /* Animatable.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Animatable.idl; sourceTree = "<group>"; };
 		71C916071D1483A300ACA47D /* UserInterfaceLayoutDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInterfaceLayoutDirection.h; sourceTree = "<group>"; };
 		71CC7A1F152A0BFE009EEAF9 /* SVGAnimatedEnumeration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedEnumeration.cpp; sourceTree = "<group>"; };
 		71D02D901DB55C4E00DD5CF5 /* main.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = main.js; sourceTree = "<group>"; };
@@ -18622,6 +18623,7 @@
 		71025EC11F99F096004A250C /* animation */ = {
 			isa = PBXGroup;
 			children = (
+				71C5BB1B1FB611EA0007A2AE /* Animatable.idl */,
 				71556CB11F9F099F00E78D08 /* AnimationEffect.cpp */,
 				71556CAD1F9F099D00E78D08 /* AnimationEffect.h */,
 				71556CB01F9F099E00E78D08 /* AnimationEffect.idl */,

Copied: trunk/Source/WebCore/animation/Animatable.idl (from rev 224759, trunk/Source/WebCore/animation/AnimationEffect.h) (0 => 224760)


--- trunk/Source/WebCore/animation/Animatable.idl	                        (rev 0)
+++ trunk/Source/WebCore/animation/Animatable.idl	2017-11-13 19:14:47 UTC (rev 224760)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+[
+    EnabledAtRuntime=WebAnimations,
+    NoInterfaceObject
+] interface Animatable {
+    sequence<WebAnimation> getAnimations();
+};

Modified: trunk/Source/WebCore/animation/AnimationEffect.h (224759 => 224760)


--- trunk/Source/WebCore/animation/AnimationEffect.h	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/AnimationEffect.h	2017-11-13 19:14:47 UTC (rev 224760)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "AnimationEffectTiming.h"
+#include "WebAnimation.h"
 #include <wtf/Forward.h>
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
@@ -40,6 +41,9 @@
 
     virtual ~AnimationEffect() { }
 
+    WebAnimation* animation() const { return m_animation.get(); }
+    void setAnimation(RefPtr<WebAnimation>&& animation) { m_animation = animation; }
+
 protected:
     enum ClassType {
         KeyframeEffectClass
@@ -51,6 +55,7 @@
 
 private:
     ClassType m_classType;
+    RefPtr<WebAnimation> m_animation;
     RefPtr<AnimationEffectTiming> m_timing;
 };
 

Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (224759 => 224760)


--- trunk/Source/WebCore/animation/AnimationTimeline.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -68,6 +68,34 @@
     animationTimingModelDidChange();
 }
 
+void AnimationTimeline::animationWasAddedToElement(WebAnimation& animation, Element& element)
+{
+    auto result = m_elementToAnimationsMap.ensure(&element, [] {
+        return Vector<RefPtr<WebAnimation>>();
+    });
+    result.iterator->value.append(&animation);
+}
+
+void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, Element& element)
+{
+    auto iterator = m_elementToAnimationsMap.find(&element);
+    if (iterator == m_elementToAnimationsMap.end())
+        return;
+
+    auto& animations = iterator->value;
+    animations.removeFirst(&animation);
+    if (!animations.size())
+        m_elementToAnimationsMap.remove(iterator);
+}
+
+Vector<RefPtr<WebAnimation>> AnimationTimeline::animationsForElement(Element& element)
+{
+    Vector<RefPtr<WebAnimation>> animations;
+    if (m_elementToAnimationsMap.contains(&element))
+        animations = m_elementToAnimationsMap.get(&element);
+    return animations;
+}
+
 String AnimationTimeline::description()
 {
     TextStream stream;

Modified: trunk/Source/WebCore/animation/AnimationTimeline.h (224759 => 224760)


--- trunk/Source/WebCore/animation/AnimationTimeline.h	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/AnimationTimeline.h	2017-11-13 19:14:47 UTC (rev 224760)
@@ -28,6 +28,7 @@
 
 #include "WebAnimation.h"
 #include <wtf/Forward.h>
+#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Optional.h>
 #include <wtf/Ref.h>
@@ -36,6 +37,8 @@
 
 namespace WebCore {
 
+class AnimationEffect;
+class Element;
 class WebAnimation;
 
 class AnimationTimeline : public RefCounted<AnimationTimeline> {
@@ -51,6 +54,11 @@
 
     virtual void animationTimingModelDidChange() { };
 
+    const HashSet<RefPtr<WebAnimation>>& animations() const { return m_animations; }
+    Vector<RefPtr<WebAnimation>> animationsForElement(Element&);
+    void animationWasAddedToElement(WebAnimation&, Element&);
+    void animationWasRemovedFromElement(WebAnimation&, Element&);
+
     virtual ~AnimationTimeline();
 
 protected:
@@ -60,13 +68,12 @@
 
     ClassType classType() const { return m_classType; }
 
-    HashSet<RefPtr<WebAnimation>> animations() const { return m_animations; }
-
     explicit AnimationTimeline(ClassType);
 
 private:
     ClassType m_classType;
     std::optional<Seconds> m_currentTime;
+    HashMap<RefPtr<Element>, Vector<RefPtr<WebAnimation>>> m_elementToAnimationsMap;
     HashSet<RefPtr<WebAnimation>> m_animations;
 };
 

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (224759 => 224760)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -45,7 +45,7 @@
 
 DocumentTimeline::DocumentTimeline(Document& document, PlatformDisplayID displayID)
     : AnimationTimeline(DocumentTimelineClass)
-    , m_document(document)
+    , m_document(&document)
     , m_animationScheduleTimer(*this, &DocumentTimeline::animationScheduleTimerFired)
 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     , m_animationResolutionTimer(*this, &DocumentTimeline::animationResolutionTimerFired)
@@ -59,9 +59,14 @@
     m_invalidationTaskQueue.close();
 }
 
+void DocumentTimeline::detachFromDocument()
+{
+    m_document = nullptr;
+}
+
 std::optional<Seconds> DocumentTimeline::currentTime()
 {
-    if (m_paused)
+    if (m_paused || !m_document)
         return AnimationTimeline::currentTime();
 
     if (!m_cachedCurrentTime) {
@@ -170,7 +175,7 @@
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 RefPtr<DisplayRefreshMonitor> DocumentTimeline::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
 {
-    if (!m_document->page())
+    if (!m_document || !m_document->page())
         return nullptr;
 
     if (auto monitor = m_document->page()->chrome().client().createDisplayRefreshMonitor(displayID))

Modified: trunk/Source/WebCore/animation/DocumentTimeline.h (224759 => 224760)


--- trunk/Source/WebCore/animation/DocumentTimeline.h	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h	2017-11-13 19:14:47 UTC (rev 224760)
@@ -52,6 +52,8 @@
     void animationTimingModelDidChange() override;
     void windowScreenDidChange(PlatformDisplayID);
 
+    void detachFromDocument();
+
 private:
     DocumentTimeline(Document&, PlatformDisplayID);
 
@@ -62,7 +64,7 @@
     void scheduleAnimationResolution();
     void resolveAnimations();
 
-    Ref<Document> m_document;
+    RefPtr<Document> m_document;
     bool m_paused { false };
     std::optional<Seconds> m_cachedCurrentTime;
     GenericTaskQueue<Timer> m_invalidationTaskQueue;

Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (224759 => 224760)


--- trunk/Source/WebCore/animation/WebAnimation.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -29,6 +29,7 @@
 #include "AnimationEffect.h"
 #include "AnimationTimeline.h"
 #include "Document.h"
+#include "KeyframeEffect.h"
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -38,7 +39,7 @@
     auto result = adoptRef(*new WebAnimation());
 
     result->setEffect(effect);
-    
+
     // FIXME: the spec mandates distinguishing between an omitted timeline parameter
     // and an explicit null or undefined value (webkit.org/b/179065).
     result->setTimeline(timeline ? timeline : &document.timeline());
@@ -61,6 +62,33 @@
     if (effect == m_effect)
         return;
 
+    if (m_effect) {
+        m_effect->setAnimation(nullptr);
+
+        // Update the Element to Animation map.
+        if (m_timeline && m_effect->isKeyframeEffect()) {
+            auto* keyframeEffect = downcast<KeyframeEffect>(m_effect.get());
+            auto* target = keyframeEffect->target();
+            if (target)
+                m_timeline->animationWasRemovedFromElement(*this, *target);
+        }
+    }
+
+    if (effect) {
+        // An animation effect can only be associated with a single animation.
+        if (effect->animation())
+            effect->animation()->setEffect(nullptr);
+
+        effect->setAnimation(this);
+
+        if (m_timeline && effect->isKeyframeEffect()) {
+            auto* keyframeEffect = downcast<KeyframeEffect>(effect.get());
+            auto* target = keyframeEffect->target();
+            if (target)
+                m_timeline->animationWasAddedToElement(*this, *target);
+        }
+    }
+
     m_effect = WTFMove(effect);
 }
 
@@ -78,6 +106,17 @@
     if (timeline)
         timeline->addAnimation(*this);
 
+    if (m_effect && m_effect->isKeyframeEffect()) {
+        auto* keyframeEffect = downcast<KeyframeEffect>(m_effect.get());
+        auto* target = keyframeEffect->target();
+        if (target) {
+            if (m_timeline)
+                m_timeline->animationWasRemovedFromElement(*this, *target);
+            if (timeline)
+                timeline->animationWasAddedToElement(*this, *target);
+        }
+    }
+
     m_timeline = WTFMove(timeline);
 }
     

Modified: trunk/Source/WebCore/dom/Document.cpp (224759 => 224760)


--- trunk/Source/WebCore/dom/Document.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Document.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -58,6 +58,7 @@
 #include "DocumentLoader.h"
 #include "DocumentMarkerController.h"
 #include "DocumentSharedObjectPool.h"
+#include "DocumentTimeline.h"
 #include "DocumentType.h"
 #include "Editing.h"
 #include "Editor.h"
@@ -195,6 +196,7 @@
 #include "ValidationMessageClient.h"
 #include "VisibilityChangeClient.h"
 #include "VisitedLinkState.h"
+#include "WebAnimation.h"
 #include "WheelEvent.h"
 #include "WindowFeatures.h"
 #include "XMLDocument.h"
@@ -2312,6 +2314,11 @@
     if (m_hasPreparedForDestruction)
         return;
 
+    if (m_timeline) {
+        m_timeline->detachFromDocument();
+        m_timeline = nullptr;
+    }
+
     if (m_frame)
         m_frame->animation().detachFromDocument(this);
 
@@ -7463,6 +7470,17 @@
     return *m_timeline;
 }
 
+Vector<RefPtr<WebAnimation>> Document::getAnimations()
+{
+    Vector<RefPtr<WebAnimation>> animations;
+    if (m_timeline) {
+        // FIXME: Filter and order the list as specified (webkit.org/b/179535).
+        for (auto& animation : m_timeline->animations())
+            animations.append(animation);
+    }
+    return animations;
+}
+
 #if ENABLE(ATTACHMENT_ELEMENT)
 
 void Document::didInsertAttachmentElement(HTMLAttachmentElement& attachment)

Modified: trunk/Source/WebCore/dom/Document.h (224759 => 224760)


--- trunk/Source/WebCore/dom/Document.h	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Document.h	2017-11-13 19:14:47 UTC (rev 224760)
@@ -30,7 +30,6 @@
 #include "Color.h"
 #include "ContainerNode.h"
 #include "DocumentEventQueue.h"
-#include "DocumentTimeline.h"
 #include "DocumentTiming.h"
 #include "FocusDirection.h"
 #include "FontSelectorClient.h"
@@ -102,6 +101,7 @@
 class DocumentMarkerController;
 class DocumentParser;
 class DocumentSharedObjectPool;
+class DocumentTimeline;
 class DocumentType;
 class ExtensionStyleSheets;
 class FloatQuad;
@@ -173,6 +173,7 @@
 class TreeWalker;
 class VisibilityChangeClient;
 class VisitedLinkState;
+class WebAnimation;
 class WebGL2RenderingContext;
 class WebGLRenderingContext;
 class WebGPURenderingContext;
@@ -1376,6 +1377,7 @@
     WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
 
     DocumentTimeline& timeline();
+    Vector<RefPtr<WebAnimation>> getAnimations();
         
 #if ENABLE(ATTACHMENT_ELEMENT)
     void didInsertAttachmentElement(HTMLAttachmentElement&);

Modified: trunk/Source/WebCore/dom/Document.idl (224759 => 224760)


--- trunk/Source/WebCore/dom/Document.idl	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Document.idl	2017-11-13 19:14:47 UTC (rev 224760)
@@ -212,6 +212,7 @@
     [Replaceable] readonly attribute HTMLAllCollection all; /* [SameObject] */
 
     [EnabledAtRuntime=WebAnimations] readonly attribute DocumentTimeline timeline;
+    [EnabledAtRuntime=WebAnimations] sequence<WebAnimation> getAnimations();
 };
 
 enum DocumentReadyState { "loading", "interactive", "complete" };

Modified: trunk/Source/WebCore/dom/Element.cpp (224759 => 224760)


--- trunk/Source/WebCore/dom/Element.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Element.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -42,6 +42,7 @@
 #include "DOMRectList.h"
 #include "DOMTokenList.h"
 #include "DocumentSharedObjectPool.h"
+#include "DocumentTimeline.h"
 #include "Editing.h"
 #include "ElementIterator.h"
 #include "ElementRareData.h"
@@ -3700,4 +3701,10 @@
     return nullptr;
 }
 
+Vector<RefPtr<WebAnimation>> Element::getAnimations()
+{
+    // FIXME: Filter and order the list as specified (webkit.org/b/179535).
+    return document().timeline().animationsForElement(*this);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/Element.h (224759 => 224760)


--- trunk/Source/WebCore/dom/Element.h	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Element.h	2017-11-13 19:14:47 UTC (rev 224760)
@@ -552,6 +552,8 @@
 
     Element* findAnchorElementForLink(String& outAnchorName);
 
+    Vector<RefPtr<WebAnimation>> getAnimations();
+
 protected:
     Element(const QualifiedName&, Document&, ConstructionType);
 

Modified: trunk/Source/WebCore/dom/Element.idl (224759 => 224760)


--- trunk/Source/WebCore/dom/Element.idl	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/dom/Element.idl	2017-11-13 19:14:47 UTC (rev 224760)
@@ -146,6 +146,7 @@
     required ShadowRootMode mode;
 };
 
+Element implements Animatable;
 Element implements ChildNode;
 Element implements DocumentAndElementEventHandlers;
 Element implements NonDocumentTypeChildNode;

Modified: trunk/Source/WebCore/testing/Internals.cpp (224759 => 224760)


--- trunk/Source/WebCore/testing/Internals.cpp	2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/Source/WebCore/testing/Internals.cpp	2017-11-13 19:14:47 UTC (rev 224760)
@@ -29,6 +29,7 @@
 
 #include "AXObjectCache.h"
 #include "ActiveDOMCallbackMicrotask.h"
+#include "AnimationTimeline.h"
 #include "ApplicationCacheStorage.h"
 #include "AudioSession.h"
 #include "Autofill.h"
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to