Title: [237929] trunk
Revision
237929
Author
aj...@chromium.org
Date
2018-11-07 10:30:30 -0800 (Wed, 07 Nov 2018)

Log Message

IntersectionObserverEntry doesn't keep JS wrappers of rects alive
https://bugs.webkit.org/show_bug.cgi?id=191330

Reviewed by Chris Dumez.

Source/WebCore:

Retain wrappers of each rect in an IntersectionObserverEntry as long as the entry's wrapper
is alive, by adding these wrappers as opaque roots.

Test: intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html

* bindings/js/JSIntersectionObserverEntryCustom.cpp:
(WebCore::JSIntersectionObserverEntry::visitAdditionalChildren):
* dom/DOMRectReadOnly.idl:
* page/IntersectionObserverEntry.h:
(WebCore::IntersectionObserverEntry::rootBounds const): Make this return a raw pointer instead of a RefPtr so that it
can be called in JSIntersectionObserverEntry::visitAdditionalChildren, which can be called from non-main threads.
(WebCore::IntersectionObserverEntry::boundingClientRect const): Ditto.
(WebCore::IntersectionObserverEntry::intersectionRect const): Ditto.

LayoutTests:

Add test coverage.

* intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive-expected.txt: Added.
* intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (237928 => 237929)


--- trunk/LayoutTests/ChangeLog	2018-11-07 17:30:39 UTC (rev 237928)
+++ trunk/LayoutTests/ChangeLog	2018-11-07 18:30:30 UTC (rev 237929)
@@ -1,3 +1,15 @@
+2018-11-07  Ali Juma  <aj...@chromium.org>
+
+        IntersectionObserverEntry doesn't keep JS wrappers of rects alive
+        https://bugs.webkit.org/show_bug.cgi?id=191330
+
+        Reviewed by Chris Dumez.
+
+        Add test coverage.
+
+        * intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive-expected.txt: Added.
+        * intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html: Added.
+
 2018-11-07  Ryan Haddad  <ryanhad...@apple.com>
 
         Unreviewed, update test expectations for fast/events/pointer.

Added: trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive-expected.txt (0 => 237929)


--- trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive-expected.txt	2018-11-07 18:30:30 UTC (rev 237929)
@@ -0,0 +1,8 @@
+This tests that JS wrappers of rects in an IntersectionObserverEntry do not get collected.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+

Added: trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html (0 => 237929)


--- trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html	                        (rev 0)
+++ trunk/LayoutTests/intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html	2018-11-07 18:30:30 UTC (rev 237929)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This tests that JS wrappers of rects in an IntersectionObserverEntry do not get collected.</p>
+<pre id="log"></pre>
+<script src=""
+<script>
+
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+const targetCount = 5;
+const iterationCount = 5;
+
+for (let i = 0; i < targetCount; ++i) {
+    let target = document.createElement('div');
+    document.body.appendChild(target);
+}
+
+async function observe() {
+    return new Promise((resolve) => {
+        const observer = new IntersectionObserver(entries => {
+            for (const entry of entries) {
+                entry.rootBounds.myState = 'live';
+                entry.boundingClientRect.myState = 'live';
+                entry.intersectionRect.myState = 'live';
+            }
+            resolve(entries);
+            observer.disconnect();
+        });
+        document.querySelectorAll('div').forEach(target => { observer.observe(target); });
+    });
+}
+
+function check(entries) {
+    let deadCount = 0;
+    for (const entry of entries) {
+        if (entry.rootBounds.myState != 'live')
+            deadCount++;
+        if (entry.boundingClientRect.myState != 'live')
+            deadCount++;
+        if (entry.intersectionRect.myState != 'live')
+            deadCount++;
+    }
+    document.getElementById('log').textContent += (deadCount ? `FAIL - ${deadCount} rects lost JS wrappers` : 'PASS') + '\n';
+}
+
+async function runAll() {
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    for (let j = 0; j < iterationCount; ++j) {
+        const entries = await observe();
+        await Promise.resolve();
+        gc();
+        check(entries);
+    }
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+runAll();
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (237928 => 237929)


--- trunk/Source/WebCore/ChangeLog	2018-11-07 17:30:39 UTC (rev 237928)
+++ trunk/Source/WebCore/ChangeLog	2018-11-07 18:30:30 UTC (rev 237929)
@@ -1,3 +1,24 @@
+2018-11-07  Ali Juma  <aj...@chromium.org>
+
+        IntersectionObserverEntry doesn't keep JS wrappers of rects alive
+        https://bugs.webkit.org/show_bug.cgi?id=191330
+
+        Reviewed by Chris Dumez.
+
+        Retain wrappers of each rect in an IntersectionObserverEntry as long as the entry's wrapper
+        is alive, by adding these wrappers as opaque roots.
+
+        Test: intersection-observer/intersection-observer-entry-keeps-js-wrappers-of-rects-alive.html
+
+        * bindings/js/JSIntersectionObserverEntryCustom.cpp:
+        (WebCore::JSIntersectionObserverEntry::visitAdditionalChildren):
+        * dom/DOMRectReadOnly.idl:
+        * page/IntersectionObserverEntry.h:
+        (WebCore::IntersectionObserverEntry::rootBounds const): Make this return a raw pointer instead of a RefPtr so that it
+        can be called in JSIntersectionObserverEntry::visitAdditionalChildren, which can be called from non-main threads.
+        (WebCore::IntersectionObserverEntry::boundingClientRect const): Ditto.
+        (WebCore::IntersectionObserverEntry::intersectionRect const): Ditto.
+
 2018-11-07  Simon Fraser  <simon.fra...@apple.com>
 
         TileController::tileSize() should not have side effects

Modified: trunk/Source/WebCore/bindings/js/JSIntersectionObserverEntryCustom.cpp (237928 => 237929)


--- trunk/Source/WebCore/bindings/js/JSIntersectionObserverEntryCustom.cpp	2018-11-07 17:30:39 UTC (rev 237928)
+++ trunk/Source/WebCore/bindings/js/JSIntersectionObserverEntryCustom.cpp	2018-11-07 18:30:30 UTC (rev 237929)
@@ -33,6 +33,9 @@
 void JSIntersectionObserverEntry::visitAdditionalChildren(JSC::SlotVisitor& visitor)
 {
     visitor.addOpaqueRoot(root(wrapped().target()));
+    visitor.addOpaqueRoot(wrapped().boundingClientRect());
+    visitor.addOpaqueRoot(wrapped().intersectionRect());
+    visitor.addOpaqueRoot(wrapped().rootBounds());
 }
 
 }

Modified: trunk/Source/WebCore/dom/DOMRectReadOnly.idl (237928 => 237929)


--- trunk/Source/WebCore/dom/DOMRectReadOnly.idl	2018-11-07 17:30:39 UTC (rev 237928)
+++ trunk/Source/WebCore/dom/DOMRectReadOnly.idl	2018-11-07 18:30:30 UTC (rev 237929)
@@ -29,6 +29,7 @@
     Constructor(optional unrestricted double x = 0, optional unrestricted double y = 0,
         optional unrestricted double width = 0, optional unrestricted double height = 0),
     Exposed=(Window,Worker),
+    GenerateIsReachable=Impl,
     ImplementationLacksVTable
 ]
 interface DOMRectReadOnly {

Modified: trunk/Source/WebCore/page/IntersectionObserverEntry.h (237928 => 237929)


--- trunk/Source/WebCore/page/IntersectionObserverEntry.h	2018-11-07 17:30:39 UTC (rev 237928)
+++ trunk/Source/WebCore/page/IntersectionObserverEntry.h	2018-11-07 18:30:30 UTC (rev 237929)
@@ -57,9 +57,9 @@
     }
     
     double time() const { return m_time; }
-    RefPtr<DOMRectReadOnly> rootBounds() const { return m_rootBounds; }
-    RefPtr<DOMRectReadOnly> boundingClientRect() const { return m_boundingClientRect; }
-    RefPtr<DOMRectReadOnly> intersectionRect() const { return m_intersectionRect; }
+    DOMRectReadOnly* rootBounds() const { return m_rootBounds.get(); }
+    DOMRectReadOnly* boundingClientRect() const { return m_boundingClientRect.get(); }
+    DOMRectReadOnly* intersectionRect() const { return m_intersectionRect.get(); }
     Element* target() const { return m_target.get(); }
 
     bool isIntersecting() const { return m_isIntersecting; }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to