// If there is no window.gc() already defined, define one using the best // method we can find. // The slow fallback should not hit in the actual test environment. if (!window.gc) { window.gc = function() { if (window.GCController) return GCController.collect(); console.warn('Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.'); function gcRec(n) { if (n < 1) return {}; var temp = {i: "ab" + i + (i / 100000)}; temp += "foo"; gcRec(n-1); } for (var i = 0; i < 10000; i++) gcRec(10); } } // Fill array with null to avoid potential GC reachability. frames = null can be enough in 99.9% cases, // but we are extra careful to make tests non-flaky: considering about the case that array is captured // somewhere (like DFG constants). function nukeArray(array) { for (let index = 0; index < array.length; ++index) array[index] = null; array.length = 0; } async function testDocumentIsNotLeaked(init, options = {}) { let gcCount = options.gcCount ?? 50; let documentCount = options.documentCount ?? 20; let additionalCheck = options.additionalCheck ?? function () { return true; }; function waitFor(duration) { return new Promise((resolve) => setTimeout(resolve, duration)); } let frameIdentifiers = await init(documentCount); for (let counter = 0; counter < gcCount; ++counter) { for (let i = 0; i < documentCount; ++i) { let frameIdentifier = frameIdentifiers[i]; if (!internals.isDocumentAlive(frameIdentifier) && additionalCheck()) return "Document did not leak"; } gc(); await waitFor(50); } throw new Error("Document is leaked"); }