toolkit/devtools/Require.jsm

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict";
michael@0 6
michael@0 7 /**
michael@0 8 * Require.jsm is a small module loader that loads JavaScript modules as
michael@0 9 * defined by AMD/RequireJS and CommonJS, or specifically as used by:
michael@0 10 * GCLI, Orion, Firebug, CCDump, NetPanel/HTTPMonitor and others.
michael@0 11 *
michael@0 12 * To date, no attempt has been made to ensure that Require.jsm closely follows
michael@0 13 * either the AMD or CommonJS specs. It is hoped that a more formal JavaScript
michael@0 14 * module standard will arrive before this is necessary. In the mean time it
michael@0 15 * serves the projects it loads.
michael@0 16 */
michael@0 17
michael@0 18 this.EXPORTED_SYMBOLS = [ "define", "require" ];
michael@0 19
michael@0 20 const console = (function() {
michael@0 21 const tempScope = {};
michael@0 22 Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
michael@0 23 return tempScope.console;
michael@0 24 })();
michael@0 25
michael@0 26 /**
michael@0 27 * Define a module along with a payload.
michael@0 28 * @param moduleName Name for the payload
michael@0 29 * @param deps Ignored. For compatibility with CommonJS AMD Spec
michael@0 30 * @param payload Function with (require, exports, module) params
michael@0 31 */
michael@0 32 this.define = function define(moduleName, deps, payload) {
michael@0 33 if (typeof moduleName != "string") {
michael@0 34 throw new Error("Error: Module name is not a string");
michael@0 35 }
michael@0 36
michael@0 37 if (arguments.length == 2) {
michael@0 38 payload = deps;
michael@0 39 }
michael@0 40 else {
michael@0 41 payload.deps = deps;
michael@0 42 }
michael@0 43
michael@0 44 if (define.debugDependencies) {
michael@0 45 console.log("define: " + moduleName + " -> " + payload.toString()
michael@0 46 .slice(0, 40).replace(/\n/, '\\n').replace(/\r/, '\\r') + "...");
michael@0 47 }
michael@0 48
michael@0 49 if (moduleName in define.modules) {
michael@0 50 throw new Error("Error: Redefining module: " + moduleName);
michael@0 51 }
michael@0 52
michael@0 53 // Mark the payload so we know we need to call it to get the real module
michael@0 54 payload.__uncompiled = true;
michael@0 55 define.modules[moduleName] = payload;
michael@0 56 }
michael@0 57
michael@0 58 /**
michael@0 59 * The global store of un-instantiated modules
michael@0 60 */
michael@0 61 define.modules = {};
michael@0 62
michael@0 63 /**
michael@0 64 * Should we console.log on module definition/instantiation/requirement?
michael@0 65 */
michael@0 66 define.debugDependencies = false;
michael@0 67
michael@0 68
michael@0 69 /**
michael@0 70 * We invoke require() in the context of a Domain so we can have multiple
michael@0 71 * sets of modules running separate from each other.
michael@0 72 * This contrasts with JSMs which are singletons, Domains allows us to
michael@0 73 * optionally load a CommonJS module twice with separate data each time.
michael@0 74 * Perhaps you want 2 command lines with a different set of commands in each,
michael@0 75 * for example.
michael@0 76 */
michael@0 77 function Domain() {
michael@0 78 this.modules = {};
michael@0 79
michael@0 80 if (define.debugDependencies) {
michael@0 81 this.depth = "";
michael@0 82 }
michael@0 83 }
michael@0 84
michael@0 85 /**
michael@0 86 * Lookup module names and resolve them by calling the definition function if
michael@0 87 * needed.
michael@0 88 * There are 2 ways to call this, either with an array of dependencies and a
michael@0 89 * callback to call when the dependencies are found (which can happen
michael@0 90 * asynchronously in an in-page context) or with a single string an no
michael@0 91 * callback where the dependency is resolved synchronously and returned.
michael@0 92 * The API is designed to be compatible with the CommonJS AMD spec and
michael@0 93 * RequireJS.
michael@0 94 * @param deps A name, or array of names for the payload
michael@0 95 * @param callback Function to call when the dependencies are resolved
michael@0 96 * @return The module required or undefined for array/callback method
michael@0 97 */
michael@0 98 Domain.prototype.require = function(config, deps, callback) {
michael@0 99 if (arguments.length <= 2) {
michael@0 100 callback = deps;
michael@0 101 deps = config;
michael@0 102 config = undefined;
michael@0 103 }
michael@0 104
michael@0 105 if (Array.isArray(deps)) {
michael@0 106 var params = deps.map(function(dep) {
michael@0 107 return this.lookup(dep);
michael@0 108 }, this);
michael@0 109 if (callback) {
michael@0 110 callback.apply(null, params);
michael@0 111 }
michael@0 112 return undefined;
michael@0 113 }
michael@0 114 else {
michael@0 115 return this.lookup(deps);
michael@0 116 }
michael@0 117 };
michael@0 118
michael@0 119 /**
michael@0 120 * Lookup module names and resolve them by calling the definition function if
michael@0 121 * needed.
michael@0 122 * @param moduleName A name for the payload to lookup
michael@0 123 * @return The module specified by aModuleName or null if not found
michael@0 124 */
michael@0 125 Domain.prototype.lookup = function(moduleName) {
michael@0 126 if (moduleName in this.modules) {
michael@0 127 var module = this.modules[moduleName];
michael@0 128 if (define.debugDependencies) {
michael@0 129 console.log(this.depth + " Using module: " + moduleName);
michael@0 130 }
michael@0 131 return module;
michael@0 132 }
michael@0 133
michael@0 134 if (!(moduleName in define.modules)) {
michael@0 135 throw new Error("Missing module: " + moduleName);
michael@0 136 }
michael@0 137
michael@0 138 var module = define.modules[moduleName];
michael@0 139
michael@0 140 if (define.debugDependencies) {
michael@0 141 console.log(this.depth + " Compiling module: " + moduleName);
michael@0 142 }
michael@0 143
michael@0 144 if (module.__uncompiled) {
michael@0 145 if (define.debugDependencies) {
michael@0 146 this.depth += ".";
michael@0 147 }
michael@0 148
michael@0 149 var exports = {};
michael@0 150 try {
michael@0 151 var params = module.deps.map(function(dep) {
michael@0 152 if (dep === "require") {
michael@0 153 return this.require.bind(this);
michael@0 154 }
michael@0 155 if (dep === "exports") {
michael@0 156 return exports;
michael@0 157 }
michael@0 158 if (dep === "module") {
michael@0 159 return { id: moduleName, uri: "" };
michael@0 160 }
michael@0 161 return this.lookup(dep);
michael@0 162 }.bind(this));
michael@0 163
michael@0 164 var reply = module.apply(null, params);
michael@0 165 module = (reply !== undefined) ? reply : exports;
michael@0 166 }
michael@0 167 catch (ex) {
michael@0 168 dump("Error using module '" + moduleName + "' - " + ex + "\n");
michael@0 169 throw ex;
michael@0 170 }
michael@0 171
michael@0 172 if (define.debugDependencies) {
michael@0 173 this.depth = this.depth.slice(0, -1);
michael@0 174 }
michael@0 175 }
michael@0 176
michael@0 177 // cache the resulting module object for next time
michael@0 178 this.modules[moduleName] = module;
michael@0 179
michael@0 180 return module;
michael@0 181 };
michael@0 182
michael@0 183 /**
michael@0 184 * Expose the Domain constructor and a global domain (on the define function
michael@0 185 * to avoid exporting more than we need. This is a common pattern with
michael@0 186 * require systems)
michael@0 187 */
michael@0 188 define.Domain = Domain;
michael@0 189 define.globalDomain = new Domain();
michael@0 190
michael@0 191 /**
michael@0 192 * Expose a default require function which is the require of the global
michael@0 193 * sandbox to make it easy to use.
michael@0 194 */
michael@0 195 this.require = define.globalDomain.require.bind(define.globalDomain);

mercurial