From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- toolkit/components/workerloader/require.js | 182 +++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 toolkit/components/workerloader/require.js (limited to 'toolkit/components/workerloader/require.js') diff --git a/toolkit/components/workerloader/require.js b/toolkit/components/workerloader/require.js new file mode 100644 index 0000000000..246c4a1884 --- /dev/null +++ b/toolkit/components/workerloader/require.js @@ -0,0 +1,182 @@ +/* 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/. */ + +/** + * Implementation of a CommonJS module loader for workers. + * + * Use: + * // in the .js file loaded by the constructor of the worker + * importScripts("resource://gre/modules/workers/require.js"); + * let module = require("resource://gre/modules/worker/myModule.js"); + * + * // in myModule.js + * // Load dependencies + * let SimpleTest = require("resource://gre/modules/workers/SimpleTest.js"); + * let Logger = require("resource://gre/modules/workers/Logger.js"); + * + * // Define things that will not be exported + * let someValue = // ... + * + * // Export symbols + * exports.foo = // ... + * exports.bar = // ... + * + * + * Note #1: + * Properties |fileName| and |stack| of errors triggered from a module + * contain file names that do not correspond to human-readable module paths. + * Human readers should rather use properties |moduleName| and |moduleStack|. + * + * Note #2: + * By opposition to some other module loader implementations, this module + * loader does not enforce separation of global objects. Consequently, if + * a module modifies a global object (e.g. |String.prototype|), all other + * modules in the same worker may be affected. + */ + +/* global require */ +/* exported require */ + +(function (exports) { + "use strict"; + + if (exports.require) { + // Avoid double-imports + return; + } + + // Simple implementation of |require| + let require = (function () { + /** + * Mapping from module URI to module exports. + * + * @keys {string} The absolute URI to a module. + * @values {object} The |exports| objects for that module. + */ + let modules = new Map(); + + /** + * A human-readable version of |stack|. + * + * @type {string} + */ + Object.defineProperty(Error.prototype, "moduleStack", { + get() { + return this.stack; + }, + }); + /** + * A human-readable version of |fileName|. + * + * @type {string} + */ + Object.defineProperty(Error.prototype, "moduleName", { + get() { + let match = this.stack.match(/\@(.*):.*:/); + if (match) { + return match[1]; + } + return "(unknown module)"; + }, + }); + + /** + * Import a module + * + * @param {string} baseURL The URL of the modules from which we load a new module. + * This will be null for the first loaded module and so expect an absolute URI in path. + * Note that this first parameter is bound before `require` method is passed outside + * of this module. So that typical callsites will only path the second `path` parameter. + * @param {string} path The path to the module. + * @return {*} An object containing the properties exported by the module. + */ + return function require(baseURL, path) { + let startTime = performance.now(); + if (typeof path != "string") { + throw new TypeError( + "The argument to require() must be a string got " + path + ); + } + + // Resolve relative paths + if ((path.startsWith("./") || path.startsWith("../")) && baseURL) { + path = new URL(path, baseURL).href; + } + + if (!path.includes("://")) { + throw new TypeError( + "The argument to require() must be a string uri, got " + path + ); + } + // Automatically add ".js" if there is no extension + let uri; + if (path.lastIndexOf(".") <= path.lastIndexOf("/")) { + uri = path + ".js"; + } else { + uri = path; + } + + // Exports provided by the module + let exports = Object.create(null); + + // Identification of the module + let module = { + id: path, + uri, + exports, + }; + + // Make module available immediately + // (necessary in case of circular dependencies) + if (modules.has(uri)) { + return modules.get(uri).exports; + } + modules.set(uri, module); + + try { + // Load source of module, synchronously + let xhr = new XMLHttpRequest(); + xhr.open("GET", uri, false); + xhr.responseType = "text"; + xhr.send(); + + let source = xhr.responseText; + if (source == "") { + // There doesn't seem to be a better way to detect that the file couldn't be found + throw new Error("Could not find module " + path); + } + // Use `Function` to leave this scope, use `eval` to start the line + // number from 1 that is observed by `source` and the error message + // thrown from the module, and also use `arguments` for accessing + // `source` and `uri` to avoid polluting the module's environment. + let code = new Function( + "exports", + "require", + "module", + `eval(arguments[3] + "\\n//# sourceURL=" + arguments[4] + "\\n")` + ); + code(exports, require.bind(null, path), module, source, uri); + } catch (ex) { + // Module loading has failed, exports should not be made available + // after all. + modules.delete(uri); + throw ex; + } finally { + ChromeUtils.addProfilerMarker("require", startTime, path); + } + + Object.freeze(module.exports); + Object.freeze(module); + return module.exports; + }; + })(); + + Object.freeze(require); + + Object.defineProperty(exports, "require", { + value: require.bind(null, null), + enumerable: true, + configurable: false, + }); +})(this); -- cgit v1.2.3