diff options
Diffstat (limited to 'dom/events/test/test_event_handler_cc.html')
-rw-r--r-- | dom/events/test/test_event_handler_cc.html | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/dom/events/test/test_event_handler_cc.html b/dom/events/test/test_event_handler_cc.html new file mode 100644 index 0000000000..bc2f504b12 --- /dev/null +++ b/dom/events/test/test_event_handler_cc.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for cycle collection of event handlers</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> + <script> + SimpleTest.waitForExplicitFinish(); + + function listener() {} + + function make_weak_ref(obj) { + let m = new WeakMap; + m.set(obj, {}); + return m; + } + + function weak_ref_dead(r) { + return !SpecialPowers.nondeterministicGetWeakMapKeys(r).length; + } + + function setupTarget1() { + let ifr = document.getElementById("target1"); + let doc = ifr.contentDocument; + let b = doc.createElement("button"); + doc.body.appendChild(b); + b.onclick = listener; + ifr.remove(); + return make_weak_ref(b); + } + + function setupTarget2() { + let ifr = document.getElementById("target2"); + let doc = ifr.contentDocument; + let b = doc.createElement("button"); + doc.body.appendChild(b); + let setFunc = new ifr.contentWindow.Function(` + var b = document.querySelector("button"); + var proto = parent.HTMLElement.prototype; + var setter = Object.getOwnPropertyDescriptor(proto, "onclick").set; + // Here the current global (and hence CallbackObject global) will be + // the parent, the callback will be a known-live thing from the + // parent, but the incumbent global will be the child. + setter.call(b, parent.listener); + `); + setFunc(); + ifr.remove(); + return make_weak_ref(b); + } + + var ref1; + var ref2; + var maxCounter = 10; + + function GCCCUntilCollected() { + SpecialPowers.exactGC(function () { + SpecialPowers.forceCC(); + SpecialPowers.forceGC(); + SpecialPowers.forceGC(); + + if ((!weak_ref_dead(ref1) || !weak_ref_dead(ref2)) && --maxCounter > 0) { + requestIdleCallback(GCCCUntilCollected, {timeout: 250}); + return; + } + + ok(weak_ref_dead(ref1), + "Should collect cycle through callback global"); + ok(weak_ref_dead(ref2), + "Should collect cycle through incumbent global"); + + SimpleTest.finish(); + }); + } + + addLoadEvent(function() { + ref1 = setupTarget1(); + ref2 = setupTarget2(); + GCCCUntilCollected(); + }); + </script> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"></div> +<iframe id="target1"></iframe> +<iframe id="target2"></iframe> +<pre id="test"></pre> +</body> +</html> |