requirejs-rails 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2037 +1,1993 @@
1
1
  /** vim: et:ts=4:sw=4:sts=4
2
- * @license RequireJS 2.0.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
2
+ * @license RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
3
3
  * Available via the MIT or new BSD license.
4
4
  * see: http://github.com/jrburke/requirejs for details
5
5
  */
6
- /*jslint regexp: true, nomen: true */
6
+ //Not using strict: uneven strict support in browsers, #392, and causes
7
+ //problems with requirejs.exec()/transpiler plugins that may not be strict.
8
+ /*jslint regexp: true, nomen: true, sloppy: true */
7
9
  /*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
8
10
 
9
11
  var requirejs, require, define;
10
12
  (function (global) {
11
- 'use strict';
12
-
13
- var version = '2.0.2',
14
- commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
15
- cjsRequireRegExp = /require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
16
- jsSuffixRegExp = /\.js$/,
17
- currDirRegExp = /^\.\//,
18
- ostring = Object.prototype.toString,
19
- ap = Array.prototype,
20
- aps = ap.slice,
21
- apsp = ap.splice,
22
- isBrowser = !!(typeof window !== 'undefined' && navigator && document),
23
- isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
24
- //PS3 indicates loaded and complete, but need to wait for complete
25
- //specifically. Sequence is 'loading', 'loaded', execution,
26
- // then 'complete'. The UA check is unfortunate, but not sure how
27
- //to feature test w/o causing perf issues.
28
- readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
29
- /^complete$/ : /^(complete|loaded)$/,
30
- defContextName = '_',
31
- //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
32
- isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
33
- contexts = {},
34
- cfg = {},
35
- globalDefQueue = [],
36
- useInteractive = false,
37
- req, s, head, baseElement, dataMain, src,
38
- interactiveScript, currentlyAddingScript, mainScript, subPath;
39
-
40
- function isFunction(it) {
41
- return ostring.call(it) === '[object Function]';
13
+ var req, s, head, baseElement, dataMain, src,
14
+ interactiveScript, currentlyAddingScript, mainScript, subPath,
15
+ version = '2.1.2',
16
+ commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
17
+ cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
18
+ jsSuffixRegExp = /\.js$/,
19
+ currDirRegExp = /^\.\//,
20
+ op = Object.prototype,
21
+ ostring = op.toString,
22
+ hasOwn = op.hasOwnProperty,
23
+ ap = Array.prototype,
24
+ aps = ap.slice,
25
+ apsp = ap.splice,
26
+ isBrowser = !!(typeof window !== 'undefined' && navigator && document),
27
+ isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
28
+ //PS3 indicates loaded and complete, but need to wait for complete
29
+ //specifically. Sequence is 'loading', 'loaded', execution,
30
+ // then 'complete'. The UA check is unfortunate, but not sure how
31
+ //to feature test w/o causing perf issues.
32
+ readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
33
+ /^complete$/ : /^(complete|loaded)$/,
34
+ defContextName = '_',
35
+ //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
36
+ isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
37
+ contexts = {},
38
+ cfg = {},
39
+ globalDefQueue = [],
40
+ useInteractive = false;
41
+
42
+ function isFunction(it) {
43
+ return ostring.call(it) === '[object Function]';
44
+ }
45
+
46
+ function isArray(it) {
47
+ return ostring.call(it) === '[object Array]';
48
+ }
49
+
50
+ /**
51
+ * Helper function for iterating over an array. If the func returns
52
+ * a true value, it will break out of the loop.
53
+ */
54
+ function each(ary, func) {
55
+ if (ary) {
56
+ var i;
57
+ for (i = 0; i < ary.length; i += 1) {
58
+ if (ary[i] && func(ary[i], i, ary)) {
59
+ break;
60
+ }
61
+ }
42
62
  }
43
-
44
- function isArray(it) {
45
- return ostring.call(it) === '[object Array]';
63
+ }
64
+
65
+ /**
66
+ * Helper function for iterating over an array backwards. If the func
67
+ * returns a true value, it will break out of the loop.
68
+ */
69
+ function eachReverse(ary, func) {
70
+ if (ary) {
71
+ var i;
72
+ for (i = ary.length - 1; i > -1; i -= 1) {
73
+ if (ary[i] && func(ary[i], i, ary)) {
74
+ break;
75
+ }
76
+ }
46
77
  }
47
-
48
- /**
49
- * Helper function for iterating over an array. If the func returns
50
- * a true value, it will break out of the loop.
51
- */
52
- function each(ary, func) {
53
- if (ary) {
54
- var i;
55
- for (i = 0; i < ary.length; i += 1) {
56
- if (ary[i] && func(ary[i], i, ary)) {
57
- break;
58
- }
59
- }
78
+ }
79
+
80
+ function hasProp(obj, prop) {
81
+ return hasOwn.call(obj, prop);
82
+ }
83
+
84
+ function getOwn(obj, prop) {
85
+ return hasProp(obj, prop) && obj[prop];
86
+ }
87
+
88
+ /**
89
+ * Cycles over properties in an object and calls a function for each
90
+ * property value. If the function returns a truthy value, then the
91
+ * iteration is stopped.
92
+ */
93
+ function eachProp(obj, func) {
94
+ var prop;
95
+ for (prop in obj) {
96
+ if (hasProp(obj, prop)) {
97
+ if (func(obj[prop], prop)) {
98
+ break;
60
99
  }
100
+ }
61
101
  }
62
-
63
- /**
64
- * Helper function for iterating over an array backwards. If the func
65
- * returns a true value, it will break out of the loop.
66
- */
67
- function eachReverse(ary, func) {
68
- if (ary) {
69
- var i;
70
- for (i = ary.length - 1; i > -1; i -= 1) {
71
- if (ary[i] && func(ary[i], i, ary)) {
72
- break;
73
- }
102
+ }
103
+
104
+ /**
105
+ * Simple function to mix in properties from source into target,
106
+ * but only if target does not already have a property of the same name.
107
+ */
108
+ function mixin(target, source, force, deepStringMixin) {
109
+ if (source) {
110
+ eachProp(source, function (value, prop) {
111
+ if (force || !hasProp(target, prop)) {
112
+ if (deepStringMixin && typeof value !== 'string') {
113
+ if (!target[prop]) {
114
+ target[prop] = {};
74
115
  }
116
+ mixin(target[prop], value, force, deepStringMixin);
117
+ } else {
118
+ target[prop] = value;
119
+ }
75
120
  }
121
+ });
76
122
  }
123
+ return target;
124
+ }
125
+
126
+ //Similar to Function.prototype.bind, but the 'this' object is specified
127
+ //first, since it is easier to read/figure out what 'this' will be.
128
+ function bind(obj, fn) {
129
+ return function () {
130
+ return fn.apply(obj, arguments);
131
+ };
132
+ }
77
133
 
78
- function hasProp(obj, prop) {
79
- return obj.hasOwnProperty(prop);
134
+ function scripts() {
135
+ return document.getElementsByTagName('script');
136
+ }
137
+
138
+ //Allow getting a global that expressed in
139
+ //dot notation, like 'a.b.c'.
140
+ function getGlobal(value) {
141
+ if (!value) {
142
+ return value;
143
+ }
144
+ var g = global;
145
+ each(value.split('.'), function (part) {
146
+ g = g[part];
147
+ });
148
+ return g;
149
+ }
150
+
151
+ /**
152
+ * Constructs an error with a pointer to an URL with more information.
153
+ * @param {String} id the error ID that maps to an ID on a web page.
154
+ * @param {String} message human readable error.
155
+ * @param {Error} [err] the original error, if there is one.
156
+ *
157
+ * @returns {Error}
158
+ */
159
+ function makeError(id, msg, err, requireModules) {
160
+ var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
161
+ e.requireType = id;
162
+ e.requireModules = requireModules;
163
+ if (err) {
164
+ e.originalError = err;
80
165
  }
166
+ return e;
167
+ }
168
+
169
+ if (typeof define !== 'undefined') {
170
+ //If a define is already in play via another AMD loader,
171
+ //do not overwrite.
172
+ return;
173
+ }
174
+
175
+ if (typeof requirejs !== 'undefined') {
176
+ if (isFunction(requirejs)) {
177
+ //Do not overwrite and existing requirejs instance.
178
+ return;
179
+ }
180
+ cfg = requirejs;
181
+ requirejs = undefined;
182
+ }
183
+
184
+ //Allow for a require config object
185
+ if (typeof require !== 'undefined' && !isFunction(require)) {
186
+ //assume it is a config object.
187
+ cfg = require;
188
+ require = undefined;
189
+ }
190
+
191
+ function newContext(contextName) {
192
+ var inCheckLoaded, Module, context, handlers,
193
+ checkLoadedTimeoutId,
194
+ config = {
195
+ waitSeconds: 7,
196
+ baseUrl: './',
197
+ paths: {},
198
+ pkgs: {},
199
+ shim: {},
200
+ map: {},
201
+ config: {}
202
+ },
203
+ registry = {},
204
+ undefEvents = {},
205
+ defQueue = [],
206
+ defined = {},
207
+ urlFetched = {},
208
+ requireCounter = 1,
209
+ unnormalizedCounter = 1;
81
210
 
82
211
  /**
83
- * Cycles over properties in an object and calls a function for each
84
- * property value. If the function returns a truthy value, then the
85
- * iteration is stopped.
212
+ * Trims the . and .. from an array of path segments.
213
+ * It will keep a leading path segment if a .. will become
214
+ * the first path segment, to help with module name lookups,
215
+ * which act like paths, but can be remapped. But the end result,
216
+ * all paths that use this function should look normalized.
217
+ * NOTE: this method MODIFIES the input array.
218
+ * @param {Array} ary the array of path segments.
86
219
  */
87
- function eachProp(obj, func) {
88
- var prop;
89
- for (prop in obj) {
90
- if (obj.hasOwnProperty(prop)) {
91
- if (func(obj[prop], prop)) {
92
- break;
93
- }
94
- }
220
+ function trimDots(ary) {
221
+ var i, part;
222
+ for (i = 0; ary[i]; i += 1) {
223
+ part = ary[i];
224
+ if (part === '.') {
225
+ ary.splice(i, 1);
226
+ i -= 1;
227
+ } else if (part === '..') {
228
+ if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
229
+ //End of the line. Keep at least one non-dot
230
+ //path segment at the front so it can be mapped
231
+ //correctly to disk. Otherwise, there is likely
232
+ //no path mapping for a path starting with '..'.
233
+ //This can still fail, but catches the most reasonable
234
+ //uses of ..
235
+ break;
236
+ } else if (i > 0) {
237
+ ary.splice(i - 1, 2);
238
+ i -= 2;
239
+ }
95
240
  }
241
+ }
96
242
  }
97
243
 
98
244
  /**
99
- * Simple function to mix in properties from source into target,
100
- * but only if target does not already have a property of the same name.
101
- * This is not robust in IE for transferring methods that match
102
- * Object.prototype names, but the uses of mixin here seem unlikely to
103
- * trigger a problem related to that.
245
+ * Given a relative module name, like ./something, normalize it to
246
+ * a real name that can be mapped to a path.
247
+ * @param {String} name the relative name
248
+ * @param {String} baseName a real name that the name arg is relative
249
+ * to.
250
+ * @param {Boolean} applyMap apply the map config to the value. Should
251
+ * only be done if this normalization is for a dependency ID.
252
+ * @returns {String} normalized name
104
253
  */
105
- function mixin(target, source, force, deepStringMixin) {
106
- if (source) {
107
- eachProp(source, function (value, prop) {
108
- if (force || !hasProp(target, prop)) {
109
- if (deepStringMixin && typeof value !== 'string') {
110
- if (!target[prop]) {
111
- target[prop] = {};
112
- }
113
- mixin(target[prop], value, force, deepStringMixin);
114
- } else {
115
- target[prop] = value;
116
- }
254
+ function normalize(name, baseName, applyMap) {
255
+ var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
256
+ foundMap, foundI, foundStarMap, starI,
257
+ baseParts = baseName && baseName.split('/'),
258
+ normalizedBaseParts = baseParts,
259
+ map = config.map,
260
+ starMap = map && map['*'];
261
+
262
+ //Adjust any relative paths.
263
+ if (name && name.charAt(0) === '.') {
264
+ //If have a base name, try to normalize against it,
265
+ //otherwise, assume it is a top-level require that will
266
+ //be relative to baseUrl in the end.
267
+ if (baseName) {
268
+ if (getOwn(config.pkgs, baseName)) {
269
+ //If the baseName is a package name, then just treat it as one
270
+ //name to concat the name with.
271
+ normalizedBaseParts = baseParts = [baseName];
272
+ } else {
273
+ //Convert baseName to array, and lop off the last part,
274
+ //so that . matches that 'directory' and not name of the baseName's
275
+ //module. For instance, baseName of 'one/two/three', maps to
276
+ //'one/two/three.js', but we want the directory, 'one/two' for
277
+ //this normalization.
278
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
279
+ }
280
+
281
+ name = normalizedBaseParts.concat(name.split('/'));
282
+ trimDots(name);
283
+
284
+ //Some use of packages may use a . path to reference the
285
+ //'main' module name, so normalize for that.
286
+ pkgConfig = getOwn(config.pkgs, (pkgName = name[0]));
287
+ name = name.join('/');
288
+ if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
289
+ name = pkgName;
290
+ }
291
+ } else if (name.indexOf('./') === 0) {
292
+ // No baseName, so this is ID is resolved relative
293
+ // to baseUrl, pull off the leading dot.
294
+ name = name.substring(2);
295
+ }
296
+ }
297
+
298
+ //Apply map config if available.
299
+ if (applyMap && (baseParts || starMap) && map) {
300
+ nameParts = name.split('/');
301
+
302
+ for (i = nameParts.length; i > 0; i -= 1) {
303
+ nameSegment = nameParts.slice(0, i).join('/');
304
+
305
+ if (baseParts) {
306
+ //Find the longest baseName segment match in the config.
307
+ //So, do joins on the biggest to smallest lengths of baseParts.
308
+ for (j = baseParts.length; j > 0; j -= 1) {
309
+ mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
310
+
311
+ //baseName segment has config, find if it has one for
312
+ //this name.
313
+ if (mapValue) {
314
+ mapValue = getOwn(mapValue, nameSegment);
315
+ if (mapValue) {
316
+ //Match, update name to the new value.
317
+ foundMap = mapValue;
318
+ foundI = i;
319
+ break;
117
320
  }
118
- });
321
+ }
322
+ }
323
+ }
324
+
325
+ if (foundMap) {
326
+ break;
327
+ }
328
+
329
+ //Check for a star map match, but just hold on to it,
330
+ //if there is a shorter segment match later in a matching
331
+ //config, then favor over this star map.
332
+ if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
333
+ foundStarMap = getOwn(starMap, nameSegment);
334
+ starI = i;
335
+ }
119
336
  }
120
- return target;
121
- }
122
337
 
123
- //Similar to Function.prototype.bind, but the 'this' object is specified
124
- //first, since it is easier to read/figure out what 'this' will be.
125
- function bind(obj, fn) {
126
- return function () {
127
- return fn.apply(obj, arguments);
128
- };
129
- }
338
+ if (!foundMap && foundStarMap) {
339
+ foundMap = foundStarMap;
340
+ foundI = starI;
341
+ }
342
+
343
+ if (foundMap) {
344
+ nameParts.splice(0, foundI, foundMap);
345
+ name = nameParts.join('/');
346
+ }
347
+ }
130
348
 
131
- function scripts() {
132
- return document.getElementsByTagName('script');
349
+ return name;
133
350
  }
134
351
 
135
- //Allow getting a global that expressed in
136
- //dot notation, like 'a.b.c'.
137
- function getGlobal(value) {
138
- if (!value) {
139
- return value;
140
- }
141
- var g = global;
142
- each(value.split('.'), function (part) {
143
- g = g[part];
352
+ function removeScript(name) {
353
+ if (isBrowser) {
354
+ each(scripts(), function (scriptNode) {
355
+ if (scriptNode.getAttribute('data-requiremodule') === name &&
356
+ scriptNode.getAttribute('data-requirecontext') === context.contextName) {
357
+ scriptNode.parentNode.removeChild(scriptNode);
358
+ return true;
359
+ }
144
360
  });
145
- return g;
361
+ }
146
362
  }
147
363
 
148
- function makeContextModuleFunc(func, relMap, enableBuildCallback) {
149
- return function () {
150
- //A version of a require function that passes a moduleName
151
- //value for items that may need to
152
- //look up paths relative to the moduleName
153
- var args = aps.call(arguments, 0), lastArg;
154
- if (enableBuildCallback &&
155
- isFunction((lastArg = args[args.length - 1]))) {
156
- lastArg.__requireJsBuild = true;
157
- }
158
- args.push(relMap);
159
- return func.apply(null, args);
160
- };
364
+ function hasPathFallback(id) {
365
+ var pathConfig = getOwn(config.paths, id);
366
+ if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
367
+ removeScript(id);
368
+ //Pop off the first array value, since it failed, and
369
+ //retry
370
+ pathConfig.shift();
371
+ context.require.undef(id);
372
+ context.require([id]);
373
+ return true;
374
+ }
161
375
  }
162
376
 
163
- function addRequireMethods(req, context, relMap) {
164
- each([
165
- ['toUrl'],
166
- ['undef'],
167
- ['defined', 'requireDefined'],
168
- ['specified', 'requireSpecified']
169
- ], function (item) {
170
- var prop = item[1] || item[0];
171
- req[item[0]] = context ? makeContextModuleFunc(context[prop], relMap) :
172
- //If no context, then use default context. Reference from
173
- //contexts instead of early binding to default context, so
174
- //that during builds, the latest instance of the default
175
- //context with its config gets used.
176
- function () {
177
- var ctx = contexts[defContextName];
178
- return ctx[prop].apply(ctx, arguments);
179
- };
180
- });
377
+ //Turns a plugin!resource to [plugin, resource]
378
+ //with the plugin being undefined if the name
379
+ //did not have a plugin prefix.
380
+ function splitPrefix(name) {
381
+ var prefix,
382
+ index = name ? name.indexOf('!') : -1;
383
+ if (index > -1) {
384
+ prefix = name.substring(0, index);
385
+ name = name.substring(index + 1, name.length);
386
+ }
387
+ return [prefix, name];
181
388
  }
182
389
 
183
390
  /**
184
- * Constructs an error with a pointer to an URL with more information.
185
- * @param {String} id the error ID that maps to an ID on a web page.
186
- * @param {String} message human readable error.
187
- * @param {Error} [err] the original error, if there is one.
391
+ * Creates a module mapping that includes plugin prefix, module
392
+ * name, and path. If parentModuleMap is provided it will
393
+ * also normalize the name via require.normalize()
394
+ *
395
+ * @param {String} name the module name
396
+ * @param {String} [parentModuleMap] parent module map
397
+ * for the module name, used to resolve relative names.
398
+ * @param {Boolean} isNormalized: is the ID already normalized.
399
+ * This is true if this call is done for a define() module ID.
400
+ * @param {Boolean} applyMap: apply the map config to the ID.
401
+ * Should only be true if this map is for a dependency.
188
402
  *
189
- * @returns {Error}
403
+ * @returns {Object}
190
404
  */
191
- function makeError(id, msg, err, requireModules) {
192
- var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
193
- e.requireType = id;
194
- e.requireModules = requireModules;
195
- if (err) {
196
- e.originalError = err;
405
+ function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
406
+ var url, pluginModule, suffix, nameParts,
407
+ prefix = null,
408
+ parentName = parentModuleMap ? parentModuleMap.name : null,
409
+ originalName = name,
410
+ isDefine = true,
411
+ normalizedName = '';
412
+
413
+ //If no name, then it means it is a require call, generate an
414
+ //internal name.
415
+ if (!name) {
416
+ isDefine = false;
417
+ name = '_@r' + (requireCounter += 1);
418
+ }
419
+
420
+ nameParts = splitPrefix(name);
421
+ prefix = nameParts[0];
422
+ name = nameParts[1];
423
+
424
+ if (prefix) {
425
+ prefix = normalize(prefix, parentName, applyMap);
426
+ pluginModule = getOwn(defined, prefix);
427
+ }
428
+
429
+ //Account for relative paths if there is a base name.
430
+ if (name) {
431
+ if (prefix) {
432
+ if (pluginModule && pluginModule.normalize) {
433
+ //Plugin is loaded, use its normalize method.
434
+ normalizedName = pluginModule.normalize(name, function (name) {
435
+ return normalize(name, parentName, applyMap);
436
+ });
437
+ } else {
438
+ normalizedName = normalize(name, parentName, applyMap);
439
+ }
440
+ } else {
441
+ //A regular module.
442
+ normalizedName = normalize(name, parentName, applyMap);
443
+
444
+ //Normalized name may be a plugin ID due to map config
445
+ //application in normalize. The map config values must
446
+ //already be normalized, so do not need to redo that part.
447
+ nameParts = splitPrefix(normalizedName);
448
+ prefix = nameParts[0];
449
+ normalizedName = nameParts[1];
450
+ isNormalized = true;
451
+
452
+ url = context.nameToUrl(normalizedName);
197
453
  }
198
- return e;
454
+ }
455
+
456
+ //If the id is a plugin id that cannot be determined if it needs
457
+ //normalization, stamp it with a unique ID so two matching relative
458
+ //ids that may conflict can be separate.
459
+ suffix = prefix && !pluginModule && !isNormalized ?
460
+ '_unnormalized' + (unnormalizedCounter += 1) :
461
+ '';
462
+
463
+ return {
464
+ prefix: prefix,
465
+ name: normalizedName,
466
+ parentMap: parentModuleMap,
467
+ unnormalized: !!suffix,
468
+ url: url,
469
+ originalName: originalName,
470
+ isDefine: isDefine,
471
+ id: (prefix ?
472
+ prefix + '!' + normalizedName :
473
+ normalizedName) + suffix
474
+ };
199
475
  }
200
476
 
201
- if (typeof define !== 'undefined') {
202
- //If a define is already in play via another AMD loader,
203
- //do not overwrite.
204
- return;
205
- }
477
+ function getModule(depMap) {
478
+ var id = depMap.id,
479
+ mod = getOwn(registry, id);
206
480
 
207
- if (typeof requirejs !== 'undefined') {
208
- if (isFunction(requirejs)) {
209
- //Do not overwrite and existing requirejs instance.
210
- return;
211
- }
212
- cfg = requirejs;
213
- requirejs = undefined;
214
- }
481
+ if (!mod) {
482
+ mod = registry[id] = new context.Module(depMap);
483
+ }
215
484
 
216
- //Allow for a require config object
217
- if (typeof require !== 'undefined' && !isFunction(require)) {
218
- //assume it is a config object.
219
- cfg = require;
220
- require = undefined;
485
+ return mod;
221
486
  }
222
487
 
223
- function newContext(contextName) {
224
- var config = {
225
- waitSeconds: 7,
226
- baseUrl: './',
227
- paths: {},
228
- pkgs: {},
229
- shim: {}
230
- },
231
- registry = {},
232
- undefEvents = {},
233
- defQueue = [],
234
- defined = {},
235
- urlFetched = {},
236
- requireCounter = 1,
237
- unnormalizedCounter = 1,
238
- //Used to track the order in which modules
239
- //should be executed, by the order they
240
- //load. Important for consistent cycle resolution
241
- //behavior.
242
- waitAry = [],
243
- inCheckLoaded, Module, context, handlers,
244
- checkLoadedTimeoutId;
245
-
246
- /**
247
- * Trims the . and .. from an array of path segments.
248
- * It will keep a leading path segment if a .. will become
249
- * the first path segment, to help with module name lookups,
250
- * which act like paths, but can be remapped. But the end result,
251
- * all paths that use this function should look normalized.
252
- * NOTE: this method MODIFIES the input array.
253
- * @param {Array} ary the array of path segments.
254
- */
255
- function trimDots(ary) {
256
- var i, part;
257
- for (i = 0; ary[i]; i+= 1) {
258
- part = ary[i];
259
- if (part === '.') {
260
- ary.splice(i, 1);
261
- i -= 1;
262
- } else if (part === '..') {
263
- if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
264
- //End of the line. Keep at least one non-dot
265
- //path segment at the front so it can be mapped
266
- //correctly to disk. Otherwise, there is likely
267
- //no path mapping for a path starting with '..'.
268
- //This can still fail, but catches the most reasonable
269
- //uses of ..
270
- break;
271
- } else if (i > 0) {
272
- ary.splice(i - 1, 2);
273
- i -= 2;
274
- }
275
- }
276
- }
277
- }
278
-
279
- /**
280
- * Given a relative module name, like ./something, normalize it to
281
- * a real name that can be mapped to a path.
282
- * @param {String} name the relative name
283
- * @param {String} baseName a real name that the name arg is relative
284
- * to.
285
- * @param {Boolean} applyMap apply the map config to the value. Should
286
- * only be done if this normalization is for a dependency ID.
287
- * @returns {String} normalized name
288
- */
289
- function normalize(name, baseName, applyMap) {
290
- var baseParts = baseName && baseName.split('/'),
291
- map = config.map,
292
- starMap = map && map['*'],
293
- pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
294
- foundMap;
295
-
296
- //Adjust any relative paths.
297
- if (name && name.charAt(0) === '.') {
298
- //If have a base name, try to normalize against it,
299
- //otherwise, assume it is a top-level require that will
300
- //be relative to baseUrl in the end.
301
- if (baseName) {
302
- if (config.pkgs[baseName]) {
303
- //If the baseName is a package name, then just treat it as one
304
- //name to concat the name with.
305
- baseParts = [baseName];
306
- } else {
307
- //Convert baseName to array, and lop off the last part,
308
- //so that . matches that 'directory' and not name of the baseName's
309
- //module. For instance, baseName of 'one/two/three', maps to
310
- //'one/two/three.js', but we want the directory, 'one/two' for
311
- //this normalization.
312
- baseParts = baseParts.slice(0, baseParts.length - 1);
313
- }
314
-
315
- name = baseParts.concat(name.split('/'));
316
- trimDots(name);
317
-
318
- //Some use of packages may use a . path to reference the
319
- //'main' module name, so normalize for that.
320
- pkgConfig = config.pkgs[(pkgName = name[0])];
321
- name = name.join('/');
322
- if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
323
- name = pkgName;
324
- }
325
- } else if (name.indexOf('./') === 0) {
326
- // No baseName, so this is ID is resolved relative
327
- // to baseUrl, pull off the leading dot.
328
- name = name.substring(2);
329
- }
330
- }
331
-
332
- //Apply map config if available.
333
- if (applyMap && (baseParts || starMap) && map) {
334
- nameParts = name.split('/');
335
-
336
- for (i = nameParts.length; i > 0; i -= 1) {
337
- nameSegment = nameParts.slice(0, i).join('/');
338
-
339
- if (baseParts) {
340
- //Find the longest baseName segment match in the config.
341
- //So, do joins on the biggest to smallest lengths of baseParts.
342
- for (j = baseParts.length; j > 0; j -= 1) {
343
- mapValue = map[baseParts.slice(0, j).join('/')];
344
-
345
- //baseName segment has config, find if it has one for
346
- //this name.
347
- if (mapValue) {
348
- mapValue = mapValue[nameSegment];
349
- if (mapValue) {
350
- //Match, update name to the new value.
351
- foundMap = mapValue;
352
- break;
353
- }
354
- }
355
- }
356
- }
357
-
358
- if (!foundMap && starMap && starMap[nameSegment]) {
359
- foundMap = starMap[nameSegment];
360
- }
361
-
362
- if (foundMap) {
363
- nameParts.splice(0, i, foundMap);
364
- name = nameParts.join('/');
365
- break;
366
- }
367
- }
368
- }
488
+ function on(depMap, name, fn) {
489
+ var id = depMap.id,
490
+ mod = getOwn(registry, id);
369
491
 
370
- return name;
492
+ if (hasProp(defined, id) &&
493
+ (!mod || mod.defineEmitComplete)) {
494
+ if (name === 'defined') {
495
+ fn(defined[id]);
371
496
  }
497
+ } else {
498
+ getModule(depMap).on(name, fn);
499
+ }
500
+ }
372
501
 
373
- function removeScript(name) {
374
- if (isBrowser) {
375
- each(scripts(), function (scriptNode) {
376
- if (scriptNode.getAttribute('data-requiremodule') === name &&
377
- scriptNode.getAttribute('data-requirecontext') === context.contextName) {
378
- scriptNode.parentNode.removeChild(scriptNode);
379
- return true;
380
- }
381
- });
502
+ function onError(err, errback) {
503
+ var ids = err.requireModules,
504
+ notified = false;
505
+
506
+ if (errback) {
507
+ errback(err);
508
+ } else {
509
+ each(ids, function (id) {
510
+ var mod = getOwn(registry, id);
511
+ if (mod) {
512
+ //Set error on module, so it skips timeout checks.
513
+ mod.error = err;
514
+ if (mod.events.error) {
515
+ notified = true;
516
+ mod.emit('error', err);
382
517
  }
383
- }
518
+ }
519
+ });
384
520
 
385
- function hasPathFallback(id) {
386
- var pathConfig = config.paths[id];
387
- if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
388
- removeScript(id);
389
- //Pop off the first array value, since it failed, and
390
- //retry
391
- pathConfig.shift();
392
- context.undef(id);
393
- context.require([id]);
394
- return true;
395
- }
521
+ if (!notified) {
522
+ req.onError(err);
396
523
  }
524
+ }
525
+ }
397
526
 
398
- /**
399
- * Creates a module mapping that includes plugin prefix, module
400
- * name, and path. If parentModuleMap is provided it will
401
- * also normalize the name via require.normalize()
402
- *
403
- * @param {String} name the module name
404
- * @param {String} [parentModuleMap] parent module map
405
- * for the module name, used to resolve relative names.
406
- * @param {Boolean} isNormalized: is the ID already normalized.
407
- * This is true if this call is done for a define() module ID.
408
- * @param {Boolean} applyMap: apply the map config to the ID.
409
- * Should only be true if this map is for a dependency.
410
- *
411
- * @returns {Object}
412
- */
413
- function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
414
- var index = name ? name.indexOf('!') : -1,
415
- prefix = null,
416
- parentName = parentModuleMap ? parentModuleMap.name : null,
417
- originalName = name,
418
- isDefine = true,
419
- normalizedName = '',
420
- url, pluginModule, suffix;
421
-
422
- //If no name, then it means it is a require call, generate an
423
- //internal name.
424
- if (!name) {
425
- isDefine = false;
426
- name = '_@r' + (requireCounter += 1);
427
- }
527
+ /**
528
+ * Internal method to transfer globalQueue items to this context's
529
+ * defQueue.
530
+ */
531
+ function takeGlobalQueue() {
532
+ //Push all the globalDefQueue items into the context's defQueue
533
+ if (globalDefQueue.length) {
534
+ //Array splice in the values since the context code has a
535
+ //local var ref to defQueue, so cannot just reassign the one
536
+ //on context.
537
+ apsp.apply(defQueue,
538
+ [defQueue.length - 1, 0].concat(globalDefQueue));
539
+ globalDefQueue = [];
540
+ }
541
+ }
428
542
 
429
- if (index !== -1) {
430
- prefix = name.substring(0, index);
431
- name = name.substring(index + 1, name.length);
432
- }
543
+ handlers = {
544
+ 'require': function (mod) {
545
+ if (mod.require) {
546
+ return mod.require;
547
+ } else {
548
+ return (mod.require = context.makeRequire(mod.map));
549
+ }
550
+ },
551
+ 'exports': function (mod) {
552
+ mod.usingExports = true;
553
+ if (mod.map.isDefine) {
554
+ if (mod.exports) {
555
+ return mod.exports;
556
+ } else {
557
+ return (mod.exports = defined[mod.map.id] = {});
558
+ }
559
+ }
560
+ },
561
+ 'module': function (mod) {
562
+ if (mod.module) {
563
+ return mod.module;
564
+ } else {
565
+ return (mod.module = {
566
+ id: mod.map.id,
567
+ uri: mod.map.url,
568
+ config: function () {
569
+ return (config.config && getOwn(config.config, mod.map.id)) || {};
570
+ },
571
+ exports: defined[mod.map.id]
572
+ });
573
+ }
574
+ }
575
+ };
433
576
 
434
- if (prefix) {
435
- prefix = normalize(prefix, parentName, applyMap);
436
- pluginModule = defined[prefix];
437
- }
577
+ function cleanRegistry(id) {
578
+ //Clean up machinery used for waiting modules.
579
+ delete registry[id];
580
+ }
438
581
 
439
- //Account for relative paths if there is a base name.
440
- if (name) {
441
- if (prefix) {
442
- if (pluginModule && pluginModule.normalize) {
443
- //Plugin is loaded, use its normalize method.
444
- normalizedName = pluginModule.normalize(name, function (name) {
445
- return normalize(name, parentName, applyMap);
446
- });
447
- } else {
448
- normalizedName = normalize(name, parentName, applyMap);
449
- }
450
- } else {
451
- //A regular module.
452
- normalizedName = normalize(name, parentName, applyMap);
453
-
454
- //Calculate url for the module, if it has a name.
455
- //Use name here since nameToUrl also calls normalize,
456
- //and for relative names that are outside the baseUrl
457
- //this causes havoc. Was thinking of just removing
458
- //parentModuleMap to avoid extra normalization, but
459
- //normalize() still does a dot removal because of
460
- //issue #142, so just pass in name here and redo
461
- //the normalization. Paths outside baseUrl are just
462
- //messy to support.
463
- url = context.nameToUrl(name, null, parentModuleMap);
464
- }
582
+ function breakCycle(mod, traced, processed) {
583
+ var id = mod.map.id;
584
+
585
+ if (mod.error) {
586
+ mod.emit('error', mod.error);
587
+ } else {
588
+ traced[id] = true;
589
+ each(mod.depMaps, function (depMap, i) {
590
+ var depId = depMap.id,
591
+ dep = getOwn(registry, depId);
592
+
593
+ //Only force things that have not completed
594
+ //being defined, so still in the registry,
595
+ //and only if it has not been matched up
596
+ //in the module already.
597
+ if (dep && !mod.depMatched[i] && !processed[depId]) {
598
+ if (getOwn(traced, depId)) {
599
+ mod.defineDep(i, defined[depId]);
600
+ mod.check(); //pass false?
601
+ } else {
602
+ breakCycle(dep, traced, processed);
465
603
  }
604
+ }
605
+ });
606
+ processed[id] = true;
607
+ }
608
+ }
466
609
 
467
- //If the id is a plugin id that cannot be determined if it needs
468
- //normalization, stamp it with a unique ID so two matching relative
469
- //ids that may conflict can be separate.
470
- suffix = prefix && !pluginModule && !isNormalized ?
471
- '_unnormalized' + (unnormalizedCounter += 1) :
472
- '';
473
-
474
- return {
475
- prefix: prefix,
476
- name: normalizedName,
477
- parentMap: parentModuleMap,
478
- unnormalized: !!suffix,
479
- url: url,
480
- originalName: originalName,
481
- isDefine: isDefine,
482
- id: (prefix ?
483
- prefix + '!' + normalizedName :
484
- normalizedName) + suffix
485
- };
486
- }
610
+ function checkLoaded() {
611
+ var map, modId, err, usingPathFallback,
612
+ waitInterval = config.waitSeconds * 1000,
613
+ //It is possible to disable the wait interval by using waitSeconds of 0.
614
+ expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
615
+ noLoads = [],
616
+ reqCalls = [],
617
+ stillLoading = false,
618
+ needCycleCheck = true;
619
+
620
+ //Do not bother if this call was a result of a cycle break.
621
+ if (inCheckLoaded) {
622
+ return;
623
+ }
487
624
 
488
- function getModule(depMap) {
489
- var id = depMap.id,
490
- mod = registry[id];
625
+ inCheckLoaded = true;
491
626
 
492
- if (!mod) {
493
- mod = registry[id] = new context.Module(depMap);
494
- }
627
+ //Figure out the state of all the modules.
628
+ eachProp(registry, function (mod) {
629
+ map = mod.map;
630
+ modId = map.id;
495
631
 
496
- return mod;
632
+ //Skip things that are not enabled or in error state.
633
+ if (!mod.enabled) {
634
+ return;
497
635
  }
498
636
 
499
- function on(depMap, name, fn) {
500
- var id = depMap.id,
501
- mod = registry[id];
502
-
503
- if (hasProp(defined, id) &&
504
- (!mod || mod.defineEmitComplete)) {
505
- if (name === 'defined') {
506
- fn(defined[id]);
507
- }
508
- } else {
509
- getModule(depMap).on(name, fn);
510
- }
637
+ if (!map.isDefine) {
638
+ reqCalls.push(mod);
511
639
  }
512
640
 
513
- function onError(err, errback) {
514
- var ids = err.requireModules,
515
- notified = false;
516
-
517
- if (errback) {
518
- errback(err);
641
+ if (!mod.error) {
642
+ //If the module should be executed, and it has not
643
+ //been inited and time is up, remember it.
644
+ if (!mod.inited && expired) {
645
+ if (hasPathFallback(modId)) {
646
+ usingPathFallback = true;
647
+ stillLoading = true;
519
648
  } else {
520
- each(ids, function (id) {
521
- var mod = registry[id];
522
- if (mod) {
523
- //Set error on module, so it skips timeout checks.
524
- mod.error = err;
525
- if (mod.events.error) {
526
- notified = true;
527
- mod.emit('error', err);
528
- }
529
- }
530
- });
531
-
532
- if (!notified) {
533
- req.onError(err);
534
- }
649
+ noLoads.push(modId);
650
+ removeScript(modId);
535
651
  }
536
- }
537
-
538
- /**
539
- * Internal method to transfer globalQueue items to this context's
540
- * defQueue.
541
- */
542
- function takeGlobalQueue() {
543
- //Push all the globalDefQueue items into the context's defQueue
544
- if (globalDefQueue.length) {
545
- //Array splice in the values since the context code has a
546
- //local var ref to defQueue, so cannot just reassign the one
547
- //on context.
548
- apsp.apply(defQueue,
549
- [defQueue.length - 1, 0].concat(globalDefQueue));
550
- globalDefQueue = [];
652
+ } else if (!mod.inited && mod.fetched && map.isDefine) {
653
+ stillLoading = true;
654
+ if (!map.prefix) {
655
+ //No reason to keep looking for unfinished
656
+ //loading. If the only stillLoading is a
657
+ //plugin resource though, keep going,
658
+ //because it may be that a plugin resource
659
+ //is waiting on a non-plugin cycle.
660
+ return (needCycleCheck = false);
551
661
  }
662
+ }
552
663
  }
553
-
554
- /**
555
- * Helper function that creates a require function object to give to
556
- * modules that ask for it as a dependency. It needs to be specific
557
- * per module because of the implication of path mappings that may
558
- * need to be relative to the module name.
559
- */
560
- function makeRequire(mod, enableBuildCallback, altRequire) {
561
- var relMap = mod && mod.map,
562
- modRequire = makeContextModuleFunc(altRequire || context.require,
563
- relMap,
564
- enableBuildCallback);
565
-
566
- addRequireMethods(modRequire, context, relMap);
567
- modRequire.isBrowser = isBrowser;
568
-
569
- return modRequire;
664
+ });
665
+
666
+ if (expired && noLoads.length) {
667
+ //If wait time expired, throw error of unloaded modules.
668
+ err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
669
+ err.contextName = context.contextName;
670
+ return onError(err);
671
+ }
672
+
673
+ //Not expired, check for a cycle.
674
+ if (needCycleCheck) {
675
+ each(reqCalls, function (mod) {
676
+ breakCycle(mod, {}, {});
677
+ });
678
+ }
679
+
680
+ //If still waiting on loads, and the waiting load is something
681
+ //other than a plugin resource, or there are still outstanding
682
+ //scripts, then just try back later.
683
+ if ((!expired || usingPathFallback) && stillLoading) {
684
+ //Something is still waiting to load. Wait for it, but only
685
+ //if a timeout is not already in effect.
686
+ if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
687
+ checkLoadedTimeoutId = setTimeout(function () {
688
+ checkLoadedTimeoutId = 0;
689
+ checkLoaded();
690
+ }, 50);
570
691
  }
692
+ }
571
693
 
572
- handlers = {
573
- 'require': function (mod) {
574
- return makeRequire(mod);
575
- },
576
- 'exports': function (mod) {
577
- mod.usingExports = true;
578
- if (mod.map.isDefine) {
579
- return (mod.exports = defined[mod.map.id] = {});
580
- }
581
- },
582
- 'module': function (mod) {
583
- return (mod.module = {
584
- id: mod.map.id,
585
- uri: mod.map.url,
586
- config: function () {
587
- return (config.config && config.config[mod.map.id]) || {};
588
- },
589
- exports: defined[mod.map.id]
590
- });
591
- }
592
- };
694
+ inCheckLoaded = false;
695
+ }
593
696
 
594
- function removeWaiting(id) {
595
- //Clean up machinery used for waiting modules.
596
- delete registry[id];
697
+ Module = function (map) {
698
+ this.events = getOwn(undefEvents, map.id) || {};
699
+ this.map = map;
700
+ this.shim = getOwn(config.shim, map.id);
701
+ this.depExports = [];
702
+ this.depMaps = [];
703
+ this.depMatched = [];
704
+ this.pluginMaps = {};
705
+ this.depCount = 0;
706
+
707
+ /* this.exports this.factory
708
+ this.depMaps = [],
709
+ this.enabled, this.fetched
710
+ */
711
+ };
597
712
 
598
- each(waitAry, function (mod, i) {
599
- if (mod.map.id === id) {
600
- waitAry.splice(i, 1);
601
- if (!mod.defined) {
602
- context.waitCount -= 1;
603
- }
604
- return true;
605
- }
606
- });
713
+ Module.prototype = {
714
+ init: function (depMaps, factory, errback, options) {
715
+ options = options || {};
716
+
717
+ //Do not do more inits if already done. Can happen if there
718
+ //are multiple define calls for the same module. That is not
719
+ //a normal, common case, but it is also not unexpected.
720
+ if (this.inited) {
721
+ return;
607
722
  }
608
723
 
609
- function findCycle(mod, traced) {
610
- var id = mod.map.id,
611
- depArray = mod.depMaps,
612
- foundModule;
724
+ this.factory = factory;
725
+
726
+ if (errback) {
727
+ //Register for errors on this module.
728
+ this.on('error', errback);
729
+ } else if (this.events.error) {
730
+ //If no errback already, but there are error listeners
731
+ //on this module, set up an errback to pass to the deps.
732
+ errback = bind(this, function (err) {
733
+ this.emit('error', err);
734
+ });
735
+ }
613
736
 
614
- //Do not bother with unitialized modules or not yet enabled
615
- //modules.
616
- if (!mod.inited) {
617
- return;
618
- }
737
+ //Do a copy of the dependency array, so that
738
+ //source inputs are not modified. For example
739
+ //"shim" deps are passed in here directly, and
740
+ //doing a direct modification of the depMaps array
741
+ //would affect that config.
742
+ this.depMaps = depMaps && depMaps.slice(0);
743
+
744
+ this.errback = errback;
745
+
746
+ //Indicate this module has be initialized
747
+ this.inited = true;
748
+
749
+ this.ignore = options.ignore;
750
+
751
+ //Could have option to init this module in enabled mode,
752
+ //or could have been previously marked as enabled. However,
753
+ //the dependencies are not known until init is called. So
754
+ //if enabled previously, now trigger dependencies as enabled.
755
+ if (options.enabled || this.enabled) {
756
+ //Enable this module and dependencies.
757
+ //Will call this.check()
758
+ this.enable();
759
+ } else {
760
+ this.check();
761
+ }
762
+ },
763
+
764
+ defineDep: function (i, depExports) {
765
+ //Because of cycles, defined callback for a given
766
+ //export can be called more than once.
767
+ if (!this.depMatched[i]) {
768
+ this.depMatched[i] = true;
769
+ this.depCount -= 1;
770
+ this.depExports[i] = depExports;
771
+ }
772
+ },
619
773
 
620
- //Found the cycle.
621
- if (traced[id]) {
622
- return mod;
623
- }
774
+ fetch: function () {
775
+ if (this.fetched) {
776
+ return;
777
+ }
778
+ this.fetched = true;
779
+
780
+ context.startTime = (new Date()).getTime();
781
+
782
+ var map = this.map;
783
+
784
+ //If the manager is for a plugin managed resource,
785
+ //ask the plugin to load it now.
786
+ if (this.shim) {
787
+ context.makeRequire(this.map, {
788
+ enableBuildCallback: true
789
+ })(this.shim.deps || [], bind(this, function () {
790
+ return map.prefix ? this.callPlugin() : this.load();
791
+ }));
792
+ } else {
793
+ //Regular dependency.
794
+ return map.prefix ? this.callPlugin() : this.load();
795
+ }
796
+ },
624
797
 
625
- traced[id] = true;
798
+ load: function () {
799
+ var url = this.map.url;
626
800
 
627
- //Trace through the dependencies.
628
- each(depArray, function (depMap) {
629
- var depId = depMap.id,
630
- depMod = registry[depId];
801
+ //Regular dependency.
802
+ if (!urlFetched[url]) {
803
+ urlFetched[url] = true;
804
+ context.load(this.map.id, url);
805
+ }
806
+ },
807
+
808
+ /**
809
+ * Checks is the module is ready to define itself, and if so,
810
+ * define it.
811
+ */
812
+ check: function () {
813
+ if (!this.enabled || this.enabling) {
814
+ return;
815
+ }
631
816
 
632
- if (!depMod) {
633
- return;
817
+ var err, cjsModule,
818
+ id = this.map.id,
819
+ depExports = this.depExports,
820
+ exports = this.exports,
821
+ factory = this.factory;
822
+
823
+ if (!this.inited) {
824
+ this.fetch();
825
+ } else if (this.error) {
826
+ this.emit('error', this.error);
827
+ } else if (!this.defining) {
828
+ //The factory could trigger another require call
829
+ //that would result in checking this module to
830
+ //define itself again. If already in the process
831
+ //of doing that, skip this work.
832
+ this.defining = true;
833
+
834
+ if (this.depCount < 1 && !this.defined) {
835
+ if (isFunction(factory)) {
836
+ //If there is an error listener, favor passing
837
+ //to that instead of throwing an error.
838
+ if (this.events.error) {
839
+ try {
840
+ exports = context.execCb(id, factory, depExports, exports);
841
+ } catch (e) {
842
+ err = e;
634
843
  }
635
-
636
- if (!depMod.inited || !depMod.enabled) {
637
- //Dependency is not inited, so this cannot
638
- //be used to determine a cycle.
639
- foundModule = null;
640
- delete traced[id];
641
- return true;
844
+ } else {
845
+ exports = context.execCb(id, factory, depExports, exports);
846
+ }
847
+
848
+ if (this.map.isDefine) {
849
+ //If setting exports via 'module' is in play,
850
+ //favor that over return value and exports. After that,
851
+ //favor a non-undefined return value over exports use.
852
+ cjsModule = this.module;
853
+ if (cjsModule &&
854
+ cjsModule.exports !== undefined &&
855
+ //Make sure it is not already the exports value
856
+ cjsModule.exports !== this.exports) {
857
+ exports = cjsModule.exports;
858
+ } else if (exports === undefined && this.usingExports) {
859
+ //exports already set the defined value.
860
+ exports = this.exports;
642
861
  }
862
+ }
643
863
 
644
- //mixin traced to a new object for each dependency, so that
645
- //sibling dependencies in this object to not generate a
646
- //false positive match on a cycle. Ideally an Object.create
647
- //type of prototype delegation would be used here, but
648
- //optimizing for file size vs. execution speed since hopefully
649
- //the trees are small for circular dependency scans relative
650
- //to the full app perf.
651
- return (foundModule = findCycle(depMod, mixin({}, traced)));
652
- });
864
+ if (err) {
865
+ err.requireMap = this.map;
866
+ err.requireModules = [this.map.id];
867
+ err.requireType = 'define';
868
+ return onError((this.error = err));
869
+ }
653
870
 
654
- return foundModule;
655
- }
871
+ } else {
872
+ //Just a literal value
873
+ exports = factory;
874
+ }
656
875
 
657
- function forceExec(mod, traced, uninited) {
658
- var id = mod.map.id,
659
- depArray = mod.depMaps;
876
+ this.exports = exports;
660
877
 
661
- if (!mod.inited || !mod.map.isDefine) {
662
- return;
663
- }
878
+ if (this.map.isDefine && !this.ignore) {
879
+ defined[id] = exports;
664
880
 
665
- if (traced[id]) {
666
- return defined[id];
881
+ if (req.onResourceLoad) {
882
+ req.onResourceLoad(context, this.map, this.depMaps);
883
+ }
667
884
  }
668
885
 
669
- traced[id] = mod;
670
-
671
- each(depArray, function(depMap) {
672
- var depId = depMap.id,
673
- depMod = registry[depId],
674
- value;
886
+ //Clean up
887
+ delete registry[id];
675
888
 
676
- if (handlers[depId]) {
677
- return;
678
- }
889
+ this.defined = true;
890
+ }
679
891
 
680
- if (depMod) {
681
- if (!depMod.inited || !depMod.enabled) {
682
- //Dependency is not inited,
683
- //so this module cannot be
684
- //given a forced value yet.
685
- uninited[id] = true;
686
- return;
687
- }
688
-
689
- //Get the value for the current dependency
690
- value = forceExec(depMod, traced, uninited);
691
-
692
- //Even with forcing it may not be done,
693
- //in particular if the module is waiting
694
- //on a plugin resource.
695
- if (!uninited[depId]) {
696
- mod.defineDepById(depId, value);
697
- }
698
- }
699
- });
892
+ //Finished the define stage. Allow calling check again
893
+ //to allow define notifications below in the case of a
894
+ //cycle.
895
+ this.defining = false;
700
896
 
701
- mod.check(true);
897
+ if (this.defined && !this.defineEmitted) {
898
+ this.defineEmitted = true;
899
+ this.emit('defined', this.exports);
900
+ this.defineEmitComplete = true;
901
+ }
702
902
 
703
- return defined[id];
704
903
  }
904
+ },
905
+
906
+ callPlugin: function () {
907
+ var map = this.map,
908
+ id = map.id,
909
+ //Map already normalized the prefix.
910
+ pluginMap = makeModuleMap(map.prefix);
911
+
912
+ //Mark this as a dependency for this plugin, so it
913
+ //can be traced for cycles.
914
+ this.depMaps.push(pluginMap);
915
+
916
+ on(pluginMap, 'defined', bind(this, function (plugin) {
917
+ var load, normalizedMap, normalizedMod,
918
+ name = this.map.name,
919
+ parentName = this.map.parentMap ? this.map.parentMap.name : null,
920
+ localRequire = context.makeRequire(map.parentMap, {
921
+ enableBuildCallback: true,
922
+ skipMap: true
923
+ });
924
+
925
+ //If current map is not normalized, wait for that
926
+ //normalized name to load instead of continuing.
927
+ if (this.map.unnormalized) {
928
+ //Normalize the ID if the plugin allows it.
929
+ if (plugin.normalize) {
930
+ name = plugin.normalize(name, function (name) {
931
+ return normalize(name, parentName, true);
932
+ }) || '';
933
+ }
705
934
 
706
- function modCheck(mod) {
707
- mod.check();
708
- }
935
+ //prefix and name should already be normalized, no need
936
+ //for applying map config again either.
937
+ normalizedMap = makeModuleMap(map.prefix + '!' + name,
938
+ this.map.parentMap);
939
+ on(normalizedMap,
940
+ 'defined', bind(this, function (value) {
941
+ this.init([], function () { return value; }, null, {
942
+ enabled: true,
943
+ ignore: true
944
+ });
945
+ }));
946
+
947
+ normalizedMod = getOwn(registry, normalizedMap.id);
948
+ if (normalizedMod) {
949
+ //Mark this as a dependency for this plugin, so it
950
+ //can be traced for cycles.
951
+ this.depMaps.push(normalizedMap);
709
952
 
710
- function checkLoaded() {
711
- var waitInterval = config.waitSeconds * 1000,
712
- //It is possible to disable the wait interval by using waitSeconds of 0.
713
- expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
714
- noLoads = [],
715
- stillLoading = false,
716
- needCycleCheck = true,
717
- map, modId, err, usingPathFallback;
718
-
719
- //Do not bother if this call was a result of a cycle break.
720
- if (inCheckLoaded) {
721
- return;
953
+ if (this.events.error) {
954
+ normalizedMod.on('error', bind(this, function (err) {
955
+ this.emit('error', err);
956
+ }));
957
+ }
958
+ normalizedMod.enable();
722
959
  }
723
960
 
724
- inCheckLoaded = true;
961
+ return;
962
+ }
725
963
 
726
- //Figure out the state of all the modules.
727
- eachProp(registry, function (mod) {
728
- map = mod.map;
729
- modId = map.id;
964
+ load = bind(this, function (value) {
965
+ this.init([], function () { return value; }, null, {
966
+ enabled: true
967
+ });
968
+ });
730
969
 
731
- //Skip things that are not enabled or in error state.
732
- if (!mod.enabled) {
733
- return;
734
- }
970
+ load.error = bind(this, function (err) {
971
+ this.inited = true;
972
+ this.error = err;
973
+ err.requireModules = [id];
735
974
 
736
- if (!mod.error) {
737
- //If the module should be executed, and it has not
738
- //been inited and time is up, remember it.
739
- if (!mod.inited && expired) {
740
- if (hasPathFallback(modId)) {
741
- usingPathFallback = true;
742
- stillLoading = true;
743
- } else {
744
- noLoads.push(modId);
745
- removeScript(modId);
746
- }
747
- } else if (!mod.inited && mod.fetched && map.isDefine) {
748
- stillLoading = true;
749
- if (!map.prefix) {
750
- //No reason to keep looking for unfinished
751
- //loading. If the only stillLoading is a
752
- //plugin resource though, keep going,
753
- //because it may be that a plugin resource
754
- //is waiting on a non-plugin cycle.
755
- return (needCycleCheck = false);
756
- }
757
- }
758
- }
975
+ //Remove temp unnormalized modules for this module,
976
+ //since they will never be resolved otherwise now.
977
+ eachProp(registry, function (mod) {
978
+ if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
979
+ cleanRegistry(mod.map.id);
980
+ }
759
981
  });
760
982
 
761
- if (expired && noLoads.length) {
762
- //If wait time expired, throw error of unloaded modules.
763
- err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
764
- err.contextName = context.contextName;
765
- return onError(err);
766
- }
767
-
768
- //Not expired, check for a cycle.
769
- if (needCycleCheck) {
770
-
771
- each(waitAry, function (mod) {
772
- if (mod.defined) {
773
- return;
774
- }
775
-
776
- var cycleMod = findCycle(mod, {}),
777
- traced = {};
778
-
779
- if (cycleMod) {
780
- forceExec(cycleMod, traced, {});
781
-
782
- //traced modules may have been
783
- //removed from the registry, but
784
- //their listeners still need to
785
- //be called.
786
- eachProp(traced, modCheck);
787
- }
788
- });
789
-
790
- //Now that dependencies have
791
- //been satisfied, trigger the
792
- //completion check that then
793
- //notifies listeners.
794
- eachProp(registry, modCheck);
983
+ onError(err);
984
+ });
985
+
986
+ //Allow plugins to load other code without having to know the
987
+ //context or how to 'complete' the load.
988
+ load.fromText = bind(this, function (text, textAlt) {
989
+ /*jslint evil: true */
990
+ var moduleName = map.name,
991
+ moduleMap = makeModuleMap(moduleName),
992
+ hasInteractive = useInteractive;
993
+
994
+ //As of 2.1.0, support just passing the text, to reinforce
995
+ //fromText only being called once per resource. Still
996
+ //support old style of passing moduleName but discard
997
+ //that moduleName in favor of the internal ref.
998
+ if (textAlt) {
999
+ text = textAlt;
795
1000
  }
796
1001
 
797
- //If still waiting on loads, and the waiting load is something
798
- //other than a plugin resource, or there are still outstanding
799
- //scripts, then just try back later.
800
- if ((!expired || usingPathFallback) && stillLoading) {
801
- //Something is still waiting to load. Wait for it, but only
802
- //if a timeout is not already in effect.
803
- if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
804
- checkLoadedTimeoutId = setTimeout(function () {
805
- checkLoadedTimeoutId = 0;
806
- checkLoaded();
807
- }, 50);
808
- }
1002
+ //Turn off interactive script matching for IE for any define
1003
+ //calls in the text, then turn it back on at the end.
1004
+ if (hasInteractive) {
1005
+ useInteractive = false;
809
1006
  }
810
1007
 
811
- inCheckLoaded = false;
812
- }
813
-
814
- Module = function (map) {
815
- this.events = undefEvents[map.id] || {};
816
- this.map = map;
817
- this.shim = config.shim[map.id];
818
- this.depExports = [];
819
- this.depMaps = [];
820
- this.depMatched = [];
821
- this.pluginMaps = {};
822
- this.depCount = 0;
823
-
824
- /* this.exports this.factory
825
- this.depMaps = [],
826
- this.enabled, this.fetched
827
- */
828
- };
829
-
830
- Module.prototype = {
831
- init: function(depMaps, factory, errback, options) {
832
- options = options || {};
833
-
834
- //Do not do more inits if already done. Can happen if there
835
- //are multiple define calls for the same module. That is not
836
- //a normal, common case, but it is also not unexpected.
837
- if (this.inited) {
838
- return;
839
- }
840
-
841
- this.factory = factory;
842
-
843
- if (errback) {
844
- //Register for errors on this module.
845
- this.on('error', errback);
846
- } else if (this.events.error) {
847
- //If no errback already, but there are error listeners
848
- //on this module, set up an errback to pass to the deps.
849
- errback = bind(this, function (err) {
850
- this.emit('error', err);
851
- });
852
- }
853
-
854
- //Do a copy of the dependency array, so that
855
- //source inputs are not modified. For example
856
- //"shim" deps are passed in here directly, and
857
- //doing a direct modification of the depMaps array
858
- //would affect that config.
859
- this.depMaps = depMaps && depMaps.slice(0);
860
- this.depMaps.rjsSkipMap = depMaps.rjsSkipMap;
861
-
862
- this.errback = errback;
863
-
864
- //Indicate this module has be initialized
865
- this.inited = true;
866
-
867
- this.ignore = options.ignore;
868
-
869
- //Could have option to init this module in enabled mode,
870
- //or could have been previously marked as enabled. However,
871
- //the dependencies are not known until init is called. So
872
- //if enabled previously, now trigger dependencies as enabled.
873
- if (options.enabled || this.enabled) {
874
- //Enable this module and dependencies.
875
- //Will call this.check()
876
- this.enable();
877
- } else {
878
- this.check();
879
- }
880
- },
881
-
882
- defineDepById: function (id, depExports) {
883
- var i;
884
-
885
- //Find the index for this dependency.
886
- each(this.depMaps, function (map, index) {
887
- if (map.id === id) {
888
- i = index;
889
- return true;
890
- }
891
- });
1008
+ //Prime the system by creating a module instance for
1009
+ //it.
1010
+ getModule(moduleMap);
892
1011
 
893
- return this.defineDep(i, depExports);
894
- },
895
-
896
- defineDep: function (i, depExports) {
897
- //Because of cycles, defined callback for a given
898
- //export can be called more than once.
899
- if (!this.depMatched[i]) {
900
- this.depMatched[i] = true;
901
- this.depCount -= 1;
902
- this.depExports[i] = depExports;
903
- }
904
- },
905
-
906
- fetch: function () {
907
- if (this.fetched) {
908
- return;
909
- }
910
- this.fetched = true;
911
-
912
- context.startTime = (new Date()).getTime();
1012
+ //Transfer any config to this other module.
1013
+ if (hasProp(config.config, id)) {
1014
+ config.config[moduleName] = config.config[id];
1015
+ }
913
1016
 
914
- var map = this.map;
1017
+ try {
1018
+ req.exec(text);
1019
+ } catch (e) {
1020
+ throw new Error('fromText eval for ' + moduleName +
1021
+ ' failed: ' + e);
1022
+ }
915
1023
 
916
- //If the manager is for a plugin managed resource,
917
- //ask the plugin to load it now.
918
- if (this.shim) {
919
- makeRequire(this, true)(this.shim.deps || [], bind(this, function () {
920
- return map.prefix ? this.callPlugin() : this.load();
921
- }));
922
- } else {
923
- //Regular dependency.
924
- return map.prefix ? this.callPlugin() : this.load();
925
- }
926
- },
1024
+ if (hasInteractive) {
1025
+ useInteractive = true;
1026
+ }
927
1027
 
928
- load: function() {
929
- var url = this.map.url;
1028
+ //Mark this as a dependency for the plugin
1029
+ //resource
1030
+ this.depMaps.push(moduleMap);
930
1031
 
931
- //Regular dependency.
932
- if (!urlFetched[url]) {
933
- urlFetched[url] = true;
934
- context.load(this.map.id, url);
935
- }
936
- },
1032
+ //Support anonymous modules.
1033
+ context.completeLoad(moduleName);
937
1034
 
938
- /**
939
- * Checks is the module is ready to define itself, and if so,
940
- * define it. If the silent argument is true, then it will just
941
- * define, but not notify listeners, and not ask for a context-wide
942
- * check of all loaded modules. That is useful for cycle breaking.
943
- */
944
- check: function (silent) {
945
- if (!this.enabled || this.enabling) {
946
- return;
947
- }
1035
+ //Bind the value of that module to the value for this
1036
+ //resource ID.
1037
+ localRequire([moduleName], load);
1038
+ });
1039
+
1040
+ //Use parentName here since the plugin's name is not reliable,
1041
+ //could be some weird string with no path that actually wants to
1042
+ //reference the parentName's path.
1043
+ plugin.load(map.name, localRequire, load, config);
1044
+ }));
1045
+
1046
+ context.enable(pluginMap, this);
1047
+ this.pluginMaps[pluginMap.id] = pluginMap;
1048
+ },
1049
+
1050
+ enable: function () {
1051
+ this.enabled = true;
1052
+
1053
+ //Set flag mentioning that the module is enabling,
1054
+ //so that immediate calls to the defined callbacks
1055
+ //for dependencies do not trigger inadvertent load
1056
+ //with the depCount still being zero.
1057
+ this.enabling = true;
1058
+
1059
+ //Enable each dependency
1060
+ each(this.depMaps, bind(this, function (depMap, i) {
1061
+ var id, mod, handler;
1062
+
1063
+ if (typeof depMap === 'string') {
1064
+ //Dependency needs to be converted to a depMap
1065
+ //and wired up to this module.
1066
+ depMap = makeModuleMap(depMap,
1067
+ (this.map.isDefine ? this.map : this.map.parentMap),
1068
+ false,
1069
+ !this.skipMap);
1070
+ this.depMaps[i] = depMap;
1071
+
1072
+ handler = getOwn(handlers, depMap.id);
1073
+
1074
+ if (handler) {
1075
+ this.depExports[i] = handler(this);
1076
+ return;
1077
+ }
948
1078
 
949
- var id = this.map.id,
950
- depExports = this.depExports,
951
- exports = this.exports,
952
- factory = this.factory,
953
- err, cjsModule;
954
-
955
- if (!this.inited) {
956
- this.fetch();
957
- } else if (this.error) {
958
- this.emit('error', this.error);
959
- } else if (!this.defining) {
960
- //The factory could trigger another require call
961
- //that would result in checking this module to
962
- //define itself again. If already in the process
963
- //of doing that, skip this work.
964
- this.defining = true;
965
-
966
- if (this.depCount < 1 && !this.defined) {
967
- if (isFunction(factory)) {
968
- //If there is an error listener, favor passing
969
- //to that instead of throwing an error.
970
- if (this.events.error) {
971
- try {
972
- exports = context.execCb(id, factory, depExports, exports);
973
- } catch (e) {
974
- err = e;
975
- }
976
- } else {
977
- exports = context.execCb(id, factory, depExports, exports);
978
- }
979
-
980
- if (this.map.isDefine) {
981
- //If setting exports via 'module' is in play,
982
- //favor that over return value and exports. After that,
983
- //favor a non-undefined return value over exports use.
984
- cjsModule = this.module;
985
- if (cjsModule &&
986
- cjsModule.exports !== undefined &&
987
- //Make sure it is not already the exports value
988
- cjsModule.exports !== this.exports) {
989
- exports = cjsModule.exports;
990
- } else if (exports === undefined && this.usingExports) {
991
- //exports already set the defined value.
992
- exports = this.exports;
993
- }
994
- }
995
-
996
- if (err) {
997
- err.requireMap = this.map;
998
- err.requireModules = [this.map.id];
999
- err.requireType = 'define';
1000
- return onError((this.error = err));
1001
- }
1002
-
1003
- } else {
1004
- //Just a literal value
1005
- exports = factory;
1006
- }
1007
-
1008
- this.exports = exports;
1009
-
1010
- if (this.map.isDefine && !this.ignore) {
1011
- defined[id] = exports;
1012
-
1013
- if (req.onResourceLoad) {
1014
- req.onResourceLoad(context, this.map, this.depMaps);
1015
- }
1016
- }
1017
-
1018
- //Clean up
1019
- delete registry[id];
1020
-
1021
- this.defined = true;
1022
- context.waitCount -= 1;
1023
- if (context.waitCount === 0) {
1024
- //Clear the wait array used for cycles.
1025
- waitAry = [];
1026
- }
1027
- }
1028
-
1029
- //Finished the define stage. Allow calling check again
1030
- //to allow define notifications below in the case of a
1031
- //cycle.
1032
- this.defining = false;
1033
-
1034
- if (!silent) {
1035
- if (this.defined && !this.defineEmitted) {
1036
- this.defineEmitted = true;
1037
- this.emit('defined', this.exports);
1038
- this.defineEmitComplete = true;
1039
- }
1040
- }
1041
- }
1042
- },
1079
+ this.depCount += 1;
1043
1080
 
1044
- callPlugin: function() {
1045
- var map = this.map,
1046
- id = map.id,
1047
- pluginMap = makeModuleMap(map.prefix, null, false, true);
1048
-
1049
- on(pluginMap, 'defined', bind(this, function (plugin) {
1050
- var name = this.map.name,
1051
- parentName = this.map.parentMap ? this.map.parentMap.name : null,
1052
- load, normalizedMap, normalizedMod;
1053
-
1054
- //If current map is not normalized, wait for that
1055
- //normalized name to load instead of continuing.
1056
- if (this.map.unnormalized) {
1057
- //Normalize the ID if the plugin allows it.
1058
- if (plugin.normalize) {
1059
- name = plugin.normalize(name, function (name) {
1060
- return normalize(name, parentName, true);
1061
- }) || '';
1062
- }
1063
-
1064
- normalizedMap = makeModuleMap(map.prefix + '!' + name,
1065
- this.map.parentMap,
1066
- false,
1067
- true);
1068
- on(normalizedMap,
1069
- 'defined', bind(this, function (value) {
1070
- this.init([], function () { return value; }, null, {
1071
- enabled: true,
1072
- ignore: true
1073
- });
1074
- }));
1075
- normalizedMod = registry[normalizedMap.id];
1076
- if (normalizedMod) {
1077
- if (this.events.error) {
1078
- normalizedMod.on('error', bind(this, function (err) {
1079
- this.emit('error', err);
1080
- }));
1081
- }
1082
- normalizedMod.enable();
1083
- }
1084
-
1085
- return;
1086
- }
1087
-
1088
- load = bind(this, function (value) {
1089
- this.init([], function () { return value; }, null, {
1090
- enabled: true
1091
- });
1092
- });
1093
-
1094
- load.error = bind(this, function (err) {
1095
- this.inited = true;
1096
- this.error = err;
1097
- err.requireModules = [id];
1098
-
1099
- //Remove temp unnormalized modules for this module,
1100
- //since they will never be resolved otherwise now.
1101
- eachProp(registry, function (mod) {
1102
- if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
1103
- removeWaiting(mod.map.id);
1104
- }
1105
- });
1106
-
1107
- onError(err);
1108
- });
1109
-
1110
- //Allow plugins to load other code without having to know the
1111
- //context or how to 'complete' the load.
1112
- load.fromText = function (moduleName, text) {
1113
- /*jslint evil: true */
1114
- var hasInteractive = useInteractive;
1115
-
1116
- //Turn off interactive script matching for IE for any define
1117
- //calls in the text, then turn it back on at the end.
1118
- if (hasInteractive) {
1119
- useInteractive = false;
1120
- }
1121
-
1122
- //Prime the system by creating a module instance for
1123
- //it.
1124
- getModule(makeModuleMap(moduleName));
1125
-
1126
- req.exec(text);
1127
-
1128
- if (hasInteractive) {
1129
- useInteractive = true;
1130
- }
1131
-
1132
- //Support anonymous modules.
1133
- context.completeLoad(moduleName);
1134
- };
1135
-
1136
- //Use parentName here since the plugin's name is not reliable,
1137
- //could be some weird string with no path that actually wants to
1138
- //reference the parentName's path.
1139
- plugin.load(map.name, makeRequire(map.parentMap, true, function (deps, cb) {
1140
- deps.rjsSkipMap = true;
1141
- return context.require(deps, cb);
1142
- }), load, config);
1143
- }));
1081
+ on(depMap, 'defined', bind(this, function (depExports) {
1082
+ this.defineDep(i, depExports);
1083
+ this.check();
1084
+ }));
1144
1085
 
1145
- context.enable(pluginMap, this);
1146
- this.pluginMaps[pluginMap.id] = pluginMap;
1147
- },
1086
+ if (this.errback) {
1087
+ on(depMap, 'error', this.errback);
1088
+ }
1089
+ }
1090
+
1091
+ id = depMap.id;
1092
+ mod = registry[id];
1093
+
1094
+ //Skip special modules like 'require', 'exports', 'module'
1095
+ //Also, don't call enable if it is already enabled,
1096
+ //important in circular dependency cases.
1097
+ if (!hasProp(handlers, id) && mod && !mod.enabled) {
1098
+ context.enable(depMap, this);
1099
+ }
1100
+ }));
1101
+
1102
+ //Enable each plugin that is used in
1103
+ //a dependency
1104
+ eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1105
+ var mod = getOwn(registry, pluginMap.id);
1106
+ if (mod && !mod.enabled) {
1107
+ context.enable(pluginMap, this);
1108
+ }
1109
+ }));
1110
+
1111
+ this.enabling = false;
1112
+
1113
+ this.check();
1114
+ },
1115
+
1116
+ on: function (name, cb) {
1117
+ var cbs = this.events[name];
1118
+ if (!cbs) {
1119
+ cbs = this.events[name] = [];
1120
+ }
1121
+ cbs.push(cb);
1122
+ },
1148
1123
 
1149
- enable: function () {
1150
- this.enabled = true;
1124
+ emit: function (name, evt) {
1125
+ each(this.events[name], function (cb) {
1126
+ cb(evt);
1127
+ });
1128
+ if (name === 'error') {
1129
+ //Now that the error handler was triggered, remove
1130
+ //the listeners, since this broken Module instance
1131
+ //can stay around for a while in the registry.
1132
+ delete this.events[name];
1133
+ }
1134
+ }
1135
+ };
1151
1136
 
1152
- if (!this.waitPushed) {
1153
- waitAry.push(this);
1154
- context.waitCount += 1;
1155
- this.waitPushed = true;
1156
- }
1137
+ function callGetModule(args) {
1138
+ //Skip modules already defined.
1139
+ if (!hasProp(defined, args[0])) {
1140
+ getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1141
+ }
1142
+ }
1157
1143
 
1158
- //Set flag mentioning that the module is enabling,
1159
- //so that immediate calls to the defined callbacks
1160
- //for dependencies do not trigger inadvertent load
1161
- //with the depCount still being zero.
1162
- this.enabling = true;
1163
-
1164
- //Enable each dependency
1165
- each(this.depMaps, bind(this, function (depMap, i) {
1166
- var id, mod, handler;
1167
-
1168
- if (typeof depMap === 'string') {
1169
- //Dependency needs to be converted to a depMap
1170
- //and wired up to this module.
1171
- depMap = makeModuleMap(depMap,
1172
- (this.map.isDefine ? this.map : this.map.parentMap),
1173
- false,
1174
- !this.depMaps.rjsSkipMap);
1175
- this.depMaps[i] = depMap;
1176
-
1177
- handler = handlers[depMap.id];
1178
-
1179
- if (handler) {
1180
- this.depExports[i] = handler(this);
1181
- return;
1182
- }
1183
-
1184
- this.depCount += 1;
1185
-
1186
- on(depMap, 'defined', bind(this, function (depExports) {
1187
- this.defineDep(i, depExports);
1188
- this.check();
1189
- }));
1190
-
1191
- if (this.errback) {
1192
- on(depMap, 'error', this.errback);
1193
- }
1194
- }
1195
-
1196
- id = depMap.id;
1197
- mod = registry[id];
1198
-
1199
- //Skip special modules like 'require', 'exports', 'module'
1200
- //Also, don't call enable if it is already enabled,
1201
- //important in circular dependency cases.
1202
- if (!handlers[id] && mod && !mod.enabled) {
1203
- context.enable(depMap, this);
1204
- }
1205
- }));
1144
+ function removeListener(node, func, name, ieName) {
1145
+ //Favor detachEvent because of IE9
1146
+ //issue, see attachEvent/addEventListener comment elsewhere
1147
+ //in this file.
1148
+ if (node.detachEvent && !isOpera) {
1149
+ //Probably IE. If not it will throw an error, which will be
1150
+ //useful to know.
1151
+ if (ieName) {
1152
+ node.detachEvent(ieName, func);
1153
+ }
1154
+ } else {
1155
+ node.removeEventListener(name, func, false);
1156
+ }
1157
+ }
1206
1158
 
1207
- //Enable each plugin that is used in
1208
- //a dependency
1209
- eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1210
- var mod = registry[pluginMap.id];
1211
- if (mod && !mod.enabled) {
1212
- context.enable(pluginMap, this);
1213
- }
1214
- }));
1159
+ /**
1160
+ * Given an event from a script node, get the requirejs info from it,
1161
+ * and then removes the event listeners on the node.
1162
+ * @param {Event} evt
1163
+ * @returns {Object}
1164
+ */
1165
+ function getScriptData(evt) {
1166
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
1167
+ //all old browsers will be supported, but this one was easy enough
1168
+ //to support and still makes sense.
1169
+ var node = evt.currentTarget || evt.srcElement;
1170
+
1171
+ //Remove the listeners once here.
1172
+ removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1173
+ removeListener(node, context.onScriptError, 'error');
1174
+
1175
+ return {
1176
+ node: node,
1177
+ id: node && node.getAttribute('data-requiremodule')
1178
+ };
1179
+ }
1215
1180
 
1216
- this.enabling = false;
1181
+ function intakeDefines() {
1182
+ var args;
1183
+
1184
+ //Any defined modules in the global queue, intake them now.
1185
+ takeGlobalQueue();
1186
+
1187
+ //Make sure any remaining defQueue items get properly processed.
1188
+ while (defQueue.length) {
1189
+ args = defQueue.shift();
1190
+ if (args[0] === null) {
1191
+ return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1192
+ } else {
1193
+ //args are id, deps, factory. Should be normalized by the
1194
+ //define() function.
1195
+ callGetModule(args);
1196
+ }
1197
+ }
1198
+ }
1217
1199
 
1218
- this.check();
1219
- },
1200
+ context = {
1201
+ config: config,
1202
+ contextName: contextName,
1203
+ registry: registry,
1204
+ defined: defined,
1205
+ urlFetched: urlFetched,
1206
+ defQueue: defQueue,
1207
+ Module: Module,
1208
+ makeModuleMap: makeModuleMap,
1209
+ nextTick: req.nextTick,
1210
+
1211
+ /**
1212
+ * Set a configuration for the context.
1213
+ * @param {Object} cfg config object to integrate.
1214
+ */
1215
+ configure: function (cfg) {
1216
+ //Make sure the baseUrl ends in a slash.
1217
+ if (cfg.baseUrl) {
1218
+ if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1219
+ cfg.baseUrl += '/';
1220
+ }
1221
+ }
1220
1222
 
1221
- on: function(name, cb) {
1222
- var cbs = this.events[name];
1223
- if (!cbs) {
1224
- cbs = this.events[name] = [];
1225
- }
1226
- cbs.push(cb);
1227
- },
1223
+ //Save off the paths and packages since they require special processing,
1224
+ //they are additive.
1225
+ var pkgs = config.pkgs,
1226
+ shim = config.shim,
1227
+ objs = {
1228
+ paths: true,
1229
+ config: true,
1230
+ map: true
1231
+ };
1228
1232
 
1229
- emit: function (name, evt) {
1230
- each(this.events[name], function (cb) {
1231
- cb(evt);
1232
- });
1233
- if (name === 'error') {
1234
- //Now that the error handler was triggered, remove
1235
- //the listeners, since this broken Module instance
1236
- //can stay around for a while in the registry/waitAry.
1237
- delete this.events[name];
1238
- }
1233
+ eachProp(cfg, function (value, prop) {
1234
+ if (objs[prop]) {
1235
+ if (prop === 'map') {
1236
+ mixin(config[prop], value, true, true);
1237
+ } else {
1238
+ mixin(config[prop], value, true);
1239
1239
  }
1240
- };
1241
-
1242
- function callGetModule(args) {
1243
- getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1244
- }
1240
+ } else {
1241
+ config[prop] = value;
1242
+ }
1243
+ });
1245
1244
 
1246
- function removeListener(node, func, name, ieName) {
1247
- //Favor detachEvent because of IE9
1248
- //issue, see attachEvent/addEventListener comment elsewhere
1249
- //in this file.
1250
- if (node.detachEvent && !isOpera) {
1251
- //Probably IE. If not it will throw an error, which will be
1252
- //useful to know.
1253
- if (ieName) {
1254
- node.detachEvent(ieName, func);
1255
- }
1256
- } else {
1257
- node.removeEventListener(name, func, false);
1245
+ //Merge shim
1246
+ if (cfg.shim) {
1247
+ eachProp(cfg.shim, function (value, id) {
1248
+ //Normalize the structure
1249
+ if (isArray(value)) {
1250
+ value = {
1251
+ deps: value
1252
+ };
1253
+ }
1254
+ if ((value.exports || value.init) && !value.exportsFn) {
1255
+ value.exportsFn = context.makeShimExports(value);
1258
1256
  }
1257
+ shim[id] = value;
1258
+ });
1259
+ config.shim = shim;
1259
1260
  }
1260
1261
 
1261
- /**
1262
- * Given an event from a script node, get the requirejs info from it,
1263
- * and then removes the event listeners on the node.
1264
- * @param {Event} evt
1265
- * @returns {Object}
1266
- */
1267
- function getScriptData(evt) {
1268
- //Using currentTarget instead of target for Firefox 2.0's sake. Not
1269
- //all old browsers will be supported, but this one was easy enough
1270
- //to support and still makes sense.
1271
- var node = evt.currentTarget || evt.srcElement;
1272
-
1273
- //Remove the listeners once here.
1274
- removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1275
- removeListener(node, context.onScriptError, 'error');
1276
-
1277
- return {
1278
- node: node,
1279
- id: node && node.getAttribute('data-requiremodule')
1262
+ //Adjust packages if necessary.
1263
+ if (cfg.packages) {
1264
+ each(cfg.packages, function (pkgObj) {
1265
+ var location;
1266
+
1267
+ pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
1268
+ location = pkgObj.location;
1269
+
1270
+ //Create a brand new object on pkgs, since currentPackages can
1271
+ //be passed in again, and config.pkgs is the internal transformed
1272
+ //state for all package configs.
1273
+ pkgs[pkgObj.name] = {
1274
+ name: pkgObj.name,
1275
+ location: location || pkgObj.name,
1276
+ //Remove leading dot in main, so main paths are normalized,
1277
+ //and remove any trailing .js, since different package
1278
+ //envs have different conventions: some use a module name,
1279
+ //some use a file name.
1280
+ main: (pkgObj.main || 'main')
1281
+ .replace(currDirRegExp, '')
1282
+ .replace(jsSuffixRegExp, '')
1280
1283
  };
1281
- }
1282
-
1283
- return (context = {
1284
- config: config,
1285
- contextName: contextName,
1286
- registry: registry,
1287
- defined: defined,
1288
- urlFetched: urlFetched,
1289
- waitCount: 0,
1290
- defQueue: defQueue,
1291
- Module: Module,
1292
- makeModuleMap: makeModuleMap,
1293
-
1294
- /**
1295
- * Set a configuration for the context.
1296
- * @param {Object} cfg config object to integrate.
1297
- */
1298
- configure: function (cfg) {
1299
- //Make sure the baseUrl ends in a slash.
1300
- if (cfg.baseUrl) {
1301
- if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1302
- cfg.baseUrl += '/';
1303
- }
1304
- }
1305
-
1306
- //Save off the paths and packages since they require special processing,
1307
- //they are additive.
1308
- var pkgs = config.pkgs,
1309
- shim = config.shim,
1310
- paths = config.paths,
1311
- map = config.map;
1312
-
1313
- //Mix in the config values, favoring the new values over
1314
- //existing ones in context.config.
1315
- mixin(config, cfg, true);
1316
-
1317
- //Merge paths.
1318
- config.paths = mixin(paths, cfg.paths, true);
1319
-
1320
- //Merge map
1321
- if (cfg.map) {
1322
- config.map = mixin(map || {}, cfg.map, true, true);
1323
- }
1324
-
1325
- //Merge shim
1326
- if (cfg.shim) {
1327
- eachProp(cfg.shim, function (value, id) {
1328
- //Normalize the structure
1329
- if (isArray(value)) {
1330
- value = {
1331
- deps: value
1332
- };
1333
- }
1334
- if (value.exports && !value.exports.__buildReady) {
1335
- value.exports = context.makeShimExports(value.exports);
1336
- }
1337
- shim[id] = value;
1338
- });
1339
- config.shim = shim;
1340
- }
1284
+ });
1341
1285
 
1342
- //Adjust packages if necessary.
1343
- if (cfg.packages) {
1344
- each(cfg.packages, function (pkgObj) {
1345
- var location;
1346
-
1347
- pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;
1348
- location = pkgObj.location;
1349
-
1350
- //Create a brand new object on pkgs, since currentPackages can
1351
- //be passed in again, and config.pkgs is the internal transformed
1352
- //state for all package configs.
1353
- pkgs[pkgObj.name] = {
1354
- name: pkgObj.name,
1355
- location: location || pkgObj.name,
1356
- //Remove leading dot in main, so main paths are normalized,
1357
- //and remove any trailing .js, since different package
1358
- //envs have different conventions: some use a module name,
1359
- //some use a file name.
1360
- main: (pkgObj.main || 'main')
1361
- .replace(currDirRegExp, '')
1362
- .replace(jsSuffixRegExp, '')
1363
- };
1364
- });
1365
-
1366
- //Done with modifications, assing packages back to context config
1367
- config.pkgs = pkgs;
1368
- }
1286
+ //Done with modifications, assing packages back to context config
1287
+ config.pkgs = pkgs;
1288
+ }
1369
1289
 
1370
- //If there are any "waiting to execute" modules in the registry,
1371
- //update the maps for them, since their info, like URLs to load,
1372
- //may have changed.
1373
- eachProp(registry, function (mod, id) {
1374
- mod.map = makeModuleMap(id);
1375
- });
1376
-
1377
- //If a deps array or a config callback is specified, then call
1378
- //require with those args. This is useful when require is defined as a
1379
- //config object before require.js is loaded.
1380
- if (cfg.deps || cfg.callback) {
1381
- context.require(cfg.deps || [], cfg.callback);
1382
- }
1383
- },
1290
+ //If there are any "waiting to execute" modules in the registry,
1291
+ //update the maps for them, since their info, like URLs to load,
1292
+ //may have changed.
1293
+ eachProp(registry, function (mod, id) {
1294
+ //If module already has init called, since it is too
1295
+ //late to modify them, and ignore unnormalized ones
1296
+ //since they are transient.
1297
+ if (!mod.inited && !mod.map.unnormalized) {
1298
+ mod.map = makeModuleMap(id);
1299
+ }
1300
+ });
1384
1301
 
1385
- makeShimExports: function (exports) {
1386
- var func;
1387
- if (typeof exports === 'string') {
1388
- func = function () {
1389
- return getGlobal(exports);
1390
- };
1391
- //Save the exports for use in nodefine checking.
1392
- func.exports = exports;
1393
- return func;
1394
- } else {
1395
- return function () {
1396
- return exports.apply(global, arguments);
1397
- };
1398
- }
1399
- },
1302
+ //If a deps array or a config callback is specified, then call
1303
+ //require with those args. This is useful when require is defined as a
1304
+ //config object before require.js is loaded.
1305
+ if (cfg.deps || cfg.callback) {
1306
+ context.require(cfg.deps || [], cfg.callback);
1307
+ }
1308
+ },
1309
+
1310
+ makeShimExports: function (value) {
1311
+ function fn() {
1312
+ var ret;
1313
+ if (value.init) {
1314
+ ret = value.init.apply(global, arguments);
1315
+ }
1316
+ return ret || (value.exports && getGlobal(value.exports));
1317
+ }
1318
+ return fn;
1319
+ },
1400
1320
 
1401
- requireDefined: function (id, relMap) {
1402
- return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1403
- },
1321
+ makeRequire: function (relMap, options) {
1322
+ options = options || {};
1404
1323
 
1405
- requireSpecified: function (id, relMap) {
1406
- id = makeModuleMap(id, relMap, false, true).id;
1407
- return hasProp(defined, id) || hasProp(registry, id);
1408
- },
1324
+ function localRequire(deps, callback, errback) {
1325
+ var id, map, requireMod;
1409
1326
 
1410
- require: function (deps, callback, errback, relMap) {
1411
- var moduleName, id, map, requireMod, args;
1412
- if (typeof deps === 'string') {
1413
- if (isFunction(callback)) {
1414
- //Invalid call
1415
- return onError(makeError('requireargs', 'Invalid require call'), errback);
1416
- }
1417
-
1418
- //Synchronous access to one module. If require.get is
1419
- //available (as in the Node adapter), prefer that.
1420
- //In this case deps is the moduleName and callback is
1421
- //the relMap
1422
- if (req.get) {
1423
- return req.get(context, deps, callback);
1424
- }
1425
-
1426
- //Just return the module wanted. In this scenario, the
1427
- //second arg (if passed) is just the relMap.
1428
- moduleName = deps;
1429
- relMap = callback;
1430
-
1431
- //Normalize module name, if it contains . or ..
1432
- map = makeModuleMap(moduleName, relMap, false, true);
1433
- id = map.id;
1434
-
1435
- if (!hasProp(defined, id)) {
1436
- return onError(makeError('notloaded', 'Module name "' +
1437
- id +
1438
- '" has not been loaded yet for context: ' +
1439
- contextName));
1440
- }
1441
- return defined[id];
1442
- }
1327
+ if (options.enableBuildCallback && callback && isFunction(callback)) {
1328
+ callback.__requireJsBuild = true;
1329
+ }
1443
1330
 
1444
- //Callback require. Normalize args. if callback or errback is
1445
- //not a function, it means it is a relMap. Test errback first.
1446
- if (errback && !isFunction(errback)) {
1447
- relMap = errback;
1448
- errback = undefined;
1449
- }
1450
- if (callback && !isFunction(callback)) {
1451
- relMap = callback;
1452
- callback = undefined;
1453
- }
1331
+ if (typeof deps === 'string') {
1332
+ if (isFunction(callback)) {
1333
+ //Invalid call
1334
+ return onError(makeError('requireargs', 'Invalid require call'), errback);
1335
+ }
1454
1336
 
1455
- //Any defined modules in the global queue, intake them now.
1456
- takeGlobalQueue();
1457
-
1458
- //Make sure any remaining defQueue items get properly processed.
1459
- while (defQueue.length) {
1460
- args = defQueue.shift();
1461
- if (args[0] === null) {
1462
- return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
1463
- } else {
1464
- //args are id, deps, factory. Should be normalized by the
1465
- //define() function.
1466
- callGetModule(args);
1467
- }
1468
- }
1337
+ //If require|exports|module are requested, get the
1338
+ //value for them from the special handlers. Caveat:
1339
+ //this only works while module is being defined.
1340
+ if (relMap && hasProp(handlers, deps)) {
1341
+ return handlers[deps](registry[relMap.id]);
1342
+ }
1469
1343
 
1470
- //Mark all the dependencies as needing to be loaded.
1471
- requireMod = getModule(makeModuleMap(null, relMap));
1344
+ //Synchronous access to one module. If require.get is
1345
+ //available (as in the Node adapter), prefer that.
1346
+ if (req.get) {
1347
+ return req.get(context, deps, relMap);
1348
+ }
1472
1349
 
1473
- requireMod.init(deps, callback, errback, {
1474
- enabled: true
1475
- });
1350
+ //Normalize module name, if it contains . or ..
1351
+ map = makeModuleMap(deps, relMap, false, true);
1352
+ id = map.id;
1476
1353
 
1477
- checkLoaded();
1354
+ if (!hasProp(defined, id)) {
1355
+ return onError(makeError('notloaded', 'Module name "' +
1356
+ id +
1357
+ '" has not been loaded yet for context: ' +
1358
+ contextName +
1359
+ (relMap ? '' : '. Use require([])')));
1360
+ }
1361
+ return defined[id];
1362
+ }
1478
1363
 
1479
- return context.require;
1480
- },
1364
+ //Grab defines waiting in the global queue.
1365
+ intakeDefines();
1481
1366
 
1482
- undef: function (id) {
1483
- var map = makeModuleMap(id, null, true),
1484
- mod = registry[id];
1367
+ //Mark all the dependencies as needing to be loaded.
1368
+ context.nextTick(function () {
1369
+ //Some defines could have been added since the
1370
+ //require call, collect them.
1371
+ intakeDefines();
1485
1372
 
1486
- delete defined[id];
1487
- delete urlFetched[map.url];
1488
- delete undefEvents[id];
1373
+ requireMod = getModule(makeModuleMap(null, relMap));
1489
1374
 
1490
- if (mod) {
1491
- //Hold on to listeners in case the
1492
- //module will be attempted to be reloaded
1493
- //using a different config.
1494
- if (mod.events.defined) {
1495
- undefEvents[id] = mod.events;
1496
- }
1375
+ //Store if map config should be applied to this require
1376
+ //call for dependencies.
1377
+ requireMod.skipMap = options.skipMap;
1497
1378
 
1498
- removeWaiting(id);
1499
- }
1500
- },
1379
+ requireMod.init(deps, callback, errback, {
1380
+ enabled: true
1381
+ });
1501
1382
 
1502
- /**
1503
- * Called to enable a module if it is still in the registry
1504
- * awaiting enablement. parent module is passed in for context,
1505
- * used by the optimizer.
1506
- */
1507
- enable: function (depMap, parent) {
1508
- var mod = registry[depMap.id];
1509
- if (mod) {
1510
- getModule(depMap).enable();
1511
- }
1512
- },
1383
+ checkLoaded();
1384
+ });
1513
1385
 
1514
- /**
1515
- * Internal method used by environment adapters to complete a load event.
1516
- * A load event could be a script load or just a load pass from a synchronous
1517
- * load call.
1518
- * @param {String} moduleName the name of the module to potentially complete.
1519
- */
1520
- completeLoad: function (moduleName) {
1521
- var shim = config.shim[moduleName] || {},
1522
- shExports = shim.exports && shim.exports.exports,
1523
- found, args, mod;
1524
-
1525
- takeGlobalQueue();
1526
-
1527
- while (defQueue.length) {
1528
- args = defQueue.shift();
1529
- if (args[0] === null) {
1530
- args[0] = moduleName;
1531
- //If already found an anonymous module and bound it
1532
- //to this name, then this is some other anon module
1533
- //waiting for its completeLoad to fire.
1534
- if (found) {
1535
- break;
1536
- }
1537
- found = true;
1538
- } else if (args[0] === moduleName) {
1539
- //Found matching define call for this script!
1540
- found = true;
1541
- }
1542
-
1543
- callGetModule(args);
1544
- }
1386
+ return localRequire;
1387
+ }
1545
1388
 
1546
- //Do this after the cycle of callGetModule in case the result
1547
- //of those calls/init calls changes the registry.
1548
- mod = registry[moduleName];
1549
-
1550
- if (!found &&
1551
- !defined[moduleName] &&
1552
- mod && !mod.inited) {
1553
- if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1554
- if (hasPathFallback(moduleName)) {
1555
- return;
1556
- } else {
1557
- return onError(makeError('nodefine',
1558
- 'No define call for ' + moduleName,
1559
- null,
1560
- [moduleName]));
1561
- }
1562
- } else {
1563
- //A script that does not call define(), so just simulate
1564
- //the call for it.
1565
- callGetModule([moduleName, (shim.deps || []), shim.exports]);
1566
- }
1567
- }
1389
+ mixin(localRequire, {
1390
+ isBrowser: isBrowser,
1568
1391
 
1569
- checkLoaded();
1570
- },
1392
+ /**
1393
+ * Converts a module name + .extension into an URL path.
1394
+ * *Requires* the use of a module name. It does not support using
1395
+ * plain URLs like nameToUrl.
1396
+ */
1397
+ toUrl: function (moduleNamePlusExt) {
1398
+ var index = moduleNamePlusExt.lastIndexOf('.'),
1399
+ ext = null;
1571
1400
 
1572
- /**
1573
- * Converts a module name + .extension into an URL path.
1574
- * *Requires* the use of a module name. It does not support using
1575
- * plain URLs like nameToUrl.
1576
- */
1577
- toUrl: function (moduleNamePlusExt, relModuleMap) {
1578
- var index = moduleNamePlusExt.lastIndexOf('.'),
1579
- ext = null;
1580
-
1581
- if (index !== -1) {
1582
- ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1583
- moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1584
- }
1401
+ if (index !== -1) {
1402
+ ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1403
+ moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1404
+ }
1585
1405
 
1586
- return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);
1587
- },
1406
+ return context.nameToUrl(normalize(moduleNamePlusExt,
1407
+ relMap && relMap.id, true), ext);
1408
+ },
1588
1409
 
1589
- /**
1590
- * Converts a module name to a file path. Supports cases where
1591
- * moduleName may actually be just an URL.
1592
- */
1593
- nameToUrl: function (moduleName, ext, relModuleMap) {
1594
- var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
1595
- parentPath;
1596
-
1597
- //Normalize module name if have a base relative module name to work from.
1598
- moduleName = normalize(moduleName, relModuleMap && relModuleMap.id, true);
1599
-
1600
- //If a colon is in the URL, it indicates a protocol is used and it is just
1601
- //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1602
- //or ends with .js, then assume the user meant to use an url and not a module id.
1603
- //The slash is important for protocol-less URLs as well as full paths.
1604
- if (req.jsExtRegExp.test(moduleName)) {
1605
- //Just a plain path, not module name lookup, so just return it.
1606
- //Add extension if it is included. This is a bit wonky, only non-.js things pass
1607
- //an extension, this method probably needs to be reworked.
1608
- url = moduleName + (ext || '');
1609
- } else {
1610
- //A module that needs to be converted to a path.
1611
- paths = config.paths;
1612
- pkgs = config.pkgs;
1613
-
1614
- syms = moduleName.split('/');
1615
- //For each module name segment, see if there is a path
1616
- //registered for it. Start with most specific name
1617
- //and work up from it.
1618
- for (i = syms.length; i > 0; i -= 1) {
1619
- parentModule = syms.slice(0, i).join('/');
1620
- pkg = pkgs[parentModule];
1621
- parentPath = paths[parentModule];
1622
- if (parentPath) {
1623
- //If an array, it means there are a few choices,
1624
- //Choose the one that is desired
1625
- if (isArray(parentPath)) {
1626
- parentPath = parentPath[0];
1627
- }
1628
- syms.splice(0, i, parentPath);
1629
- break;
1630
- } else if (pkg) {
1631
- //If module name is just the package name, then looking
1632
- //for the main module.
1633
- if (moduleName === pkg.name) {
1634
- pkgPath = pkg.location + '/' + pkg.main;
1635
- } else {
1636
- pkgPath = pkg.location;
1637
- }
1638
- syms.splice(0, i, pkgPath);
1639
- break;
1640
- }
1641
- }
1642
-
1643
- //Join the path parts together, then figure out if baseUrl is needed.
1644
- url = syms.join('/') + (ext || '.js');
1645
- url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1646
- }
1410
+ defined: function (id) {
1411
+ return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1412
+ },
1647
1413
 
1648
- return config.urlArgs ? url +
1649
- ((url.indexOf('?') === -1 ? '?' : '&') +
1650
- config.urlArgs) : url;
1651
- },
1414
+ specified: function (id) {
1415
+ id = makeModuleMap(id, relMap, false, true).id;
1416
+ return hasProp(defined, id) || hasProp(registry, id);
1417
+ }
1418
+ });
1652
1419
 
1653
- //Delegates to req.load. Broken out as a separate function to
1654
- //allow overriding in the optimizer.
1655
- load: function (id, url) {
1656
- req.load(context, id, url);
1657
- },
1420
+ //Only allow undef on top level require calls
1421
+ if (!relMap) {
1422
+ localRequire.undef = function (id) {
1423
+ //Bind any waiting define() calls to this context,
1424
+ //fix for #408
1425
+ takeGlobalQueue();
1426
+
1427
+ var map = makeModuleMap(id, relMap, true),
1428
+ mod = getOwn(registry, id);
1429
+
1430
+ delete defined[id];
1431
+ delete urlFetched[map.url];
1432
+ delete undefEvents[id];
1433
+
1434
+ if (mod) {
1435
+ //Hold on to listeners in case the
1436
+ //module will be attempted to be reloaded
1437
+ //using a different config.
1438
+ if (mod.events.defined) {
1439
+ undefEvents[id] = mod.events;
1440
+ }
1441
+
1442
+ cleanRegistry(id);
1443
+ }
1444
+ };
1445
+ }
1658
1446
 
1659
- /**
1660
- * Executes a module callack function. Broken out as a separate function
1661
- * solely to allow the build system to sequence the files in the built
1662
- * layer in the right sequence.
1663
- *
1664
- * @private
1665
- */
1666
- execCb: function (name, callback, args, exports) {
1667
- return callback.apply(exports, args);
1668
- },
1447
+ return localRequire;
1448
+ },
1449
+
1450
+ /**
1451
+ * Called to enable a module if it is still in the registry
1452
+ * awaiting enablement. parent module is passed in for context,
1453
+ * used by the optimizer.
1454
+ */
1455
+ enable: function (depMap, parent) {
1456
+ var mod = getOwn(registry, depMap.id);
1457
+ if (mod) {
1458
+ getModule(depMap).enable();
1459
+ }
1460
+ },
1461
+
1462
+ /**
1463
+ * Internal method used by environment adapters to complete a load event.
1464
+ * A load event could be a script load or just a load pass from a synchronous
1465
+ * load call.
1466
+ * @param {String} moduleName the name of the module to potentially complete.
1467
+ */
1468
+ completeLoad: function (moduleName) {
1469
+ var found, args, mod,
1470
+ shim = getOwn(config.shim, moduleName) || {},
1471
+ shExports = shim.exports;
1472
+
1473
+ takeGlobalQueue();
1474
+
1475
+ while (defQueue.length) {
1476
+ args = defQueue.shift();
1477
+ if (args[0] === null) {
1478
+ args[0] = moduleName;
1479
+ //If already found an anonymous module and bound it
1480
+ //to this name, then this is some other anon module
1481
+ //waiting for its completeLoad to fire.
1482
+ if (found) {
1483
+ break;
1484
+ }
1485
+ found = true;
1486
+ } else if (args[0] === moduleName) {
1487
+ //Found matching define call for this script!
1488
+ found = true;
1489
+ }
1669
1490
 
1670
- /**
1671
- * callback for script loads, used to check status of loading.
1672
- *
1673
- * @param {Event} evt the event from the browser for the script
1674
- * that was loaded.
1675
- */
1676
- onScriptLoad: function (evt) {
1677
- //Using currentTarget instead of target for Firefox 2.0's sake. Not
1678
- //all old browsers will be supported, but this one was easy enough
1679
- //to support and still makes sense.
1680
- if (evt.type === 'load' ||
1681
- (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1682
- //Reset interactive script so a script node is not held onto for
1683
- //to long.
1684
- interactiveScript = null;
1685
-
1686
- //Pull out the name of the module and the context.
1687
- var data = getScriptData(evt);
1688
- context.completeLoad(data.id);
1689
- }
1690
- },
1491
+ callGetModule(args);
1492
+ }
1691
1493
 
1692
- /**
1693
- * Callback for script errors.
1694
- */
1695
- onScriptError: function (evt) {
1696
- var data = getScriptData(evt);
1697
- if (!hasPathFallback(data.id)) {
1698
- return onError(makeError('scripterror', 'Script error', evt, [data.id]));
1699
- }
1700
- }
1701
- });
1702
- }
1494
+ //Do this after the cycle of callGetModule in case the result
1495
+ //of those calls/init calls changes the registry.
1496
+ mod = getOwn(registry, moduleName);
1703
1497
 
1704
- /**
1705
- * Main entry point.
1706
- *
1707
- * If the only argument to require is a string, then the module that
1708
- * is represented by that string is fetched for the appropriate context.
1709
- *
1710
- * If the first argument is an array, then it will be treated as an array
1711
- * of dependency string names to fetch. An optional function callback can
1712
- * be specified to execute when all of those dependencies are available.
1713
- *
1714
- * Make a local req variable to help Caja compliance (it assumes things
1715
- * on a require that are not standardized), and to give a short
1716
- * name for minification/local scope use.
1717
- */
1718
- req = requirejs = function (deps, callback, errback, optional) {
1719
-
1720
- //Find the right context, use default
1721
- var contextName = defContextName,
1722
- context, config;
1723
-
1724
- // Determine if have config object in the call.
1725
- if (!isArray(deps) && typeof deps !== 'string') {
1726
- // deps is a config object
1727
- config = deps;
1728
- if (isArray(callback)) {
1729
- // Adjust args if there are dependencies
1730
- deps = callback;
1731
- callback = errback;
1732
- errback = optional;
1498
+ if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1499
+ if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1500
+ if (hasPathFallback(moduleName)) {
1501
+ return;
1733
1502
  } else {
1734
- deps = [];
1503
+ return onError(makeError('nodefine',
1504
+ 'No define call for ' + moduleName,
1505
+ null,
1506
+ [moduleName]));
1735
1507
  }
1508
+ } else {
1509
+ //A script that does not call define(), so just simulate
1510
+ //the call for it.
1511
+ callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1512
+ }
1736
1513
  }
1737
1514
 
1738
- if (config && config.context) {
1739
- contextName = config.context;
1740
- }
1515
+ checkLoaded();
1516
+ },
1517
+
1518
+ /**
1519
+ * Converts a module name to a file path. Supports cases where
1520
+ * moduleName may actually be just an URL.
1521
+ * Note that it **does not** call normalize on the moduleName,
1522
+ * it is assumed to have already been normalized. This is an
1523
+ * internal API, not a public one. Use toUrl for the public API.
1524
+ */
1525
+ nameToUrl: function (moduleName, ext) {
1526
+ var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
1527
+ parentPath;
1528
+
1529
+ //If a colon is in the URL, it indicates a protocol is used and it is just
1530
+ //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1531
+ //or ends with .js, then assume the user meant to use an url and not a module id.
1532
+ //The slash is important for protocol-less URLs as well as full paths.
1533
+ if (req.jsExtRegExp.test(moduleName)) {
1534
+ //Just a plain path, not module name lookup, so just return it.
1535
+ //Add extension if it is included. This is a bit wonky, only non-.js things pass
1536
+ //an extension, this method probably needs to be reworked.
1537
+ url = moduleName + (ext || '');
1538
+ } else {
1539
+ //A module that needs to be converted to a path.
1540
+ paths = config.paths;
1541
+ pkgs = config.pkgs;
1542
+
1543
+ syms = moduleName.split('/');
1544
+ //For each module name segment, see if there is a path
1545
+ //registered for it. Start with most specific name
1546
+ //and work up from it.
1547
+ for (i = syms.length; i > 0; i -= 1) {
1548
+ parentModule = syms.slice(0, i).join('/');
1549
+ pkg = getOwn(pkgs, parentModule);
1550
+ parentPath = getOwn(paths, parentModule);
1551
+ if (parentPath) {
1552
+ //If an array, it means there are a few choices,
1553
+ //Choose the one that is desired
1554
+ if (isArray(parentPath)) {
1555
+ parentPath = parentPath[0];
1556
+ }
1557
+ syms.splice(0, i, parentPath);
1558
+ break;
1559
+ } else if (pkg) {
1560
+ //If module name is just the package name, then looking
1561
+ //for the main module.
1562
+ if (moduleName === pkg.name) {
1563
+ pkgPath = pkg.location + '/' + pkg.main;
1564
+ } else {
1565
+ pkgPath = pkg.location;
1566
+ }
1567
+ syms.splice(0, i, pkgPath);
1568
+ break;
1569
+ }
1570
+ }
1741
1571
 
1742
- context = contexts[contextName];
1743
- if (!context) {
1744
- context = contexts[contextName] = req.s.newContext(contextName);
1572
+ //Join the path parts together, then figure out if baseUrl is needed.
1573
+ url = syms.join('/');
1574
+ url += (ext || (/\?/.test(url) ? '' : '.js'));
1575
+ url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1745
1576
  }
1746
1577
 
1747
- if (config) {
1748
- context.configure(config);
1578
+ return config.urlArgs ? url +
1579
+ ((url.indexOf('?') === -1 ? '?' : '&') +
1580
+ config.urlArgs) : url;
1581
+ },
1582
+
1583
+ //Delegates to req.load. Broken out as a separate function to
1584
+ //allow overriding in the optimizer.
1585
+ load: function (id, url) {
1586
+ req.load(context, id, url);
1587
+ },
1588
+
1589
+ /**
1590
+ * Executes a module callack function. Broken out as a separate function
1591
+ * solely to allow the build system to sequence the files in the built
1592
+ * layer in the right sequence.
1593
+ *
1594
+ * @private
1595
+ */
1596
+ execCb: function (name, callback, args, exports) {
1597
+ return callback.apply(exports, args);
1598
+ },
1599
+
1600
+ /**
1601
+ * callback for script loads, used to check status of loading.
1602
+ *
1603
+ * @param {Event} evt the event from the browser for the script
1604
+ * that was loaded.
1605
+ */
1606
+ onScriptLoad: function (evt) {
1607
+ //Using currentTarget instead of target for Firefox 2.0's sake. Not
1608
+ //all old browsers will be supported, but this one was easy enough
1609
+ //to support and still makes sense.
1610
+ if (evt.type === 'load' ||
1611
+ (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1612
+ //Reset interactive script so a script node is not held onto for
1613
+ //to long.
1614
+ interactiveScript = null;
1615
+
1616
+ //Pull out the name of the module and the context.
1617
+ var data = getScriptData(evt);
1618
+ context.completeLoad(data.id);
1749
1619
  }
1750
-
1751
- return context.require(deps, callback, errback);
1752
- };
1753
-
1754
- /**
1755
- * Support require.config() to make it easier to cooperate with other
1756
- * AMD loaders on globally agreed names.
1757
- */
1758
- req.config = function (config) {
1759
- return req(config);
1620
+ },
1621
+
1622
+ /**
1623
+ * Callback for script errors.
1624
+ */
1625
+ onScriptError: function (evt) {
1626
+ var data = getScriptData(evt);
1627
+ if (!hasPathFallback(data.id)) {
1628
+ return onError(makeError('scripterror', 'Script error', evt, [data.id]));
1629
+ }
1630
+ }
1760
1631
  };
1761
1632
 
1762
- /**
1763
- * Export require as a global, but only if it does not already exist.
1764
- */
1765
- if (!require) {
1766
- require = req;
1633
+ context.require = context.makeRequire();
1634
+ return context;
1635
+ }
1636
+
1637
+ /**
1638
+ * Main entry point.
1639
+ *
1640
+ * If the only argument to require is a string, then the module that
1641
+ * is represented by that string is fetched for the appropriate context.
1642
+ *
1643
+ * If the first argument is an array, then it will be treated as an array
1644
+ * of dependency string names to fetch. An optional function callback can
1645
+ * be specified to execute when all of those dependencies are available.
1646
+ *
1647
+ * Make a local req variable to help Caja compliance (it assumes things
1648
+ * on a require that are not standardized), and to give a short
1649
+ * name for minification/local scope use.
1650
+ */
1651
+ req = requirejs = function (deps, callback, errback, optional) {
1652
+
1653
+ //Find the right context, use default
1654
+ var context, config,
1655
+ contextName = defContextName;
1656
+
1657
+ // Determine if have config object in the call.
1658
+ if (!isArray(deps) && typeof deps !== 'string') {
1659
+ // deps is a config object
1660
+ config = deps;
1661
+ if (isArray(callback)) {
1662
+ // Adjust args if there are dependencies
1663
+ deps = callback;
1664
+ callback = errback;
1665
+ errback = optional;
1666
+ } else {
1667
+ deps = [];
1668
+ }
1767
1669
  }
1768
1670
 
1769
- req.version = version;
1770
-
1771
- //Used to filter out dependencies that are already paths.
1772
- req.jsExtRegExp = /^\/|:|\?|\.js$/;
1773
- req.isBrowser = isBrowser;
1774
- s = req.s = {
1775
- contexts: contexts,
1776
- newContext: newContext
1777
- };
1778
-
1779
- //Create default context.
1780
- req({});
1671
+ if (config && config.context) {
1672
+ contextName = config.context;
1673
+ }
1781
1674
 
1782
- //Exports some context-sensitive methods on global require, using
1783
- //default context if no context specified.
1784
- addRequireMethods(req);
1675
+ context = getOwn(contexts, contextName);
1676
+ if (!context) {
1677
+ context = contexts[contextName] = req.s.newContext(contextName);
1678
+ }
1785
1679
 
1786
- if (isBrowser) {
1787
- head = s.head = document.getElementsByTagName('head')[0];
1788
- //If BASE tag is in play, using appendChild is a problem for IE6.
1789
- //When that browser dies, this can be removed. Details in this jQuery bug:
1790
- //http://dev.jquery.com/ticket/2709
1791
- baseElement = document.getElementsByTagName('base')[0];
1792
- if (baseElement) {
1793
- head = s.head = baseElement.parentNode;
1794
- }
1680
+ if (config) {
1681
+ context.configure(config);
1795
1682
  }
1796
1683
 
1797
- /**
1798
- * Any errors that require explicitly generates will be passed to this
1799
- * function. Intercept/override it if you want custom error handling.
1800
- * @param {Error} err the error object.
1801
- */
1802
- req.onError = function (err) {
1803
- throw err;
1684
+ return context.require(deps, callback, errback);
1685
+ };
1686
+
1687
+ /**
1688
+ * Support require.config() to make it easier to cooperate with other
1689
+ * AMD loaders on globally agreed names.
1690
+ */
1691
+ req.config = function (config) {
1692
+ return req(config);
1693
+ };
1694
+
1695
+ /**
1696
+ * Execute something after the current tick
1697
+ * of the event loop. Override for other envs
1698
+ * that have a better solution than setTimeout.
1699
+ * @param {Function} fn function to execute later.
1700
+ */
1701
+ req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
1702
+ setTimeout(fn, 4);
1703
+ } : function (fn) { fn(); };
1704
+
1705
+ /**
1706
+ * Export require as a global, but only if it does not already exist.
1707
+ */
1708
+ if (!require) {
1709
+ require = req;
1710
+ }
1711
+
1712
+ req.version = version;
1713
+
1714
+ //Used to filter out dependencies that are already paths.
1715
+ req.jsExtRegExp = /^\/|:|\?|\.js$/;
1716
+ req.isBrowser = isBrowser;
1717
+ s = req.s = {
1718
+ contexts: contexts,
1719
+ newContext: newContext
1720
+ };
1721
+
1722
+ //Create default context.
1723
+ req({});
1724
+
1725
+ //Exports some context-sensitive methods on global require.
1726
+ each([
1727
+ 'toUrl',
1728
+ 'undef',
1729
+ 'defined',
1730
+ 'specified'
1731
+ ], function (prop) {
1732
+ //Reference from contexts instead of early binding to default context,
1733
+ //so that during builds, the latest instance of the default context
1734
+ //with its config gets used.
1735
+ req[prop] = function () {
1736
+ var ctx = contexts[defContextName];
1737
+ return ctx.require[prop].apply(ctx, arguments);
1804
1738
  };
1805
-
1806
- /**
1807
- * Does the request to load a module for the browser case.
1808
- * Make this a separate function to allow other environments
1809
- * to override it.
1810
- *
1811
- * @param {Object} context the require context to find state.
1812
- * @param {String} moduleName the name of the module.
1813
- * @param {Object} url the URL to the module.
1814
- */
1815
- req.load = function (context, moduleName, url) {
1816
- var config = (context && context.config) || {},
1817
- node;
1818
- if (isBrowser) {
1819
- //In the browser so use a script tag
1820
- node = config.xhtml ?
1821
- document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
1822
- document.createElement('script');
1823
- node.type = config.scriptType || 'text/javascript';
1824
- node.charset = 'utf-8';
1825
-
1826
- node.setAttribute('data-requirecontext', context.contextName);
1827
- node.setAttribute('data-requiremodule', moduleName);
1828
-
1829
- //Set up load listener. Test attachEvent first because IE9 has
1830
- //a subtle issue in its addEventListener and script onload firings
1831
- //that do not match the behavior of all other browsers with
1832
- //addEventListener support, which fire the onload event for a
1833
- //script right after the script execution. See:
1834
- //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1835
- //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1836
- //script execution mode.
1837
- if (node.attachEvent &&
1838
- //Check if node.attachEvent is artificially added by custom script or
1839
- //natively supported by browser
1840
- //read https://github.com/jrburke/requirejs/issues/187
1841
- //if we can NOT find [native code] then it must NOT natively supported.
1842
- //in IE8, node.attachEvent does not have toString()
1843
- //Note the test for "[native code" with no closing brace, see:
1844
- //https://github.com/jrburke/requirejs/issues/273
1845
- !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
1846
- !isOpera) {
1847
- //Probably IE. IE (at least 6-8) do not fire
1848
- //script onload right after executing the script, so
1849
- //we cannot tie the anonymous define call to a name.
1850
- //However, IE reports the script as being in 'interactive'
1851
- //readyState at the time of the define call.
1852
- useInteractive = true;
1853
-
1854
- node.attachEvent('onreadystatechange', context.onScriptLoad);
1855
- //It would be great to add an error handler here to catch
1856
- //404s in IE9+. However, onreadystatechange will fire before
1857
- //the error handler, so that does not help. If addEvenListener
1858
- //is used, then IE will fire error before load, but we cannot
1859
- //use that pathway given the connect.microsoft.com issue
1860
- //mentioned above about not doing the 'script execute,
1861
- //then fire the script load event listener before execute
1862
- //next script' that other browsers do.
1863
- //Best hope: IE10 fixes the issues,
1864
- //and then destroys all installs of IE 6-9.
1865
- //node.attachEvent('onerror', context.onScriptError);
1866
- } else {
1867
- node.addEventListener('load', context.onScriptLoad, false);
1868
- node.addEventListener('error', context.onScriptError, false);
1869
- }
1870
- node.src = url;
1871
-
1872
- //For some cache cases in IE 6-8, the script executes before the end
1873
- //of the appendChild execution, so to tie an anonymous define
1874
- //call to the module name (which is stored on the node), hold on
1875
- //to a reference to this node, but clear after the DOM insertion.
1876
- currentlyAddingScript = node;
1877
- if (baseElement) {
1878
- head.insertBefore(node, baseElement);
1879
- } else {
1880
- head.appendChild(node);
1881
- }
1882
- currentlyAddingScript = null;
1883
-
1884
- return node;
1885
- } else if (isWebWorker) {
1886
- //In a web worker, use importScripts. This is not a very
1887
- //efficient use of importScripts, importScripts will block until
1888
- //its script is downloaded and evaluated. However, if web workers
1889
- //are in play, the expectation that a build has been done so that
1890
- //only one script needs to be loaded anyway. This may need to be
1891
- //reevaluated if other use cases become common.
1892
- importScripts(url);
1893
-
1894
- //Account for anonymous modules
1895
- context.completeLoad(moduleName);
1896
- }
1897
- };
1898
-
1899
- function getInteractiveScript() {
1900
- if (interactiveScript && interactiveScript.readyState === 'interactive') {
1901
- return interactiveScript;
1902
- }
1903
-
1904
- eachReverse(scripts(), function (script) {
1905
- if (script.readyState === 'interactive') {
1906
- return (interactiveScript = script);
1907
- }
1908
- });
1909
- return interactiveScript;
1739
+ });
1740
+
1741
+ if (isBrowser) {
1742
+ head = s.head = document.getElementsByTagName('head')[0];
1743
+ //If BASE tag is in play, using appendChild is a problem for IE6.
1744
+ //When that browser dies, this can be removed. Details in this jQuery bug:
1745
+ //http://dev.jquery.com/ticket/2709
1746
+ baseElement = document.getElementsByTagName('base')[0];
1747
+ if (baseElement) {
1748
+ head = s.head = baseElement.parentNode;
1910
1749
  }
1911
-
1912
- //Look for a data-main script attribute, which could also adjust the baseUrl.
1750
+ }
1751
+
1752
+ /**
1753
+ * Any errors that require explicitly generates will be passed to this
1754
+ * function. Intercept/override it if you want custom error handling.
1755
+ * @param {Error} err the error object.
1756
+ */
1757
+ req.onError = function (err) {
1758
+ throw err;
1759
+ };
1760
+
1761
+ /**
1762
+ * Does the request to load a module for the browser case.
1763
+ * Make this a separate function to allow other environments
1764
+ * to override it.
1765
+ *
1766
+ * @param {Object} context the require context to find state.
1767
+ * @param {String} moduleName the name of the module.
1768
+ * @param {Object} url the URL to the module.
1769
+ */
1770
+ req.load = function (context, moduleName, url) {
1771
+ var config = (context && context.config) || {},
1772
+ node;
1913
1773
  if (isBrowser) {
1914
- //Figure out baseUrl. Get it from the script tag with require.js in it.
1915
- eachReverse(scripts(), function (script) {
1916
- //Set the 'head' where we can append children by
1917
- //using the script's parent.
1918
- if (!head) {
1919
- head = script.parentNode;
1920
- }
1921
-
1922
- //Look for a data-main attribute to set main script for the page
1923
- //to load. If it is there, the path to data main becomes the
1924
- //baseUrl, if it is not already set.
1925
- dataMain = script.getAttribute('data-main');
1926
- if (dataMain) {
1927
-
1928
- //Pull off the directory of data-main for use as the
1929
- //baseUrl.
1930
- src = dataMain.split('/');
1931
- mainScript = src.pop();
1932
- subPath = src.length ? src.join('/') + '/' : './';
1933
-
1934
- //Set final baseUrl if there is not already an explicit one.
1935
- if (!cfg.baseUrl) {
1936
- cfg.baseUrl = subPath;
1937
- }
1938
-
1939
- //Strip off any trailing .js since dataMain is now
1940
- //like a module name.
1941
- dataMain = mainScript.replace(jsSuffixRegExp, '');
1942
-
1943
- //Put the data-main script in the files to load.
1944
- cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
1945
-
1946
- return true;
1947
- }
1948
- });
1774
+ //In the browser so use a script tag
1775
+ node = config.xhtml ?
1776
+ document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
1777
+ document.createElement('script');
1778
+ node.type = config.scriptType || 'text/javascript';
1779
+ node.charset = 'utf-8';
1780
+ node.async = true;
1781
+
1782
+ node.setAttribute('data-requirecontext', context.contextName);
1783
+ node.setAttribute('data-requiremodule', moduleName);
1784
+
1785
+ //Set up load listener. Test attachEvent first because IE9 has
1786
+ //a subtle issue in its addEventListener and script onload firings
1787
+ //that do not match the behavior of all other browsers with
1788
+ //addEventListener support, which fire the onload event for a
1789
+ //script right after the script execution. See:
1790
+ //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1791
+ //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1792
+ //script execution mode.
1793
+ if (node.attachEvent &&
1794
+ //Check if node.attachEvent is artificially added by custom script or
1795
+ //natively supported by browser
1796
+ //read https://github.com/jrburke/requirejs/issues/187
1797
+ //if we can NOT find [native code] then it must NOT natively supported.
1798
+ //in IE8, node.attachEvent does not have toString()
1799
+ //Note the test for "[native code" with no closing brace, see:
1800
+ //https://github.com/jrburke/requirejs/issues/273
1801
+ !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
1802
+ !isOpera) {
1803
+ //Probably IE. IE (at least 6-8) do not fire
1804
+ //script onload right after executing the script, so
1805
+ //we cannot tie the anonymous define call to a name.
1806
+ //However, IE reports the script as being in 'interactive'
1807
+ //readyState at the time of the define call.
1808
+ useInteractive = true;
1809
+
1810
+ node.attachEvent('onreadystatechange', context.onScriptLoad);
1811
+ //It would be great to add an error handler here to catch
1812
+ //404s in IE9+. However, onreadystatechange will fire before
1813
+ //the error handler, so that does not help. If addEvenListener
1814
+ //is used, then IE will fire error before load, but we cannot
1815
+ //use that pathway given the connect.microsoft.com issue
1816
+ //mentioned above about not doing the 'script execute,
1817
+ //then fire the script load event listener before execute
1818
+ //next script' that other browsers do.
1819
+ //Best hope: IE10 fixes the issues,
1820
+ //and then destroys all installs of IE 6-9.
1821
+ //node.attachEvent('onerror', context.onScriptError);
1822
+ } else {
1823
+ node.addEventListener('load', context.onScriptLoad, false);
1824
+ node.addEventListener('error', context.onScriptError, false);
1825
+ }
1826
+ node.src = url;
1827
+
1828
+ //For some cache cases in IE 6-8, the script executes before the end
1829
+ //of the appendChild execution, so to tie an anonymous define
1830
+ //call to the module name (which is stored on the node), hold on
1831
+ //to a reference to this node, but clear after the DOM insertion.
1832
+ currentlyAddingScript = node;
1833
+ if (baseElement) {
1834
+ head.insertBefore(node, baseElement);
1835
+ } else {
1836
+ head.appendChild(node);
1837
+ }
1838
+ currentlyAddingScript = null;
1839
+
1840
+ return node;
1841
+ } else if (isWebWorker) {
1842
+ //In a web worker, use importScripts. This is not a very
1843
+ //efficient use of importScripts, importScripts will block until
1844
+ //its script is downloaded and evaluated. However, if web workers
1845
+ //are in play, the expectation that a build has been done so that
1846
+ //only one script needs to be loaded anyway. This may need to be
1847
+ //reevaluated if other use cases become common.
1848
+ importScripts(url);
1849
+
1850
+ //Account for anonymous modules
1851
+ context.completeLoad(moduleName);
1949
1852
  }
1853
+ };
1950
1854
 
1951
- /**
1952
- * The function that handles definitions of modules. Differs from
1953
- * require() in that a string for the module should be the first argument,
1954
- * and the function to execute after dependencies are loaded should
1955
- * return a value to define the module corresponding to the first argument's
1956
- * name.
1957
- */
1958
- define = function (name, deps, callback) {
1959
- var node, context;
1960
-
1961
- //Allow for anonymous functions
1962
- if (typeof name !== 'string') {
1963
- //Adjust args appropriately
1964
- callback = deps;
1965
- deps = name;
1966
- name = null;
1967
- }
1968
-
1969
- //This module may not have dependencies
1970
- if (!isArray(deps)) {
1971
- callback = deps;
1972
- deps = [];
1973
- }
1855
+ function getInteractiveScript() {
1856
+ if (interactiveScript && interactiveScript.readyState === 'interactive') {
1857
+ return interactiveScript;
1858
+ }
1974
1859
 
1975
- //If no name, and callback is a function, then figure out if it a
1976
- //CommonJS thing with dependencies.
1977
- if (!deps.length && isFunction(callback)) {
1978
- //Remove comments from the callback string,
1979
- //look for require calls, and pull them into the dependencies,
1980
- //but only if there are function args.
1981
- if (callback.length) {
1982
- callback
1983
- .toString()
1984
- .replace(commentRegExp, '')
1985
- .replace(cjsRequireRegExp, function (match, dep) {
1986
- deps.push(dep);
1987
- });
1988
-
1989
- //May be a CommonJS thing even without require calls, but still
1990
- //could use exports, and module. Avoid doing exports and module
1991
- //work though if it just needs require.
1992
- //REQUIRES the function to expect the CommonJS variables in the
1993
- //order listed below.
1994
- deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
1995
- }
1860
+ eachReverse(scripts(), function (script) {
1861
+ if (script.readyState === 'interactive') {
1862
+ return (interactiveScript = script);
1863
+ }
1864
+ });
1865
+ return interactiveScript;
1866
+ }
1867
+
1868
+ //Look for a data-main script attribute, which could also adjust the baseUrl.
1869
+ if (isBrowser) {
1870
+ //Figure out baseUrl. Get it from the script tag with require.js in it.
1871
+ eachReverse(scripts(), function (script) {
1872
+ //Set the 'head' where we can append children by
1873
+ //using the script's parent.
1874
+ if (!head) {
1875
+ head = script.parentNode;
1876
+ }
1877
+
1878
+ //Look for a data-main attribute to set main script for the page
1879
+ //to load. If it is there, the path to data main becomes the
1880
+ //baseUrl, if it is not already set.
1881
+ dataMain = script.getAttribute('data-main');
1882
+ if (dataMain) {
1883
+ //Set final baseUrl if there is not already an explicit one.
1884
+ if (!cfg.baseUrl) {
1885
+ //Pull off the directory of data-main for use as the
1886
+ //baseUrl.
1887
+ src = dataMain.split('/');
1888
+ mainScript = src.pop();
1889
+ subPath = src.length ? src.join('/') + '/' : './';
1890
+
1891
+ cfg.baseUrl = subPath;
1892
+ dataMain = mainScript;
1996
1893
  }
1997
1894
 
1998
- //If in IE 6-8 and hit an anonymous define() call, do the interactive
1999
- //work.
2000
- if (useInteractive) {
2001
- node = currentlyAddingScript || getInteractiveScript();
2002
- if (node) {
2003
- if (!name) {
2004
- name = node.getAttribute('data-requiremodule');
2005
- }
2006
- context = contexts[node.getAttribute('data-requirecontext')];
2007
- }
2008
- }
1895
+ //Strip off any trailing .js since dataMain is now
1896
+ //like a module name.
1897
+ dataMain = dataMain.replace(jsSuffixRegExp, '');
1898
+
1899
+ //Put the data-main script in the files to load.
1900
+ cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
1901
+
1902
+ return true;
1903
+ }
1904
+ });
1905
+ }
1906
+
1907
+ /**
1908
+ * The function that handles definitions of modules. Differs from
1909
+ * require() in that a string for the module should be the first argument,
1910
+ * and the function to execute after dependencies are loaded should
1911
+ * return a value to define the module corresponding to the first argument's
1912
+ * name.
1913
+ */
1914
+ define = function (name, deps, callback) {
1915
+ var node, context;
1916
+
1917
+ //Allow for anonymous modules
1918
+ if (typeof name !== 'string') {
1919
+ //Adjust args appropriately
1920
+ callback = deps;
1921
+ deps = name;
1922
+ name = null;
1923
+ }
2009
1924
 
2010
- //Always save off evaluating the def call until the script onload handler.
2011
- //This allows multiple modules to be in a file without prematurely
2012
- //tracing dependencies, and allows for anonymous module support,
2013
- //where the module name is not known until the script onload event
2014
- //occurs. If no context, use the global queue, and get it processed
2015
- //in the onscript load callback.
2016
- (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
2017
- };
1925
+ //This module may not have dependencies
1926
+ if (!isArray(deps)) {
1927
+ callback = deps;
1928
+ deps = [];
1929
+ }
2018
1930
 
2019
- define.amd = {
2020
- jQuery: true
2021
- };
1931
+ //If no name, and callback is a function, then figure out if it a
1932
+ //CommonJS thing with dependencies.
1933
+ if (!deps.length && isFunction(callback)) {
1934
+ //Remove comments from the callback string,
1935
+ //look for require calls, and pull them into the dependencies,
1936
+ //but only if there are function args.
1937
+ if (callback.length) {
1938
+ callback
1939
+ .toString()
1940
+ .replace(commentRegExp, '')
1941
+ .replace(cjsRequireRegExp, function (match, dep) {
1942
+ deps.push(dep);
1943
+ });
2022
1944
 
1945
+ //May be a CommonJS thing even without require calls, but still
1946
+ //could use exports, and module. Avoid doing exports and module
1947
+ //work though if it just needs require.
1948
+ //REQUIRES the function to expect the CommonJS variables in the
1949
+ //order listed below.
1950
+ deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
1951
+ }
1952
+ }
2023
1953
 
2024
- /**
2025
- * Executes the text. Normally just uses eval, but can be modified
2026
- * to use a better, environment-specific call. Only used for transpiling
2027
- * loader plugins, not for plain JS modules.
2028
- * @param {String} text the text to execute/evaluate.
2029
- */
2030
- req.exec = function (text) {
2031
- /*jslint evil: true */
2032
- return eval(text);
2033
- };
1954
+ //If in IE 6-8 and hit an anonymous define() call, do the interactive
1955
+ //work.
1956
+ if (useInteractive) {
1957
+ node = currentlyAddingScript || getInteractiveScript();
1958
+ if (node) {
1959
+ if (!name) {
1960
+ name = node.getAttribute('data-requiremodule');
1961
+ }
1962
+ context = contexts[node.getAttribute('data-requirecontext')];
1963
+ }
1964
+ }
2034
1965
 
2035
- //Set up with config info.
2036
- req(cfg);
1966
+ //Always save off evaluating the def call until the script onload handler.
1967
+ //This allows multiple modules to be in a file without prematurely
1968
+ //tracing dependencies, and allows for anonymous module support,
1969
+ //where the module name is not known until the script onload event
1970
+ //occurs. If no context, use the global queue, and get it processed
1971
+ //in the onscript load callback.
1972
+ (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);
1973
+ };
1974
+
1975
+ define.amd = {
1976
+ jQuery: true
1977
+ };
1978
+
1979
+
1980
+ /**
1981
+ * Executes the text. Normally just uses eval, but can be modified
1982
+ * to use a better, environment-specific call. Only used for transpiling
1983
+ * loader plugins, not for plain JS modules.
1984
+ * @param {String} text the text to execute/evaluate.
1985
+ */
1986
+ req.exec = function (text) {
1987
+ /*jslint evil: true */
1988
+ return eval(text);
1989
+ };
1990
+
1991
+ //Set up with config info.
1992
+ req(cfg);
2037
1993
  }(this));