зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1596756 - Add browser tests for FinalizationGroup r=mccr8
These are mochitests because there's currently no way to trigger a GC from WPT. I tried to do this with xpcshell tests but I couldn't get the pref to enable weak refs to work. Differential Revision: https://phabricator.services.mozilla.com/D59375 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
18a075eec7
Коммит
0f4b542755
|
@ -0,0 +1,96 @@
|
|||
let holdings1 = [];
|
||||
let holdings2 = [];
|
||||
let holdings3 = [];
|
||||
let holdings4 = [];
|
||||
let holdings5 = [];
|
||||
|
||||
onmessage = (event) => {
|
||||
switch (event.data) {
|
||||
case 'startTest':
|
||||
startTest();
|
||||
break;
|
||||
case 'checkResults':
|
||||
checkResults();
|
||||
break;
|
||||
default:
|
||||
throw "Unknown message";
|
||||
}
|
||||
};
|
||||
|
||||
function startTest() {
|
||||
// Group with no registered objects.
|
||||
let group1 = new FinalizationGroup(i => holdings1 = [...i]);
|
||||
|
||||
// Group with three registered objects.
|
||||
let group2 = new FinalizationGroup(i => holdings2 = [...i]);
|
||||
group2.register({}, 1);
|
||||
group2.register({}, 2);
|
||||
group2.register({}, 3);
|
||||
|
||||
// Group with registered object that is then unregistered.
|
||||
let group3 = new FinalizationGroup(i => holdings3 = [...i]);
|
||||
let token3 = {}
|
||||
group3.register({}, 1, token3);
|
||||
group3.unregister(token3);
|
||||
|
||||
// Group with registered object that doesn't die.
|
||||
let group4 = new FinalizationGroup(i => holdings4 = [...i]);
|
||||
let object4 = {};
|
||||
group4.register(object4, 1);
|
||||
|
||||
// Group observing cyclic JS data structure.
|
||||
let group5 = new FinalizationGroup(i => holdings5 = [...i]);
|
||||
group5.register(makeJSCycle(4), 5);
|
||||
|
||||
const { gc } = getJSTestingFunctions();
|
||||
gc();
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
checkNoCallbacks();
|
||||
});
|
||||
|
||||
postMessage('started');
|
||||
}
|
||||
|
||||
function checkNoCallbacks() {
|
||||
is(holdings1.length, 0);
|
||||
is(holdings2.length, 0);
|
||||
is(holdings3.length, 0);
|
||||
is(holdings4.length, 0);
|
||||
is(holdings5.length, 0);
|
||||
}
|
||||
|
||||
function checkResults() {
|
||||
is(holdings1.length, 0);
|
||||
|
||||
let result = holdings2.sort((a, b) => a - b);
|
||||
is(result.length, 3);
|
||||
is(result[0], 1);
|
||||
is(result[1], 2);
|
||||
is(result[2], 3);
|
||||
|
||||
is(holdings3.length, 0);
|
||||
is(holdings4.length, 0);
|
||||
|
||||
is(holdings5.length, 1);
|
||||
is(holdings5[0], 5);
|
||||
|
||||
postMessage('passed');
|
||||
}
|
||||
|
||||
function is(a, b) {
|
||||
if (a !== b) {
|
||||
throw `Expected ${b} but got ${a}`;
|
||||
}
|
||||
}
|
||||
|
||||
function makeJSCycle(size) {
|
||||
let first = {};
|
||||
let current = first;
|
||||
for (let i = 0; i < size; i++) {
|
||||
current.next = {};
|
||||
current = current.next;
|
||||
}
|
||||
current.next = first;
|
||||
return first;
|
||||
}
|
|
@ -36,6 +36,9 @@ support-files =
|
|||
inner.html
|
||||
test1_bug629331.html
|
||||
test2_bug629331.html
|
||||
finalizationGroup_worker.js
|
||||
prefs =
|
||||
javascript.options.experimental.weakrefs=true
|
||||
|
||||
[test_bug384632.html]
|
||||
[test_bug390488.html]
|
||||
|
@ -110,3 +113,7 @@ skip-if = (debug == false)
|
|||
support-files =
|
||||
../../../../dom/tests/mochitest/fetch/test_fetch_basic.js
|
||||
[test_weakmaps.html]
|
||||
[test_finalizationGroup.html]
|
||||
skip-if = !nightly_build
|
||||
[test_finalizationGroupInWorker.html]
|
||||
skip-if = !nightly_build
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test FinalizationGroup works in the browser</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript">
|
||||
function go() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Group with no registered objects.
|
||||
let holdings1 = [];
|
||||
let group1 = new FinalizationGroup(i => holdings1 = [...i]);
|
||||
|
||||
// Group with three registered objects.
|
||||
let holdings2 = [];
|
||||
let group2 = new FinalizationGroup(i => holdings2 = [...i]);
|
||||
group2.register({}, 1);
|
||||
group2.register({}, 2);
|
||||
group2.register({}, 3);
|
||||
|
||||
// Group with registered object that is then unregistered.
|
||||
let holdings3 = [];
|
||||
let group3 = new FinalizationGroup(i => holdings3 = [...i]);
|
||||
let token3 = {}
|
||||
group3.register({}, 1, token3);
|
||||
group3.unregister(token3);
|
||||
|
||||
// Group with registered object that doesn't die.
|
||||
let holdings4 = [];
|
||||
let group4 = new FinalizationGroup(i => holdings4 = [...i]);
|
||||
let object4 = {};
|
||||
group4.register(object4, 1);
|
||||
|
||||
// Group observing cyclic JS data structure.
|
||||
let holdings5 = [];
|
||||
let group5 = new FinalizationGroup(i => holdings5 = [...i]);
|
||||
group5.register(makeJSCycle(4), 5);
|
||||
|
||||
// Group observing cyclic DOM/JS data structure.
|
||||
let holdings6 = [];
|
||||
let group6 = new FinalizationGroup(i => holdings6 = [...i]);
|
||||
group6.register(makeDOMCycle(4), 6);
|
||||
|
||||
// Need to run full GC/CC/GC cycle to collect cyclic garbage through DOM
|
||||
// and JS heaps.
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
SpecialPowers.DOMWindowUtils.cycleCollect();
|
||||
SpecialPowers.DOMWindowUtils.garbageCollect();
|
||||
|
||||
// Microtasks are run before cleanup callbacks.
|
||||
Promise.resolve().then(() => {
|
||||
is(holdings1.length, 0);
|
||||
is(holdings2.length, 0);
|
||||
is(holdings3.length, 0);
|
||||
is(holdings4.length, 0);
|
||||
is(holdings5.length, 0);
|
||||
is(holdings6.length, 0);
|
||||
});
|
||||
|
||||
// setTimeout queues a task which will run after cleanup callbacks.
|
||||
setTimeout(() => {
|
||||
is(holdings1.length, 0);
|
||||
|
||||
let result = holdings2.sort((a, b) => a - b);
|
||||
is(result.length, 3);
|
||||
is(result[0], 1);
|
||||
is(result[1], 2);
|
||||
is(result[2], 3);
|
||||
|
||||
is(holdings3.length, 0);
|
||||
is(holdings4.length, 0);
|
||||
|
||||
is(holdings5.length, 1);
|
||||
is(holdings5[0], 5);
|
||||
|
||||
is(holdings6.length, 1);
|
||||
is(holdings6[0], 6);
|
||||
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function makeJSCycle(size) {
|
||||
let first = {};
|
||||
let current = first;
|
||||
for (let i = 0; i < size; i++) {
|
||||
current.next = {};
|
||||
current = current.next;
|
||||
}
|
||||
current.next = first;
|
||||
return first;
|
||||
}
|
||||
|
||||
function makeDOMCycle(size) {
|
||||
let first = {};
|
||||
let current = first;
|
||||
for (let i = 0; i < size; i++) {
|
||||
if (i % 2 === 0) {
|
||||
current.next = document.createElement("div");
|
||||
} else {
|
||||
current.next = {};
|
||||
}
|
||||
current = current.next;
|
||||
}
|
||||
current.next = first;
|
||||
return first;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="go()"></body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test FinalizationGroup works in workers</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript">
|
||||
function go() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let worker = new Worker('finalizationGroup_worker.js');
|
||||
|
||||
worker.onevent = (event) => {
|
||||
console.log(event.message);
|
||||
throw event.error;
|
||||
};
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
switch (event.data) {
|
||||
case 'started':
|
||||
worker.postMessage('checkResults');
|
||||
break;
|
||||
|
||||
case 'passed':
|
||||
ok(true, "Tests passed");
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(event.data);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
worker.postMessage('startTest');
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="go()"></body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче