WebKit Bugzilla
Attachment 370681 Details for
Bug 197457
: The JS wrapper of target in an ResizeObserverEntry should not get collected
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-197457-20190527171748.patch (text/plain), 20.46 KB, created by
cathiechen
on 2019-05-27 02:17:49 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
cathiechen
Created:
2019-05-27 02:17:49 PDT
Size:
20.46 KB
patch
obsolete
>Subversion Revision: 245788 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index bb6aacac69a440eed3d117098bb1f977589fe5b7..d772ef4c3c16b43428f16d197541546700b79791 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,33 @@ >+2019-05-27 Cathie Chen <cathiechen@igalia.com> >+ >+ JS wrapper of target in ResizeObserverEntry/ResizeObserver shouldn't get collected ahead >+ https://bugs.webkit.org/show_bug.cgi?id=197457 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add JSCustomMarkFunction to make sure JS wrappers wouldn't be collected when JSResizeObserverEntry live. >+ >+ For ResizeObserver, if targets are removed, it will get fired for the last time. We also need to keep these JS >+ wrappers live. So add these targets to a GCReachableRef list once they're observed. >+ >+ Add element-leak.html to test the targets with `entry.target.myEntry = entry` could be released properly. >+ >+ Tests: resize-observer/element-leak.html >+ resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive.html >+ resize-observer/resize-observer-keeps-js-wrapper-of-target-alive.html >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * bindings/js/JSResizeObserverEntryCustom.cpp: Copied from Source/WebCore/page/ResizeObserverEntry.idl. >+ (WebCore::JSResizeObserverEntry::visitAdditionalChildren): >+ * page/ResizeObserver.cpp: >+ (WebCore::ResizeObserver::observe): >+ (WebCore::ResizeObserver::removeAllTargets): >+ (WebCore::ResizeObserver::removeObservation): >+ (WebCore::ResizeObserver::stop): >+ * page/ResizeObserver.h: >+ * page/ResizeObserverEntry.idl: >+ > 2019-05-27 Carlos Garcia Campos <cgarcia@igalia.com> > > Touch support is reported even when the device doesn't have a touch screen >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 2e2cfd14109813ab510017a122c1faf00201f33d..176b48e9df8b48b44865390dfa28a9bb5b3728d7 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -532,6 +532,7 @@ bindings/js/JSPromiseRejectionEventCustom.cpp > bindings/js/JSReadableStreamSourceCustom.cpp > bindings/js/JSRemoteDOMWindowBase.cpp > bindings/js/JSRemoteDOMWindowCustom.cpp >+bindings/js/JSResizeObserverEntryCustom.cpp > bindings/js/JSSVGPathSegCustom.cpp > bindings/js/JSSVGViewSpecCustom.cpp > bindings/js/JSStyleSheetCustom.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index e95a8f930e4c38159c12ad63d3abf9aa3cf704b4..d8e867097c95f85bcc63213b705f2e6c4e297e12 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -8782,6 +8782,7 @@ > 585D6DFB1A15355600FA4F12 /* SimpleLineLayoutResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayoutResolver.cpp; sourceTree = "<group>"; }; > 585D6E011A1A792E00FA4F12 /* SimpleLineLayoutFlowContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayoutFlowContents.cpp; sourceTree = "<group>"; }; > 585D6E021A1A792E00FA4F12 /* SimpleLineLayoutFlowContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayoutFlowContents.h; sourceTree = "<group>"; }; >+ 5884FE5622813E2D0040AFF6 /* JSResizeObserverEntryCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSResizeObserverEntryCustom.cpp; sourceTree = "<group>"; }; > 589556EC18D4A44000764B03 /* BorderEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BorderEdge.h; sourceTree = "<group>"; }; > 58AEE2F318D4BCCF0022E7FE /* BorderEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BorderEdge.cpp; sourceTree = "<group>"; }; > 58B2F9EA2232D43B00938D63 /* ResizeObserverEntry.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ResizeObserverEntry.idl; sourceTree = "<group>"; }; >@@ -20672,6 +20673,7 @@ > CB38FD551CD21D5B00592A3F /* JSPerformanceEntryCustom.cpp */, > 833CF70F20DB3F5F00141BCC /* JSPerformanceObserverCustom.cpp */, > A4A69B8BB91B49D0A804C31D /* JSPromiseRejectionEventCustom.cpp */, >+ 5884FE5622813E2D0040AFF6 /* JSResizeObserverEntryCustom.cpp */, > 83F572941FA1066F003837BE /* JSServiceWorkerClientCustom.cpp */, > 460D19441FCE21DD00C3DB85 /* JSServiceWorkerGlobalScopeCustom.cpp */, > BC98A27C0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp */, >diff --git a/Source/WebCore/bindings/js/JSResizeObserverEntryCustom.cpp b/Source/WebCore/bindings/js/JSResizeObserverEntryCustom.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..6b2a4c2d34127cdc6e51d9431d2e90252f8b2e69 >--- /dev/null >+++ b/Source/WebCore/bindings/js/JSResizeObserverEntryCustom.cpp >@@ -0,0 +1,39 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "JSResizeObserverEntry.h" >+ >+#include "JSNodeCustom.h" >+ >+namespace WebCore { >+ >+void JSResizeObserverEntry::visitAdditionalChildren(JSC::SlotVisitor& visitor) >+{ >+ visitor.addOpaqueRoot(root(wrapped().target())); >+ visitor.addOpaqueRoot(wrapped().contentRect()); >+} >+ >+} >diff --git a/Source/WebCore/page/ResizeObserver.cpp b/Source/WebCore/page/ResizeObserver.cpp >index 9ff2b6ebc455462e436166f9d35367ea7fde8d7a..b9bd9bd9665c28da60dbe6461c0f03f5ae5ee5a4 100644 >--- a/Source/WebCore/page/ResizeObserver.cpp >+++ b/Source/WebCore/page/ResizeObserver.cpp >@@ -69,6 +69,7 @@ void ResizeObserver::observe(Element& target) > observerData.observers.append(makeWeakPtr(this)); > > m_observations.append(ResizeObservation::create(&target)); >+ m_pendingTargets.append(target); > > if (m_document) { > m_document->addResizeObserver(*this); >@@ -140,11 +141,17 @@ void ResizeObserver::removeAllTargets() > bool removed = removeTarget(*observation->target()); > ASSERT_UNUSED(removed, removed); > } >+ m_pendingTargets.clear(); >+ m_activeObservations.clear(); > m_observations.clear(); > } > > bool ResizeObserver::removeObservation(const Element& target) > { >+ m_pendingTargets.removeFirstMatching([&target](auto& pendingTarget) { >+ return pendingTarget.ptr() == ⌖ >+ }); >+ > m_activeObservations.removeFirstMatching([&target](auto& observation) { > return observation->target() == ⌖ > }); >@@ -173,8 +180,6 @@ void ResizeObserver::stop() > { > disconnect(); > m_callback = nullptr; >- m_observations.clear(); >- m_activeObservations.clear(); > } > > } // namespace WebCore >diff --git a/Source/WebCore/page/ResizeObserver.h b/Source/WebCore/page/ResizeObserver.h >index a1819609f6e0c3ee55bcdca3ac221fcaaa86b6e6..95b1c8b5be83d89b24979eaed9b9d4e90d3f4f87 100644 >--- a/Source/WebCore/page/ResizeObserver.h >+++ b/Source/WebCore/page/ResizeObserver.h >@@ -28,6 +28,7 @@ > #if ENABLE(RESIZE_OBSERVER) > > #include "ActiveDOMObject.h" >+#include "GCReachableRef.h" > #include "ResizeObservation.h" > #include "ResizeObserverCallback.h" > #include <wtf/RefCounted.h> >@@ -80,6 +81,7 @@ private: > Vector<Ref<ResizeObservation>> m_observations; > > Vector<Ref<ResizeObservation>> m_activeObservations; >+ Vector<GCReachableRef<Element>> m_pendingTargets; > bool m_hasSkippedObservations { false }; > }; > >diff --git a/Source/WebCore/page/ResizeObserverEntry.idl b/Source/WebCore/page/ResizeObserverEntry.idl >index b051bb57bec6925add74acd265442df05f79832a..72f85dcfce6bc0aa62a8980e25363102bd3492b0 100644 >--- a/Source/WebCore/page/ResizeObserverEntry.idl >+++ b/Source/WebCore/page/ResizeObserverEntry.idl >@@ -28,7 +28,8 @@ > [ > Conditional=RESIZE_OBSERVER, > ImplementationLacksVTable, >- EnabledBySetting=ResizeObserver >+ EnabledBySetting=ResizeObserver, >+ JSCustomMarkFunction > ] interface ResizeObserverEntry { > readonly attribute Element target; > readonly attribute DOMRectReadOnly contentRect; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index b2d158a875b503821e4b6b198dce1eb813ec8fb9..5baebbfb19de6dd067eb741a9d17231dccd8cf14 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,19 @@ >+2019-05-27 Cathie Chen <cathiechen@igalia.com> >+ >+ JS wrapper of target in ResizeObserverEntry/ResizeObserver shouldn't get collected ahead >+ https://bugs.webkit.org/show_bug.cgi?id=197457 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * platform/win/TestExpectations: >+ * resize-observer/element-leak-expected.txt: Added. >+ * resize-observer/element-leak.html: Added. >+ * resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive-expected.txt: Added. >+ * resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive.html: Added. >+ * resize-observer/resize-observer-keeps-js-wrapper-of-target-alive-expected.txt: Added. >+ * resize-observer/resize-observer-keeps-js-wrapper-of-target-alive.html: Added. >+ * resize-observer/resources/element-leak-frame.html: Added. >+ > 2019-05-27 Carlos Garcia Campos <cgarcia@igalia.com> > > Touch support is reported even when the device doesn't have a touch screen >diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations >index 754a4a374627ded5ac33d7320687449370ee6a9e..a8ed5e570e6016e627d00cb774b3a736fdbc3616 100644 >--- a/LayoutTests/platform/win/TestExpectations >+++ b/LayoutTests/platform/win/TestExpectations >@@ -4392,3 +4392,7 @@ webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource.html [ Skip ] > webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource-iframe.html [ Skip ] > > webkit.org/b/198112 http/tests/security/showModalDialog-sync-cross-origin-page-load2.html [ Skip ] >+ >+# The removed elements couldn't be released properly in Win. >+# The relevant bug is https://bugs.webkit.org/show_bug.cgi?id=197908 >+resize-observer/element-leak.html [ Skip ] >diff --git a/LayoutTests/resize-observer/element-leak-expected.txt b/LayoutTests/resize-observer/element-leak-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..84ad90becdf909c19b9cb30e51ce5657bc14eb9f >--- /dev/null >+++ b/LayoutTests/resize-observer/element-leak-expected.txt >@@ -0,0 +1,4 @@ >+ >+PASS ResizeObserver implemented >+PASS test0: Test elements leak >+ >diff --git a/LayoutTests/resize-observer/element-leak.html b/LayoutTests/resize-observer/element-leak.html >new file mode 100644 >index 0000000000000000000000000000000000000000..765dcbb3e3116398bd4e9f7928474c5c7ab9959f >--- /dev/null >+++ b/LayoutTests/resize-observer/element-leak.html >@@ -0,0 +1,66 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:ResizeObserverEnabled=true ] --> >+<html> >+<meta name="timeout" content="long"> >+<head> >+<script src="../resources/testharness.js"></script> >+<script src="../resources/testharnessreport.js"></script> >+<script src="../resources/gc.js"></script> >+</head> >+<body> >+<iframe id="testFrame" src="resources/element-leak-frame.html"></iframe> >+<script> >+if (window.testRunner) >+ testRunner.dumpAsText(); >+ >+var testresult; >+ >+function documentShouldDie(documentIdentifier) >+{ >+ return new Promise(function(resolve, reject) { >+ handle = setInterval(function() { >+ gc(); >+ if (internals && !internals.isDocumentAlive(documentIdentifier)) { >+ clearInterval(handle); >+ resolve(); >+ testresult = true; >+ } >+ }, 10); >+ }); >+} >+ >+function test0() { >+ let test = async_test('test0: Test elements leak'); >+ window.addEventListener('message', event => { >+ switch(event.data) { >+ case 'Notified': >+ test.step( () => { >+ var testFrame = document.getElementById("testFrame"); >+ let frameDocumentIdentifier = internals.documentIdentifier(testFrame.contentDocument); >+ testFrame.remove(); >+ documentShouldDie(frameDocumentIdentifier).then(function() { >+ assert_true(testresult, 'element leaking'); >+ test.done(); >+ }); >+ >+ }); >+ break; >+ } >+ }, false); >+ >+ test.step_timeout(() => { >+ testresult = false; >+ assert_true(testresult, 'element leaking'); >+ log('timeout: '); >+ test.done(); >+ }, 5000); >+} >+ >+test(_ => { >+ assert_own_property(window, "ResizeObserver"); >+}, "ResizeObserver implemented"); >+ >+test0(); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive-expected.txt b/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..a5be9926a5a122dc0b0441c66c1ade67718b3e55 >--- /dev/null >+++ b/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive-expected.txt >@@ -0,0 +1,22 @@ >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+CONSOLE MESSAGE: ResizeObserver loop completed with undelivered notifications. >+This tests that JS wrappers of targets in an ResizeObserverEntry do not get collected. >+ >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+PASS >+ >diff --git a/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive.html b/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive.html >new file mode 100644 >index 0000000000000000000000000000000000000000..0c2fb46c635fa489e73f4b19d356ec89dff2eae0 >--- /dev/null >+++ b/LayoutTests/resize-observer/resize-observer-entry-keeps-js-wrapper-of-target-alive.html >@@ -0,0 +1,60 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:ResizeObserverEnabled=true ] --> >+<html> >+<body> >+<p>This tests that JS wrappers of targets in an ResizeObserverEntry do not get collected.</p> >+<pre id="log"></pre> >+<script src="../resources/gc.js"></script> >+<script> >+ >+if (window.testRunner) >+ testRunner.dumpAsText(); >+ >+const targetCount = 5; >+const iterationCount = 10; >+ >+async function observe() { >+ for (let i = 0; i < targetCount; ++i) { >+ let target = document.createElement('div'); >+ target.myState = 'live'; >+ document.body.appendChild(target); >+ } >+ >+ return new Promise((resolve) => { >+ const observer = new ResizeObserver(entries => { >+ 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.target.myState != 'live') >+ deadCount++; >+ } >+ document.getElementById('log').textContent += (deadCount ? `FAIL - ${deadCount} targets lost JS wrappers` : 'PASS') + '\n'; >+} >+ >+async function runAll() { >+ if (window.testRunner) >+ testRunner.waitUntilDone(); >+ >+ for (let j = 0; j < iterationCount; ++j) { >+ const entries = await observe(); >+ document.querySelectorAll('div').forEach(target => { target.remove(); }); >+ await Promise.resolve(); >+ gc(); >+ check(entries); >+ } >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+runAll(); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive-expected.txt b/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1fe5345c387b0760b2ebea7d982807bc400fd6d8 >--- /dev/null >+++ b/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive-expected.txt >@@ -0,0 +1,4 @@ >+This tests that JS wrappers of targets removed from document to be delivered to an resize observer do not get collected. >+ >+PASS >+ >diff --git a/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive.html b/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive.html >new file mode 100644 >index 0000000000000000000000000000000000000000..3dff784c9e894700ec72472934e702ce8a16da09 >--- /dev/null >+++ b/LayoutTests/resize-observer/resize-observer-keeps-js-wrapper-of-target-alive.html >@@ -0,0 +1,55 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:ResizeObserverEnabled=true ] --> >+<html> >+<body> >+<p>This tests that JS wrappers of targets removed from document to be delivered to an resize observer do not get collected.</p> >+<pre id="log"></pre> >+<script src="../resources/gc.js"></script> >+<script> >+ >+if (window.testRunner) >+ testRunner.dumpAsText(); >+ >+const targetCount = 5; >+const iterationCount = 10; >+var deadCount = 0; >+ >+async function runAll() { >+ if (window.testRunner) >+ testRunner.waitUntilDone(); >+ >+ for (let i = 0; i < iterationCount; ++i) { >+ runTest(); >+ gc(); >+ await new Promise((resolve) => requestAnimationFrame(resolve)) >+ } >+ >+ document.getElementById('log').textContent = (deadCount ? `FAIL - ${deadCount} targets lost JS wrappers` : 'PASS') + '\n'; >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+function runTest() { >+ document.querySelectorAll('div').forEach(target => { target.remove(); }); >+ >+ for (let i = 0; i < targetCount; ++i) { >+ let target = document.createElement('div'); >+ target.myState = 'live'; >+ document.body.appendChild(target); >+ } >+ >+ document.querySelectorAll('div').forEach(target => { observer.observe(target); }); >+} >+ >+const observer = new ResizeObserver(entries => { >+ for (const entry of entries) { >+ if (entry.target.myState != 'live') >+ deadCount++; >+ } >+}); >+ >+runAll(); >+ >+</script> >+</body> >+</html> >diff --git a/LayoutTests/resize-observer/resources/element-leak-frame.html b/LayoutTests/resize-observer/resources/element-leak-frame.html >new file mode 100644 >index 0000000000000000000000000000000000000000..344f60e06b20d5450633b63e594bc4916756e71e >--- /dev/null >+++ b/LayoutTests/resize-observer/resources/element-leak-frame.html >@@ -0,0 +1,30 @@ >+<body></body> >+<script src="../../resources/gc.js"></script> >+<script type="text/javascript"> >+ >+const targetCount = 1000; >+ >+var ro = new ResizeObserver( entries => { >+ for (let entry of entries) { >+ entry.target.myEntry = entry; >+ } >+ ro.disconnect(); >+ document.querySelectorAll('div').forEach(target => { >+ target.remove(); >+ }); >+ // Make sure targets be added to m_opaqueRoots. >+ gc(); >+ parent.postMessage('Notified', '*') >+}); >+ >+ >+for (let i = 0; i < targetCount; ++i) { >+ var target = document.createElement('div'); >+ document.body.appendChild(target); >+} >+ >+document.querySelectorAll('div').forEach(target => { >+ ro.observe(target); >+}); >+ >+</script> >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 197457
:
368670
|
369394
|
369426
|
369680
|
369681
|
369683
|
369738
|
369746
|
369752
|
369755
|
369756
|
369764
|
369833
|
369837
|
369840
|
369844
|
369845
|
369846
|
369847
|
369848
|
369854
|
369861
|
369862
|
369866
|
369870
|
369876
|
369877
|
369921
|
369922
|
369923
|
369925
|
369926
|
369927
|
369935
|
369942
|
370111
|
370681
|
371183
|
371186
|
371241