diff --git a/js/xpconnect/tests/mochitest/finalizationGroup_worker.js b/js/xpconnect/tests/mochitest/finalizationGroup_worker.js new file mode 100644 index 000000000000..fddf68a480a9 --- /dev/null +++ b/js/xpconnect/tests/mochitest/finalizationGroup_worker.js @@ -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; +} diff --git a/js/xpconnect/tests/mochitest/mochitest.ini b/js/xpconnect/tests/mochitest/mochitest.ini index db00d80b48ae..d57b3dceb8b5 100644 --- a/js/xpconnect/tests/mochitest/mochitest.ini +++ b/js/xpconnect/tests/mochitest/mochitest.ini @@ -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 diff --git a/js/xpconnect/tests/mochitest/test_finalizationGroup.html b/js/xpconnect/tests/mochitest/test_finalizationGroup.html new file mode 100644 index 000000000000..635bdbef1cf4 --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_finalizationGroup.html @@ -0,0 +1,112 @@ + + + + + Test FinalizationGroup works in the browser + + + + + diff --git a/js/xpconnect/tests/mochitest/test_finalizationGroupInWorker.html b/js/xpconnect/tests/mochitest/test_finalizationGroupInWorker.html new file mode 100644 index 000000000000..551dd2e011d4 --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_finalizationGroupInWorker.html @@ -0,0 +1,40 @@ + + + + + Test FinalizationGroup works in workers + + + + +