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