haikuwebkit/LayoutTests/intersection-observer/no-document-leak.html

63 lines
2.0 KiB
HTML
Raw Permalink Normal View History

IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
<!DOCTYPE html>
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
Code pattern in GC tests in LayoutTests is broken https://bugs.webkit.org/show_bug.cgi?id=211595 Reviewed by Saam Barati. LayoutTests have several tests which attempt to ensure that document is not leaked. But they are broken since these tests are not correctly handling conservative GC of JavaScriptCore. These tests are taking a following approach. 1. Allocate *one* iframe doing something inside it. 2. Remove iframe from the parent document to make it released. 3. Repeatedly invoke GC and test whether (1)'s document gets collected. This is not the right approach. Since JavaScriptCore has conservative GC, it is easily possible that (1)'s pointer value remains in some of conservative roots: CPU registers, stack etc. And JavaScriptCore conservative GC scans it and keeps it alive. The above approach makes the test super flaky and any unrelated changes in JavaScriptCore and C compiler can make this test failed. This is not a problem in practice. Web pages are executing various kind of code and they clobber conservative roots. However, tests in LayoutTests are too simple to keep it alive accidentally. The right approach for conservative GC is the following. 1. Allocate *many* iframes doing something inside them with loop. By creating iframes with loop, for every iteration, it is likely that the same CPU registers and stack locations are overwritten by the last created iframe reference. This dramatically reduces the possibility for GC to find these addresses in conservative roots. 2. Remove iframes from the parent document to make them released. 3. Repeatedly invoke GC and test whether *one of (1) iframes* gets collected at least. Theoretically this is still possible that completely unrelated integer value in conservative roots can point to the reference of (1). By allocating many iframes in (1) and testing one of them, we can reduce the possibility of this conflict. This patch adds testDocumentIsNotLeaked helper function to enforce this pattern. And rewrite broken tests with this helper to make it less-flaky. * highlight/highlight-world-leak.html: * http/tests/IndexedDB/collect-IDB-objects.https.html: * http/tests/media/clearkey/collect-webkit-media-session.html: * http/tests/media/media-stream/collect-media-devices.https.html: * http/tests/resources/gc.js: Added. (window.gc.gcRec): (window.gc.window.gc): (nukeArray): (async testDocumentIsNotLeaked): * intersection-observer/no-document-leak.html: * performance-api/performance-observer-no-document-leak.html: * resources/gc.js: (nukeArray): (async testDocumentIsNotLeaked): * webanimations/leak-document-with-web-animation.html: Canonical link: https://commits.webkit.org/224541@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261391 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-08 17:14:15 +00:00
<script src="../resources/gc.js"></script>
IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
</head>
<body>
Code pattern in GC tests in LayoutTests is broken https://bugs.webkit.org/show_bug.cgi?id=211595 Reviewed by Saam Barati. LayoutTests have several tests which attempt to ensure that document is not leaked. But they are broken since these tests are not correctly handling conservative GC of JavaScriptCore. These tests are taking a following approach. 1. Allocate *one* iframe doing something inside it. 2. Remove iframe from the parent document to make it released. 3. Repeatedly invoke GC and test whether (1)'s document gets collected. This is not the right approach. Since JavaScriptCore has conservative GC, it is easily possible that (1)'s pointer value remains in some of conservative roots: CPU registers, stack etc. And JavaScriptCore conservative GC scans it and keeps it alive. The above approach makes the test super flaky and any unrelated changes in JavaScriptCore and C compiler can make this test failed. This is not a problem in practice. Web pages are executing various kind of code and they clobber conservative roots. However, tests in LayoutTests are too simple to keep it alive accidentally. The right approach for conservative GC is the following. 1. Allocate *many* iframes doing something inside them with loop. By creating iframes with loop, for every iteration, it is likely that the same CPU registers and stack locations are overwritten by the last created iframe reference. This dramatically reduces the possibility for GC to find these addresses in conservative roots. 2. Remove iframes from the parent document to make them released. 3. Repeatedly invoke GC and test whether *one of (1) iframes* gets collected at least. Theoretically this is still possible that completely unrelated integer value in conservative roots can point to the reference of (1). By allocating many iframes in (1) and testing one of them, we can reduce the possibility of this conflict. This patch adds testDocumentIsNotLeaked helper function to enforce this pattern. And rewrite broken tests with this helper to make it less-flaky. * highlight/highlight-world-leak.html: * http/tests/IndexedDB/collect-IDB-objects.https.html: * http/tests/media/clearkey/collect-webkit-media-session.html: * http/tests/media/media-stream/collect-media-devices.https.html: * http/tests/resources/gc.js: Added. (window.gc.gcRec): (window.gc.window.gc): (nukeArray): (async testDocumentIsNotLeaked): * intersection-observer/no-document-leak.html: * performance-api/performance-observer-no-document-leak.html: * resources/gc.js: (nukeArray): (async testDocumentIsNotLeaked): * webanimations/leak-document-with-web-animation.html: Canonical link: https://commits.webkit.org/224541@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261391 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-08 17:14:15 +00:00
<iframe id="testFrame" src=></iframe>
IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
<script>
description("Tests that using IntersectionObserver does not cause the document to get leaked.");
window.jsTestIsAsync = true;
Code pattern in GC tests in LayoutTests is broken https://bugs.webkit.org/show_bug.cgi?id=211595 Reviewed by Saam Barati. LayoutTests have several tests which attempt to ensure that document is not leaked. But they are broken since these tests are not correctly handling conservative GC of JavaScriptCore. These tests are taking a following approach. 1. Allocate *one* iframe doing something inside it. 2. Remove iframe from the parent document to make it released. 3. Repeatedly invoke GC and test whether (1)'s document gets collected. This is not the right approach. Since JavaScriptCore has conservative GC, it is easily possible that (1)'s pointer value remains in some of conservative roots: CPU registers, stack etc. And JavaScriptCore conservative GC scans it and keeps it alive. The above approach makes the test super flaky and any unrelated changes in JavaScriptCore and C compiler can make this test failed. This is not a problem in practice. Web pages are executing various kind of code and they clobber conservative roots. However, tests in LayoutTests are too simple to keep it alive accidentally. The right approach for conservative GC is the following. 1. Allocate *many* iframes doing something inside them with loop. By creating iframes with loop, for every iteration, it is likely that the same CPU registers and stack locations are overwritten by the last created iframe reference. This dramatically reduces the possibility for GC to find these addresses in conservative roots. 2. Remove iframes from the parent document to make them released. 3. Repeatedly invoke GC and test whether *one of (1) iframes* gets collected at least. Theoretically this is still possible that completely unrelated integer value in conservative roots can point to the reference of (1). By allocating many iframes in (1) and testing one of them, we can reduce the possibility of this conflict. This patch adds testDocumentIsNotLeaked helper function to enforce this pattern. And rewrite broken tests with this helper to make it less-flaky. * highlight/highlight-world-leak.html: * http/tests/IndexedDB/collect-IDB-objects.https.html: * http/tests/media/clearkey/collect-webkit-media-session.html: * http/tests/media/media-stream/collect-media-devices.https.html: * http/tests/resources/gc.js: Added. (window.gc.gcRec): (window.gc.window.gc): (nukeArray): (async testDocumentIsNotLeaked): * intersection-observer/no-document-leak.html: * performance-api/performance-observer-no-document-leak.html: * resources/gc.js: (nukeArray): (async testDocumentIsNotLeaked): * webanimations/leak-document-with-web-animation.html: Canonical link: https://commits.webkit.org/224541@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261391 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-08 17:14:15 +00:00
let totalCount = 0;
window.onload = function () {
testDocumentIsNotLeaked(
async function initAndRemove(frameCount)
{
totalCount = frameCount;
let frames = await new Promise((resolve, reject) => {
let frames = [];
let counter = 0;
function onLoad() {
counter++;
if (counter == frameCount)
resolve(frames);
}
for (let i = 0; i < frameCount; ++i) {
let frame = document.createElement('iframe');
frame.src = "resources/no-document-leak-frame.html";
frame.onload = onLoad;
document.body.appendChild(frame);
frames.push(frame);
}
});
totalCount = internals.numberOfIntersectionObservers(document);
let frameIdentifiers = [];
for (let i = 0; i < frameCount; ++i) {
let frame = frames[i];
frameIdentifiers.push(internals.documentIdentifier(frame.contentDocument));
frame.remove();
IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
}
Code pattern in GC tests in LayoutTests is broken https://bugs.webkit.org/show_bug.cgi?id=211595 Reviewed by Saam Barati. LayoutTests have several tests which attempt to ensure that document is not leaked. But they are broken since these tests are not correctly handling conservative GC of JavaScriptCore. These tests are taking a following approach. 1. Allocate *one* iframe doing something inside it. 2. Remove iframe from the parent document to make it released. 3. Repeatedly invoke GC and test whether (1)'s document gets collected. This is not the right approach. Since JavaScriptCore has conservative GC, it is easily possible that (1)'s pointer value remains in some of conservative roots: CPU registers, stack etc. And JavaScriptCore conservative GC scans it and keeps it alive. The above approach makes the test super flaky and any unrelated changes in JavaScriptCore and C compiler can make this test failed. This is not a problem in practice. Web pages are executing various kind of code and they clobber conservative roots. However, tests in LayoutTests are too simple to keep it alive accidentally. The right approach for conservative GC is the following. 1. Allocate *many* iframes doing something inside them with loop. By creating iframes with loop, for every iteration, it is likely that the same CPU registers and stack locations are overwritten by the last created iframe reference. This dramatically reduces the possibility for GC to find these addresses in conservative roots. 2. Remove iframes from the parent document to make them released. 3. Repeatedly invoke GC and test whether *one of (1) iframes* gets collected at least. Theoretically this is still possible that completely unrelated integer value in conservative roots can point to the reference of (1). By allocating many iframes in (1) and testing one of them, we can reduce the possibility of this conflict. This patch adds testDocumentIsNotLeaked helper function to enforce this pattern. And rewrite broken tests with this helper to make it less-flaky. * highlight/highlight-world-leak.html: * http/tests/IndexedDB/collect-IDB-objects.https.html: * http/tests/media/clearkey/collect-webkit-media-session.html: * http/tests/media/media-stream/collect-media-devices.https.html: * http/tests/resources/gc.js: Added. (window.gc.gcRec): (window.gc.window.gc): (nukeArray): (async testDocumentIsNotLeaked): * intersection-observer/no-document-leak.html: * performance-api/performance-observer-no-document-leak.html: * resources/gc.js: (nukeArray): (async testDocumentIsNotLeaked): * webanimations/leak-document-with-web-animation.html: Canonical link: https://commits.webkit.org/224541@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261391 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-08 17:14:15 +00:00
nukeArray(frames);
frames = null;
return frameIdentifiers;
},
{
additionalCheck: function()
{
let count = internals.numberOfIntersectionObservers(document);
return count < totalCount || count === 0;
}
}
).then(
() => testPassed("Document did not leak"),
(error) => testFailed(error.message)
).finally(finishJSTest);
IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
};
Code pattern in GC tests in LayoutTests is broken https://bugs.webkit.org/show_bug.cgi?id=211595 Reviewed by Saam Barati. LayoutTests have several tests which attempt to ensure that document is not leaked. But they are broken since these tests are not correctly handling conservative GC of JavaScriptCore. These tests are taking a following approach. 1. Allocate *one* iframe doing something inside it. 2. Remove iframe from the parent document to make it released. 3. Repeatedly invoke GC and test whether (1)'s document gets collected. This is not the right approach. Since JavaScriptCore has conservative GC, it is easily possible that (1)'s pointer value remains in some of conservative roots: CPU registers, stack etc. And JavaScriptCore conservative GC scans it and keeps it alive. The above approach makes the test super flaky and any unrelated changes in JavaScriptCore and C compiler can make this test failed. This is not a problem in practice. Web pages are executing various kind of code and they clobber conservative roots. However, tests in LayoutTests are too simple to keep it alive accidentally. The right approach for conservative GC is the following. 1. Allocate *many* iframes doing something inside them with loop. By creating iframes with loop, for every iteration, it is likely that the same CPU registers and stack locations are overwritten by the last created iframe reference. This dramatically reduces the possibility for GC to find these addresses in conservative roots. 2. Remove iframes from the parent document to make them released. 3. Repeatedly invoke GC and test whether *one of (1) iframes* gets collected at least. Theoretically this is still possible that completely unrelated integer value in conservative roots can point to the reference of (1). By allocating many iframes in (1) and testing one of them, we can reduce the possibility of this conflict. This patch adds testDocumentIsNotLeaked helper function to enforce this pattern. And rewrite broken tests with this helper to make it less-flaky. * highlight/highlight-world-leak.html: * http/tests/IndexedDB/collect-IDB-objects.https.html: * http/tests/media/clearkey/collect-webkit-media-session.html: * http/tests/media/media-stream/collect-media-devices.https.html: * http/tests/resources/gc.js: Added. (window.gc.gcRec): (window.gc.window.gc): (nukeArray): (async testDocumentIsNotLeaked): * intersection-observer/no-document-leak.html: * performance-api/performance-observer-no-document-leak.html: * resources/gc.js: (nukeArray): (async testDocumentIsNotLeaked): * webanimations/leak-document-with-web-animation.html: Canonical link: https://commits.webkit.org/224541@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261391 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-08 17:14:15 +00:00
IntersectionObserver leaks documents https://bugs.webkit.org/show_bug.cgi?id=189128 Reviewed by Simon Fraser. Source/WebCore: Currently, Documents own IntersectionObservers while IntersectionObservers own callbacks that have strong references to Documents. To break this cycle, make Documents only have weak pointers to IntersectionObservers. Instead, manage the lifetime of an IntersectionObserver as an ActiveDOMObject, overriding hasPendingActivity to keep the observer alive while there are ongoing observations. However, there is a still a potential reference cycle. The callback keeps global references alive, so if there's a global reference to the observer in JavaScript, we have an observer->callback->observer cycle, keeping the callback (and hence the Document) alive. To break this cycle, make IntersectionObserver release the callback when its Document is stopped. With these changes, there are no longer any leaks reported with run-webkit-tests --world-leaks on LayoutTests/intersection-observer and LayoutTests/imported/w3c/web-platform-tests/intersection-observer. Tests: intersection-observer/no-document-leak.html intersection-observer/observer-and-callback-without-js-references.html * dom/Document.cpp: (WebCore::Document::addIntersectionObserver): (WebCore::Document::removeIntersectionObserver): * dom/Document.h: * dom/Element.cpp: (WebCore::Element::didMoveToNewDocument): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::IntersectionObserver): (WebCore::IntersectionObserver::~IntersectionObserver): (WebCore::IntersectionObserver::observe): (WebCore::IntersectionObserver::rootDestroyed): (WebCore::IntersectionObserver::createTimestamp const): (WebCore::IntersectionObserver::notify): (WebCore::IntersectionObserver::hasPendingActivity const): (WebCore::IntersectionObserver::activeDOMObjectName const): (WebCore::IntersectionObserver::canSuspendForDocumentSuspension const): (WebCore::IntersectionObserver::stop): * page/IntersectionObserver.h: (WebCore::IntersectionObserver::trackingDocument const): (WebCore::IntersectionObserver::trackingDocument): Deleted. * page/IntersectionObserver.idl: LayoutTests: * intersection-observer/no-document-leak-expected.txt: Added. * intersection-observer/no-document-leak.html: Added. * intersection-observer/observer-and-callback-without-js-references-expected.txt: Added. * intersection-observer/observer-and-callback-without-js-references.html: Added. * intersection-observer/resources/no-document-leak-frame.html: Added. Canonical link: https://commits.webkit.org/204346@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235736 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-06 13:51:24 +00:00
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>