summaryrefslogtreecommitdiffstats
path: root/devtools/shared/worker
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/worker')
-rw-r--r--devtools/shared/worker/moz.build2
-rw-r--r--devtools/shared/worker/tests/browser/browser_worker-01.js22
-rw-r--r--devtools/shared/worker/tests/browser/browser_worker-02.js6
-rw-r--r--devtools/shared/worker/tests/browser/browser_worker-03.js4
-rw-r--r--devtools/shared/worker/worker.js174
-rw-r--r--devtools/shared/worker/worker.sys.mjs157
6 files changed, 171 insertions, 194 deletions
diff --git a/devtools/shared/worker/moz.build b/devtools/shared/worker/moz.build
index 79a71ca5ce..87dfbbedf7 100644
--- a/devtools/shared/worker/moz.build
+++ b/devtools/shared/worker/moz.build
@@ -9,5 +9,5 @@ if CONFIG["MOZ_BUILD_APP"] != "mobile/android":
DevToolsModules(
"helper.js",
- "worker.js",
+ "worker.sys.mjs",
)
diff --git a/devtools/shared/worker/tests/browser/browser_worker-01.js b/devtools/shared/worker/tests/browser/browser_worker-01.js
index a8dafcf4cb..f8323e218e 100644
--- a/devtools/shared/worker/tests/browser/browser_worker-01.js
+++ b/devtools/shared/worker/tests/browser/browser_worker-01.js
@@ -3,8 +3,9 @@
"use strict";
-// Tests that the devtools/shared/worker communicates properly
-// as both CommonJS module and as a JSM.
+const { DevToolsWorker, workerify } = ChromeUtils.importESModule(
+ "resource://devtools/shared/worker/worker.sys.mjs"
+);
const BUFFER_SIZE = 8;
@@ -15,22 +16,16 @@ registerCleanupFunction(function () {
add_task(async function () {
// Test both CJS and JSM versions
- await testWorker("JSM", () =>
- ChromeUtils.import("resource://devtools/shared/worker/worker.js")
- );
- await testWorker("CommonJS", () =>
- require("resource://devtools/shared/worker/worker.js")
- );
+ await testWorker();
await testTransfer();
});
-async function testWorker(context, workerFactory) {
+async function testWorker() {
// Needed for blob:null
Services.prefs.setBoolPref(
"security.allow_parent_unrestricted_js_loads",
true
);
- const { DevToolsWorker, workerify } = workerFactory();
const blob = new Blob(
[
@@ -71,13 +66,13 @@ createTask(self, "groupByField", function({
is(
Object.keys(results.groups).join(","),
"France,Nigeria",
- `worker should have returned the expected result in ${context}`
+ `worker should have returned the expected result`
);
URL.revokeObjectURL(WORKER_URL);
const fn = workerify(x => x * x);
- is(await fn(5), 25, `workerify works in ${context}`);
+ is(await fn(5), 25, `workerify works`);
fn.destroy();
worker.destroy();
@@ -88,9 +83,6 @@ async function testTransfer() {
"security.allow_parent_unrestricted_js_loads",
true
);
- const { workerify } = ChromeUtils.import(
- "resource://devtools/shared/worker/worker.js"
- );
const workerFn = workerify(({ buf }) => buf.byteLength);
const buf = new ArrayBuffer(BUFFER_SIZE);
diff --git a/devtools/shared/worker/tests/browser/browser_worker-02.js b/devtools/shared/worker/tests/browser/browser_worker-02.js
index 80c50cf887..c051946aee 100644
--- a/devtools/shared/worker/tests/browser/browser_worker-02.js
+++ b/devtools/shared/worker/tests/browser/browser_worker-02.js
@@ -5,9 +5,9 @@
// Tests errors are handled properly by the DevToolsWorker.
-const {
- DevToolsWorker,
-} = require("resource://devtools/shared/worker/worker.js");
+const { DevToolsWorker } = ChromeUtils.importESModule(
+ "resource://devtools/shared/worker/worker.sys.mjs"
+);
const blob = new Blob(
[
diff --git a/devtools/shared/worker/tests/browser/browser_worker-03.js b/devtools/shared/worker/tests/browser/browser_worker-03.js
index 34e7688e73..9a7659979e 100644
--- a/devtools/shared/worker/tests/browser/browser_worker-03.js
+++ b/devtools/shared/worker/tests/browser/browser_worker-03.js
@@ -8,7 +8,9 @@
//
// And tests `workerify` by doing so.
-const { workerify } = require("resource://devtools/shared/worker/worker.js");
+const { workerify } = ChromeUtils.importESModule(
+ "resource://devtools/shared/worker/worker.sys.mjs"
+);
function square(x) {
return x * x;
}
diff --git a/devtools/shared/worker/worker.js b/devtools/shared/worker/worker.js
deleted file mode 100644
index f9e5c7f4f0..0000000000
--- a/devtools/shared/worker/worker.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/* global ChromeWorker */
-
-(function (factory) {
- if (this.module && module.id.includes("worker")) {
- // require
- const dumpn = require("devtools/shared/DevToolsUtils").dumpn;
- factory.call(this, require, exports, module, ChromeWorker, dumpn);
- } else {
- // Cu.import
- const { require } = ChromeUtils.importESModule(
- "resource://devtools/shared/loader/Loader.sys.mjs"
- );
- this.isWorker = false;
- this.console = console;
- factory.call(this, require, this, { exports: this }, ChromeWorker, null);
- this.EXPORTED_SYMBOLS = ["DevToolsWorker", "workerify"];
- }
-}).call(this, function (require, exports, module, ChromeWorker, dumpn) {
- let MESSAGE_COUNTER = 0;
-
- /**
- * Creates a wrapper around a ChromeWorker, providing easy
- * communication to offload demanding tasks. The corresponding URL
- * must implement the interface provided by `devtools/shared/worker/helper`.
- *
- * @param {string} url
- * The URL of the worker.
- * @param Object opts
- * An option with the following optional fields:
- * - name: a name that will be printed with logs
- * - verbose: log incoming and outgoing messages
- */
- function DevToolsWorker(url, opts) {
- opts = opts || {};
- this._worker = new ChromeWorker(url);
- this._verbose = opts.verbose;
- this._name = opts.name;
-
- this._worker.addEventListener("error", this.onError);
- }
- exports.DevToolsWorker = DevToolsWorker;
-
- /**
- * Performs the given task in a chrome worker, passing in data.
- * Returns a promise that resolves when the task is completed, resulting in
- * the return value of the task.
- *
- * @param {string} task
- * The name of the task to execute in the worker.
- * @param {any} data
- * Data to be passed into the task implemented by the worker.
- * @param {undefined|Array} transfer
- * Optional array of transferable objects to transfer ownership of.
- * @return {Promise}
- */
- DevToolsWorker.prototype.performTask = function (task, data, transfer) {
- if (this._destroyed) {
- return Promise.reject(
- "Cannot call performTask on a destroyed DevToolsWorker"
- );
- }
- const worker = this._worker;
- const id = ++MESSAGE_COUNTER;
- const payload = { task, id, data };
-
- if (this._verbose && dumpn) {
- dumpn(
- "Sending message to worker" +
- (this._name ? " (" + this._name + ")" : "") +
- ": " +
- JSON.stringify(payload, null, 2)
- );
- }
- worker.postMessage(payload, transfer);
-
- return new Promise((resolve, reject) => {
- const listener = ({ data: result }) => {
- if (this._verbose && dumpn) {
- dumpn(
- "Received message from worker" +
- (this._name ? " (" + this._name + ")" : "") +
- ": " +
- JSON.stringify(result, null, 2)
- );
- }
-
- if (result.id !== id) {
- return;
- }
- worker.removeEventListener("message", listener);
- if (result.error) {
- reject(result.error);
- } else {
- resolve(result.response);
- }
- };
-
- worker.addEventListener("message", listener);
- });
- };
-
- /**
- * Terminates the underlying worker. Use when no longer needing the worker.
- */
- DevToolsWorker.prototype.destroy = function () {
- this._worker.terminate();
- this._worker = null;
- this._destroyed = true;
- };
-
- DevToolsWorker.prototype.onError = function ({ message, filename, lineno }) {
- dump(new Error(message + " @ " + filename + ":" + lineno) + "\n");
- };
-
- /**
- * Takes a function and returns a Worker-wrapped version of the same function.
- * Returns a promise upon resolution.
- * @see `./devtools/shared/shared/tests/browser/browser_devtools-worker-03.js
- *
- * ⚠ This should only be used for tests or A/B testing performance ⚠
- *
- * The original function must:
- *
- * Be a pure function, that is, not use any variables not declared within the
- * function, or its arguments.
- *
- * Return a value or a promise.
- *
- * Note any state change in the worker will not affect the callee's context.
- *
- * @param {function} fn
- * @return {function}
- */
- function workerify(fn) {
- console.warn(
- "`workerify` should only be used in tests or measuring performance. " +
- "This creates an object URL on the browser window, and should not be " +
- "used in production."
- );
- // Fetch modules here as we don't want to include it normally.
- const { URL, Blob } = Services.wm.getMostRecentWindow("navigator:browser");
- const stringifiedFn = createWorkerString(fn);
- const blob = new Blob([stringifiedFn]);
- const url = URL.createObjectURL(blob);
- const worker = new DevToolsWorker(url);
-
- const wrapperFn = (data, transfer) =>
- worker.performTask("workerifiedTask", data, transfer);
-
- wrapperFn.destroy = function () {
- URL.revokeObjectURL(url);
- worker.destroy();
- };
-
- return wrapperFn;
- }
- exports.workerify = workerify;
-
- /**
- * Takes a function, and stringifies it, attaching the worker-helper.js
- * boilerplate hooks.
- */
- function createWorkerString(fn) {
- return `importScripts("resource://gre/modules/workers/require.js");
- const { createTask } = require("resource://devtools/shared/worker/helper.js");
- createTask(self, "workerifiedTask", ${fn.toString()});`;
- }
-});
diff --git a/devtools/shared/worker/worker.sys.mjs b/devtools/shared/worker/worker.sys.mjs
new file mode 100644
index 0000000000..4b8840dde2
--- /dev/null
+++ b/devtools/shared/worker/worker.sys.mjs
@@ -0,0 +1,157 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* global ChromeWorker */
+
+let MESSAGE_COUNTER = 0;
+
+function dumpn(_msg) {
+ // dump(msg + "\n");
+}
+
+/**
+ * Creates a wrapper around a ChromeWorker, providing easy
+ * communication to offload demanding tasks. The corresponding URL
+ * must implement the interface provided by `devtools/shared/worker/helper`.
+ *
+ * @param {string} url
+ * The URL of the worker.
+ * @param Object opts
+ * An option with the following optional fields:
+ * - name: a name that will be printed with logs
+ * - verbose: log incoming and outgoing messages
+ */
+export function DevToolsWorker(url, opts) {
+ opts = opts || {};
+ this._worker = new ChromeWorker(url);
+ this._verbose = opts.verbose;
+ this._name = opts.name;
+
+ this._worker.addEventListener("error", this.onError);
+}
+
+/**
+ * Performs the given task in a chrome worker, passing in data.
+ * Returns a promise that resolves when the task is completed, resulting in
+ * the return value of the task.
+ *
+ * @param {string} task
+ * The name of the task to execute in the worker.
+ * @param {any} data
+ * Data to be passed into the task implemented by the worker.
+ * @param {undefined|Array} transfer
+ * Optional array of transferable objects to transfer ownership of.
+ * @return {Promise}
+ */
+DevToolsWorker.prototype.performTask = function (task, data, transfer) {
+ if (this._destroyed) {
+ return Promise.reject(
+ "Cannot call performTask on a destroyed DevToolsWorker"
+ );
+ }
+ const worker = this._worker;
+ const id = ++MESSAGE_COUNTER;
+ const payload = { task, id, data };
+
+ if (this._verbose && dumpn) {
+ dumpn(
+ "Sending message to worker" +
+ (this._name ? " (" + this._name + ")" : "") +
+ ": " +
+ JSON.stringify(payload, null, 2)
+ );
+ }
+ worker.postMessage(payload, transfer);
+
+ return new Promise((resolve, reject) => {
+ const listener = ({ data: result }) => {
+ if (this._verbose && dumpn) {
+ dumpn(
+ "Received message from worker" +
+ (this._name ? " (" + this._name + ")" : "") +
+ ": " +
+ JSON.stringify(result, null, 2)
+ );
+ }
+
+ if (result.id !== id) {
+ return;
+ }
+ worker.removeEventListener("message", listener);
+ if (result.error) {
+ reject(result.error);
+ } else {
+ resolve(result.response);
+ }
+ };
+
+ worker.addEventListener("message", listener);
+ });
+};
+
+/**
+ * Terminates the underlying worker. Use when no longer needing the worker.
+ */
+DevToolsWorker.prototype.destroy = function () {
+ this._worker.terminate();
+ this._worker = null;
+ this._destroyed = true;
+};
+
+DevToolsWorker.prototype.onError = function ({ message, filename, lineno }) {
+ dump(new Error(message + " @ " + filename + ":" + lineno) + "\n");
+};
+
+/**
+ * Takes a function and returns a Worker-wrapped version of the same function.
+ * Returns a promise upon resolution.
+ * @see `./devtools/shared/shared/tests/browser/browser_devtools-worker-03.js
+ *
+ * ⚠ This should only be used for tests or A/B testing performance ⚠
+ *
+ * The original function must:
+ *
+ * Be a pure function, that is, not use any variables not declared within the
+ * function, or its arguments.
+ *
+ * Return a value or a promise.
+ *
+ * Note any state change in the worker will not affect the callee's context.
+ *
+ * @param {function} fn
+ * @return {function}
+ */
+export function workerify(fn) {
+ console.warn(
+ "`workerify` should only be used in tests or measuring performance. " +
+ "This creates an object URL on the browser window, and should not be " +
+ "used in production."
+ );
+ // Fetch modules here as we don't want to include it normally.
+ const { URL, Blob } = Services.wm.getMostRecentWindow("navigator:browser");
+ const stringifiedFn = createWorkerString(fn);
+ const blob = new Blob([stringifiedFn]);
+ const url = URL.createObjectURL(blob);
+ const worker = new DevToolsWorker(url);
+
+ const wrapperFn = (data, transfer) =>
+ worker.performTask("workerifiedTask", data, transfer);
+
+ wrapperFn.destroy = function () {
+ URL.revokeObjectURL(url);
+ worker.destroy();
+ };
+
+ return wrapperFn;
+}
+
+/**
+ * Takes a function, and stringifies it, attaching the worker-helper.js
+ * boilerplate hooks.
+ */
+function createWorkerString(fn) {
+ return `importScripts("resource://gre/modules/workers/require.js");
+ const { createTask } = require("resource://devtools/shared/worker/helper.js");
+ createTask(self, "workerifiedTask", ${fn.toString()});`;
+}