[Web Animations] DocumentTimeline::updateAnimations() is called endlessly
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Sep 2018 11:28:40 +0000 (11:28 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Sep 2018 11:28:40 +0000 (11:28 +0000)
commit3e52a6652f50072762fbb5bbbff03e671c3d79b0
treeeb53218c27873baaf10e27ab8f158b5dc836bb2d
parentdc977270ef2a16f9a12ab69c39a8fe0c5ad34636
[Web Animations] DocumentTimeline::updateAnimations() is called endlessly
https://bugs.webkit.org/show_bug.cgi?id=189784
<rdar://problem/41705679>

Reviewed by Dean Jackson.

Source/WebCore:

Test: webanimations/accelerated-animation-interruption-display-none.html

We have code that keeps queueing pending accelerated actions for an animation that does not have a renderer until it has one
so that we can deal with situations where animations are ready to commited before its composited renderer is available. This
code ended up running continuously when an element with an accelerated animation had its renderer removed without the animation
being removed itself, such as setting "display: none" on an element with an acceelerated CSS Animation targeting it.

We fix this by queueing up a "Stop" accelerated action when updating the accelerated state if there is no renderer for the current
animation target. Then, we no longer re-queue pending accelerated actions if the last queued operation is "Stop". This ensures that
we no longer queue actions endlessly when there is no longer a visible animation.

To test this, we add a new internals.numberOfAnimationTimelineInvalidations() method that indicates the number of times the current
document's animation timeline was invalidated.

* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::updateAnimations):
(WebCore::DocumentTimeline::numberOfAnimationTimelineInvalidationsForTesting const):
* animation/DocumentTimeline.h:
* animation/KeyframeEffectReadOnly.cpp:
(WebCore::KeyframeEffectReadOnly::updateAcceleratedAnimationState): If the animation target does not have a renderer and it's still
marked as running, enqueue a "Stop" accelerated action.
(WebCore::KeyframeEffectReadOnly::addPendingAcceleratedAction): If we enqueue a "Stop" accelerated action, remove any other queued
action so that we only process the "Stop" action, which would have superseded all previously queued actions anyway.
(WebCore::KeyframeEffectReadOnly::applyPendingAcceleratedActions): Only re-queue pending accelerated actions when a composited renderer
is not yet available if we don't have a "Stop" action queued.
* testing/Internals.cpp:
(WebCore::Internals::numberOfAnimationTimelineInvalidations const):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Add a new test that checks that setting "display: none" on an element with an accelerated CSS animation on it
will no longer update the animation timeline.

* webanimations/accelerated-animation-interruption-display-none-expected.txt: Added.
* webanimations/accelerated-animation-interruption-display-none.html: Added.
* platform/win/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236308 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/platform/win/TestExpectations
LayoutTests/webanimations/accelerated-animation-interruption-display-none-expected.txt [new file with mode: 0644]
LayoutTests/webanimations/accelerated-animation-interruption-display-none.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/animation/KeyframeEffectReadOnly.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl