]> git.wh0rd.org Git - tt-rss.git/blob - lib/dojo/_base/loader.js.uncompressed.js
23f0b6db8f8f29bb8ffbd4839ec9e4f3d9428f74
[tt-rss.git] / lib / dojo / _base / loader.js.uncompressed.js
1 define("dojo/_base/loader", ["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) {
2         // module:
3         //              dojo/_base/loader
4
5         //              This module defines the v1.x synchronous loader API.
6
7         // signal the loader in sync mode...
8         //>>pure-amd
9
10         if (! 1 ){
11                 console.error("cannot load the Dojo v1.x loader with a foreign loader");
12                 return 0;
13         }
14
15          1 || has.add("dojo-fast-sync-require", 1);
16
17
18         var makeErrorToken = function(id){
19                         return {src:thisModule.id, id:id};
20                 },
21
22                 slashName = function(name){
23                         return name.replace(/\./g, "/");
24                 },
25
26                 buildDetectRe = /\/\/>>built/,
27
28                 dojoRequireCallbacks = [],
29                 dojoRequireModuleStack = [],
30
31                 dojoRequirePlugin = function(mid, require, loaded){
32                         dojoRequireCallbacks.push(loaded);
33                         array.forEach(mid.split(","), function(mid){
34                                 var module = getModule(mid, require.module);
35                                 dojoRequireModuleStack.push(module);
36                                 injectModule(module);
37                         });
38                         checkDojoRequirePlugin();
39                 },
40
41                 checkDojoRequirePlugin = ( 1  ?
42                         // This version of checkDojoRequirePlugin makes the observation that all dojoRequireCallbacks can be released
43                         // when all *non-dojo/require!, dojo/loadInit!* modules are either executed, not requested, or arrived. This is
44                         // the case since there are no more modules the loader is waiting for, therefore, dojo/require! must have
45                         // everything it needs on board.
46                         //
47                         // The potential weakness of this algorithm is that dojo/require will not execute callbacks until *all* dependency
48                         // trees are ready. It is possible that some trees may be ready earlier than others, and this extra wait is non-optimal.
49                         // Still, for big projects, this seems better than the original algorithm below that proved slow in some cases.
50                         // Note, however, the original algorithm had the potential to execute partial trees,  but that potential was never enabled.
51                         // There are also other optimization available with the original algorithm that have not been explored.
52                         function(){
53                                 var module, mid;
54                                 for(mid in modules){
55                                         module = modules[mid];
56                                         if(module.noReqPluginCheck===undefined){
57                                                 // tag the module as either a loadInit or require plugin or not for future reference
58                                                 module.noReqPluginCheck = /loadInit\!/.test(mid) || /require\!/.test(mid) ? 1 : 0;
59                                         }
60                                         if(!module.executed && !module.noReqPluginCheck && module.injected==requested){
61                                                 return;
62                                         }
63                                 }
64
65                                 guardCheckComplete(function(){
66                                         var oldCallbacks = dojoRequireCallbacks;
67                                         dojoRequireCallbacks = [];
68                                         array.forEach(oldCallbacks, function(cb){cb(1);});
69                                 });
70                 } : (function(){
71                         // Note: this is the original checkDojoRequirePlugin that is much slower than the algorithm above. However, we know it
72                         // works, so we leave it here in case the algorithm above fails in some corner case.
73                         //
74                         // checkDojoRequirePlugin inspects all of the modules demanded by a dojo/require!<module-list> dependency
75                         // to see if they have arrived. The loader does not release *any* of these modules to be instantiated
76                         // until *all* of these modules are on board, thereby preventing the evaluation of a module with dojo.require's
77                         // that reference modules that are not available.
78                         //
79                         // The algorithm works by traversing the dependency graphs (remember, there can be cycles so they are not trees)
80                         // of each module in the dojoRequireModuleStack array (which contains the list of modules demanded by dojo/require!).
81                         // The moment a single module is discovered that is missing, the algorithm gives up and indicates that not all
82                         // modules are on board. dojo/loadInit! and dojo/require! are ignored because there dependencies are inserted
83                         // directly in dojoRequireModuleStack. For example, if "your/module" module depends on "dojo/require!my/module", then
84                         // *both* "dojo/require!my/module" and "my/module" will be in dojoRequireModuleStack. Obviously, if "my/module"
85                         // is on board, then "dojo/require!my/module" is also satisfied, so the algorithm doesn't check for "dojo/require!my/module".
86                         //
87                         // Note: inserting a dojo/require!<some-module-list> dependency in the dojoRequireModuleStack achieves nothing
88                         // with the current algorithm; however, having such modules present makes it possible to optimize the algorithm
89                         //
90                         // Note: prior versions of this algorithm had an optimization that signaled loaded on dojo/require! dependencies
91                         // individually (rather than waiting for them all to be resolved). The implementation proved problematic with cycles
92                         // and plugins. However, it is possible to reattach that strategy in the future.
93
94                         // a set from module-id to {undefined | 1 | 0}, where...
95                         //       undefined => the module has not been inspected
96                         //       0 => the module or at least one of its dependencies has not arrived
97                         //       1 => the module is a loadInit! or require! plugin resource, or is currently being traversed (therefore, assume
98                         //                OK until proven otherwise), or has been completely traversed and all dependencies have arrived
99
100                         var touched,
101                         traverse = function(m){
102                                 touched[m.mid] = 1;
103                                 for(var t, module, deps = m.deps || [], i= 0; i<deps.length; i++){
104                                         module = deps[i];
105                                         if(!(t = touched[module.mid])){
106                                                 if(t===0 || !traverse(module)){
107                                                         touched[m.mid] = 0;
108                                                         return false;
109                                                 }
110                                         }
111                                 }
112                                 return true;
113                         };
114
115                         return function(){
116                                 // initialize the touched hash with easy-to-compute values that help short circuit recursive algorithm;
117                                 // recall loadInit/require plugin modules are dependencies of modules in dojoRequireModuleStack...
118                                 // which would cause a circular dependency chain that would never be resolved if checked here
119                                 // notice all dependencies of any particular loadInit/require plugin module will already
120                                 // be checked since those are pushed into dojoRequireModuleStack explicitly by the
121                                 // plugin...so if a particular loadInitPlugin module's dependencies are not really
122                                 // on board, that *will* be detected elsewhere in the traversal.
123                                 var module, mid;
124                                 touched = {};
125                                 for(mid in modules){
126                                         module = modules[mid];
127                                         if(module.executed || module.noReqPluginCheck){
128                                                 touched[mid] = 1;
129                                         }else{
130                                                 if(module.noReqPluginCheck!==0){
131                                                         // tag the module as either a loadInit or require plugin or not for future reference
132                                                         module.noReqPluginCheck = /loadInit\!/.test(mid) || /require\!/.test(mid) ? 1 : 0;
133                                                 }
134                                                 if(module.noReqPluginCheck){
135                                                         touched[mid] = 1;
136                                                 }else if(module.injected!==arrived){
137                                                         // not executed, has not arrived, and is not a loadInit or require plugin resource
138                                                         touched[mid] = 0;
139                                                 }// else, leave undefined and we'll traverse the dependencies
140                                         }
141                                 }
142                                 for(var t, i = 0, end = dojoRequireModuleStack.length; i<end; i++){
143                                         module = dojoRequireModuleStack[i];
144                                         if(!(t = touched[module.mid])){
145                                                 if(t===0 || !traverse(module)){
146                                                         return;
147                                                 }
148                                         }
149                                 }
150                                 guardCheckComplete(function(){
151                                         var oldCallbacks = dojoRequireCallbacks;
152                                         dojoRequireCallbacks = [];
153                                         array.forEach(oldCallbacks, function(cb){cb(1);});
154                                 });
155                         };
156                 })()),
157
158                 dojoLoadInitPlugin = function(mid, require, loaded){
159                         // mid names a module that defines a "dojo load init" bundle, an object with two properties:
160                         //
161                         //       * names: a vector of module ids that give top-level names to define in the lexical scope of def
162                         //       * def: a function that contains some some legacy loader API applications
163                         //
164                         // The point of def is to possibly cause some modules to be loaded (but not executed) by dojo/require! where the module
165                         // ids are possibly-determined at runtime. For example, here is dojox.gfx from v1.6 expressed as an AMD module using the dojo/loadInit
166                         // and dojo/require plugins.
167                         //
168                         // // dojox/gfx:
169                         //
170                         //       define("*loadInit_12, {
171                         //         names:["dojo", "dijit", "dojox"],
172                         //         def: function(){
173                         //               dojo.loadInit(function(){
174                         //                 var gfx = lang.getObject("dojox.gfx", true);
175                         //
176                         //                 //
177                         //                 // code required to set gfx properties ommitted...
178                         //                 //
179                         //
180                         //                 // now use the calculations to include the runtime-dependent module
181                         //                 dojo.require("dojox.gfx." + gfx.renderer);
182                         //               });
183                         //         }
184                         //       });
185                         //
186                         //       define(["dojo", "dojo/loadInit!" + id].concat("dojo/require!dojox/gfx/matric,dojox/gfx/_base"), function(dojo){
187                         //         // when this AMD factory function is executed, the following modules are guaranteed downloaded but not executed:
188                         //         //   "dojox.gfx." + gfx.renderer
189                         //         //   dojox.gfx.matrix
190                         //         //   dojox.gfx._base
191                         //         dojo.provide("dojo.gfx");
192                         //         dojo.require("dojox.gfx.matrix");
193                         //         dojo.require("dojox.gfx._base");
194                         //         dojo.require("dojox.gfx." + gfx.renderer);
195                         //         return lang.getObject("dojo.gfx");
196                         //       });
197                         //      })();
198                         //
199                         // The idea is to run the legacy loader API with global variables shadowed, which allows these variables to
200                         // be relocated. For example, dojox and dojo could be relocated to different names by giving a map and the code above will
201                         // execute properly (because the plugin below resolves the load init bundle.names module with respect to the module that demanded
202                         // the plugin resource).
203                         //
204                         // Note that the relocation is specified in the runtime configuration; relocated names need not be set at build-time.
205                         //
206                         // Warning: this is not the best way to express dojox.gfx as and AMD module. In fact, the module has been properly converted in
207                         // v1.7. However, this technique allows the builder to convert legacy modules into AMD modules and guarantee the codepath is the
208                         // same in the converted AMD module.
209                         require([mid], function(bundle){
210                                 // notice how names is resolved with respect to the module that demanded the plugin resource
211                                 require(bundle.names, function(){
212                                         // bring the bundle names into scope
213                                         for(var scopeText = "", args= [], i = 0; i<arguments.length; i++){
214                                                 scopeText+= "var " + bundle.names[i] + "= arguments[" + i + "]; ";
215                                                 args.push(arguments[i]);
216                                         }
217                                         eval(scopeText);
218
219                                         var callingModule = require.module,
220                                                 // the list of modules that need to be downloaded but not executed before the callingModule can be executed
221                                                 requireList = [],
222
223                                                 // the list of i18n bundles that are xdomain; undefined if none
224                                                 i18nDeps,
225
226                                                 syncLoaderApi = {
227                                                         provide:function(moduleName){
228                                                                 // mark modules that arrive consequent to multiple provides in this module as arrived since they can't be injected
229                                                                 moduleName = slashName(moduleName);
230                                                                 var providedModule = getModule(moduleName, callingModule);
231                                                                 if(providedModule!==callingModule){
232                                                                         setArrived(providedModule);
233                                                                 }
234                                                         },
235                                                         require:function(moduleName, omitModuleCheck){
236                                                                 moduleName = slashName(moduleName);
237                                                                 omitModuleCheck && (getModule(moduleName, callingModule).result = nonmodule);
238                                                                 requireList.push(moduleName);
239                                                         },
240                                                         requireLocalization:function(moduleName, bundleName, locale){
241                                                                 // since we're going to need dojo/i8n, add it to i18nDeps if not already there
242                                                                 if(!i18nDeps){
243                                                                         // don't have to map since that will occur when the dependency is resolved
244                                                                         i18nDeps = ["dojo/i18n"];
245                                                                 }
246
247                                                                 // figure out if the bundle is xdomain; if so, add it to the i18nDepsSet
248                                                                 locale = (locale || dojo.locale).toLowerCase();
249                                                                 moduleName = slashName(moduleName) + "/nls/" + (/root/i.test(locale) ? "" : locale + "/") + slashName(bundleName);
250                                                                 if(getModule(moduleName, callingModule).isXd){
251                                                                         // don't have to map since that will occur when the dependency is resolved
252                                                                         i18nDeps.push("dojo/i18n!" + moduleName);
253                                                                 }// else the bundle will be loaded synchronously when the module is evaluated
254                                                         },
255                                                         loadInit:function(f){
256                                                                 f();
257                                                         }
258                                                 },
259
260                                                 hold = {},
261                                                 p;
262
263                                         // hijack the correct dojo and apply bundle.def
264                                         try{
265                                                 for(p in syncLoaderApi){
266                                                         hold[p] = dojo[p];
267                                                         dojo[p] = syncLoaderApi[p];
268                                                 }
269                                                 bundle.def.apply(null, args);
270                                         }catch(e){
271                                                 signal("error", [makeErrorToken("failedDojoLoadInit"), e]);
272                                         }finally{
273                                                 for(p in syncLoaderApi){
274                                                         dojo[p] = hold[p];
275                                                 }
276                                         }
277
278                                         if(i18nDeps){
279                                                 requireList = requireList.concat(i18nDeps);
280                                         }
281
282                                         if(requireList.length){
283                                                 dojoRequirePlugin(requireList.join(","), require, loaded);
284                                         }else{
285                                                 loaded();
286                                         }
287                                 });
288                         });
289                 },
290
291                 extractApplication = function(
292                         text,                     // the text to search
293                         startSearch,      // the position in text to start looking for the closing paren
294                         startApplication  // the position in text where the function application expression starts
295                 ){
296                         // find end of the call by finding the matching end paren
297                         // Warning: as usual, this will fail in the presense of unmatched right parans contained in strings, regexs, or unremoved comments
298                         var parenRe = /\(|\)/g,
299                                 matchCount = 1,
300                                 match;
301                         parenRe.lastIndex = startSearch;
302                         while((match = parenRe.exec(text))){
303                                 if(match[0] == ")"){
304                                         matchCount -= 1;
305                                 }else{
306                                         matchCount += 1;
307                                 }
308                                 if(matchCount == 0){
309                                         break;
310                                 }
311                         }
312
313                         if(matchCount != 0){
314                                 throw "unmatched paren around character " + parenRe.lastIndex + " in: " + text;
315                         }
316
317                         //Put the master matching string in the results.
318                         return [dojo.trim(text.substring(startApplication, parenRe.lastIndex))+";\n", parenRe.lastIndex];
319                 },
320
321                 // the following regex is taken from 1.6. It is a very poor technique to remove comments and
322                 // will fail in some cases; for example, consider the code...
323                 //
324                 //        var message = "Category-1 */* Category-2";
325                 //
326                 // The regex that follows will see a /* comment and trash the code accordingly. In fact, there are all
327                 // kinds of cases like this with strings and regexs that will cause this design to fail miserably.
328                 //
329                 // Alternative regex designs exist that will result in less-likely failures, but will still fail in many cases.
330                 // The only solution guaranteed 100% correct is to parse the code and that seems overkill for this
331                 // backcompat/unbuilt-xdomain layer. In the end, since it's been this way for a while, we won't change it.
332                 // See the opening paragraphs of Chapter 7 or ECME-262 which describes the lexical abiguity further.
333                 removeCommentRe = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,
334
335                 syncLoaderApiRe = /(^|\s)dojo\.(loadInit|require|provide|requireLocalization|requireIf|requireAfterIf|platformRequire)\s*\(/mg,
336
337                 amdLoaderApiRe = /(^|\s)(require|define)\s*\(/m,
338
339                 extractLegacyApiApplications = function(text, noCommentText){
340                         // scan the noCommentText for any legacy loader API applications. Copy such applications into result (this is
341                         // used by the builder). Move dojo.loadInit applications to loadInitApplications string. Copy all other applications
342                         // to otherApplications string. If no applications were found, return 0, signalling an AMD module. Otherwise, return
343                         // loadInitApplications + otherApplications. Fixup text by replacing
344                         //
345                         //       dojo.loadInit(// etc...
346                         //
347                         // with
348                         //
349                         //       \n 0 && dojo.loadInit(// etc...
350                         //
351                         // Which results in the dojo.loadInit from *not* being applied. This design goes a long way towards protecting the
352                         // code from an over-agressive removeCommentRe. However...
353                         //
354                         // WARNING: the removeCommentRe will cause an error if a detected comment removes all or part of a legacy-loader application
355                         // that is not in a comment.
356
357                         var match, startSearch, startApplication, application,
358                                 loadInitApplications = [],
359                                 otherApplications = [],
360                                 allApplications = [];
361
362                         // noCommentText may be provided by a build app with comments extracted by a better method than regex (hopefully)
363                         noCommentText = noCommentText || text.replace(removeCommentRe, function(match){
364                                 // remove iff the detected comment has text that looks like a sync loader API application; this helps by
365                                 // removing as little as possible, minimizing the changes the janky regex will kill the module
366                                 syncLoaderApiRe.lastIndex = amdLoaderApiRe.lastIndex = 0;
367                                 return (syncLoaderApiRe.test(match) || amdLoaderApiRe.test(match)) ? "" : match;
368                         });
369
370                         // find and extract all dojo.loadInit applications
371                         while((match = syncLoaderApiRe.exec(noCommentText))){
372                                 startSearch = syncLoaderApiRe.lastIndex;
373                                 startApplication = startSearch  - match[0].length;
374                                 application = extractApplication(noCommentText, startSearch, startApplication);
375                                 if(match[2]=="loadInit"){
376                                         loadInitApplications.push(application[0]);
377                                 }else{
378                                         otherApplications.push(application[0]);
379                                 }
380                                 syncLoaderApiRe.lastIndex = application[1];
381                         }
382                         allApplications = loadInitApplications.concat(otherApplications);
383                         if(allApplications.length || !amdLoaderApiRe.test(noCommentText)){
384                                 // either there were some legacy loader API applications or there were no AMD API applications
385                                 return [text.replace(/(^|\s)dojo\.loadInit\s*\(/g, "\n0 && dojo.loadInit("), allApplications.join(""), allApplications];
386                         }else{
387                                 // legacy loader API *was not* detected and AMD API *was* detected; therefore, assume it's an AMD module
388                                 return 0;
389                         }
390                 },
391
392                 transformToAmd = function(module, text){
393                         // This is roughly the equivalent of dojo._xdCreateResource in 1.6-; however, it expresses a v1.6- dojo
394                         // module in terms of AMD define instead of creating the dojo proprietary xdomain module expression.
395                         // The module could have originated from several sources:
396                         //
397                         //       * amd require() a module, e.g., require(["my/module"])
398                         //       * amd require() a nonmodule, e.g., require(["my/resource.js"')
399                         //       * amd define() deps vector (always a module)
400                         //       * dojo.require() a module, e.g. dojo.require("my.module")
401                         //       * dojo.require() a nonmodule, e.g., dojo.require("my.module", true)
402                         //       * dojo.requireIf/requireAfterIf/platformRequire a module
403                         //
404                         // The module is scanned for legacy loader API applications; if none are found, then assume the module is an
405                         // AMD module and return 0. Otherwise, a synthetic dojo/loadInit plugin resource is created and the module text
406                         // is rewritten as an AMD module with the single dependency of this synthetic resource. When the dojo/loadInit
407                         // plugin loaded the synthetic resource, it will cause all dojo.loadInit's to be executed, find all dojo.require's
408                         // (either directly consequent to dojo.require or indirectly consequent to dojo.require[After]If or
409                         // dojo.platformRequire, and finally cause loading of all dojo.required modules with the dojo/require plugin. Thus,
410                         // when the dojo/loadInit plugin reports it has been loaded, all modules required by the given module are guaranteed
411                         // loaded (but not executed). This then allows the module to execute it's code path without interupts, thereby
412                         // following the synchronous code path.
413                         //
414                         // Notice that this function behaves the same whether or not it happens to be in a mapped dojo/loader module.
415
416                         var extractResult, id, names = [], namesAsStrings = [];
417                         if(buildDetectRe.test(text) || !(extractResult = extractLegacyApiApplications(text))){
418                                 // buildDetectRe.test(text) => a built module, always AMD
419                                 // extractResult==0 => no sync API
420                                 return 0;
421                         }
422
423                         // manufacture a synthetic module id that can never be a real mdule id (just like require does)
424                         id = module.mid + "-*loadInit";
425
426                         // construct the dojo/loadInit names vector which causes any relocated names to be defined as lexical variables under their not-relocated name
427                         // the dojo/loadInit plugin assumes the first name in names is "dojo"
428
429                         for(var p in getModule("dojo", module).result.scopeMap){
430                                 names.push(p);
431                                 namesAsStrings.push('"' + p + '"');
432                         }
433
434                         // rewrite the module as a synthetic dojo/loadInit plugin resource + the module expressed as an AMD module that depends on this synthetic resource
435                         // don't have to map dojo/init since that will occur when the dependency is resolved
436                         return "// xdomain rewrite of " + module.mid + "\n" +
437                                 "define('" + id + "',{\n" +
438                                 "\tnames:" + dojo.toJson(names) + ",\n" +
439                                 "\tdef:function(" + names.join(",") + "){" + extractResult[1] + "}" +
440                                 "});\n\n" +
441                                 "define(" + dojo.toJson(names.concat(["dojo/loadInit!"+id])) + ", function(" + names.join(",") + "){\n" + extractResult[0] + "});";
442                 },
443
444                 loaderVars = require.initSyncLoader(dojoRequirePlugin, checkDojoRequirePlugin, transformToAmd),
445
446                 sync =
447                         loaderVars.sync,
448
449                 requested =
450                         loaderVars.requested,
451
452                 arrived =
453                         loaderVars.arrived,
454
455                 nonmodule =
456                         loaderVars.nonmodule,
457
458                 executing =
459                         loaderVars.executing,
460
461                 executed =
462                         loaderVars.executed,
463
464                 syncExecStack =
465                         loaderVars.syncExecStack,
466
467                 modules =
468                         loaderVars.modules,
469
470                 execQ =
471                         loaderVars.execQ,
472
473                 getModule =
474                         loaderVars.getModule,
475
476                 injectModule =
477                         loaderVars.injectModule,
478
479                 setArrived =
480                         loaderVars.setArrived,
481
482                 signal =
483                         loaderVars.signal,
484
485                 finishExec =
486                         loaderVars.finishExec,
487
488                 execModule =
489                         loaderVars.execModule,
490
491                 getLegacyMode =
492                         loaderVars.getLegacyMode,
493
494                 guardCheckComplete =
495                         loaderVars.guardCheckComplete;
496
497         // there is exactly one dojoRequirePlugin among possibly-many dojo/_base/loader's (owing to mapping)
498         dojoRequirePlugin = loaderVars.dojoRequirePlugin;
499
500         dojo.provide = function(mid){
501                 var executingModule = syncExecStack[0],
502                         module = lang.mixin(getModule(slashName(mid), require.module), {
503                                 executed:executing,
504                                 result:lang.getObject(mid, true)
505                         });
506                 setArrived(module);
507                 if(executingModule){
508                         (executingModule.provides || (executingModule.provides = [])).push(function(){
509                                 module.result = lang.getObject(mid);
510                                 delete module.provides;
511                                 module.executed!==executed && finishExec(module);
512                         });
513                 }// else dojo.provide called not consequent to loading; therefore, give up trying to publish module value to loader namespace
514                 return module.result;
515         };
516
517         has.add("config-publishRequireResult", 1, 0, 0);
518
519         dojo.require = function(moduleName, omitModuleCheck) {
520                 // summary:
521                 //              loads a Javascript module from the appropriate URI
522                 //
523                 // moduleName: String
524                 //              module name to load, using periods for separators,
525                 //               e.g. "dojo.date.locale".  Module paths are de-referenced by dojo's
526                 //              internal mapping of locations to names and are disambiguated by
527                 //              longest prefix. See `dojo.registerModulePath()` for details on
528                 //              registering new modules.
529                 //
530                 // omitModuleCheck: Boolean?
531                 //              if `true`, omitModuleCheck skips the step of ensuring that the
532                 //              loaded file actually defines the symbol it is referenced by.
533                 //              For example if it called as `dojo.require("a.b.c")` and the
534                 //              file located at `a/b/c.js` does not define an object `a.b.c`,
535                 //              and exception will be throws whereas no exception is raised
536                 //              when called as `dojo.require("a.b.c", true)`
537                 //
538                 // description:
539                 //              Modules are loaded via dojo.require by using one of two loaders: the normal loader
540                 //              and the xdomain loader. The xdomain loader is used when dojo was built with a
541                 //              custom build that specified loader=xdomain and the module lives on a modulePath
542                 //              that is a whole URL, with protocol and a domain. The versions of Dojo that are on
543                 //              the Google and AOL CDNs use the xdomain loader.
544                 //
545                 //              If the module is loaded via the xdomain loader, it is an asynchronous load, since
546                 //              the module is added via a dynamically created script tag. This
547                 //              means that dojo.require() can return before the module has loaded. However, this
548                 //              should only happen in the case where you do dojo.require calls in the top-level
549                 //              HTML page, or if you purposely avoid the loader checking for dojo.require
550                 //              dependencies in your module by using a syntax like dojo["require"] to load the module.
551                 //
552                 //              Sometimes it is useful to not have the loader detect the dojo.require calls in the
553                 //              module so that you can dynamically load the modules as a result of an action on the
554                 //              page, instead of right at module load time.
555                 //
556                 //              Also, for script blocks in an HTML page, the loader does not pre-process them, so
557                 //              it does not know to download the modules before the dojo.require calls occur.
558                 //
559                 //              So, in those two cases, when you want on-the-fly module loading or for script blocks
560                 //              in the HTML page, special care must be taken if the dojo.required code is loaded
561                 //              asynchronously. To make sure you can execute code that depends on the dojo.required
562                 //              modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
563                 //              callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
564                 //              executing.
565                 //
566                 //              This type of syntax works with both xdomain and normal loaders, so it is good
567                 //              practice to always use this idiom for on-the-fly code loading and in HTML script
568                 //              blocks. If at some point you change loaders and where the code is loaded from,
569                 //              it will all still work.
570                 //
571                 //              More on how dojo.require
572                 //              `dojo.require("A.B")` first checks to see if symbol A.B is
573                 //              defined. If it is, it is simply returned (nothing to do).
574                 //
575                 //              If it is not defined, it will look for `A/B.js` in the script root
576                 //              directory.
577                 //
578                 //              `dojo.require` throws an exception if it cannot find a file
579                 //              to load, or if the symbol `A.B` is not defined after loading.
580                 //
581                 //              It returns the object `A.B`, but note the caveats above about on-the-fly loading and
582                 //              HTML script blocks when the xdomain loader is loading a module.
583                 //
584                 //              `dojo.require()` does nothing about importing symbols into
585                 //              the current namespace.  It is presumed that the caller will
586                 //              take care of that.
587                 //
588                 // example:
589                 //              To use dojo.require in conjunction with dojo.ready:
590                 //
591                 //              |       dojo.require("foo");
592                 //              |       dojo.require("bar");
593                 //              |       dojo.addOnLoad(function(){
594                 //              |               //you can now safely do something with foo and bar
595                 //              |       });
596                 //
597                 // example:
598                 //              For example, to import all symbols into a local block, you might write:
599                 //
600                 //              |       with (dojo.require("A.B")) {
601                 //              |               ...
602                 //              |       }
603                 //
604                 //              And to import just the leaf symbol to a local variable:
605                 //
606                 //              |       var B = dojo.require("A.B");
607                 //              |       ...
608                 //
609                 // returns:
610                 //              the required namespace object
611                 function doRequire(mid, omitModuleCheck){
612                         var module = getModule(slashName(mid), require.module);
613                         if(syncExecStack.length && syncExecStack[0].finish){
614                                 // switched to async loading in the middle of evaluating a legacy module; stop
615                                 // applying dojo.require so the remaining dojo.requires are applied in order
616                                 syncExecStack[0].finish.push(mid);
617                                 return undefined;
618                         }
619
620                         // recall module.executed has values {0, executing, executed}; therefore, truthy indicates executing or executed
621                         if(module.executed){
622                                 return module.result;
623                         }
624                         omitModuleCheck && (module.result = nonmodule);
625
626                         // rcg...why here and in two lines??
627                         var currentMode = getLegacyMode();
628
629                         // recall, in sync mode to inject is to *eval* the module text
630                         // if the module is a legacy module, this is the same as executing
631                         // but if the module is an AMD module, this means defining, not executing
632                         injectModule(module);
633                         // the inject may have changed the mode
634                         currentMode = getLegacyMode();
635
636                         // in sync mode to dojo.require is to execute
637                         if(module.executed!==executed && module.injected===arrived){
638                                 // the module was already here before injectModule was called probably finishing up a xdomain
639                                 // load, but maybe a module given to the loader directly rather than having the loader retrieve it
640
641                                 loaderVars.guardCheckComplete(function(){
642                                         execModule(module);
643                                 });
644                         }
645                         if(module.executed){
646                                 return module.result;
647                         }
648
649                         if(currentMode==sync){
650                                 // the only way to get here is in sync mode and dojo.required a module that
651                                 //       * was loaded async in the injectModule application a few lines up
652                                 //       * was an AMD module that had deps that are being loaded async and therefore couldn't execute
653                                 if(module.cjs){
654                                         // the module was an AMD module; unshift, not push, which causes the current traversal to be reattempted from the top
655                                         execQ.unshift(module);
656                                 }else{
657                                         // the module was a legacy module
658                                         syncExecStack.length && (syncExecStack[0].finish= [mid]);
659                                 }
660                         }else{
661                                 // the loader wasn't in sync mode on entry; probably async mode; therefore, no expectation of getting
662                                 // the module value synchronously; make sure it gets executed though
663                                 execQ.push(module);
664                         }
665
666                         return undefined;
667                 }
668
669                 var result = doRequire(moduleName, omitModuleCheck);
670                 if(has("config-publishRequireResult") && !lang.exists(moduleName) && result!==undefined){
671                         lang.setObject(moduleName, result);
672                 }
673                 return result;
674         };
675
676         dojo.loadInit = function(f) {
677                 f();
678         };
679
680         dojo.registerModulePath = function(/*String*/moduleName, /*String*/prefix){
681                 // summary:
682                 //              Maps a module name to a path
683                 // description:
684                 //              An unregistered module is given the default path of ../[module],
685                 //              relative to Dojo root. For example, module acme is mapped to
686                 //              ../acme.  If you want to use a different module name, use
687                 //              dojo.registerModulePath.
688                 // example:
689                 //              If your dojo.js is located at this location in the web root:
690                 //      |       /myapp/js/dojo/dojo/dojo.js
691                 //              and your modules are located at:
692                 //      |       /myapp/js/foo/bar.js
693                 //      |       /myapp/js/foo/baz.js
694                 //      |       /myapp/js/foo/thud/xyzzy.js
695                 //              Your application can tell Dojo to locate the "foo" namespace by calling:
696                 //      |       dojo.registerModulePath("foo", "../../foo");
697                 //              At which point you can then use dojo.require() to load the
698                 //              modules (assuming they provide() the same things which are
699                 //              required). The full code might be:
700                 //      |       <script type="text/javascript"
701                 //      |               src="/myapp/js/dojo/dojo/dojo.js"></script>
702                 //      |       <script type="text/javascript">
703                 //      |               dojo.registerModulePath("foo", "../../foo");
704                 //      |               dojo.require("foo.bar");
705                 //      |               dojo.require("foo.baz");
706                 //      |               dojo.require("foo.thud.xyzzy");
707                 //      |       </script>
708
709                 var paths = {};
710                 paths[moduleName.replace(/\./g, "/")] = prefix;
711                 require({paths:paths});
712         };
713
714         dojo.platformRequire = function(/*Object*/modMap){
715                 // summary:
716                 //              require one or more modules based on which host environment
717                 //              Dojo is currently operating in
718                 // description:
719                 //              This method takes a "map" of arrays which one can use to
720                 //              optionally load dojo modules. The map is indexed by the
721                 //              possible dojo.name_ values, with two additional values:
722                 //              "default" and "common". The items in the "default" array will
723                 //              be loaded if none of the other items have been choosen based on
724                 //              dojo.name_, set by your host environment. The items in the
725                 //              "common" array will *always* be loaded, regardless of which
726                 //              list is chosen.
727                 // example:
728                 //              |       dojo.platformRequire({
729                 //              |               browser: [
730                 //              |                       "foo.sample", // simple module
731                 //              |                       "foo.test",
732                 //              |                       ["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
733                 //              |               ],
734                 //              |               default: [ "foo.sample._base" ],
735                 //              |               common: [ "important.module.common" ]
736                 //              |       });
737
738                 var result = (modMap.common || []).concat(modMap[dojo._name] || modMap["default"] || []),
739                         temp;
740                 while(result.length){
741                         if(lang.isArray(temp = result.shift())){
742                                 dojo.require.apply(dojo, temp);
743                         }else{
744                                 dojo.require(temp);
745                         }
746                 }
747         };
748
749         dojo.requireIf = dojo.requireAfterIf = function(/*Boolean*/ condition, /*String*/ moduleName, /*Boolean?*/omitModuleCheck){
750                 // summary:
751                 //              If the condition is true then call `dojo.require()` for the specified
752                 //              resource
753                 //
754                 // example:
755                 //      |       dojo.requireIf(dojo.isBrowser, "my.special.Module");
756
757                 if(condition){
758                         dojo.require(moduleName, omitModuleCheck);
759                 }
760         };
761
762         dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale){
763                 require(["../i18n"], function(i18n){
764                         i18n.getLocalization(moduleName, bundleName, locale);
765                 });
766         };
767
768         return {
769                 // summary:
770                 //              This module defines the v1.x synchronous loader API.
771
772                 extractLegacyApiApplications:extractLegacyApiApplications,
773                 require:dojoRequirePlugin,
774                 loadInit:dojoLoadInitPlugin
775         };
776 });