[Web Animations] Add a supporting object for Document to manage timelines
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Apr 2020 07:16:51 +0000 (07:16 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Apr 2020 07:16:51 +0000 (07:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=210817

Reviewed by Dean Jackson.

Add a new DocumentTimelinesController object owned by Document to manage DocumentTimelines created for it. This simple piece of refactoring is the first
step towards a coordinated "update animations and send events" procedure where all timelines are updated at once with a single microtask checkpoint instead
of each timeline running one.

No change in behavior, so no new tests.

* Headers.cmake:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::~DocumentTimeline):
(WebCore::DocumentTimeline::controller const):
(WebCore::DocumentTimeline::detachFromDocument):
* animation/DocumentTimeline.h:
* animation/DocumentTimelinesController.cpp: Added.
(WebCore::DocumentTimelinesController::DocumentTimelinesController):
(WebCore::DocumentTimelinesController::~DocumentTimelinesController):
(WebCore::DocumentTimelinesController::addTimeline):
(WebCore::DocumentTimelinesController::removeTimeline):
(WebCore::DocumentTimelinesController::detachFromDocument):
(WebCore::DocumentTimelinesController::updateAnimationsAndSendEvents):
* animation/DocumentTimelinesController.h: Added.
* dom/Document.cpp:
(WebCore::Document::commonTeardown):
(WebCore::Document::ensureTimelinesController):
(WebCore::Document::updateAnimationsAndSendEvents): Deleted.
(WebCore::Document::addTimeline): Deleted.
(WebCore::Document::removeTimeline): Deleted.
* dom/Document.h:
(WebCore::Document::timelinesController const):
* page/Page.cpp:
(WebCore::Page::updateRendering):

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

Source/WebCore/ChangeLog
Source/WebCore/Headers.cmake
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/animation/DocumentTimelinesController.cpp [new file with mode: 0644]
Source/WebCore/animation/DocumentTimelinesController.h [new file with mode: 0644]
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/page/Page.cpp

index d6193ab..0468c26 100644 (file)
@@ -1,3 +1,44 @@
+2020-04-21  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Add a supporting object for Document to manage timelines
+        https://bugs.webkit.org/show_bug.cgi?id=210817
+
+        Reviewed by Dean Jackson.
+
+        Add a new DocumentTimelinesController object owned by Document to manage DocumentTimelines created for it. This simple piece of refactoring is the first
+        step towards a coordinated "update animations and send events" procedure where all timelines are updated at once with a single microtask checkpoint instead
+        of each timeline running one.
+
+        No change in behavior, so no new tests.
+
+        * Headers.cmake:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::DocumentTimeline):
+        (WebCore::DocumentTimeline::~DocumentTimeline):
+        (WebCore::DocumentTimeline::controller const):
+        (WebCore::DocumentTimeline::detachFromDocument):
+        * animation/DocumentTimeline.h:
+        * animation/DocumentTimelinesController.cpp: Added.
+        (WebCore::DocumentTimelinesController::DocumentTimelinesController):
+        (WebCore::DocumentTimelinesController::~DocumentTimelinesController):
+        (WebCore::DocumentTimelinesController::addTimeline):
+        (WebCore::DocumentTimelinesController::removeTimeline):
+        (WebCore::DocumentTimelinesController::detachFromDocument):
+        (WebCore::DocumentTimelinesController::updateAnimationsAndSendEvents):
+        * animation/DocumentTimelinesController.h: Added.
+        * dom/Document.cpp:
+        (WebCore::Document::commonTeardown):
+        (WebCore::Document::ensureTimelinesController):
+        (WebCore::Document::updateAnimationsAndSendEvents): Deleted.
+        (WebCore::Document::addTimeline): Deleted.
+        (WebCore::Document::removeTimeline): Deleted.
+        * dom/Document.h:
+        (WebCore::Document::timelinesController const):
+        * page/Page.cpp:
+        (WebCore::Page::updateRendering):
+
 2020-04-21  Cathie Chen  <cathiechen@igalia.com>
 
         REGRESSION (r254790): No longer get smooth scrolling on music.apple.com
index 893b9be..806a281 100644 (file)
@@ -180,6 +180,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
 
     animation/CSSPropertyBlendingClient.h
     animation/CompositeOperation.h
+    animation/DocumentTimelinesController.h
     animation/EffectTiming.h
     animation/FillMode.h
     animation/GetAnimationsOptions.h
index c57478c..6f154f1 100644 (file)
@@ -480,6 +480,7 @@ animation/CSSAnimation.cpp
 animation/CSSTransition.cpp
 animation/DeclarativeAnimation.cpp
 animation/DocumentTimeline.cpp
+animation/DocumentTimelinesController.cpp
 animation/ElementAnimationRareData.cpp
 animation/KeyframeEffect.cpp
 animation/KeyframeEffectStack.cpp
index 28a0017..7c8200b 100644 (file)
                715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
                71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71729F7E20F3BB4700801CE6 /* JSDocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */; };
+               7181A16C244F0F40007D8A24 /* DocumentTimelinesController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7181A169244F0F2C007D8A24 /* DocumentTimelinesController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71A1B6081DEE5AD70073BCFB /* modern-media-controls-localized-strings.js in Resources */ = {isa = PBXBuildFile; fileRef = 71A1B6061DEE5A820073BCFB /* modern-media-controls-localized-strings.js */; };
                71A57DF2154BE25C0009D120 /* SVGPathUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A57DF0154BE25C0009D120 /* SVGPathUtilities.h */; };
                71A58196236F467600D81A24 /* KeyframeEffectStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A58193236F466400D81A24 /* KeyframeEffectStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
                717F618E1E43D61A00F37024 /* text-tracks.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "text-tracks.css"; sourceTree = "<group>"; };
                717F90571DC40ED60006F520 /* volume-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-support.js"; sourceTree = "<group>"; };
                717F90581DC4BB600006F520 /* airplay-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-support.js"; sourceTree = "<group>"; };
+               7181A169244F0F2C007D8A24 /* DocumentTimelinesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentTimelinesController.h; sourceTree = "<group>"; };
+               7181A16B244F0F2D007D8A24 /* DocumentTimelinesController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentTimelinesController.cpp; sourceTree = "<group>"; };
                718675431DF101AD0033D7F3 /* seek-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "seek-button.js"; sourceTree = "<group>"; };
                718675441DF101C60033D7F3 /* seek-backward-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "seek-backward-support.js"; sourceTree = "<group>"; };
                718675451DF101C60033D7F3 /* seek-forward-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "seek-forward-support.js"; sourceTree = "<group>"; };
                                71025ECA1F99F096004A250C /* DocumentTimeline.idl */,
                                71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */,
                                71729F7920F3BA3900801CE6 /* DocumentTimelineOptions.idl */,
+                               7181A16B244F0F2D007D8A24 /* DocumentTimelinesController.cpp */,
+                               7181A169244F0F2C007D8A24 /* DocumentTimelinesController.h */,
                                712BE47C1FE86448002031CC /* EffectTiming.h */,
                                712BE47A1FE86447002031CC /* EffectTiming.idl */,
                                7119465524181E8400466C11 /* ElementAnimationRareData.cpp */,
                                0B90561A0F2578BF0095FF6A /* DocumentThreadableLoader.h in Headers */,
                                71025ED01F99F0CE004A250C /* DocumentTimeline.h in Headers */,
                                71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */,
+                               7181A16C244F0F40007D8A24 /* DocumentTimelinesController.h in Headers */,
                                86D982F7125C154000AD9E3D /* DocumentTiming.h in Headers */,
                                A8185F3909765766005826D9 /* DocumentType.h in Headers */,
                                973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */,
index aff6fb5..1cc142c 100644 (file)
@@ -32,6 +32,7 @@
 #include "DOMWindow.h"
 #include "DeclarativeAnimation.h"
 #include "Document.h"
+#include "DocumentTimelinesController.h"
 #include "EventLoop.h"
 #include "EventNames.h"
 #include "GraphicsLayer.h"
@@ -67,7 +68,8 @@ DocumentTimeline::DocumentTimeline(Document& document, Seconds originTime)
     , m_document(makeWeakPtr(document))
     , m_originTime(originTime)
 {
-    document.addTimeline(*this);
+    if (auto* controller = this->controller())
+        controller->addTimeline(*this);
     if (auto* page = document.page()) {
         if (page->settings().hiddenPageCSSAnimationSuspensionEnabled() && !page->isVisible())
             suspendAnimations();
@@ -76,15 +78,22 @@ DocumentTimeline::DocumentTimeline(Document& document, Seconds originTime)
 
 DocumentTimeline::~DocumentTimeline()
 {
+    if (auto* controller = this->controller())
+        controller->removeTimeline(*this);
+}
+
+DocumentTimelinesController* DocumentTimeline::controller() const
+{
     if (m_document)
-        m_document->removeTimeline(*this);
+        return &m_document->ensureTimelinesController();
+    return nullptr;
 }
 
 void DocumentTimeline::detachFromDocument()
 {
     Ref<DocumentTimeline> protectedThis(*this);
-    if (m_document)
-        m_document->removeTimeline(*this);
+    if (auto* controller = this->controller())
+        controller->removeTimeline(*this);
 
     m_pendingAnimationEvents.clear();
     m_currentTimeClearingTaskQueue.close();
index 5f6a8dc..75d7748 100644 (file)
@@ -36,6 +36,7 @@
 namespace WebCore {
 
 class AnimationEventBase;
+class DocumentTimelinesController;
 class RenderElement;
 
 class DocumentTimeline final : public AnimationTimeline
@@ -87,6 +88,7 @@ public:
 private:
     DocumentTimeline(Document&, Seconds);
 
+    DocumentTimelinesController* controller() const;
     DOMHighResTimeStamp liveCurrentTime() const;
     void applyPendingAcceleratedAnimations();
     void cacheCurrentTime(DOMHighResTimeStamp);
diff --git a/Source/WebCore/animation/DocumentTimelinesController.cpp b/Source/WebCore/animation/DocumentTimelinesController.cpp
new file mode 100644 (file)
index 0000000..d6a01e5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DocumentTimelinesController.h"
+
+#include "DocumentTimeline.h"
+
+namespace WebCore {
+
+DocumentTimelinesController::DocumentTimelinesController()
+{
+}
+
+DocumentTimelinesController::~DocumentTimelinesController()
+{
+}
+
+void DocumentTimelinesController::addTimeline(DocumentTimeline& timeline)
+{
+    m_timelines.add(timeline);
+}
+
+void DocumentTimelinesController::removeTimeline(DocumentTimeline& timeline)
+{
+    m_timelines.remove(timeline);
+}
+
+void DocumentTimelinesController::detachFromDocument()
+{
+    while (!m_timelines.computesEmpty())
+        m_timelines.begin()->detachFromDocument();
+}
+
+void DocumentTimelinesController::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
+{
+    ASSERT(!m_timelines.hasNullReferences());
+
+    // We need to copy m_timelines before iterating over its members since calling updateAnimationsAndSendEvents() may mutate m_timelines.
+    Vector<RefPtr<DocumentTimeline>> timelines;
+    bool shouldUpdateAnimations = false;
+    for (auto& timeline : m_timelines) {
+        if (timeline.scheduledUpdate())
+            shouldUpdateAnimations = true;
+        timelines.append(&timeline);
+    }
+
+    for (auto& timeline : timelines) {
+        timeline->updateCurrentTime(timestamp);
+        if (shouldUpdateAnimations)
+            timeline->updateAnimationsAndSendEvents();
+    }
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/animation/DocumentTimelinesController.h b/Source/WebCore/animation/DocumentTimelinesController.h
new file mode 100644 (file)
index 0000000..b6e30df
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "DOMHighResTimeStamp.h"
+#include <wtf/WeakHashSet.h>
+
+namespace WebCore {
+
+class DocumentTimeline;
+
+class DocumentTimelinesController {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit DocumentTimelinesController();
+    ~DocumentTimelinesController();
+
+    void addTimeline(DocumentTimeline&);
+    void removeTimeline(DocumentTimeline&);
+    void detachFromDocument();
+    void updateAnimationsAndSendEvents(DOMHighResTimeStamp);
+
+private:
+    WeakHashSet<DocumentTimeline> m_timelines;
+};
+
+} // namespace WebCore
+
index 55a4fc1..d35ac41 100644 (file)
@@ -62,6 +62,7 @@
 #include "DocumentMarkerController.h"
 #include "DocumentSharedObjectPool.h"
 #include "DocumentTimeline.h"
+#include "DocumentTimelinesController.h"
 #include "DocumentType.h"
 #include "DragEvent.h"
 #include "Editing.h"
@@ -799,8 +800,9 @@ void Document::commonTeardown()
 
     m_pendingScrollEventTargetList = nullptr;
 
-    while (!m_timelines.computesEmpty())
-        m_timelines.begin()->detachFromDocument();
+    if (m_timelinesController)
+        m_timelinesController->detachFromDocument();
+
     m_timeline = nullptr;
 }
 
@@ -6369,26 +6371,6 @@ void Document::resumeScriptedAnimationControllerCallbacks()
         m_scriptedAnimationController->resume();
 }
 
-void Document::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
-{
-    ASSERT(!m_timelines.hasNullReferences());
-
-    // We need to copy m_timelines before iterating over its members since calling updateAnimationsAndSendEvents() may mutate m_timelines.
-    Vector<RefPtr<DocumentTimeline>> timelines;
-    bool shouldUpdateAnimations = false;
-    for (auto& timeline : m_timelines) {
-        if (!shouldUpdateAnimations && timeline.scheduledUpdate())
-            shouldUpdateAnimations = true;
-        timelines.append(&timeline);
-    }
-
-    for (auto& timeline : timelines) {
-        timeline->updateCurrentTime(timestamp);
-        if (shouldUpdateAnimations)
-            timeline->updateAnimationsAndSendEvents();
-    }
-}
-
 void Document::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
 {
     if (m_scriptedAnimationController)
@@ -8095,14 +8077,11 @@ void Document::setConsoleMessageListener(RefPtr<StringCallback>&& listener)
     m_consoleMessageListener = listener;
 }
 
-void Document::addTimeline(DocumentTimeline& timeline)
-{
-    m_timelines.add(timeline);
-}
-
-void Document::removeTimeline(DocumentTimeline& timeline)
+DocumentTimelinesController& Document::ensureTimelinesController()
 {
-    m_timelines.remove(timeline);
+    if (!m_timelinesController)
+        m_timelinesController = makeUnique<DocumentTimelinesController>();
+    return *m_timelinesController.get();
 }
 
 DocumentTimeline& Document::timeline()
index 558a4a5..f76af2e 100644 (file)
@@ -32,6 +32,7 @@
 #include "ContainerNode.h"
 #include "DisabledAdaptations.h"
 #include "DocumentIdentifier.h"
+#include "DocumentTimelinesController.h"
 #include "DocumentTiming.h"
 #include "ElementIdentifier.h"
 #include "FocusDirection.h"
@@ -1079,7 +1080,6 @@ public:
     void suspendScriptedAnimationControllerCallbacks();
     void resumeScriptedAnimationControllerCallbacks();
 
-    void updateAnimationsAndSendEvents(DOMHighResTimeStamp);
     void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp);
 
     void windowScreenDidChange(PlatformDisplayID);
@@ -1487,12 +1487,12 @@ public:
 
     WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
 
-    void addTimeline(DocumentTimeline&);
-    void removeTimeline(DocumentTimeline&);
     WEBCORE_EXPORT DocumentTimeline& timeline();
     DocumentTimeline* existingTimeline() const { return m_timeline.get(); }
     Vector<RefPtr<WebAnimation>> getAnimations();
     Vector<RefPtr<WebAnimation>> matchingAnimations(const WTF::Function<bool(Element&)>&);
+    DocumentTimelinesController* timelinesController() const { return m_timelinesController.get(); }
+    DocumentTimelinesController& ensureTimelinesController();
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     void registerAttachmentIdentifier(const String&);
@@ -2071,7 +2071,7 @@ private:
     static bool hasEverCreatedAnAXObjectCache;
 
     RefPtr<DocumentTimeline> m_timeline;
-    WeakHashSet<DocumentTimeline> m_timelines;
+    std::unique_ptr<DocumentTimelinesController> m_timelinesController;
 
     DocumentIdentifier m_identifier;
 
index ff01838..7451511 100644 (file)
@@ -1340,7 +1340,8 @@ void Page::updateRendering()
         if (!document.domWindow())
             return;
         DOMHighResTimeStamp timestamp = document.domWindow()->nowTimestamp();
-        document.updateAnimationsAndSendEvents(timestamp);
+        if (auto* timelinesController = document.timelinesController())
+            timelinesController->updateAnimationsAndSendEvents(timestamp);
         // FIXME: Run the fullscreen steps.
         document.serviceRequestAnimationFrameCallbacks(timestamp);
     });