diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /devtools/shared/worker/helper.js | |
parent | Initial commit. (diff) | |
download | firefox-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 'devtools/shared/worker/helper.js')
-rw-r--r-- | devtools/shared/worker/helper.js | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/devtools/shared/worker/helper.js b/devtools/shared/worker/helper.js new file mode 100644 index 0000000000..20ccd3de5e --- /dev/null +++ b/devtools/shared/worker/helper.js @@ -0,0 +1,138 @@ +/* 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/. */ + +/* eslint-env amd */ + +"use strict"; + +/* global workerHelper */ +/* exported workerHelper */ +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(factory); + } else if (typeof exports === "object") { + module.exports = factory(); + } else { + root.workerHelper = factory(); + } +})(this, function () { + /** + * This file is to only be included by ChromeWorkers. This exposes + * a `createTask` function to workers to register tasks for communication + * back to `devtools/shared/worker`. + * + * Tasks can be send their responses via a return value, either a primitive + * or a promise. + * + * createTask(self, "average", function (data) { + * return data.reduce((sum, val) => sum + val, 0) / data.length; + * }); + * + * createTask(self, "average", function (data) { + * return new Promise((resolve, reject) => { + * resolve(data.reduce((sum, val) => sum + val, 0) / data.length); + * }); + * }); + * + * + * Errors: + * + * Returning an Error value, or if the returned promise is rejected, this + * propagates to the DevToolsWorker as a rejected promise. If an error is + * thrown in a synchronous function, that error is also propagated. + */ + + /** + * Takes a worker's `self` object, a task name, and a function to + * be called when that task is called. The task is called with the + * passed in data as the first argument + * + * @param {object} self + * @param {string} name + * @param {function} fn + */ + function createTask(self, name, fn) { + // Store a hash of task name to function on the Worker + if (!self._tasks) { + self._tasks = {}; + } + + // Create the onmessage handler if not yet created. + if (!self.onmessage) { + self.onmessage = createHandler(self); + } + + // Store the task on the worker. + self._tasks[name] = fn; + } + + /** + * Creates the `self.onmessage` handler for a Worker. + * + * @param {object} self + * @return {function} + */ + function createHandler(self) { + return function (e) { + const { id, task, data } = e.data; + const taskFn = self._tasks[task]; + + if (!taskFn) { + self.postMessage({ id, error: `Task "${task}" not found in worker.` }); + return; + } + + try { + handleResponse(taskFn(data)); + } catch (ex) { + handleError(ex); + } + + function handleResponse(response) { + // If a promise + if (response && typeof response.then === "function") { + response.then( + val => self.postMessage({ id, response: val }), + handleError + ); + } else if (response instanceof Error) { + // If an error object + handleError(response); + } else { + // If anything else + self.postMessage({ id, response }); + } + } + + function handleError(error = "Error") { + try { + // First, try and structured clone the error across directly. + self.postMessage({ id, error }); + } catch (x) { + // We could not clone whatever error value was given. Do our best to + // stringify it. + let errorString = `Error while performing task "${task}": `; + + try { + errorString += error.toString(); + } catch (ex) { + errorString += "<could not stringify error>"; + } + + if ("stack" in error) { + try { + errorString += "\n" + error.stack; + } catch (err) { + // Do nothing + } + } + + self.postMessage({ id, error: errorString }); + } + } + }; + } + + return { createTask }; +}); |