summaryrefslogtreecommitdiff
path: root/devtools/shared/worker/worker.js
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /devtools/shared/worker/worker.js
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloaduxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/shared/worker/worker.js')
-rw-r--r--devtools/shared/worker/worker.js171
1 files changed, 171 insertions, 0 deletions
diff --git a/devtools/shared/worker/worker.js b/devtools/shared/worker/worker.js
new file mode 100644
index 0000000000..9ed9afa279
--- /dev/null
+++ b/devtools/shared/worker/worker.js
@@ -0,0 +1,171 @@
+/* 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.indexOf("worker") >= 0) {
+ // require
+ const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
+ const dumpn = require("devtools/shared/DevToolsUtils").dumpn;
+ factory.call(this, require, exports, module, { Cc, Ci, Cu }, ChromeWorker, dumpn);
+ } else {
+ // Cu.import
+ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+ const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
+ this.isWorker = false;
+ this.Promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+ this.console = Cu.import("resource://gre/modules/Console.jsm", {}).console;
+ factory.call(
+ this, require, this, { exports: this },
+ { Cc, Ci, Cu }, ChromeWorker, null
+ );
+ this.EXPORTED_SYMBOLS = ["DevToolsWorker"];
+ }
+}).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`.
+ *
+ * @see `./devtools/client/shared/widgets/GraphsWorker.js`
+ *
+ * @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, false);
+ }
+ 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.
+ * @return {Promise}
+ */
+ DevToolsWorker.prototype.performTask = function (task, data) {
+ if (this._destroyed) {
+ return Promise.reject("Cannot call performTask on a destroyed DevToolsWorker");
+ }
+ let worker = this._worker;
+ let id = ++MESSAGE_COUNTER;
+ let 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);
+
+ return new Promise((resolve, reject) => {
+ let 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 via window/utils here as we don't want to include
+ // this module normally.
+ let { getMostRecentBrowserWindow } = require("sdk/window/utils");
+ let { URL, Blob } = getMostRecentBrowserWindow();
+ let stringifiedFn = createWorkerString(fn);
+ let blob = new Blob([stringifiedFn]);
+ let url = URL.createObjectURL(blob);
+ let worker = new DevToolsWorker(url);
+
+ let wrapperFn = data => worker.performTask("workerifiedTask", data);
+
+ 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()});`;
+ }
+});