summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js170
1 files changed, 170 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js
new file mode 100644
index 0000000000..dd47744a97
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_ports_gc.js
@@ -0,0 +1,170 @@
+"use strict";
+
+let gcExperimentAPIs = {
+ gcHelper: {
+ schema: "schema.json",
+ child: {
+ scopes: ["addon_child"],
+ script: "child.js",
+ paths: [["gcHelper"]],
+ },
+ },
+};
+
+let gcExperimentFiles = {
+ "schema.json": JSON.stringify([
+ {
+ namespace: "gcHelper",
+ functions: [
+ {
+ name: "forceGarbageCollect",
+ type: "function",
+ parameters: [],
+ async: true,
+ },
+ {
+ name: "registerWitness",
+ type: "function",
+ parameters: [
+ {
+ name: "obj",
+ // Expected type is "object", but using "any" here to ensure that
+ // the parameter is untouched (not normalized).
+ type: "any",
+ },
+ ],
+ returns: { type: "number" },
+ },
+ {
+ name: "isGarbageCollected",
+ type: "function",
+ parameters: [
+ {
+ name: "witnessId",
+ description: "return value of registerWitness",
+ type: "number",
+ },
+ ],
+ returns: { type: "boolean" },
+ },
+ ],
+ },
+ ]),
+ "child.js": () => {
+ let { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+ );
+ /* globals ExtensionAPI */
+ this.gcHelper = class extends ExtensionAPI {
+ getAPI(context) {
+ let witnesses = new Map();
+ return {
+ gcHelper: {
+ async forceGarbageCollect() {
+ // Logic copied from test_ext_contexts_gc.js
+ for (let i = 0; i < 3; ++i) {
+ Cu.forceShrinkingGC();
+ Cu.forceCC();
+ Cu.forceGC();
+ await new Promise(resolve => setTimeout(resolve, 0));
+ }
+ },
+ registerWitness(obj) {
+ let witnessId = witnesses.size;
+ witnesses.set(witnessId, Cu.getWeakReference(obj));
+ return witnessId;
+ },
+ isGarbageCollected(witnessId) {
+ return witnesses.get(witnessId).get() === null;
+ },
+ },
+ };
+ }
+ };
+ },
+};
+
+// Verify that the experiment is working as intended before using it in tests.
+add_task(async function test_gc_experiment() {
+ let extension = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+ manifest: {
+ experiment_apis: gcExperimentAPIs,
+ },
+ files: gcExperimentFiles,
+ async background() {
+ let obj1 = {};
+ let obj2 = {};
+ let witness1 = browser.gcHelper.registerWitness(obj1);
+ let witness2 = browser.gcHelper.registerWitness(obj2);
+ obj1 = null;
+ await browser.gcHelper.forceGarbageCollect();
+ browser.test.assertTrue(
+ browser.gcHelper.isGarbageCollected(witness1),
+ "obj1 should have been garbage-collected"
+ );
+ browser.test.assertFalse(
+ browser.gcHelper.isGarbageCollected(witness2),
+ "obj2 should not have been garbage-collected"
+ );
+
+ browser.test.sendMessage("done");
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("done");
+ await extension.unload();
+});
+
+add_task(async function test_port_gc() {
+ let extension = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+ manifest: {
+ experiment_apis: gcExperimentAPIs,
+ },
+ files: gcExperimentFiles,
+ async background() {
+ let witnessPortSender;
+ let witnessPortReceiver;
+
+ browser.runtime.onConnect.addListener(port => {
+ browser.test.assertEq("daName", port.name, "expected port");
+ witnessPortReceiver = browser.gcHelper.registerWitness(port);
+ port.disconnect();
+ });
+
+ // runtime.connect() only triggers onConnect for different contexts,
+ // so create a frame to have a different context.
+ // A blank frame in a moz-extension:-document will have access to the
+ // extension APIs.
+ let frameWindow = await new Promise(resolve => {
+ let f = document.createElement("iframe");
+ f.onload = () => resolve(f.contentWindow);
+ document.body.append(f);
+ });
+ await new Promise(resolve => {
+ let port = frameWindow.browser.runtime.connect({ name: "daName" });
+ witnessPortSender = browser.gcHelper.registerWitness(port);
+ port.onDisconnect.addListener(() => resolve());
+ });
+
+ await browser.gcHelper.forceGarbageCollect();
+
+ browser.test.assertTrue(
+ browser.gcHelper.isGarbageCollected(witnessPortSender),
+ "runtime.connect() port should have been garbage-collected"
+ );
+ browser.test.assertTrue(
+ browser.gcHelper.isGarbageCollected(witnessPortReceiver),
+ "runtime.onConnect port should have been garbage-collected"
+ );
+
+ browser.test.sendMessage("done");
+ },
+ });
+
+ await extension.startup();
+ await extension.awaitMessage("done");
+ await extension.unload();
+});