diff options
Diffstat (limited to 'devtools/shared/worker')
-rw-r--r-- | devtools/shared/worker/tests/browser/browser_worker-03.js | 4 | ||||
-rw-r--r-- | devtools/shared/worker/worker.js | 316 |
2 files changed, 148 insertions, 172 deletions
diff --git a/devtools/shared/worker/tests/browser/browser_worker-03.js b/devtools/shared/worker/tests/browser/browser_worker-03.js index 185ba92d5e..34e7688e73 100644 --- a/devtools/shared/worker/tests/browser/browser_worker-03.js +++ b/devtools/shared/worker/tests/browser/browser_worker-03.js @@ -17,11 +17,11 @@ function squarePromise(x) { return new Promise(resolve => resolve(x * x)); } -function squareError(x) { +function squareError() { return new Error("Nope"); } -function squarePromiseReject(x) { +function squarePromiseReject() { return new Promise((_, reject) => reject("Nope")); } diff --git a/devtools/shared/worker/worker.js b/devtools/shared/worker/worker.js index 4d753a928e..f9e5c7f4f0 100644 --- a/devtools/shared/worker/worker.js +++ b/devtools/shared/worker/worker.js @@ -10,15 +10,7 @@ if (this.module && module.id.includes("worker")) { // require const dumpn = require("devtools/shared/DevToolsUtils").dumpn; - factory.call( - this, - require, - exports, - module, - { Cc, Ci, Cu }, - ChromeWorker, - dumpn - ); + factory.call(this, require, exports, module, ChromeWorker, dumpn); } else { // Cu.import const { require } = ChromeUtils.importESModule( @@ -26,173 +18,157 @@ ); this.isWorker = false; this.console = console; - factory.call( - this, - require, - this, - { exports: this }, - { Cc, Ci, Cu }, - ChromeWorker, - null - ); + factory.call(this, require, this, { exports: this }, ChromeWorker, null); this.EXPORTED_SYMBOLS = ["DevToolsWorker", "workerify"]; } -}).call( - this, - function (require, exports, module, { Ci, Cc }, 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); +}).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" + ); } - 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." + 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) ); - // 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(); + } + 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); + } }; - 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"); + 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()});`; - } } -); +}); |