<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[224760] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/224760">224760</a></dd>
<dt>Author</dt> <dd>graouts@webkit.org</dd>
<dt>Date</dt> <dd>2017-11-13 11:14:47 -0800 (Mon, 13 Nov 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttpwptwebanimationsinterfacesAnimatableanimateexpectedtxt">trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/animate-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwebanimationsinterfacesAnimatablegetAnimationsexpectedtxt">trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwebanimationsinterfacesDocumentgetAnimationsexpectedtxt">trunk/LayoutTests/http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreanimationAnimationEffecth">trunk/Source/WebCore/animation/AnimationEffect.h</a></li>
<li><a href="#trunkSourceWebCoreanimationAnimationTimelinecpp">trunk/Source/WebCore/animation/AnimationTimeline.cpp</a></li>
<li><a href="#trunkSourceWebCoreanimationAnimationTimelineh">trunk/Source/WebCore/animation/AnimationTimeline.h</a></li>
<li><a href="#trunkSourceWebCoreanimationDocumentTimelinecpp">trunk/Source/WebCore/animation/DocumentTimeline.cpp</a></li>
<li><a href="#trunkSourceWebCoreanimationDocumentTimelineh">trunk/Source/WebCore/animation/DocumentTimeline.h</a></li>
<li><a href="#trunkSourceWebCoreanimationWebAnimationcpp">trunk/Source/WebCore/animation/WebAnimation.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumenth">trunk/Source/WebCore/dom/Document.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentidl">trunk/Source/WebCore/dom/Document.idl</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementh">trunk/Source/WebCore/dom/Element.h</a></li>
<li><a href="#trunkSourceWebCoredomElementidl">trunk/Source/WebCore/dom/Element.idl</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/</li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationsinterfacesdocumentgetanimationsexpectedtxt">trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationsinterfacesdocumentgetanimationshtml">trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations.html</a></li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationsinterfaceselementgetanimationsexpectedtxt">trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationsinterfaceselementgetanimationshtml">trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations.html</a></li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationstimingmodelanimationeffectuniquerelationshipexpectedtxt">trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttpwptwkwebanimationstimingmodelanimationeffectuniquerelationshiphtml">trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html</a></li>
<li><a href="#trunkSourceWebCoreanimationAnimatableidl">trunk/Source/WebCore/animation/Animatable.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2017-11-13 18:55:20 UTC (rev 224759)
+++ trunk/LayoutTests/ChangeLog 2017-11-13 19:14:47 UTC (rev 224760)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2017-11-13  Antoine Quint  <graouts@apple.com>
+
+        [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.
+
</ins><span class="cx"> 2017-11-13  Per Arne Vollan  <pvollan@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Mark editing/execCommand/underline-selection-containing-image.html as failing on Windows.
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebanimationsinterfacesAnimatableanimateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/animate-expected.txt (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -91,6 +91,6 @@
</span><span class="cx"> 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)
</span><span class="cx"> 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)
</span><span class="cx"> 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)
</span><del>-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)
</del><ins>+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
</ins><span class="cx">  
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebanimationsinterfacesAnimatablegetAnimationsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><del>-FAIL Test getAnimations on element with no animations div.getAnimations is not a function. (In 'div.getAnimations()', 'div.getAnimations' is undefined)
</del><ins>+PASS Test getAnimations on element with no animations 
</ins><span class="cx"> 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)
</span><span class="cx"> 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)
</span><span class="cx"> 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)
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwebanimationsinterfacesDocumentgetAnimationsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><del>-FAIL Test document.getAnimations for non-animated content document.getAnimations is not a function. (In 'document.getAnimations()', 'document.getAnimations' is undefined)
</del><ins>+PASS Test document.getAnimations for non-animated content 
</ins><span class="cx"> 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)
</span><span class="cx"> 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)
</span><span class="cx"> FAIL Test document.getAnimations with null target Can't find variable: KeyframeEffectReadOnly
</span></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationsinterfacesdocumentgetanimationsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+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(). 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationsinterfacesdocumentgetanimationshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/document-get-animations.html (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getAnimations()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<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>
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationsinterfaceselementgetanimationsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+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(). 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationsinterfaceselementgetanimationshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/interfaces/element-get-animations.html (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getAnimations()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<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>
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationstimingmodelanimationeffectuniquerelationshipexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS Check that setting an animation's effect onto another animation sets effect to null. 
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttpwptwkwebanimationstimingmodelanimationeffectuniquerelationshiphtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Check an AnimationEffect can only be used for one Animation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<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>
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -419,6 +419,7 @@
</span><span class="cx">     Modules/webvr/VRPose.idl
</span><span class="cx">     Modules/webvr/VRStageParameters.idl
</span><span class="cx"> 
</span><ins>+    animation/Animatable.idl
</ins><span class="cx">     animation/AnimationEffect.idl
</span><span class="cx">     animation/AnimationEffectTiming.idl
</span><span class="cx">     animation/AnimationTimeline.idl
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2017-11-13  Antoine Quint  <graouts@apple.com>
+
+        [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:
+
</ins><span class="cx"> 2017-11-13  Alex Christensen  <achristensen@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         Make DocumentLoader::willSendRequest asynchronous
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -343,6 +343,7 @@
</span><span class="cx">     $(WebCore)/Modules/webvr/VRLayerInit.idl \
</span><span class="cx">     $(WebCore)/Modules/webvr/VRPose.idl \
</span><span class="cx">     $(WebCore)/Modules/webvr/VRStageParameters.idl \
</span><ins>+    $(WebCore)/animation/Animatable.idl \
</ins><span class="cx">     $(WebCore)/animation/AnimationEffect.idl \
</span><span class="cx">     $(WebCore)/animation/AnimationEffectTiming.idl \
</span><span class="cx">     $(WebCore)/animation/AnimationTimeline.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -8684,6 +8684,7 @@
</span><span class="cx">          71A57DEF154BE25C0009D120 /* SVGPathUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPathUtilities.cpp; sourceTree = "<group>"; };
</span><span class="cx">          71A57DF0154BE25C0009D120 /* SVGPathUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPathUtilities.h; sourceTree = "<group>"; };
</span><span class="cx">          71B0460A1DD3C2EE00EE19CF /* status-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "status-support.js"; sourceTree = "<group>"; };
</span><ins>+               71C5BB1B1FB611EA0007A2AE /* Animatable.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Animatable.idl; sourceTree = "<group>"; };
</ins><span class="cx">           71C916071D1483A300ACA47D /* UserInterfaceLayoutDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInterfaceLayoutDirection.h; sourceTree = "<group>"; };
</span><span class="cx">          71CC7A1F152A0BFE009EEAF9 /* SVGAnimatedEnumeration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedEnumeration.cpp; sourceTree = "<group>"; };
</span><span class="cx">          71D02D901DB55C4E00DD5CF5 /* main.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = main.js; sourceTree = "<group>"; };
</span><span class="lines">@@ -18622,6 +18623,7 @@
</span><span class="cx">          71025EC11F99F096004A250C /* animation */ = {
</span><span class="cx">                  isa = PBXGroup;
</span><span class="cx">                  children = (
</span><ins>+                               71C5BB1B1FB611EA0007A2AE /* Animatable.idl */,
</ins><span class="cx">                           71556CB11F9F099F00E78D08 /* AnimationEffect.cpp */,
</span><span class="cx">                          71556CAD1F9F099D00E78D08 /* AnimationEffect.h */,
</span><span class="cx">                          71556CB01F9F099E00E78D08 /* AnimationEffect.idl */,
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationAnimatableidlfromrev224759trunkSourceWebCoreanimationAnimationEffecth"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/animation/Animatable.idl (from rev 224759, trunk/Source/WebCore/animation/AnimationEffect.h) (0 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/animation/Animatable.idl                            (rev 0)
+++ trunk/Source/WebCore/animation/Animatable.idl       2017-11-13 19:14:47 UTC (rev 224760)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+/*
+ * 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();
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreanimationAnimationEffecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/AnimationEffect.h (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include "AnimationEffectTiming.h"
</span><ins>+#include "WebAnimation.h"
</ins><span class="cx"> #include <wtf/Forward.h>
</span><span class="cx"> #include <wtf/Ref.h>
</span><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="lines">@@ -40,6 +41,9 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~AnimationEffect() { }
</span><span class="cx"> 
</span><ins>+    WebAnimation* animation() const { return m_animation.get(); }
+    void setAnimation(RefPtr<WebAnimation>&& animation) { m_animation = animation; }
+
</ins><span class="cx"> protected:
</span><span class="cx">     enum ClassType {
</span><span class="cx">         KeyframeEffectClass
</span><span class="lines">@@ -51,6 +55,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ClassType m_classType;
</span><ins>+    RefPtr<WebAnimation> m_animation;
</ins><span class="cx">     RefPtr<AnimationEffectTiming> m_timing;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationAnimationTimelinecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -68,6 +68,34 @@
</span><span class="cx">     animationTimingModelDidChange();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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;
+}
+
</ins><span class="cx"> String AnimationTimeline::description()
</span><span class="cx"> {
</span><span class="cx">     TextStream stream;
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationAnimationTimelineh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/AnimationTimeline.h (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "WebAnimation.h"
</span><span class="cx"> #include <wtf/Forward.h>
</span><ins>+#include <wtf/HashMap.h>
</ins><span class="cx"> #include <wtf/HashSet.h>
</span><span class="cx"> #include <wtf/Optional.h>
</span><span class="cx"> #include <wtf/Ref.h>
</span><span class="lines">@@ -36,6 +37,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class AnimationEffect;
+class Element;
</ins><span class="cx"> class WebAnimation;
</span><span class="cx"> 
</span><span class="cx"> class AnimationTimeline : public RefCounted<AnimationTimeline> {
</span><span class="lines">@@ -51,6 +54,11 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void animationTimingModelDidChange() { };
</span><span class="cx"> 
</span><ins>+    const HashSet<RefPtr<WebAnimation>>& animations() const { return m_animations; }
+    Vector<RefPtr<WebAnimation>> animationsForElement(Element&);
+    void animationWasAddedToElement(WebAnimation&, Element&);
+    void animationWasRemovedFromElement(WebAnimation&, Element&);
+
</ins><span class="cx">     virtual ~AnimationTimeline();
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -60,13 +68,12 @@
</span><span class="cx"> 
</span><span class="cx">     ClassType classType() const { return m_classType; }
</span><span class="cx"> 
</span><del>-    HashSet<RefPtr<WebAnimation>> animations() const { return m_animations; }
-
</del><span class="cx">     explicit AnimationTimeline(ClassType);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ClassType m_classType;
</span><span class="cx">     std::optional<Seconds> m_currentTime;
</span><ins>+    HashMap<RefPtr<Element>, Vector<RefPtr<WebAnimation>>> m_elementToAnimationsMap;
</ins><span class="cx">     HashSet<RefPtr<WebAnimation>> m_animations;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationDocumentTimelinecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> 
</span><span class="cx"> DocumentTimeline::DocumentTimeline(Document& document, PlatformDisplayID displayID)
</span><span class="cx">     : AnimationTimeline(DocumentTimelineClass)
</span><del>-    , m_document(document)
</del><ins>+    , m_document(&document)
</ins><span class="cx">     , m_animationScheduleTimer(*this, &DocumentTimeline::animationScheduleTimerFired)
</span><span class="cx"> #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
</span><span class="cx">     , m_animationResolutionTimer(*this, &DocumentTimeline::animationResolutionTimerFired)
</span><span class="lines">@@ -59,9 +59,14 @@
</span><span class="cx">     m_invalidationTaskQueue.close();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void DocumentTimeline::detachFromDocument()
+{
+    m_document = nullptr;
+}
+
</ins><span class="cx"> std::optional<Seconds> DocumentTimeline::currentTime()
</span><span class="cx"> {
</span><del>-    if (m_paused)
</del><ins>+    if (m_paused || !m_document)
</ins><span class="cx">         return AnimationTimeline::currentTime();
</span><span class="cx"> 
</span><span class="cx">     if (!m_cachedCurrentTime) {
</span><span class="lines">@@ -170,7 +175,7 @@
</span><span class="cx"> #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
</span><span class="cx"> RefPtr<DisplayRefreshMonitor> DocumentTimeline::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
</span><span class="cx"> {
</span><del>-    if (!m_document->page())
</del><ins>+    if (!m_document || !m_document->page())
</ins><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     if (auto monitor = m_document->page()->chrome().client().createDisplayRefreshMonitor(displayID))
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationDocumentTimelineh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/DocumentTimeline.h (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -52,6 +52,8 @@
</span><span class="cx">     void animationTimingModelDidChange() override;
</span><span class="cx">     void windowScreenDidChange(PlatformDisplayID);
</span><span class="cx"> 
</span><ins>+    void detachFromDocument();
+
</ins><span class="cx"> private:
</span><span class="cx">     DocumentTimeline(Document&, PlatformDisplayID);
</span><span class="cx"> 
</span><span class="lines">@@ -62,7 +64,7 @@
</span><span class="cx">     void scheduleAnimationResolution();
</span><span class="cx">     void resolveAnimations();
</span><span class="cx"> 
</span><del>-    Ref<Document> m_document;
</del><ins>+    RefPtr<Document> m_document;
</ins><span class="cx">     bool m_paused { false };
</span><span class="cx">     std::optional<Seconds> m_cachedCurrentTime;
</span><span class="cx">     GenericTaskQueue<Timer> m_invalidationTaskQueue;
</span></span></pre></div>
<a id="trunkSourceWebCoreanimationWebAnimationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include "AnimationEffect.h"
</span><span class="cx"> #include "AnimationTimeline.h"
</span><span class="cx"> #include "Document.h"
</span><ins>+#include "KeyframeEffect.h"
</ins><span class="cx"> #include <wtf/text/WTFString.h>
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -38,7 +39,7 @@
</span><span class="cx">     auto result = adoptRef(*new WebAnimation());
</span><span class="cx"> 
</span><span class="cx">     result->setEffect(effect);
</span><del>-    
</del><ins>+
</ins><span class="cx">     // FIXME: the spec mandates distinguishing between an omitted timeline parameter
</span><span class="cx">     // and an explicit null or undefined value (webkit.org/b/179065).
</span><span class="cx">     result->setTimeline(timeline ? timeline : &document.timeline());
</span><span class="lines">@@ -61,6 +62,33 @@
</span><span class="cx">     if (effect == m_effect)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    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);
+        }
+    }
+
</ins><span class="cx">     m_effect = WTFMove(effect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -78,6 +106,17 @@
</span><span class="cx">     if (timeline)
</span><span class="cx">         timeline->addAnimation(*this);
</span><span class="cx"> 
</span><ins>+    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);
+        }
+    }
+
</ins><span class="cx">     m_timeline = WTFMove(timeline);
</span><span class="cx"> }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> #include "DocumentLoader.h"
</span><span class="cx"> #include "DocumentMarkerController.h"
</span><span class="cx"> #include "DocumentSharedObjectPool.h"
</span><ins>+#include "DocumentTimeline.h"
</ins><span class="cx"> #include "DocumentType.h"
</span><span class="cx"> #include "Editing.h"
</span><span class="cx"> #include "Editor.h"
</span><span class="lines">@@ -195,6 +196,7 @@
</span><span class="cx"> #include "ValidationMessageClient.h"
</span><span class="cx"> #include "VisibilityChangeClient.h"
</span><span class="cx"> #include "VisitedLinkState.h"
</span><ins>+#include "WebAnimation.h"
</ins><span class="cx"> #include "WheelEvent.h"
</span><span class="cx"> #include "WindowFeatures.h"
</span><span class="cx"> #include "XMLDocument.h"
</span><span class="lines">@@ -2312,6 +2314,11 @@
</span><span class="cx">     if (m_hasPreparedForDestruction)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (m_timeline) {
+        m_timeline->detachFromDocument();
+        m_timeline = nullptr;
+    }
+
</ins><span class="cx">     if (m_frame)
</span><span class="cx">         m_frame->animation().detachFromDocument(this);
</span><span class="cx"> 
</span><span class="lines">@@ -7463,6 +7470,17 @@
</span><span class="cx">     return *m_timeline;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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;
+}
+
</ins><span class="cx"> #if ENABLE(ATTACHMENT_ELEMENT)
</span><span class="cx"> 
</span><span class="cx"> void Document::didInsertAttachmentElement(HTMLAttachmentElement& attachment)
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.h (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -30,7 +30,6 @@
</span><span class="cx"> #include "Color.h"
</span><span class="cx"> #include "ContainerNode.h"
</span><span class="cx"> #include "DocumentEventQueue.h"
</span><del>-#include "DocumentTimeline.h"
</del><span class="cx"> #include "DocumentTiming.h"
</span><span class="cx"> #include "FocusDirection.h"
</span><span class="cx"> #include "FontSelectorClient.h"
</span><span class="lines">@@ -102,6 +101,7 @@
</span><span class="cx"> class DocumentMarkerController;
</span><span class="cx"> class DocumentParser;
</span><span class="cx"> class DocumentSharedObjectPool;
</span><ins>+class DocumentTimeline;
</ins><span class="cx"> class DocumentType;
</span><span class="cx"> class ExtensionStyleSheets;
</span><span class="cx"> class FloatQuad;
</span><span class="lines">@@ -173,6 +173,7 @@
</span><span class="cx"> class TreeWalker;
</span><span class="cx"> class VisibilityChangeClient;
</span><span class="cx"> class VisitedLinkState;
</span><ins>+class WebAnimation;
</ins><span class="cx"> class WebGL2RenderingContext;
</span><span class="cx"> class WebGLRenderingContext;
</span><span class="cx"> class WebGPURenderingContext;
</span><span class="lines">@@ -1376,6 +1377,7 @@
</span><span class="cx">     WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
</span><span class="cx"> 
</span><span class="cx">     DocumentTimeline& timeline();
</span><ins>+    Vector<RefPtr<WebAnimation>> getAnimations();
</ins><span class="cx">         
</span><span class="cx"> #if ENABLE(ATTACHMENT_ELEMENT)
</span><span class="cx">     void didInsertAttachmentElement(HTMLAttachmentElement&);
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.idl (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -212,6 +212,7 @@
</span><span class="cx">     [Replaceable] readonly attribute HTMLAllCollection all; /* [SameObject] */
</span><span class="cx"> 
</span><span class="cx">     [EnabledAtRuntime=WebAnimations] readonly attribute DocumentTimeline timeline;
</span><ins>+    [EnabledAtRuntime=WebAnimations] sequence<WebAnimation> getAnimations();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> enum DocumentReadyState { "loading", "interactive", "complete" };
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include "DOMRectList.h"
</span><span class="cx"> #include "DOMTokenList.h"
</span><span class="cx"> #include "DocumentSharedObjectPool.h"
</span><ins>+#include "DocumentTimeline.h"
</ins><span class="cx"> #include "Editing.h"
</span><span class="cx"> #include "ElementIterator.h"
</span><span class="cx"> #include "ElementRareData.h"
</span><span class="lines">@@ -3700,4 +3701,10 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Vector<RefPtr<WebAnimation>> Element::getAnimations()
+{
+    // FIXME: Filter and order the list as specified (webkit.org/b/179535).
+    return document().timeline().animationsForElement(*this);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.h (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -552,6 +552,8 @@
</span><span class="cx"> 
</span><span class="cx">     Element* findAnchorElementForLink(String& outAnchorName);
</span><span class="cx"> 
</span><ins>+    Vector<RefPtr<WebAnimation>> getAnimations();
+
</ins><span class="cx"> protected:
</span><span class="cx">     Element(const QualifiedName&, Document&, ConstructionType);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.idl (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -146,6 +146,7 @@
</span><span class="cx">     required ShadowRootMode mode;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+Element implements Animatable;
</ins><span class="cx"> Element implements ChildNode;
</span><span class="cx"> Element implements DocumentAndElementEventHandlers;
</span><span class="cx"> Element implements NonDocumentTypeChildNode;
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (224759 => 224760)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "AXObjectCache.h"
</span><span class="cx"> #include "ActiveDOMCallbackMicrotask.h"
</span><ins>+#include "AnimationTimeline.h"
</ins><span class="cx"> #include "ApplicationCacheStorage.h"
</span><span class="cx"> #include "AudioSession.h"
</span><span class="cx"> #include "Autofill.h"
</span></span></pre>
</div>
</div>

</body>
</html>