Title: [244031] trunk
Revision
244031
Author
[email protected]
Date
2019-04-08 11:49:04 -0700 (Mon, 08 Apr 2019)

Log Message

[Web Animations] JS wrapper may be deleted while animation is yet to dispatch its finish event
https://bugs.webkit.org/show_bug.cgi?id=196118
<rdar://problem/46614137>

Reviewed by Chris Dumez.

Source/WebCore:

Test: webanimations/js-wrapper-kept-alive.html

We need to teach WebAnimation to keep its JS wrapper alive if it's relevant or could become relevant again by virtue of having a timeline.
We also need to ensure that the new implementation of hasPendingActivity() does not interfere with the ability of pages to enter the page
cache when running animations.

* animation/WebAnimation.cpp:
(WebCore::WebAnimation::canSuspendForDocumentSuspension const):
(WebCore::WebAnimation::stop):
(WebCore::WebAnimation::hasPendingActivity const):
* animation/WebAnimation.h:

LayoutTests:

Add a test that starts a short animation, sets a custom property on it, registers a "finish" event listener on it and deletes
the sole reference to it in the JS world before triggering garbage collection. Prior to this fix, this test would time out
because the JS wrapper would be garbage-collected prior to the animation completing and thus the event listener would not
be called. To complete successfully, this test checks that it receives the event and its target is the same animation object
that was originally created by checking the custom property is still set.

We also make sure that a test, which was found to have regressed with a previous version of this patch, uses the animation
engine that it is expected to be testing.

* legacy-animation-engine/animations/resume-after-page-cache.html:
* webanimations/js-wrapper-kept-alive-expected.txt: Added.
* webanimations/js-wrapper-kept-alive.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (244030 => 244031)


--- trunk/LayoutTests/ChangeLog	2019-04-08 18:45:15 UTC (rev 244030)
+++ trunk/LayoutTests/ChangeLog	2019-04-08 18:49:04 UTC (rev 244031)
@@ -1,3 +1,24 @@
+2019-04-08  Antoine Quint  <[email protected]>
+
+        [Web Animations] JS wrapper may be deleted while animation is yet to dispatch its finish event
+        https://bugs.webkit.org/show_bug.cgi?id=196118
+        <rdar://problem/46614137>
+
+        Reviewed by Chris Dumez.
+
+        Add a test that starts a short animation, sets a custom property on it, registers a "finish" event listener on it and deletes
+        the sole reference to it in the JS world before triggering garbage collection. Prior to this fix, this test would time out
+        because the JS wrapper would be garbage-collected prior to the animation completing and thus the event listener would not
+        be called. To complete successfully, this test checks that it receives the event and its target is the same animation object
+        that was originally created by checking the custom property is still set.
+
+        We also make sure that a test, which was found to have regressed with a previous version of this patch, uses the animation
+        engine that it is expected to be testing.
+
+        * legacy-animation-engine/animations/resume-after-page-cache.html:
+        * webanimations/js-wrapper-kept-alive-expected.txt: Added.
+        * webanimations/js-wrapper-kept-alive.html: Added.
+
 2019-04-08  Eric Liang  <[email protected]>
 
         AX: <svg> elements with labels and no accessible contents are exposed as empty AXGroups

Modified: trunk/LayoutTests/legacy-animation-engine/animations/resume-after-page-cache.html (244030 => 244031)


--- trunk/LayoutTests/legacy-animation-engine/animations/resume-after-page-cache.html	2019-04-08 18:45:15 UTC (rev 244030)
+++ trunk/LayoutTests/legacy-animation-engine/animations/resume-after-page-cache.html	2019-04-08 18:49:04 UTC (rev 244031)
@@ -1,3 +1,4 @@
+<!-- webkit-test-runner [ experimental:WebAnimationsCSSIntegrationEnabled=false ] -->
 <style>
 @-webkit-keyframes bounce {
     from {

Added: trunk/LayoutTests/webanimations/js-wrapper-kept-alive-expected.txt (0 => 244031)


--- trunk/LayoutTests/webanimations/js-wrapper-kept-alive-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webanimations/js-wrapper-kept-alive-expected.txt	2019-04-08 18:49:04 UTC (rev 244031)
@@ -0,0 +1,10 @@
+This test checks that registering an event listener on an animation whose JS wrapper would otherwise be garbage-collected still fires registered event listeners.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS event.target._isMyAnimation is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/webanimations/js-wrapper-kept-alive.html (0 => 244031)


--- trunk/LayoutTests/webanimations/js-wrapper-kept-alive.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/js-wrapper-kept-alive.html	2019-04-08 18:49:04 UTC (rev 244031)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="target"></div>
+<script src=""
+<script>
+description("This test checks that registering an event listener on an animation whose JS wrapper would otherwise be garbage-collected still fires registered event listeners.");
+
+if (window.internals)
+    jsTestIsAsync = true;
+
+// A longer animation that could not be garbage-collected under any circumstance allows us to finish the test
+// with a reasonable delay without hard-coding a timeout.
+const timeoutAnimation = document.getElementById("target").animate({ marginRight: ["0px", "100px"] }, 1000);
+timeoutAnimation.addEventListener("finish", finishJSTest);
+
+function runTest() {
+    const animation = document.getElementById("target").animate({ marginLeft: ["0px", "100px"] }, 100);
+    animation._isMyAnimation = true;
+    animation.addEventListener("finish", event => {
+        shouldBeTrue("event.target._isMyAnimation");
+        finishJSTest();
+    });
+}
+
+gc();
+runTest();
+gc();
+
+</script>
+<script src=""
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (244030 => 244031)


--- trunk/Source/WebCore/ChangeLog	2019-04-08 18:45:15 UTC (rev 244030)
+++ trunk/Source/WebCore/ChangeLog	2019-04-08 18:49:04 UTC (rev 244031)
@@ -1,3 +1,23 @@
+2019-04-08  Antoine Quint  <[email protected]>
+
+        [Web Animations] JS wrapper may be deleted while animation is yet to dispatch its finish event
+        https://bugs.webkit.org/show_bug.cgi?id=196118
+        <rdar://problem/46614137>
+
+        Reviewed by Chris Dumez.
+
+        Test: webanimations/js-wrapper-kept-alive.html
+
+        We need to teach WebAnimation to keep its JS wrapper alive if it's relevant or could become relevant again by virtue of having a timeline.
+        We also need to ensure that the new implementation of hasPendingActivity() does not interfere with the ability of pages to enter the page
+        cache when running animations.
+
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::canSuspendForDocumentSuspension const):
+        (WebCore::WebAnimation::stop):
+        (WebCore::WebAnimation::hasPendingActivity const):
+        * animation/WebAnimation.h:
+
 2019-04-08  Eric Liang  <[email protected]>
 
         AX: <svg> elements with labels and no accessible contents are exposed as empty AXGroups

Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (244030 => 244031)


--- trunk/Source/WebCore/animation/WebAnimation.cpp	2019-04-08 18:45:15 UTC (rev 244030)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp	2019-04-08 18:49:04 UTC (rev 244031)
@@ -1157,15 +1157,25 @@
 
 bool WebAnimation::canSuspendForDocumentSuspension() const
 {
-    return !hasPendingActivity();
+    // Use the base class's implementation of hasPendingActivity() since we wouldn't want the custom implementation
+    // in this class designed to keep JS wrappers alive to interfere with the ability for a page using animations
+    // to enter the page cache.
+    return !ActiveDOMObject::hasPendingActivity();
 }
 
 void WebAnimation::stop()
 {
+    ActiveDOMObject::stop();
     m_isStopped = true;
     removeAllEventListeners();
 }
 
+bool WebAnimation::hasPendingActivity() const
+{
+    // Keep the JS wrapper alive if the animation is considered relevant or could become relevant again by virtue of having a timeline.
+    return m_timeline || m_isRelevant || ActiveDOMObject::hasPendingActivity();
+}
+
 void WebAnimation::updateRelevance()
 {
     m_isRelevant = computeRelevance();

Modified: trunk/Source/WebCore/animation/WebAnimation.h (244030 => 244031)


--- trunk/Source/WebCore/animation/WebAnimation.h	2019-04-08 18:45:15 UTC (rev 244030)
+++ trunk/Source/WebCore/animation/WebAnimation.h	2019-04-08 18:49:04 UTC (rev 244031)
@@ -118,6 +118,8 @@
     bool isSuspended() const { return m_isSuspended; }
     virtual void remove();
 
+    bool hasPendingActivity() const final;
+
     using RefCounted::ref;
     using RefCounted::deref;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to