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