Unreviewed, rolling out r242688, r242643, r242624.
authorryanhaddad@apple.com <ryanhaddad@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 17:19:20 +0000 (17:19 +0000)
committerryanhaddad@apple.com <ryanhaddad@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 17:19:20 +0000 (17:19 +0000)
Caused multiple layout test failures and crashes on iOS and macOS.

Reverted changeset:

"requestAnimationFrame should execute before the next frame"
https://bugs.webkit.org/show_bug.cgi?id=177484
https://trac.webkit.org/changeset/242624/webkit

Source/WebCore:

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* accessibility/mac/AXObjectCacheMac.mm:
(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
* animation/DocumentAnimationScheduler.cpp: Added.
(WebCore::DocumentAnimationScheduler::create):
(WebCore::DocumentAnimationScheduler::DocumentAnimationScheduler):
(WebCore::DocumentAnimationScheduler::detachFromDocument):
(WebCore::DocumentAnimationScheduler::scheduleWebAnimationsResolution):
(WebCore::DocumentAnimationScheduler::unscheduleWebAnimationsResolution):
(WebCore::DocumentAnimationScheduler::scheduleScriptedAnimationResolution):
(WebCore::DocumentAnimationScheduler::displayRefreshFired):
(WebCore::DocumentAnimationScheduler::windowScreenDidChange):
(WebCore::DocumentAnimationScheduler::createDisplayRefreshMonitor const):
* animation/DocumentAnimationScheduler.h: Renamed from Source/WebCore/page/RenderingUpdateScheduler.h.
(WebCore::DocumentAnimationScheduler::lastTimestamp):
(WebCore::DocumentAnimationScheduler::isFiring const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::updateThrottlingState):
(WebCore::DocumentTimeline::suspendAnimations):
(WebCore::DocumentTimeline::resumeAnimations):
(WebCore::DocumentTimeline::liveCurrentTime const):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::cacheCurrentTime):
(WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded):
(WebCore::DocumentTimeline::animationTimingDidChange):
(WebCore::DocumentTimeline::scheduleAnimationResolution):
(WebCore::DocumentTimeline::unscheduleAnimationResolution):
(WebCore::DocumentTimeline::animationResolutionTimerFired):
(WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
(WebCore::DocumentTimeline::scheduleNextTick):
(WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement):
(WebCore::DocumentTimeline::resolveAnimationsForElement):
(WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents): Deleted.
* animation/DocumentTimeline.h:
* dom/Document.cpp:
(WebCore::Document::resolveStyle):
(WebCore::Document::prepareForDestruction):
(WebCore::Document::windowScreenDidChange):
(WebCore::Document::updateIntersectionObservations):
(WebCore::Document::scheduleForcedIntersectionObservationUpdate):
(WebCore::Document::animationScheduler):
(WebCore::Document::updateAnimationsAndSendEvents): Deleted.
(WebCore::Document::serviceRequestAnimationFrameCallbacks): Deleted.
* dom/Document.h:
* dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::serviceScriptedAnimations):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::ScriptedAnimationController::animationTimerFired):
(WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire):
(WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks): Deleted.
* dom/ScriptedAnimationController.h:
* page/FrameView.cpp:
(WebCore::FrameView::viewportContentsChanged):
* page/IntersectionObserver.cpp:
(WebCore::IntersectionObserver::observe):
* page/Page.cpp:
(WebCore::Page::Page):
(WebCore::Page::willDisplayPage):
(WebCore::Page::addDocumentNeedingIntersectionObservationUpdate):
(WebCore::Page::updateIntersectionObservations):
(WebCore::Page::scheduleForcedIntersectionObservationUpdate):
(WebCore::Page::layoutIfNeeded): Deleted.
(WebCore::Page::renderingUpdate): Deleted.
(WebCore::Page::renderingUpdateScheduler): Deleted.
* page/Page.h:
* page/PageOverlayController.cpp:
(WebCore::PageOverlayController::didChangeViewExposedRect):
(WebCore::PageOverlayController::notifyFlushRequired):
* page/RenderingUpdateScheduler.cpp: Removed.
* page/ios/ContentChangeObserver.h:
* page/mac/ServicesOverlayController.mm:
(WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::scheduleLayerFlushNow):

Source/WebKit:

* WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
(WebKit::DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush):
(WebKit::DrawingAreaCoordinatedGraphics::updateBackingStoreState):
(WebKit::DrawingAreaCoordinatedGraphics::display):
* WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
(WebKit::LayerTreeHost::layerFlushTimerFired):
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::flushLayers):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::layoutIfNeeded):
(WebKit::WebPage::willDisplayPage):
(WebKit::WebPage::renderingUpdate): Deleted.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::flushLayers):

Source/WebKitLegacy/mac:

* WebView/WebView.mm:
(-[WebView _viewWillDrawInternal]):

Source/WebKitLegacy/win:

* WebView.cpp:
(WebView::updateBackingStore):
(WebView::flushPendingGraphicsLayerChangesSoon):
(WebView::flushPendingGraphicsLayerChanges):

Source/WTF:

* wtf/SystemTracing.h:

Tools:

* Tracing/SystemTracePoints.plist:

LayoutTests:

* TestExpectations:
* animations/animation-multiple-callbacks-timestamp.html:
* animations/no-style-recalc-during-accelerated-animation-expected.txt:
* animations/no-style-recalc-during-accelerated-animation.html:
* platform/mac-wk2/TestExpectations:

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

42 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/animations/animation-multiple-callbacks-timestamp.html
LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt
LayoutTests/animations/no-style-recalc-during-accelerated-animation.html
LayoutTests/platform/mac-wk2/TestExpectations
Source/WTF/ChangeLog
Source/WTF/wtf/SystemTracing.h
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/accessibility/mac/AXObjectCacheMac.mm
Source/WebCore/animation/DocumentAnimationScheduler.cpp [new file with mode: 0644]
Source/WebCore/animation/DocumentAnimationScheduler.h [moved from Source/WebCore/page/RenderingUpdateScheduler.h with 58% similarity]
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/ScriptedAnimationController.cpp
Source/WebCore/dom/ScriptedAnimationController.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/IntersectionObserver.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/page/PageOverlayController.cpp
Source/WebCore/page/RenderingUpdateScheduler.cpp [deleted file]
Source/WebCore/page/ios/ContentChangeObserver.h
Source/WebCore/page/mac/ServicesOverlayController.mm
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebView.mm
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/WebView.cpp
Tools/ChangeLog
Tools/Tracing/SystemTracePoints.plist

index f8fa3d9..f2dc306 100644 (file)
@@ -1,3 +1,21 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * TestExpectations:
+        * animations/animation-multiple-callbacks-timestamp.html:
+        * animations/no-style-recalc-during-accelerated-animation-expected.txt:
+        * animations/no-style-recalc-during-accelerated-animation.html:
+        * platform/mac-wk2/TestExpectations:
+
 2019-03-11  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Make it possible exclude localhost from classification
index e92e5e4..9035429 100644 (file)
@@ -3039,8 +3039,6 @@ webkit.org/b/187773 http/tests/webAPIStatistics [ Skip ]
 
 # This is fallout from turning Web Animations on.
 webkit.org/b/190032 animations/animation-playstate-paused-style-resolution.html [ Failure ]
-webkit.org/b/190032 animations/missing-values-first-keyframe.html [ Failure ]
-webkit.org/b/190032 animations/missing-values-last-keyframe.html [ Failure ]
 webkit.org/b/190032 compositing/backing/backing-store-attachment-fill-forwards-animation.html [ Failure ]
 webkit.org/b/190032 compositing/backing/transform-transition-from-outside-view.html [ Failure ]
 webkit.org/b/190032 compositing/layer-creation/mismatched-rotated-transform-transition-overlap.html [ Failure ]
index 750e2c7..5ddd9bf 100644 (file)
@@ -35,7 +35,7 @@
         {
             const WarmupFrames = 5;
             if (++currentFrame > WarmupFrames && timestamp != timestamp1) {
-                testFailed("timestamp = " + timestamp + ", timestamp1 = " + timestamp1  + ", window.performance.now() = " + window.performance.now());
+                testFailed("timestamp1 = " + timestamp1 + ", timestamp2 = " + timestamp2  + ", window.performance.now() = " + window.performance.now());
                 failed = true;
             }
         }
index 05f0aef..cfa01f7 100644 (file)
             box.addEventListener("animationiteration", () => result.innerText = "Got iteration event.\n");
             box.addEventListener("animationend", () => {
                 const numRecalcs = internals.styleRecalcCount();
-                if (numRecalcs > 3)
-                    result.innerText += "FAIL: saw " + numRecalcs + " style recalcs during the animation, should only see three."
+                if (numRecalcs > 2)
+                    result.innerText += "FAIL: saw " + numRecalcs + " style recalcs during the animation, should only see two."
                 else 
-                    result.innerText += "PASS: saw three or fewer style recalcs during the animation."
+                    result.innerText += "PASS: saw two or fewer style recalcs during the animation."
 
                 if (window.testRunner)
                     testRunner.notifyDone();
index 61f17b5..2cac034 100644 (file)
@@ -924,7 +924,4 @@ webkit.org/b/194253 scrollingcoordinator/scrolling-tree/fixed-inside-frame.html
 
 webkit.org/b/194350 http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-image-in-iframe-with-enforced-and-report-policies.html [ Pass Failure ]
 
-webkit.org/b/194916 fast/mediastream/MediaStream-video-element.html [ Pass Failure ]
-
-webkit.org/b/195531 accessibility/mac/selection-notification-focus-change.html [ Failure ]
-webkit.org/b/195531 compositing/video/video-clip-change-src.html [ ImageOnlyFailure ]
+webkit.org/b/194916 fast/mediastream/MediaStream-video-element.html [ Pass Failure ]
\ No newline at end of file
index b46a186..2174d3e 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * wtf/SystemTracing.h:
+
 2019-03-11  Darin Adler  <darin@apple.com>
 
         Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
index bcce0f9..ac9fda0 100644 (file)
@@ -77,11 +77,6 @@ enum TracePointCode {
     ComputeEventRegionsStart,
     ComputeEventRegionsEnd,
 
-    ScheduleRenderingUpdate,
-    TriggerRenderingUpdate,
-    RenderingUpdateStart,
-    RenderingUpdateEnd,
-
     WebKitRange = 10000,
     WebHTMLViewPaintStart,
     WebHTMLViewPaintEnd,
index e09f8e7..8c2292b 100644 (file)
@@ -1,3 +1,92 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * accessibility/mac/AXObjectCacheMac.mm:
+        (WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
+        * animation/DocumentAnimationScheduler.cpp: Added.
+        (WebCore::DocumentAnimationScheduler::create):
+        (WebCore::DocumentAnimationScheduler::DocumentAnimationScheduler):
+        (WebCore::DocumentAnimationScheduler::detachFromDocument):
+        (WebCore::DocumentAnimationScheduler::scheduleWebAnimationsResolution):
+        (WebCore::DocumentAnimationScheduler::unscheduleWebAnimationsResolution):
+        (WebCore::DocumentAnimationScheduler::scheduleScriptedAnimationResolution):
+        (WebCore::DocumentAnimationScheduler::displayRefreshFired):
+        (WebCore::DocumentAnimationScheduler::windowScreenDidChange):
+        (WebCore::DocumentAnimationScheduler::createDisplayRefreshMonitor const):
+        * animation/DocumentAnimationScheduler.h: Renamed from Source/WebCore/page/RenderingUpdateScheduler.h.
+        (WebCore::DocumentAnimationScheduler::lastTimestamp):
+        (WebCore::DocumentAnimationScheduler::isFiring const):
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::DocumentTimeline):
+        (WebCore::DocumentTimeline::updateThrottlingState):
+        (WebCore::DocumentTimeline::suspendAnimations):
+        (WebCore::DocumentTimeline::resumeAnimations):
+        (WebCore::DocumentTimeline::liveCurrentTime const):
+        (WebCore::DocumentTimeline::currentTime):
+        (WebCore::DocumentTimeline::cacheCurrentTime):
+        (WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded):
+        (WebCore::DocumentTimeline::animationTimingDidChange):
+        (WebCore::DocumentTimeline::scheduleAnimationResolution):
+        (WebCore::DocumentTimeline::unscheduleAnimationResolution):
+        (WebCore::DocumentTimeline::animationResolutionTimerFired):
+        (WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
+        (WebCore::DocumentTimeline::scheduleNextTick):
+        (WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement):
+        (WebCore::DocumentTimeline::resolveAnimationsForElement):
+        (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents): Deleted.
+        * animation/DocumentTimeline.h:
+        * dom/Document.cpp:
+        (WebCore::Document::resolveStyle):
+        (WebCore::Document::prepareForDestruction):
+        (WebCore::Document::windowScreenDidChange):
+        (WebCore::Document::updateIntersectionObservations):
+        (WebCore::Document::scheduleForcedIntersectionObservationUpdate):
+        (WebCore::Document::animationScheduler):
+        (WebCore::Document::updateAnimationsAndSendEvents): Deleted.
+        (WebCore::Document::serviceRequestAnimationFrameCallbacks): Deleted.
+        * dom/Document.h:
+        * dom/ScriptedAnimationController.cpp:
+        (WebCore::ScriptedAnimationController::serviceScriptedAnimations):
+        (WebCore::ScriptedAnimationController::scheduleAnimation):
+        (WebCore::ScriptedAnimationController::animationTimerFired):
+        (WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire):
+        (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks): Deleted.
+        * dom/ScriptedAnimationController.h:
+        * page/FrameView.cpp:
+        (WebCore::FrameView::viewportContentsChanged):
+        * page/IntersectionObserver.cpp:
+        (WebCore::IntersectionObserver::observe):
+        * page/Page.cpp:
+        (WebCore::Page::Page):
+        (WebCore::Page::willDisplayPage):
+        (WebCore::Page::addDocumentNeedingIntersectionObservationUpdate):
+        (WebCore::Page::updateIntersectionObservations):
+        (WebCore::Page::scheduleForcedIntersectionObservationUpdate):
+        (WebCore::Page::layoutIfNeeded): Deleted.
+        (WebCore::Page::renderingUpdate): Deleted.
+        (WebCore::Page::renderingUpdateScheduler): Deleted.
+        * page/Page.h:
+        * page/PageOverlayController.cpp:
+        (WebCore::PageOverlayController::didChangeViewExposedRect):
+        (WebCore::PageOverlayController::notifyFlushRequired):
+        * page/RenderingUpdateScheduler.cpp: Removed.
+        * page/ios/ContentChangeObserver.h:
+        * page/mac/ServicesOverlayController.mm:
+        (WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::scheduleLayerFlushNow):
+
 2019-03-11  Darin Adler  <darin@apple.com>
 
         Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
index d2fcdf2..18e2214 100644 (file)
@@ -420,6 +420,7 @@ animation/AnimationTimeline.cpp
 animation/CSSAnimation.cpp
 animation/CSSTransition.cpp
 animation/DeclarativeAnimation.cpp
+animation/DocumentAnimationScheduler.cpp
 animation/DocumentTimeline.cpp
 animation/KeyframeEffect.cpp
 animation/WebAnimation.cpp
@@ -1540,7 +1541,6 @@ page/ProcessWarming.cpp
 page/Quirks.cpp
 page/RemoteDOMWindow.cpp
 page/RemoteFrame.cpp
-page/RenderingUpdateScheduler.cpp
 page/ResourceUsageOverlay.cpp
 page/ResourceUsageThread.cpp
 page/RuntimeEnabledFeatures.cpp
index 582c0e8..ccdadec 100644 (file)
                5550CB421E955E3C00111AA0 /* ImageTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5550CB411E955E3C00111AA0 /* ImageTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                555130011E7CCCCB00A69E38 /* DecodingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 555130001E7CCCCA00A69E38 /* DecodingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
-               556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
                55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
                55AF14E61EAAC59B0026EEAA /* UTIRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 55AF14E41EAAC59B0026EEAA /* UTIRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7156BCA121CA350F00534397 /* BasicEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7156BC9F21CA350600534397 /* BasicEffectTiming.h */; };
                715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
+               716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                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 */; };
                71A1B6081DEE5AD70073BCFB /* modern-media-controls-localized-strings.js in Resources */ = {isa = PBXBuildFile; fileRef = 71A1B6061DEE5A820073BCFB /* modern-media-controls-localized-strings.js */; };
                555130001E7CCCCA00A69E38 /* DecodingOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecodingOptions.h; sourceTree = "<group>"; };
                555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
                555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
-               556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderingUpdateScheduler.h; sourceTree = "<group>"; };
-               556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderingUpdateScheduler.cpp; sourceTree = "<group>"; };
                5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
                5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
                5597FCCB2076C06800D35BB0 /* GlyphDisplayListCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlyphDisplayListCache.h; sourceTree = "<group>"; };
                716C8DF21E48B269005BD0DA /* volume-up-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-support.js"; sourceTree = "<group>"; };
                716C8DF31E48B284005BD0DA /* volume-down-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-down-button.js"; sourceTree = "<group>"; };
                716C8DF41E48B284005BD0DA /* volume-up-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-button.js"; sourceTree = "<group>"; };
+               716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentAnimationScheduler.h; sourceTree = "<group>"; };
+               716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentAnimationScheduler.cpp; sourceTree = "<group>"; };
                716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
                716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-button.js"; sourceTree = "<group>"; };
                716FA0DA1DB26591007323CC /* airplay-placard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-placard.js"; sourceTree = "<group>"; };
                                46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */,
                                46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
                                46B95192207D632E00A7D2DD /* RemoteFrame.h */,
-                               556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */,
-                               556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */,
                                A5071E821C56D079009951BE /* ResourceUsageData.h */,
                                ADBAD6EC1BCDD95000381325 /* ResourceUsageOverlay.cpp */,
                                ADBAD6ED1BCDD95000381325 /* ResourceUsageOverlay.h */,
                                7123C185204739B900789392 /* CSSTransition.idl */,
                                715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
                                715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
+                               716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */,
+                               716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */,
                                71025EC41F99F096004A250C /* DocumentTimeline.cpp */,
                                71025EC51F99F096004A250C /* DocumentTimeline.h */,
                                71025ECA1F99F096004A250C /* DocumentTimeline.idl */,
                                B2F34FE60E82F81400F627CD /* DNS.h in Headers */,
                                7EE6846F12D26E3800E73215 /* DNSResolveQueueCFNet.h in Headers */,
                                A8185F4009765766005826D9 /* Document.h in Headers */,
+                               716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */,
                                A3BB59F41457A40D00AC56FE /* DocumentEventQueue.h in Headers */,
                                A8185F3D09765766005826D9 /* DocumentFragment.h in Headers */,
                                46E1666E1FCC86A200C9710B /* DocumentIdentifier.h in Headers */,
                                BCEA4876097D93020094C9E4 /* RenderImage.h in Headers */,
                                08F2F00A1213E61700DCEC48 /* RenderImageResource.h in Headers */,
                                08641D4812142F7D008DE9F6 /* RenderImageResourceStyleImage.h in Headers */,
-                               556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */,
                                BCEA4878097D93020094C9E4 /* RenderInline.h in Headers */,
                                B595FF471824CEE300FF51CD /* RenderIterator.h in Headers */,
                                BCEA487A097D93020094C9E4 /* RenderLayer.h in Headers */,
index bc684d1..1bb5898 100644 (file)
@@ -539,14 +539,8 @@ void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node*)
 {
     NSAccessibilityHandleFocusChanged();
     // AXFocusChanged is a test specific notification name and not something a real AT will be listening for
-    if (UNLIKELY(!axShouldRepostNotificationsForTests))
-        return;
-
-    auto* rootWebArea = this->rootWebArea();
-    if (!rootWebArea)
-        return;
-
-    [rootWebArea->wrapper() accessibilityPostedNotification:@"AXFocusChanged" userInfo:nil];
+    if (UNLIKELY(axShouldRepostNotificationsForTests))
+        [rootWebArea()->wrapper() accessibilityPostedNotification:@"AXFocusChanged" userInfo:nil];
 }
 
 void AXObjectCache::handleScrolledToAnchor(const Node*)
diff --git a/Source/WebCore/animation/DocumentAnimationScheduler.cpp b/Source/WebCore/animation/DocumentAnimationScheduler.cpp
new file mode 100644 (file)
index 0000000..ada330a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 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 "DocumentAnimationScheduler.h"
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "DOMWindow.h"
+#include "DisplayRefreshMonitor.h"
+#include "DisplayRefreshMonitorManager.h"
+#include "Document.h"
+#include "DocumentTimeline.h"
+#include "Page.h"
+#include "ScriptedAnimationController.h"
+
+namespace WebCore {
+
+Ref<DocumentAnimationScheduler> DocumentAnimationScheduler::create(Document& document, PlatformDisplayID displayID)
+{
+    return adoptRef(*new DocumentAnimationScheduler(document, displayID));
+}
+
+DocumentAnimationScheduler::DocumentAnimationScheduler(Document& document, PlatformDisplayID displayID)
+    : m_document(&document)
+{
+    windowScreenDidChange(displayID);
+}
+
+DocumentAnimationScheduler::~DocumentAnimationScheduler() = default;
+
+void DocumentAnimationScheduler::detachFromDocument()
+{
+    m_document = nullptr;
+}
+
+bool DocumentAnimationScheduler::scheduleWebAnimationsResolution()
+{
+    m_scheduledWebAnimationsResolution = true;
+    return DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
+}
+
+void DocumentAnimationScheduler::unscheduleWebAnimationsResolution()
+{
+    m_scheduledWebAnimationsResolution = false;
+
+    if (!m_scheduledScriptedAnimationResolution)
+        DisplayRefreshMonitorManager::sharedManager().unregisterClient(*this);
+}
+
+bool DocumentAnimationScheduler::scheduleScriptedAnimationResolution()
+{
+    m_scheduledScriptedAnimationResolution = true;
+    return DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
+}
+
+void DocumentAnimationScheduler::displayRefreshFired()
+{
+    if (!m_document || !m_document->domWindow())
+        return;
+
+    // This object could be deleted after scripts in the the requestAnimationFrame callbacks are executed.
+    auto protectedThis = makeRef(*this);
+
+    m_isFiring = true;
+    m_lastTimestamp = Seconds(m_document->domWindow()->nowTimestamp());
+
+    if (m_scheduledWebAnimationsResolution) {
+        m_scheduledWebAnimationsResolution = false;
+        m_document->timeline().documentAnimationSchedulerDidFire();
+    }
+
+    if (m_scheduledScriptedAnimationResolution) {
+        m_scheduledScriptedAnimationResolution = false;
+        if (auto* scriptedAnimationController = m_document->scriptedAnimationController())
+            scriptedAnimationController->documentAnimationSchedulerDidFire();
+    }
+
+    m_isFiring = false;
+}
+
+void DocumentAnimationScheduler::windowScreenDidChange(PlatformDisplayID displayID)
+{
+    DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
+}
+
+RefPtr<DisplayRefreshMonitor> DocumentAnimationScheduler::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
+{
+    if (!m_document || !m_document->page())
+        return nullptr;
+
+    if (auto monitor = m_document->page()->chrome().client().createDisplayRefreshMonitor(displayID))
+        return monitor;
+
+    return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
+}
+
+} // namespace WebCore
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #pragma once
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
 #include "DisplayRefreshMonitorClient.h"
+#include "PlatformScreen.h"
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
 #include <wtf/Seconds.h>
 
 namespace WebCore {
 
-class Page;
-class Timer;
+class Document;
 
-class RenderingUpdateScheduler
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    : public DisplayRefreshMonitorClient
-#endif
-{
-    WTF_MAKE_FAST_ALLOCATED;
+class DocumentAnimationScheduler : public RefCounted<DocumentAnimationScheduler>
+    , public DisplayRefreshMonitorClient {
 public:
-    static std::unique_ptr<RenderingUpdateScheduler> create(Page& page)
-    {
-        return std::make_unique<RenderingUpdateScheduler>(page);
-    }
+    static Ref<DocumentAnimationScheduler> create(Document&, PlatformDisplayID);
+    ~DocumentAnimationScheduler();
 
-    RenderingUpdateScheduler(Page&);
-    void scheduleRenderingUpdate();
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    void detachFromDocument();
     void windowScreenDidChange(PlatformDisplayID);
-#endif
+
+    bool scheduleWebAnimationsResolution();
+    void unscheduleWebAnimationsResolution();
+    bool scheduleScriptedAnimationResolution();
+
+    Seconds lastTimestamp() { return m_lastTimestamp; }
+    bool isFiring() const { return m_isFiring; }
 
 private:
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
-    void displayRefreshFired() final;
-#else
-    void displayRefreshFired();
-#endif
+    DocumentAnimationScheduler(Document&, PlatformDisplayID);
 
-    bool isScheduled() const;
-    void startTimer(Seconds);
-    void clearScheduled();
+    RefPtr<Document> m_document;
+    bool m_scheduledWebAnimationsResolution { false };
+    bool m_scheduledScriptedAnimationResolution { false };
+    bool m_isFiring { false };
+    Seconds m_lastTimestamp { 0_s };
 
-    Page& m_page;
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    bool m_scheduled { false };
-#endif
-    std::unique_ptr<Timer> m_refreshTimer;
+    void displayRefreshFired() override;
+    RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
 };
 
-}
+} // namespace WebCore
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
index aba49f4..3018cbb 100644 (file)
@@ -33,6 +33,7 @@
 #include "DOMWindow.h"
 #include "DeclarativeAnimation.h"
 #include "Document.h"
+#include "DocumentAnimationScheduler.h"
 #include "GraphicsLayer.h"
 #include "KeyframeEffect.h"
 #include "Microtasks.h"
@@ -60,7 +61,10 @@ Ref<DocumentTimeline> DocumentTimeline::create(Document& document, DocumentTimel
 
 DocumentTimeline::DocumentTimeline(Document& document, Seconds originTime)
     : AnimationTimeline()
-    , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolution)
+#if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    , m_animationResolutionTimer(*this, &DocumentTimeline::animationResolutionTimerFired)
+#endif
+    , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolutionIfNeeded)
     , m_document(&document)
     , m_originTime(originTime)
 {
@@ -190,7 +194,7 @@ Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
 
 void DocumentTimeline::updateThrottlingState()
 {
-    scheduleAnimationResolution();
+    scheduleAnimationResolutionIfNeeded();
 }
 
 Seconds DocumentTimeline::animationInterval() const
@@ -206,7 +210,7 @@ void DocumentTimeline::suspendAnimations()
         return;
 
     if (!m_cachedCurrentTime)
-        m_cachedCurrentTime = Seconds(liveCurrentTime());
+        m_cachedCurrentTime = liveCurrentTime();
 
     for (const auto& animation : m_animations)
         animation->setSuspended(true);
@@ -230,7 +234,7 @@ void DocumentTimeline::resumeAnimations()
     for (const auto& animation : m_animations)
         animation->setSuspended(false);
 
-    scheduleAnimationResolution();
+    scheduleAnimationResolutionIfNeeded();
 }
 
 bool DocumentTimeline::animationsAreSuspended()
@@ -248,9 +252,13 @@ unsigned DocumentTimeline::numberOfActiveAnimationsForTesting() const
     return count;
 }
 
-DOMHighResTimeStamp DocumentTimeline::liveCurrentTime() const
+Seconds DocumentTimeline::liveCurrentTime() const
 {
-    return m_document->domWindow()->nowTimestamp();
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    return m_document->animationScheduler().lastTimestamp();
+#else
+    return Seconds(m_document->domWindow()->nowTimestamp());
+#endif
 }
 
 Optional<Seconds> DocumentTimeline::currentTime()
@@ -266,15 +274,36 @@ Optional<Seconds> DocumentTimeline::currentTime()
         }
     }
 
-    if (!m_cachedCurrentTime)
-        cacheCurrentTime(liveCurrentTime());
-    
+    auto currentTime = liveCurrentTime();
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    // If we're in the middle of firing a frame, either due to a requestAnimationFrame callback
+    // or scheduling an animation update, we want to ensure we use the same time we're using as
+    // the timestamp for requestAnimationFrame() callbacks.
+    if (m_document->animationScheduler().isFiring())
+        cacheCurrentTime(currentTime);
+#endif
+
+    if (!m_cachedCurrentTime) {
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+        // If we're not in the middle of firing a frame, let's make our best guess at what the currentTime should
+        // be since the last time a frame fired by increment of our update interval. This way code using something
+        // like setTimeout() or handling events will get a time that's only updating at around 60fps, or less if
+        // we're throttled.
+        auto lastAnimationSchedulerTimestamp = currentTime;
+        auto delta = Seconds(m_document->domWindow()->nowTimestamp()) - lastAnimationSchedulerTimestamp;
+        int frames = std::floor(delta.seconds() / animationInterval().seconds());
+        cacheCurrentTime(lastAnimationSchedulerTimestamp + Seconds(frames * animationInterval().seconds()));
+#else
+        cacheCurrentTime(currentTime);
+#endif
+    }
     return m_cachedCurrentTime.value() - m_originTime;
 }
 
-void DocumentTimeline::cacheCurrentTime(DOMHighResTimeStamp newCurrentTime)
+void DocumentTimeline::cacheCurrentTime(Seconds newCurrentTime)
 {
-    m_cachedCurrentTime = Seconds(newCurrentTime);
+    m_cachedCurrentTime = newCurrentTime;
     // We want to be sure to keep this time cached until we've both finished running JS and finished updating
     // animations, so we schedule the invalidation task and register a whenIdle callback on the VM, which will
     // fire syncronously if no JS is running.
@@ -297,10 +326,16 @@ void DocumentTimeline::maybeClearCachedCurrentTime()
         m_cachedCurrentTime = WTF::nullopt;
 }
 
+void DocumentTimeline::scheduleAnimationResolutionIfNeeded()
+{
+    if (!m_isUpdatingAnimations && !m_isSuspended && !m_animations.isEmpty())
+        scheduleAnimationResolution();
+}
+
 void DocumentTimeline::animationTimingDidChange(WebAnimation& animation)
 {
     AnimationTimeline::animationTimingDidChange(animation);
-    scheduleAnimationResolution();
+    scheduleAnimationResolutionIfNeeded();
 }
 
 void DocumentTimeline::removeAnimation(WebAnimation& animation)
@@ -313,44 +348,44 @@ void DocumentTimeline::removeAnimation(WebAnimation& animation)
 
 void DocumentTimeline::scheduleAnimationResolution()
 {
-    if (m_isSuspended || m_animations.isEmpty() || m_animationResolutionScheduled)
-        return;
-
-    if (!m_document || !m_document->page())
-        return;
-    
-    m_document->page()->renderingUpdateScheduler().scheduleRenderingUpdate();
-    m_animationResolutionScheduled = true;
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    m_document->animationScheduler().scheduleWebAnimationsResolution();
+#else
+    // FIXME: We need to use the same logic as ScriptedAnimationController here,
+    // which will be addressed by the refactor tracked by webkit.org/b/179293.
+    m_animationResolutionTimer.startOneShot(animationInterval());
+#endif
 }
 
 void DocumentTimeline::unscheduleAnimationResolution()
 {
     m_tickScheduleTimer.stop();
-    m_animationResolutionScheduled = false;
-}
-
-void DocumentTimeline::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
-{
-    // We need to freeze the current time even if no animation is running.
-    // document.timeline.currentTime may be called from a rAF callback and
-    // it has to match the rAF timestamp.
-    if (!m_isSuspended)
-        cacheCurrentTime(timestamp);
-
-    if (m_isSuspended || m_animations.isEmpty() || !m_animationResolutionScheduled)
-        return;
-
-    internalUpdateAnimationsAndSendEvents();
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    m_document->animationScheduler().unscheduleWebAnimationsResolution();
+#else
+    // FIXME: We need to use the same logic as ScriptedAnimationController here,
+    // which will be addressed by the refactor tracked by webkit.org/b/179293.
+    m_animationResolutionTimer.stop();
+#endif
+}
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+void DocumentTimeline::documentAnimationSchedulerDidFire()
+#else
+void DocumentTimeline::animationResolutionTimerFired()
+#endif
+{
+    updateAnimationsAndSendEvents();
     applyPendingAcceleratedAnimations();
-
-    m_animationResolutionScheduled = false;
     scheduleNextTick();
 }
 
-void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
+void DocumentTimeline::updateAnimationsAndSendEvents()
 {
     m_numberOfAnimationTimelineInvalidationsForTesting++;
 
+    m_isUpdatingAnimations = true;
+
     // https://drafts.csswg.org/web-animations/#update-animations-and-send-events
 
     // 1. Update the current time of all timelines associated with doc passing now as the timestamp.
@@ -413,6 +448,8 @@ void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
     // removed from the list of completed transitions otherwise.
     for (auto& completedTransition : completedTransitions)
         transitionDidComplete(completedTransition);
+
+    m_isUpdatingAnimations = false;
 }
 
 void DocumentTimeline::transitionDidComplete(RefPtr<CSSTransition> transition)
@@ -436,7 +473,7 @@ void DocumentTimeline::scheduleNextTick()
 
     for (const auto& animation : m_animations) {
         if (!animation->isRunningAccelerated()) {
-            scheduleAnimationResolution();
+            scheduleAnimationResolutionIfNeeded();
             return;
         }
     }
@@ -446,7 +483,7 @@ void DocumentTimeline::scheduleNextTick()
     for (const auto& animation : m_animations) {
         auto animationTimeToNextRequiredTick = animation->timeToNextTick();
         if (animationTimeToNextRequiredTick < animationInterval()) {
-            scheduleAnimationResolution();
+            scheduleAnimationResolutionIfNeeded();
             return;
         }
         scheduleDelay = std::min(scheduleDelay, animationTimeToNextRequiredTick);
@@ -556,20 +593,18 @@ void DocumentTimeline::animationAcceleratedRunningStateDidChange(WebAnimation& a
 void DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement(Element& element)
 {
     auto animations = animationsForElement(element);
-
-    if (animations.isEmpty()) {
-        m_elementsWithRunningAcceleratedAnimations.remove(&element);
-        return;
-    }
-
+    bool runningAnimationsForElementAreAllAccelerated = !animations.isEmpty();
     for (const auto& animation : animations) {
         if (!animation->isRunningAccelerated()) {
-            m_elementsWithRunningAcceleratedAnimations.remove(&element);
-            return;
+            runningAnimationsForElementAreAllAccelerated = false;
+            break;
         }
     }
 
-    m_elementsWithRunningAcceleratedAnimations.add(&element);
+    if (runningAnimationsForElementAreAllAccelerated)
+        m_elementsWithRunningAcceleratedAnimations.add(&element);
+    else
+        m_elementsWithRunningAcceleratedAnimations.remove(&element);
 }
 
 void DocumentTimeline::applyPendingAcceleratedAnimations()
@@ -590,28 +625,30 @@ void DocumentTimeline::applyPendingAcceleratedAnimations()
 
 bool DocumentTimeline::resolveAnimationsForElement(Element& element, RenderStyle& targetStyle)
 {
-    bool hasNonAcceleratedAnimationProperty = false;
-
+    bool hasNonAcceleratedAnimations = false;
+    bool hasPendingAcceleratedAnimations = true;
     for (const auto& animation : animationsForElement(element)) {
         animation->resolve(targetStyle);
-
-        if (hasNonAcceleratedAnimationProperty)
-            continue;
-
-        auto* effect = animation->effect();
-        if (!effect || !is<KeyframeEffect>(effect))
-            continue;
-
-        auto* keyframeEffect = downcast<KeyframeEffect>(effect);
-        for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
-            if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
-                hasNonAcceleratedAnimationProperty = true;
-                break;
+        if (!hasNonAcceleratedAnimations) {
+            if (auto* effect = animation->effect()) {
+                if (is<KeyframeEffect>(effect)) {
+                    auto* keyframeEffect = downcast<KeyframeEffect>(effect);
+                    for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
+                        if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
+                            hasNonAcceleratedAnimations = true;
+                            continue;
+                        }
+                        if (!hasPendingAcceleratedAnimations)
+                            hasPendingAcceleratedAnimations = keyframeEffect->hasPendingAcceleratedAction();
+                    }
+                }
             }
         }
     }
 
-    return !hasNonAcceleratedAnimationProperty;
+    // If there are no non-accelerated animations and we've encountered at least one pending
+    // accelerated animation, we should recomposite this element's layer for animation purposes.
+    return !hasNonAcceleratedAnimations && hasPendingAcceleratedAnimations;
 }
 
 bool DocumentTimeline::runningAnimationsForElementAreAllAccelerated(Element& element) const
index 49a1110..7cc81c9 100644 (file)
@@ -71,8 +71,10 @@ public:
     void detachFromDocument();
 
     void enqueueAnimationPlaybackEvent(AnimationPlaybackEvent&);
-    
-    void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    void documentAnimationSchedulerDidFire();
+#endif
 
     void updateThrottlingState();
     WEBCORE_EXPORT Seconds animationInterval() const;
@@ -86,19 +88,26 @@ public:
 private:
     DocumentTimeline(Document&, Seconds);
 
-    DOMHighResTimeStamp liveCurrentTime() const;
-    void cacheCurrentTime(DOMHighResTimeStamp);
-    void maybeClearCachedCurrentTime();
+    Seconds liveCurrentTime() const;
+    void cacheCurrentTime(Seconds);
+    void scheduleAnimationResolutionIfNeeded();
     void scheduleInvalidationTaskIfNeeded();
     void performInvalidationTask();
+    void animationScheduleTimerFired();
     void scheduleAnimationResolution();
     void unscheduleAnimationResolution();
-    void internalUpdateAnimationsAndSendEvents();
+    void updateAnimationsAndSendEvents();
     void performEventDispatchTask();
+    void maybeClearCachedCurrentTime();
     void updateListOfElementsWithRunningAcceleratedAnimationsForElement(Element&);
     void transitionDidComplete(RefPtr<CSSTransition>);
     void scheduleNextTick();
 
+#if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    void animationResolutionTimerFired();
+    Timer m_animationResolutionTimer;
+#endif
+
     Timer m_tickScheduleTimer;
     GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
     HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;
@@ -110,7 +119,7 @@ private:
     unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
     bool m_isSuspended { false };
     bool m_waitingOnVMIdle { false };
-    bool m_animationResolutionScheduled { false };
+    bool m_isUpdatingAnimations { false };
 };
 
 } // namespace WebCore
index 0a1a1ec..1105179 100644 (file)
@@ -57,6 +57,7 @@
 #include "DOMWindow.h"
 #include "DateComponents.h"
 #include "DebugPageOverlays.h"
+#include "DocumentAnimationScheduler.h"
 #include "DocumentLoader.h"
 #include "DocumentMarkerController.h"
 #include "DocumentSharedObjectPool.h"
@@ -1957,8 +1958,11 @@ void Document::resolveStyle(ResolveStyleType type)
             frameView.layoutContext().scheduleLayout();
 
         // Usually this is handled by post-layout.
-        if (!frameView.needsLayout())
+        if (!frameView.needsLayout()) {
             frameView.frame().selection().scheduleAppearanceUpdateAfterStyleChange();
+            if (m_needsForcedIntersectionObservationUpdate)
+                page()->scheduleForcedIntersectionObservationUpdate(*this);
+        }
 
         // As a result of the style recalculation, the currently hovered element might have been
         // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event
@@ -2555,6 +2559,13 @@ void Document::prepareForDestruction()
         m_timeline = nullptr;
     }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    if (m_animationScheduler) {
+        m_animationScheduler->detachFromDocument();
+        m_animationScheduler = nullptr;
+    }
+#endif
+
 #if ENABLE(CSS_PAINTING_API)
     for (auto& scope : m_paintWorkletGlobalScopes.values())
         scope->prepareForDestruction();
@@ -6251,20 +6262,13 @@ void Document::resumeScriptedAnimationControllerCallbacks()
         m_scriptedAnimationController->resume();
 }
 
-void Document::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
-{
-    if (m_timeline)
-        m_timeline->updateAnimationsAndSendEvents(timestamp);
-}
-
-void Document::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
-{
-    if (m_scriptedAnimationController)
-        m_scriptedAnimationController->serviceRequestAnimationFrameCallbacks(timestamp);
-}
-
 void Document::windowScreenDidChange(PlatformDisplayID displayID)
 {
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    if (m_animationScheduler)
+        m_animationScheduler->windowScreenDidChange(displayID);
+#endif
+
     if (RenderView* view = renderView()) {
         if (view->usesCompositing())
             view->compositor().windowScreenDidChange(displayID);
@@ -7926,6 +7930,8 @@ void Document::updateIntersectionObservations()
     if (needsLayout || hasPendingStyleRecalc())
         return;
 
+    m_needsForcedIntersectionObservationUpdate = false;
+
     for (const auto& observer : m_intersectionObservers) {
         bool needNotify = false;
         DOMHighResTimeStamp timestamp;
@@ -8002,6 +8008,17 @@ void Document::updateIntersectionObservations()
         m_intersectionObserversNotifyTimer.startOneShot(0_s);
 }
 
+void Document::scheduleForcedIntersectionObservationUpdate()
+{
+    ASSERT(!m_intersectionObservers.isEmpty());
+    if (m_needsForcedIntersectionObservationUpdate)
+        return;
+
+    m_needsForcedIntersectionObservationUpdate = true;
+    if (auto* page = this->page())
+        page->scheduleForcedIntersectionObservationUpdate(*this);
+}
+
 void Document::notifyIntersectionObserversTimerFired()
 {
     for (const auto& observer : m_intersectionObserversWithPendingNotifications) {
@@ -8435,6 +8452,16 @@ void Document::setConsoleMessageListener(RefPtr<StringCallback>&& listener)
     m_consoleMessageListener = listener;
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+DocumentAnimationScheduler& Document::animationScheduler()
+{
+    if (!m_animationScheduler)
+        m_animationScheduler = DocumentAnimationScheduler::create(*this, page() ? page()->chrome().displayID() : 0);
+
+    return *m_animationScheduler;
+}
+#endif
+
 DocumentTimeline& Document::timeline()
 {
     if (!m_timeline)
index 73fe8c8..7c73061 100644 (file)
@@ -108,6 +108,7 @@ class DOMWrapperWorld;
 class Database;
 class DatabaseThread;
 class DeferredPromise;
+class DocumentAnimationScheduler;
 class DocumentFragment;
 class DocumentLoader;
 class DocumentMarkerController;
@@ -1052,10 +1053,7 @@ public:
     ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); }
     void suspendScriptedAnimationControllerCallbacks();
     void resumeScriptedAnimationControllerCallbacks();
-
-    void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
-    void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
-
+    
     void windowScreenDidChange(PlatformDisplayID);
 
     void finishedParsing();
@@ -1412,6 +1410,7 @@ public:
     void addIntersectionObserver(IntersectionObserver&);
     void removeIntersectionObserver(IntersectionObserver&);
     unsigned numberOfIntersectionObservers() const { return m_intersectionObservers.size(); }
+    void scheduleForcedIntersectionObservationUpdate();
     void updateIntersectionObservations();
 #endif
 
@@ -1484,6 +1483,10 @@ public:
 
     WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    DocumentAnimationScheduler& animationScheduler();
+#endif
+
     WEBCORE_EXPORT DocumentTimeline& timeline();
     DocumentTimeline* existingTimeline() const { return m_timeline.get(); }
     Vector<RefPtr<WebAnimation>> getAnimations();
@@ -2041,6 +2044,10 @@ private:
     bool m_isTelephoneNumberParsingAllowed { true };
 #endif
 
+#if ENABLE(INTERSECTION_OBSERVER)
+    bool m_needsForcedIntersectionObservationUpdate { false };
+#endif
+
 #if ENABLE(MEDIA_STREAM)
     HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
     String m_idHashSalt;
@@ -2060,6 +2067,9 @@ private:
 
     bool m_grantStorageAccessOverride { false };
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    RefPtr<DocumentAnimationScheduler> m_animationScheduler;
+#endif
     RefPtr<DocumentTimeline> m_timeline;
     DocumentIdentifier m_identifier;
 
index 627060d..e88bb90 100644 (file)
@@ -30,6 +30,7 @@
 #include "ChromeClient.h"
 #include "DOMWindow.h"
 #include "Document.h"
+#include "DocumentAnimationScheduler.h"
 #include "DocumentLoader.h"
 #include "Frame.h"
 #include "FrameView.h"
@@ -188,7 +189,7 @@ void ScriptedAnimationController::cancelCallback(CallbackId id)
     }
 }
 
-void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
+void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
 {
     if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
         return;
@@ -196,8 +197,8 @@ void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighR
     TraceScope tracingScope(RAFCallbackStart, RAFCallbackEnd);
 
     // We round this to the nearest microsecond so that we can return a time that matches what is returned by document.timeline.currentTime.
-    DOMHighResTimeStamp highResNowMs = std::round(1000 * timestamp);
-    DOMHighResTimeStamp legacyHighResNowMs = 1000 * (timestamp + m_document->loader()->timing().referenceWallTime().secondsSinceEpoch().seconds());
+    double highResNowMs = std::round(1000 * timestamp);
+    double legacyHighResNowMs = 1000 * (timestamp + m_document->loader()->timing().referenceWallTime().secondsSinceEpoch().seconds());
 
     // First, generate a list of callbacks to consider.  Callbacks registered from this point
     // on are considered only for the "next" frame, not this one.
@@ -209,21 +210,24 @@ void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighR
     Ref<Document> protectedDocument(*m_document);
 
     for (auto& callback : callbacks) {
-        if (callback->m_firedOrCancelled)
-            continue;
-        callback->m_firedOrCancelled = true;
-        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
-        if (callback->m_useLegacyTimeBase)
-            callback->handleEvent(legacyHighResNowMs);
-        else
-            callback->handleEvent(highResNowMs);
-        InspectorInstrumentation::didFireAnimationFrame(cookie);
+        if (!callback->m_firedOrCancelled) {
+            callback->m_firedOrCancelled = true;
+            InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
+            if (callback->m_useLegacyTimeBase)
+                callback->handleEvent(legacyHighResNowMs);
+            else
+                callback->handleEvent(highResNowMs);
+            InspectorInstrumentation::didFireAnimationFrame(cookie);
+        }
     }
 
     // Remove any callbacks we fired from the list of pending callbacks.
-    m_callbacks.removeAllMatching([](auto& callback) {
-        return callback->m_firedOrCancelled;
-    });
+    for (size_t i = 0; i < m_callbacks.size();) {
+        if (m_callbacks[i]->m_firedOrCancelled)
+            m_callbacks.remove(i);
+        else
+            ++i;
+    }
 
     if (m_callbacks.size())
         scheduleAnimation();
@@ -258,10 +262,8 @@ void ScriptedAnimationController::scheduleAnimation()
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     if (!m_isUsingTimer && !isThrottled()) {
-        if (auto* page = this->page()) {
-            page->renderingUpdateScheduler().scheduleRenderingUpdate();
+        if (m_document->animationScheduler().scheduleScriptedAnimationResolution())
             return;
-        }
 
         m_isUsingTimer = true;
     }
@@ -290,7 +292,15 @@ void ScriptedAnimationController::scheduleAnimation()
 void ScriptedAnimationController::animationTimerFired()
 {
     m_lastAnimationFrameTimestamp = m_document->domWindow()->nowTimestamp();
-    serviceRequestAnimationFrameCallbacks(m_lastAnimationFrameTimestamp);
+    serviceScriptedAnimations(m_lastAnimationFrameTimestamp);
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+void ScriptedAnimationController::documentAnimationSchedulerDidFire()
+{
+    // We obtain the time from the animation scheduler so that we use the same timestamp as the DocumentTimeline.
+    serviceScriptedAnimations(m_document->animationScheduler().lastTimestamp().seconds());
+}
+#endif
+
 }
index 3abe051..7ab8ec1 100644 (file)
@@ -52,7 +52,7 @@ public:
 
     CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
     void cancelCallback(CallbackId);
-    void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
+    void serviceScriptedAnimations(double timestamp);
 
     void suspend();
     void resume();
@@ -69,6 +69,10 @@ public:
     WEBCORE_EXPORT bool isThrottled() const;
     WEBCORE_EXPORT Seconds interval() const;
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    void documentAnimationSchedulerDidFire();
+#endif
+
 private:
     ScriptedAnimationController(Document&);
 
index d6ac1f3..e18827f 100644 (file)
@@ -1962,6 +1962,21 @@ void FrameView::viewportContentsChanged()
         if (auto* renderView = frameView.frame().contentRenderer())
             renderView->updateVisibleViewportRect(visibleRect);
     });
+
+#if ENABLE(INTERSECTION_OBSERVER)
+    if (auto* document = frame().document()) {
+        if (auto* page = frame().page()) {
+            if (document->numberOfIntersectionObservers())
+                page->addDocumentNeedingIntersectionObservationUpdate(*document);
+            if (!frame().isMainFrame()) {
+                if (auto* mainDocument = frame().mainFrame().document()) {
+                    if (mainDocument->numberOfIntersectionObservers())
+                        page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument);
+                }
+            }
+        }
+    }
+#endif
 }
 
 IntRect FrameView::unobscuredContentRectExpandedByContentInsets() const
index fb16a54..eb8afe2 100644 (file)
@@ -157,6 +157,7 @@ void IntersectionObserver::observe(Element& target)
     auto* document = trackingDocument();
     if (!hadObservationTargets)
         document->addIntersectionObserver(*this);
+    document->scheduleForcedIntersectionObservationUpdate();
 }
 
 void IntersectionObserver::unobserve(Element& target)
index 59646ed..3fbdef2 100644 (file)
@@ -250,6 +250,9 @@ Page::Page(PageConfiguration&& pageConfiguration)
     , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
     , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
     , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
+#if ENABLE(INTERSECTION_OBSERVER)
+    , m_intersectionObservationUpdateTimer(*this, &Page::updateIntersectionObservations)
+#endif
     , m_sessionID(PAL::SessionID::defaultSessionID())
 #if ENABLE(VIDEO)
     , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired)
@@ -1108,6 +1111,13 @@ void Page::didFinishLoad()
         m_performanceMonitor->didFinishLoad();
 }
 
+void Page::willDisplayPage()
+{
+#if ENABLE(INTERSECTION_OBSERVER)
+    updateIntersectionObservations();
+#endif
+}
+
 bool Page::isOnlyNonUtilityPage() const
 {
     return !isUtilityPage() && nonUtilityPageCount == 1;
@@ -1249,43 +1259,31 @@ void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observ
     m_activityStateChangeObservers.remove(&observer);
 }
 
-void Page::layoutIfNeeded()
+#if ENABLE(INTERSECTION_OBSERVER)
+void Page::addDocumentNeedingIntersectionObservationUpdate(Document& document)
 {
-    if (FrameView* view = m_mainFrame->view())
-        view->updateLayoutAndStyleIfNeededRecursive();
+    if (m_documentsNeedingIntersectionObservationUpdate.find(&document) == notFound)
+        m_documentsNeedingIntersectionObservationUpdate.append(makeWeakPtr(document));
 }
 
-void Page::renderingUpdate()
+void Page::updateIntersectionObservations()
 {
-    // This function is not reentrant, e.g. a rAF callback may force repaint.
-    if (m_inRenderingUpdate) {
-        layoutIfNeeded();
-        return;
-    }
-
-    SetForScope<bool> change(m_inRenderingUpdate, true);
-
-    Vector<RefPtr<Document>> documents;
-
-    // The requestAnimationFrame callbacks may change the frame hierarchy of the page
-    forEachDocument([&documents] (Document& document) {
-        documents.append(&document);
-    });
-
-    for (auto& document : documents) {
-        DOMHighResTimeStamp timestamp = document->domWindow()->nowTimestamp();
-        document->updateAnimationsAndSendEvents(timestamp);
-        document->serviceRequestAnimationFrameCallbacks(timestamp);
+    m_intersectionObservationUpdateTimer.stop();
+    for (const auto& document : m_documentsNeedingIntersectionObservationUpdate) {
+        if (document)
+            document->updateIntersectionObservations();
     }
+    m_documentsNeedingIntersectionObservationUpdate.clear();
+}
 
-    layoutIfNeeded();
-
-    for (auto& document : documents) {
-#if ENABLE(INTERSECTION_OBSERVER)
-        document->updateIntersectionObservations();
-#endif
-    }
+void Page::scheduleForcedIntersectionObservationUpdate(Document& document)
+{
+    addDocumentNeedingIntersectionObservationUpdate(document);
+    if (m_intersectionObservationUpdateTimer.isActive())
+        return;
+    m_intersectionObservationUpdateTimer.startOneShot(0_s);
 }
+#endif
 
 void Page::suspendScriptedAnimations()
 {
@@ -2825,13 +2823,6 @@ void Page::didChangeMainDocument()
 #endif
 }
 
-RenderingUpdateScheduler& Page::renderingUpdateScheduler()
-{
-    if (!m_renderingUpdateScheduler)
-        m_renderingUpdateScheduler = RenderingUpdateScheduler::create(*this);
-    return *m_renderingUpdateScheduler;
-}
-
 void Page::forEachDocument(const Function<void(Document&)>& functor)
 {
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
index e8bc6c8..8617bd4 100644 (file)
@@ -33,7 +33,6 @@
 #include "RTCController.h"
 #include "Region.h"
 #include "RegistrableDomain.h"
-#include "RenderingUpdateScheduler.h"
 #include "ScrollTypes.h"
 #include "Supplementable.h"
 #include "Timer.h"
@@ -263,8 +262,6 @@ public:
 
     PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
 
-    RenderingUpdateScheduler& renderingUpdateScheduler();
-
     ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
     void updateValidationBubbleStateIfNeeded();
 
@@ -337,6 +334,8 @@ public:
     void didStartProvisionalLoad();
     void didFinishLoad(); // Called when the load has been committed in the main frame.
 
+    WEBCORE_EXPORT void willDisplayPage();
+
     // The view scale factor is multiplied into the page scale factor by all
     // callers of setPageScaleFactor.
     WEBCORE_EXPORT void setViewScaleFactor(float);
@@ -464,8 +463,11 @@ public:
     WEBCORE_EXPORT void addActivityStateChangeObserver(ActivityStateChangeObserver&);
     WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
 
-    WEBCORE_EXPORT void layoutIfNeeded();
-    WEBCORE_EXPORT void renderingUpdate();
+#if ENABLE(INTERSECTION_OBSERVER)
+    void addDocumentNeedingIntersectionObservationUpdate(Document&);
+    void scheduleForcedIntersectionObservationUpdate(Document&);
+    void updateIntersectionObservations();
+#endif
 
     WEBCORE_EXPORT void suspendScriptedAnimations();
     WEBCORE_EXPORT void resumeScriptedAnimations();
@@ -860,8 +862,6 @@ private:
     int m_headerHeight { 0 };
     int m_footerHeight { 0 };
 
-    std::unique_ptr<RenderingUpdateScheduler> m_renderingUpdateScheduler;
-
     HashSet<RenderObject*> m_relevantUnpaintedRenderObjects;
     Region m_topRelevantPaintedRegion;
     Region m_bottomRelevantPaintedRegion;
@@ -902,6 +902,14 @@ private:
 
     HashSet<ActivityStateChangeObserver*> m_activityStateChangeObservers;
 
+#if ENABLE(INTERSECTION_OBSERVER)
+    Vector<WeakPtr<Document>> m_documentsNeedingIntersectionObservationUpdate;
+
+    // FIXME: Schedule intersection observation updates in a way that fits into the HTML
+    // EventLoop. See https://bugs.webkit.org/show_bug.cgi?id=160711.
+    Timer m_intersectionObservationUpdateTimer;
+#endif
+
 #if ENABLE(RESOURCE_USAGE)
     std::unique_ptr<ResourceUsageOverlay> m_resourceUsageOverlay;
 #endif
@@ -962,7 +970,6 @@ private:
     bool m_shouldEnableICECandidateFilteringByDefault { true };
     bool m_mediaPlaybackIsSuspended { false };
     bool m_mediaBufferingIsSuspended { false };
-    bool m_inRenderingUpdate { false };
 };
 
 inline PageGroup& Page::group()
index c5bdb82..580694c 100644 (file)
@@ -318,7 +318,7 @@ void PageOverlayController::didChangeDeviceScaleFactor()
 
 void PageOverlayController::didChangeViewExposedRect()
 {
-    m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
+    m_page.chrome().client().scheduleCompositingLayerFlush();
 }
 
 void PageOverlayController::didScrollFrame(Frame& frame)
@@ -412,7 +412,7 @@ float PageOverlayController::deviceScaleFactor() const
 
 void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
 {
-    m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
+    m_page.chrome().client().scheduleCompositingLayerFlush();
 }
 
 void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
diff --git a/Source/WebCore/page/RenderingUpdateScheduler.cpp b/Source/WebCore/page/RenderingUpdateScheduler.cpp
deleted file mode 100644 (file)
index dccc8c2..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 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 "RenderingUpdateScheduler.h"
-
-#include "Chrome.h"
-#include "ChromeClient.h"
-#include "DisplayRefreshMonitorManager.h"
-#include "Page.h"
-#include <wtf/SystemTracing.h>
-
-namespace WebCore {
-
-RenderingUpdateScheduler::RenderingUpdateScheduler(Page& page)
-    : m_page(page)
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    windowScreenDidChange(page.chrome().displayID());
-#endif
-}
-
-void RenderingUpdateScheduler::scheduleRenderingUpdate()
-{
-    if (isScheduled())
-        return;
-
-    tracePoint(ScheduleRenderingUpdate);
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this))
-        m_scheduled = true;
-    else
-#endif
-        startTimer(Seconds(1.0 / 60));
-}
-
-bool RenderingUpdateScheduler::isScheduled() const
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (m_scheduled)
-        return true;
-#endif
-    return m_refreshTimer.get();
-}
-    
-void RenderingUpdateScheduler::startTimer(Seconds delay)
-{
-    ASSERT(!isScheduled());
-    m_refreshTimer = std::make_unique<Timer>(*this, &RenderingUpdateScheduler::displayRefreshFired);
-    m_refreshTimer->startOneShot(delay);
-}
-
-void RenderingUpdateScheduler::clearScheduled()
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    m_scheduled = false;
-#endif
-    m_refreshTimer = nullptr;
-}
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-void RenderingUpdateScheduler::windowScreenDidChange(PlatformDisplayID displayID)
-{
-    DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
-}
-
-RefPtr<DisplayRefreshMonitor> RenderingUpdateScheduler::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
-{
-    if (auto monitor = m_page.chrome().client().createDisplayRefreshMonitor(displayID))
-        return monitor;
-
-    return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
-}
-#endif
-
-void RenderingUpdateScheduler::displayRefreshFired()
-{
-    tracePoint(TriggerRenderingUpdate);
-
-    clearScheduled();
-    m_page.chrome().client().scheduleCompositingLayerFlush();
-}
-
-}
index f7a465d..8ee7848 100644 (file)
 
 #if PLATFORM(IOS_FAMILY)
 
-#include "Document.h"
 #include "PlatformEvent.h"
-#include "RenderStyleConstants.h"
 #include "Timer.h"
 #include "WKContentObservation.h"
-#include <wtf/HashSet.h>
-#include <wtf/Seconds.h>
 
 namespace WebCore {
 
 class DOMTimer;
-class Element;
+class Document;
 
 class ContentChangeObserver {
 public:
index 93b2417..c96bed1 100644 (file)
@@ -121,7 +121,7 @@ void ServicesOverlayController::Highlight::notifyFlushRequired(const GraphicsLay
     if (!m_controller)
         return;
 
-    m_controller->page().renderingUpdateScheduler().scheduleRenderingUpdate();
+    m_controller->page().chrome().client().scheduleCompositingLayerFlush();
 }
 
 void ServicesOverlayController::Highlight::paintContents(const GraphicsLayer*, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const FloatRect&, GraphicsLayerPaintBehavior)
index 6e14138..ad7da0c 100644 (file)
@@ -431,7 +431,7 @@ void RenderLayerCompositor::notifyFlushRequired(const GraphicsLayer* layer)
 void RenderLayerCompositor::scheduleLayerFlushNow()
 {
     m_hasPendingLayerFlush = false;
-    page().renderingUpdateScheduler().scheduleRenderingUpdate();
+    page().chrome().client().scheduleCompositingLayerFlush();
 }
 
 void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
index ccda61a..88a3711 100644 (file)
@@ -1,3 +1,31 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
+        (WebKit::DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush):
+        (WebKit::DrawingAreaCoordinatedGraphics::updateBackingStoreState):
+        (WebKit::DrawingAreaCoordinatedGraphics::display):
+        * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
+        (WebKit::LayerTreeHost::layerFlushTimerFired):
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::layoutIfNeeded):
+        (WebKit::WebPage::willDisplayPage):
+        (WebKit::WebPage::renderingUpdate): Deleted.
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::flushLayers):
+
 2019-03-11  Darin Adler  <darin@apple.com>
 
         Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
index 762ba81..c97e253 100644 (file)
@@ -303,8 +303,6 @@ void DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush()
 {
     if (m_layerTreeHost)
         m_layerTreeHost->scheduleLayerFlush();
-    else
-        setNeedsDisplay();
 }
 
 void DrawingAreaCoordinatedGraphics::layerHostDidFlushLayers()
@@ -383,9 +381,10 @@ void DrawingAreaCoordinatedGraphics::updateBackingStoreState(uint64_t stateID, b
 
         m_webPage.setDeviceScaleFactor(deviceScaleFactor);
         m_webPage.setSize(size);
-        m_webPage.renderingUpdate();
+        m_webPage.layoutIfNeeded();
         m_webPage.flushPendingEditorStateUpdate();
         m_webPage.scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
+        m_webPage.willDisplayPage();
 
         if (m_layerTreeHost)
             m_layerTreeHost->sizeDidChange(m_webPage.size());
@@ -704,7 +703,7 @@ void DrawingAreaCoordinatedGraphics::display(UpdateInfo& updateInfo)
     ASSERT(!m_layerTreeHost);
     ASSERT(!m_webPage.size().isEmpty());
 
-    m_webPage.renderingUpdate();
+    m_webPage.layoutIfNeeded();
     m_webPage.flushPendingEditorStateUpdate();
 
     // The layout may have put the page into accelerated compositing mode. If the LayerTreeHost is
@@ -712,6 +711,7 @@ void DrawingAreaCoordinatedGraphics::display(UpdateInfo& updateInfo)
     if (m_layerTreeHost)
         return;
 
+    m_webPage.willDisplayPage();
     updateInfo.viewSize = m_webPage.size();
     updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
 
index afc98b0..ad16b6c 100644 (file)
@@ -145,8 +145,8 @@ void LayerTreeHost::layerFlushTimerFired()
         return;
 
     m_coordinator.syncDisplayState();
-    m_webPage.renderingUpdate();
     m_webPage.flushPendingEditorStateUpdate();
+    m_webPage.willDisplayPage();
 
     if (!m_isValid || !m_coordinator.rootCompositingLayer())
         return;
index d753d59..cb706be 100644 (file)
@@ -349,7 +349,8 @@ void RemoteLayerTreeDrawingArea::flushLayers()
     RemoteLayerBackingStoreCollection& backingStoreCollection = m_remoteLayerTreeContext->backingStoreCollection();
     backingStoreCollection.willFlushLayers();
 
-    m_webPage.renderingUpdate();
+    m_webPage.layoutIfNeeded();
+    m_webPage.willDisplayPage();
 
     FloatRect visibleRect(FloatPoint(), m_viewSize);
     if (m_scrolledViewExposedRect)
index fdbb382..3028e64 100644 (file)
@@ -1554,6 +1554,12 @@ void WebPage::tryRestoreScrollPosition()
     m_page->mainFrame().loader().history().restoreScrollPositionAndViewState();
 }
 
+void WebPage::layoutIfNeeded()
+{
+    if (m_mainFrame->coreFrame()->view())
+        m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
+}
+
 WebPage* WebPage::fromCorePage(Page* page)
 {
     return &static_cast<WebChromeClient&>(page->chrome().client()).page();
@@ -3575,14 +3581,9 @@ void WebPage::didFlushLayerTreeAtTime(MonotonicTime timestamp)
 }
 #endif
 
-void WebPage::layoutIfNeeded()
-{
-    m_page->layoutIfNeeded();
-}
-    
-void WebPage::renderingUpdate()
+void WebPage::willDisplayPage()
 {
-    m_page->renderingUpdate();
+    m_page->willDisplayPage();
 }
 
 WebInspector* WebPage::inspector(LazyCreationPolicy behavior)
index b00984b..454f8f2 100644 (file)
@@ -302,8 +302,7 @@ public:
     void didFlushLayerTreeAtTime(MonotonicTime);
 #endif
 
-    void layoutIfNeeded();
-    void renderingUpdate();
+    void willDisplayPage();
 
     enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
 
@@ -336,6 +335,7 @@ public:
     // -- Called by the DrawingArea.
     // FIXME: We could genericize these into a DrawingArea client interface. Would that be beneficial?
     void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect&);
+    void layoutIfNeeded();
 
     // -- Called from WebCore clients.
     bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*);
index 2fc8d5e..6e06308 100644 (file)
@@ -59,7 +59,6 @@
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
 #import <wtf/MachSendRight.h>
 #import <wtf/MainThread.h>
-#import <wtf/SystemTracing.h>
 
 #if ENABLE(ASYNC_SCROLLING)
 #import <WebCore/AsyncScrollingCoordinator.h>
@@ -460,13 +459,12 @@ void TiledCoreAnimationDrawingArea::flushLayers()
     if (layerTreeStateIsFrozen())
         return;
 
-    TraceScope traceScope(RenderingUpdateStart, RenderingUpdateEnd);
-
     @autoreleasepool {
         scaleViewToFitDocumentIfNeeded();
 
-        m_webPage.renderingUpdate();
+        m_webPage.layoutIfNeeded();
         m_webPage.flushPendingEditorStateUpdate();
+        m_webPage.willDisplayPage();
 
         updateIntrinsicContentSizeIfNeeded();
 
index 4cfe6c3..a6d69d0 100644 (file)
@@ -1,3 +1,18 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * WebView/WebView.mm:
+        (-[WebView _viewWillDrawInternal]):
+
 2019-03-09  Andy Estes  <aestes@apple.com>
 
         [Apple Pay] CanMakePaymentsWithActiveCard and OpenPaymentSetup should be async messages
index 912b5b5..f06f518 100644 (file)
@@ -1620,8 +1620,9 @@ static void WebKitInitializeGamepadProviderIfNecessary()
 
 - (void)_viewWillDrawInternal
 {
-    if (_private->page)
-        _private->page->renderingUpdate();
+    Frame* frame = [self _mainCoreFrame];
+    if (frame && frame->view())
+        frame->view()->updateLayoutAndStyleIfNeededRecursive();
 }
 
 + (NSArray *)_supportedMIMETypes
index 1b5ab35..5e60639 100644 (file)
@@ -1,3 +1,20 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * WebView.cpp:
+        (WebView::updateBackingStore):
+        (WebView::flushPendingGraphicsLayerChangesSoon):
+        (WebView::flushPendingGraphicsLayerChanges):
+
 2019-03-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         requestAnimationFrame should execute before the next frame
index 6f7be12..b4d228f 100644 (file)
@@ -1173,7 +1173,9 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
 
     if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
         // Do a layout first so that everything we render to the backing store is always current.
-        m_page->renderingUpdate();
+        if (Frame* coreFrame = core(m_mainFrame))
+            if (FrameView* view = coreFrame->view())
+                view->updateLayoutAndStyleIfNeededRecursive();
 
         Vector<IntRect> paintRects;
         if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {
@@ -7157,10 +7159,8 @@ void WebView::setRootChildLayer(GraphicsLayer* layer)
 void WebView::flushPendingGraphicsLayerChangesSoon()
 {
 #if USE(CA)
-    if (!m_layerTreeHost) {
-        m_page->renderingUpdate();
+    if (!m_layerTreeHost)
         return;
-    }
     m_layerTreeHost->flushPendingGraphicsLayerChangesSoon();
 #elif USE(TEXTURE_MAPPER_GL)
     if (!m_acceleratedCompositingContext)
@@ -7388,7 +7388,7 @@ void WebView::flushPendingGraphicsLayerChanges()
     if (!isAcceleratedCompositing())
         return;
 
-    m_page->renderingUpdate();
+    view->updateLayoutAndStyleIfNeededRecursive();
 
     // Updating layout might have taken us out of compositing mode.
     if (m_backingLayer)
index 85ac141..7ee44bd 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-11  Ryan Haddad  <ryanhaddad@apple.com>
+
+        Unreviewed, rolling out r242688, r242643, r242624.
+
+        Caused multiple layout test failures and crashes on iOS and macOS.
+
+        Reverted changeset:
+
+        "requestAnimationFrame should execute before the next frame"
+        https://bugs.webkit.org/show_bug.cgi?id=177484
+        https://trac.webkit.org/changeset/242624/webkit
+
+        * Tracing/SystemTracePoints.plist:
+
 2019-03-11  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Make it possible exclude localhost from classification
index 23d2cb2..940140a 100644 (file)
              </dict>
              <dict>
                  <key>Name</key>
-                 <string>Schedule rendering update</string>
-                 <key>Type</key>
-                 <string>Impulse</string>
-                 <key>Component</key>
-                 <string>47</string>
-                 <key>Code</key>
-                 <string>5028</string>
-             </dict>
-             <dict>
-                 <key>Name</key>
-                 <string>Trigger rendering update</string>
-                 <key>Type</key>
-                 <string>Impulse</string>
-                 <key>Component</key>
-                 <string>47</string>
-                 <key>Code</key>
-                 <string>5029</string>
-             </dict>
-             <dict>
-                 <key>Name</key>
-                 <string>Rendering update</string>
-                 <key>Type</key>
-                 <string>Interval</string>
-                 <key>Component</key>
-                 <string>47</string>
-                 <key>CodeBegin</key>
-                 <string>5030</string>
-                 <key>CodeEnd</key>
-                 <string>5031</string>
-             </dict>
-             <dict>
-                 <key>Name</key>
                  <string>Paint WebHTMLView</string>
                  <key>Type</key>
                  <string>Interval</string>