Diff
Modified: trunk/LayoutTests/ChangeLog (242713 => 242714)
--- trunk/LayoutTests/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,21 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
Resource Load Statistics: Make it possible exclude localhost from classification
Modified: trunk/LayoutTests/TestExpectations (242713 => 242714)
--- trunk/LayoutTests/TestExpectations 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/TestExpectations 2019-03-11 17:19:20 UTC (rev 242714)
@@ -3039,8 +3039,6 @@
# 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 ]
Modified: trunk/LayoutTests/animations/animation-multiple-callbacks-timestamp.html (242713 => 242714)
--- trunk/LayoutTests/animations/animation-multiple-callbacks-timestamp.html 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/animations/animation-multiple-callbacks-timestamp.html 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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;
}
}
Modified: trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt (242713 => 242714)
--- trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,2 +1,2 @@
Got iteration event.
-PASS: saw three or fewer style recalcs during the animation.
+PASS: saw two or fewer style recalcs during the animation.
Modified: trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation.html (242713 => 242714)
--- trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation.html 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation.html 2019-03-11 17:19:20 UTC (rev 242714)
@@ -35,10 +35,10 @@
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();
Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (242713 => 242714)
--- trunk/LayoutTests/platform/mac-wk2/TestExpectations 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations 2019-03-11 17:19:20 UTC (rev 242714)
@@ -924,7 +924,4 @@
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
Modified: trunk/Source/WTF/ChangeLog (242713 => 242714)
--- trunk/Source/WTF/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WTF/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,17 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
Modified: trunk/Source/WTF/wtf/SystemTracing.h (242713 => 242714)
--- trunk/Source/WTF/wtf/SystemTracing.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WTF/wtf/SystemTracing.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -77,11 +77,6 @@
ComputeEventRegionsStart,
ComputeEventRegionsEnd,
- ScheduleRenderingUpdate,
- TriggerRenderingUpdate,
- RenderingUpdateStart,
- RenderingUpdateEnd,
-
WebKitRange = 10000,
WebHTMLViewPaintStart,
WebHTMLViewPaintEnd,
Modified: trunk/Source/WebCore/ChangeLog (242713 => 242714)
--- trunk/Source/WebCore/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,92 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
Modified: trunk/Source/WebCore/Sources.txt (242713 => 242714)
--- trunk/Source/WebCore/Sources.txt 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/Sources.txt 2019-03-11 17:19:20 UTC (rev 242714)
@@ -420,6 +420,7 @@
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/Quirks.cpp
page/RemoteDOMWindow.cpp
page/RemoteFrame.cpp
-page/RenderingUpdateScheduler.cpp
page/ResourceUsageOverlay.cpp
page/ResourceUsageThread.cpp
page/RuntimeEnabledFeatures.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (242713 => 242714)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1784,7 +1784,6 @@
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, ); }; };
@@ -2122,6 +2121,7 @@
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 */; };
@@ -8655,8 +8655,6 @@
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>"; };
@@ -9383,6 +9381,8 @@
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>"; };
@@ -20507,8 +20507,6 @@
46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */,
46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
46B95192207D632E00A7D2DD /* RemoteFrame.h */,
- 556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */,
- 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */,
A5071E821C56D079009951BE /* ResourceUsageData.h */,
ADBAD6EC1BCDD95000381325 /* ResourceUsageOverlay.cpp */,
ADBAD6ED1BCDD95000381325 /* ResourceUsageOverlay.h */,
@@ -20661,6 +20659,8 @@
7123C185204739B900789392 /* CSSTransition.idl */,
715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
+ 716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */,
+ 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */,
71025EC41F99F096004A250C /* DocumentTimeline.cpp */,
71025EC51F99F096004A250C /* DocumentTimeline.h */,
71025ECA1F99F096004A250C /* DocumentTimeline.idl */,
@@ -29094,6 +29094,7 @@
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 */,
@@ -31296,7 +31297,6 @@
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 */,
Modified: trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm (242713 => 242714)
--- trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm 2019-03-11 17:19:20 UTC (rev 242714)
@@ -539,14 +539,8 @@
{
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*)
Added: trunk/Source/WebCore/animation/DocumentAnimationScheduler.cpp (0 => 242714)
--- trunk/Source/WebCore/animation/DocumentAnimationScheduler.cpp (rev 0)
+++ trunk/Source/WebCore/animation/DocumentAnimationScheduler.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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)
Copied: trunk/Source/WebCore/animation/DocumentAnimationScheduler.h (from rev 242713, trunk/Source/WebCore/page/RenderingUpdateScheduler.h) (0 => 242714)
--- trunk/Source/WebCore/animation/DocumentAnimationScheduler.h (rev 0)
+++ trunk/Source/WebCore/animation/DocumentAnimationScheduler.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#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 Document;
+
+class DocumentAnimationScheduler : public RefCounted<DocumentAnimationScheduler>
+ , public DisplayRefreshMonitorClient {
+public:
+ static Ref<DocumentAnimationScheduler> create(Document&, PlatformDisplayID);
+ ~DocumentAnimationScheduler();
+
+ void detachFromDocument();
+ void windowScreenDidChange(PlatformDisplayID);
+
+ bool scheduleWebAnimationsResolution();
+ void unscheduleWebAnimationsResolution();
+ bool scheduleScriptedAnimationResolution();
+
+ Seconds lastTimestamp() { return m_lastTimestamp; }
+ bool isFiring() const { return m_isFiring; }
+
+private:
+ DocumentAnimationScheduler(Document&, PlatformDisplayID);
+
+ RefPtr<Document> m_document;
+ bool m_scheduledWebAnimationsResolution { false };
+ bool m_scheduledScriptedAnimationResolution { false };
+ bool m_isFiring { false };
+ Seconds m_lastTimestamp { 0_s };
+
+ void displayRefreshFired() override;
+ RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
+};
+
+} // namespace WebCore
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (242713 => 242714)
--- trunk/Source/WebCore/animation/DocumentTimeline.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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 @@
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 @@
void DocumentTimeline::updateThrottlingState()
{
- scheduleAnimationResolution();
+ scheduleAnimationResolutionIfNeeded();
}
Seconds DocumentTimeline::animationInterval() const
@@ -206,7 +210,7 @@
return;
if (!m_cachedCurrentTime)
- m_cachedCurrentTime = Seconds(liveCurrentTime());
+ m_cachedCurrentTime = liveCurrentTime();
for (const auto& animation : m_animations)
animation->setSuspended(true);
@@ -230,7 +234,7 @@
for (const auto& animation : m_animations)
animation->setSuspended(false);
- scheduleAnimationResolution();
+ scheduleAnimationResolutionIfNeeded();
}
bool DocumentTimeline::animationsAreSuspended()
@@ -248,9 +252,13 @@
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 @@
}
}
- 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 @@
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::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;
+#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
}
-void DocumentTimeline::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+void DocumentTimeline::documentAnimationSchedulerDidFire()
+#else
+void DocumentTimeline::animationResolutionTimerFired()
+#endif
{
- // 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();
+ 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 @@
// 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 @@
for (const auto& animation : m_animations) {
if (!animation->isRunningAccelerated()) {
- scheduleAnimationResolution();
+ scheduleAnimationResolutionIfNeeded();
return;
}
}
@@ -446,7 +483,7 @@
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::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 @@
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
Modified: trunk/Source/WebCore/animation/DocumentTimeline.h (242713 => 242714)
--- trunk/Source/WebCore/animation/DocumentTimeline.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -71,9 +71,11 @@
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;
WEBCORE_EXPORT void suspendAnimations();
@@ -86,19 +88,26 @@
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 @@
unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
bool m_isSuspended { false };
bool m_waitingOnVMIdle { false };
- bool m_animationResolutionScheduled { false };
+ bool m_isUpdatingAnimations { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/Document.cpp (242713 => 242714)
--- trunk/Source/WebCore/dom/Document.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/dom/Document.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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 @@
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 @@
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 @@
m_scriptedAnimationController->resume();
}
-void Document::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
+void Document::windowScreenDidChange(PlatformDisplayID displayID)
{
- if (m_timeline)
- m_timeline->updateAnimationsAndSendEvents(timestamp);
-}
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ if (m_animationScheduler)
+ m_animationScheduler->windowScreenDidChange(displayID);
+#endif
-void Document::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
-{
- if (m_scriptedAnimationController)
- m_scriptedAnimationController->serviceRequestAnimationFrameCallbacks(timestamp);
-}
-
-void Document::windowScreenDidChange(PlatformDisplayID displayID)
-{
if (RenderView* view = renderView()) {
if (view->usesCompositing())
view->compositor().windowScreenDidChange(displayID);
@@ -7926,6 +7930,8 @@
if (needsLayout || hasPendingStyleRecalc())
return;
+ m_needsForcedIntersectionObservationUpdate = false;
+
for (const auto& observer : m_intersectionObservers) {
bool needNotify = false;
DOMHighResTimeStamp timestamp;
@@ -8002,6 +8008,17 @@
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 @@
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)
Modified: trunk/Source/WebCore/dom/Document.h (242713 => 242714)
--- trunk/Source/WebCore/dom/Document.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/dom/Document.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -108,6 +108,7 @@
class Database;
class DatabaseThread;
class DeferredPromise;
+class DocumentAnimationScheduler;
class DocumentFragment;
class DocumentLoader;
class DocumentMarkerController;
@@ -1052,10 +1053,7 @@
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 @@
void addIntersectionObserver(IntersectionObserver&);
void removeIntersectionObserver(IntersectionObserver&);
unsigned numberOfIntersectionObservers() const { return m_intersectionObservers.size(); }
+ void scheduleForcedIntersectionObservationUpdate();
void updateIntersectionObservations();
#endif
@@ -1484,6 +1483,10 @@
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 @@
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 @@
bool m_grantStorageAccessOverride { false };
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ RefPtr<DocumentAnimationScheduler> m_animationScheduler;
+#endif
RefPtr<DocumentTimeline> m_timeline;
DocumentIdentifier m_identifier;
Modified: trunk/Source/WebCore/dom/ScriptedAnimationController.cpp (242713 => 242714)
--- trunk/Source/WebCore/dom/ScriptedAnimationController.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
+void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
{
if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
return;
@@ -196,8 +197,8 @@
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 @@
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 @@
#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::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
+
+}
Modified: trunk/Source/WebCore/dom/ScriptedAnimationController.h (242713 => 242714)
--- trunk/Source/WebCore/dom/ScriptedAnimationController.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -52,7 +52,7 @@
CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
void cancelCallback(CallbackId);
- void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
+ void serviceScriptedAnimations(double timestamp);
void suspend();
void resume();
@@ -69,6 +69,10 @@
WEBCORE_EXPORT bool isThrottled() const;
WEBCORE_EXPORT Seconds interval() const;
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ void documentAnimationSchedulerDidFire();
+#endif
+
private:
ScriptedAnimationController(Document&);
Modified: trunk/Source/WebCore/page/FrameView.cpp (242713 => 242714)
--- trunk/Source/WebCore/page/FrameView.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/FrameView.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1962,6 +1962,21 @@
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
Modified: trunk/Source/WebCore/page/IntersectionObserver.cpp (242713 => 242714)
--- trunk/Source/WebCore/page/IntersectionObserver.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/IntersectionObserver.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -157,6 +157,7 @@
auto* document = trackingDocument();
if (!hadObservationTargets)
document->addIntersectionObserver(*this);
+ document->scheduleForcedIntersectionObservationUpdate();
}
void IntersectionObserver::unobserve(Element& target)
Modified: trunk/Source/WebCore/page/Page.cpp (242713 => 242714)
--- trunk/Source/WebCore/page/Page.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/Page.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -250,6 +250,9 @@
, 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 @@
m_performanceMonitor->didFinishLoad();
}
+void Page::willDisplayPage()
+{
+#if ENABLE(INTERSECTION_OBSERVER)
+ updateIntersectionObservations();
+#endif
+}
+
bool Page::isOnlyNonUtilityPage() const
{
return !isUtilityPage() && nonUtilityPageCount == 1;
@@ -1249,43 +1259,31 @@
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;
+ m_intersectionObservationUpdateTimer.stop();
+ for (const auto& document : m_documentsNeedingIntersectionObservationUpdate) {
+ if (document)
+ document->updateIntersectionObservations();
}
+ m_documentsNeedingIntersectionObservationUpdate.clear();
+}
- 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);
- }
-
- layoutIfNeeded();
-
- for (auto& document : documents) {
-#if ENABLE(INTERSECTION_OBSERVER)
- document->updateIntersectionObservations();
+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 @@
#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()) {
Modified: trunk/Source/WebCore/page/Page.h (242713 => 242714)
--- trunk/Source/WebCore/page/Page.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/Page.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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 @@
PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
- RenderingUpdateScheduler& renderingUpdateScheduler();
-
ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
void updateValidationBubbleStateIfNeeded();
@@ -337,6 +334,8 @@
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 @@
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 @@
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 @@
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 @@
bool m_shouldEnableICECandidateFilteringByDefault { true };
bool m_mediaPlaybackIsSuspended { false };
bool m_mediaBufferingIsSuspended { false };
- bool m_inRenderingUpdate { false };
};
inline PageGroup& Page::group()
Modified: trunk/Source/WebCore/page/PageOverlayController.cpp (242713 => 242714)
--- trunk/Source/WebCore/page/PageOverlayController.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/PageOverlayController.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -318,7 +318,7 @@
void PageOverlayController::didChangeViewExposedRect()
{
- m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
+ m_page.chrome().client().scheduleCompositingLayerFlush();
}
void PageOverlayController::didScrollFrame(Frame& frame)
@@ -412,7 +412,7 @@
void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
{
- m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
+ m_page.chrome().client().scheduleCompositingLayerFlush();
}
void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
Deleted: trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp (242713 => 242714)
--- trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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();
-}
-
-}
Deleted: trunk/Source/WebCore/page/RenderingUpdateScheduler.h (242713 => 242714)
--- trunk/Source/WebCore/page/RenderingUpdateScheduler.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,74 +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.
- */
-
-#pragma once
-
-#include "DisplayRefreshMonitorClient.h"
-#include <wtf/Seconds.h>
-
-namespace WebCore {
-
-class Page;
-class Timer;
-
-class RenderingUpdateScheduler
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- : public DisplayRefreshMonitorClient
-#endif
-{
- WTF_MAKE_FAST_ALLOCATED;
-public:
- static std::unique_ptr<RenderingUpdateScheduler> create(Page& page)
- {
- return std::make_unique<RenderingUpdateScheduler>(page);
- }
-
- RenderingUpdateScheduler(Page&);
- void scheduleRenderingUpdate();
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- void windowScreenDidChange(PlatformDisplayID);
-#endif
-
-private:
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
- void displayRefreshFired() final;
-#else
- void displayRefreshFired();
-#endif
-
- bool isScheduled() const;
- void startTimer(Seconds);
- void clearScheduled();
-
- Page& m_page;
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- bool m_scheduled { false };
-#endif
- std::unique_ptr<Timer> m_refreshTimer;
-};
-
-}
Modified: trunk/Source/WebCore/page/ios/ContentChangeObserver.h (242713 => 242714)
--- trunk/Source/WebCore/page/ios/ContentChangeObserver.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/ios/ContentChangeObserver.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -27,18 +27,14 @@
#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:
Modified: trunk/Source/WebCore/page/mac/ServicesOverlayController.mm (242713 => 242714)
--- trunk/Source/WebCore/page/mac/ServicesOverlayController.mm 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/page/mac/ServicesOverlayController.mm 2019-03-11 17:19:20 UTC (rev 242714)
@@ -121,7 +121,7 @@
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)
Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (242713 => 242714)
--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -431,7 +431,7 @@
void RenderLayerCompositor::scheduleLayerFlushNow()
{
m_hasPendingLayerFlush = false;
- page().renderingUpdateScheduler().scheduleRenderingUpdate();
+ page().chrome().client().scheduleCompositingLayerFlush();
}
void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
Modified: trunk/Source/WebKit/ChangeLog (242713 => 242714)
--- trunk/Source/WebKit/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,31 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
Specify fixed precision explicitly to prepare to change String::number and StringBuilder::appendNumber floating point behavior
Modified: trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -303,8 +303,6 @@
{
if (m_layerTreeHost)
m_layerTreeHost->scheduleLayerFlush();
- else
- setNeedsDisplay();
}
void DrawingAreaCoordinatedGraphics::layerHostDidFlushLayers()
@@ -383,9 +381,10 @@
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 @@
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 @@
if (m_layerTreeHost)
return;
+ m_webPage.willDisplayPage();
updateInfo.viewSize = m_webPage.size();
updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
Modified: trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -145,8 +145,8 @@
return;
m_coordinator.syncDisplayState();
- m_webPage.renderingUpdate();
m_webPage.flushPendingEditorStateUpdate();
+ m_webPage.willDisplayPage();
if (!m_isValid || !m_coordinator.rootCompositingLayer())
return;
Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm 2019-03-11 17:19:20 UTC (rev 242714)
@@ -349,7 +349,8 @@
RemoteLayerBackingStoreCollection& backingStoreCollection = m_remoteLayerTreeContext->backingStoreCollection();
backingStoreCollection.willFlushLayers();
- m_webPage.renderingUpdate();
+ m_webPage.layoutIfNeeded();
+ m_webPage.willDisplayPage();
FloatRect visibleRect(FloatPoint(), m_viewSize);
if (m_scrolledViewExposedRect)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1554,6 +1554,12 @@
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,15 +3581,10 @@
}
#endif
-void WebPage::layoutIfNeeded()
+void WebPage::willDisplayPage()
{
- m_page->layoutIfNeeded();
+ m_page->willDisplayPage();
}
-
-void WebPage::renderingUpdate()
-{
- m_page->renderingUpdate();
-}
WebInspector* WebPage::inspector(LazyCreationPolicy behavior)
{
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-11 17:19:20 UTC (rev 242714)
@@ -302,8 +302,7 @@
void didFlushLayerTreeAtTime(MonotonicTime);
#endif
- void layoutIfNeeded();
- void renderingUpdate();
+ void willDisplayPage();
enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
@@ -336,6 +335,7 @@
// -- 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*);
Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm (242713 => 242714)
--- trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2019-03-11 17:19:20 UTC (rev 242714)
@@ -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 @@
if (layerTreeStateIsFrozen())
return;
- TraceScope traceScope(RenderingUpdateStart, RenderingUpdateEnd);
-
@autoreleasepool {
scaleViewToFitDocumentIfNeeded();
- m_webPage.renderingUpdate();
+ m_webPage.layoutIfNeeded();
m_webPage.flushPendingEditorStateUpdate();
+ m_webPage.willDisplayPage();
updateIntrinsicContentSizeIfNeeded();
Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (242713 => 242714)
--- trunk/Source/WebKitLegacy/mac/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,18 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
[Apple Pay] CanMakePaymentsWithActiveCard and OpenPaymentSetup should be async messages
Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (242713 => 242714)
--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1620,8 +1620,9 @@
- (void)_viewWillDrawInternal
{
- if (_private->page)
- _private->page->renderingUpdate();
+ Frame* frame = [self _mainCoreFrame];
+ if (frame && frame->view())
+ frame->view()->updateLayoutAndStyleIfNeededRecursive();
}
+ (NSArray *)_supportedMIMETypes
Modified: trunk/Source/WebKitLegacy/win/ChangeLog (242713 => 242714)
--- trunk/Source/WebKitLegacy/win/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKitLegacy/win/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,20 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
requestAnimationFrame should execute before the next frame
Modified: trunk/Source/WebKitLegacy/win/WebView.cpp (242713 => 242714)
--- trunk/Source/WebKitLegacy/win/WebView.cpp 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Source/WebKitLegacy/win/WebView.cpp 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1173,7 +1173,9 @@
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::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 @@
if (!isAcceleratedCompositing())
return;
- m_page->renderingUpdate();
+ view->updateLayoutAndStyleIfNeededRecursive();
// Updating layout might have taken us out of compositing mode.
if (m_backingLayer)
Modified: trunk/Tools/ChangeLog (242713 => 242714)
--- trunk/Tools/ChangeLog 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Tools/ChangeLog 2019-03-11 17:19:20 UTC (rev 242714)
@@ -1,3 +1,17 @@
+2019-03-11 Ryan Haddad <[email protected]>
+
+ 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 <[email protected]>
Resource Load Statistics: Make it possible exclude localhost from classification
Modified: trunk/Tools/Tracing/SystemTracePoints.plist (242713 => 242714)
--- trunk/Tools/Tracing/SystemTracePoints.plist 2019-03-11 17:11:13 UTC (rev 242713)
+++ trunk/Tools/Tracing/SystemTracePoints.plist 2019-03-11 17:19:20 UTC (rev 242714)
@@ -218,38 +218,6 @@
</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>