summaryrefslogtreecommitdiff
path: root/lib/dojo/_base/loader.js.uncompressed.js
blob: 23f0b6db8f8f29bb8ffbd4839ec9e4f3d9428f74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
define("dojo/_base/loader", ["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) {
	// module:
	//		dojo/_base/loader

	//		This module defines the v1.x synchronous loader API.

	// signal the loader in sync mode...
	//>>pure-amd

	if (! 1 ){
		console.error("cannot load the Dojo v1.x loader with a foreign loader");
		return 0;
	}

	 1 || has.add("dojo-fast-sync-require", 1);


	var makeErrorToken = function(id){
			return {src:thisModule.id, id:id};
		},

		slashName = function(name){
			return name.replace(/\./g, "/");
		},

		buildDetectRe = /\/\/>>built/,

		dojoRequireCallbacks = [],
		dojoRequireModuleStack = [],

		dojoRequirePlugin = function(mid, require, loaded){
			dojoRequireCallbacks.push(loaded);
			array.forEach(mid.split(","), function(mid){
				var module = getModule(mid, require.module);
				dojoRequireModuleStack.push(module);
				injectModule(module);
			});
			checkDojoRequirePlugin();
		},

		checkDojoRequirePlugin = ( 1  ?
			// This version of checkDojoRequirePlugin makes the observation that all dojoRequireCallbacks can be released
			// when all *non-dojo/require!, dojo/loadInit!* modules are either executed, not requested, or arrived. This is
			// the case since there are no more modules the loader is waiting for, therefore, dojo/require! must have
			// everything it needs on board.
			//
			// The potential weakness of this algorithm is that dojo/require will not execute callbacks until *all* dependency
			// trees are ready. It is possible that some trees may be ready earlier than others, and this extra wait is non-optimal.
			// Still, for big projects, this seems better than the original algorithm below that proved slow in some cases.
			// Note, however, the original algorithm had the potential to execute partial trees,  but that potential was never enabled.
			// There are also other optimization available with the original algorithm that have not been explored.
			function(){
				var module, mid;
				for(mid in modules){
					module = modules[mid];
					if(module.noReqPluginCheck===undefined){
						// tag the module as either a loadInit or require plugin or not for future reference
						module.noReqPluginCheck = /loadInit\!/.test(mid) || /require\!/.test(mid) ? 1 : 0;
					}
					if(!module.executed && !module.noReqPluginCheck && module.injected==requested){
						return;
					}
				}

				guardCheckComplete(function(){
					var oldCallbacks = dojoRequireCallbacks;
					dojoRequireCallbacks = [];
					array.forEach(oldCallbacks, function(cb){cb(1);});
				});
		} : (function(){
			// Note: this is the original checkDojoRequirePlugin that is much slower than the algorithm above. However, we know it
			// works, so we leave it here in case the algorithm above fails in some corner case.
			//
			// checkDojoRequirePlugin inspects all of the modules demanded by a dojo/require!<module-list> dependency
			// to see if they have arrived. The loader does not release *any* of these modules to be instantiated
			// until *all* of these modules are on board, thereby preventing the evaluation of a module with dojo.require's
			// that reference modules that are not available.
			//
			// The algorithm works by traversing the dependency graphs (remember, there can be cycles so they are not trees)
			// of each module in the dojoRequireModuleStack array (which contains the list of modules demanded by dojo/require!).
			// The moment a single module is discovered that is missing, the algorithm gives up and indicates that not all
			// modules are on board. dojo/loadInit! and dojo/require! are ignored because there dependencies are inserted
			// directly in dojoRequireModuleStack. For example, if "your/module" module depends on "dojo/require!my/module", then
			// *both* "dojo/require!my/module" and "my/module" will be in dojoRequireModuleStack. Obviously, if "my/module"
			// is on board, then "dojo/require!my/module" is also satisfied, so the algorithm doesn't check for "dojo/require!my/module".
			//
			// Note: inserting a dojo/require!<some-module-list> dependency in the dojoRequireModuleStack achieves nothing
			// with the current algorithm; however, having such modules present makes it possible to optimize the algorithm
			//
			// Note: prior versions of this algorithm had an optimization that signaled loaded on dojo/require! dependencies
			// individually (rather than waiting for them all to be resolved). The implementation proved problematic with cycles
			// and plugins. However, it is possible to reattach that strategy in the future.

			// a set from module-id to {undefined | 1 | 0}, where...
			//	 undefined => the module has not been inspected
			//	 0 => the module or at least one of its dependencies has not arrived
			//	 1 => the module is a loadInit! or require! plugin resource, or is currently being traversed (therefore, assume
			//		  OK until proven otherwise), or has been completely traversed and all dependencies have arrived

			var touched,
			traverse = function(m){
				touched[m.mid] = 1;
				for(var t, module, deps = m.deps || [], i= 0; i<deps.length; i++){
					module = deps[i];
					if(!(t = touched[module.mid])){
						if(t===0 || !traverse(module)){
							touched[m.mid] = 0;
							return false;
						}
					}
				}
				return true;
			};

			return function(){
				// initialize the touched hash with easy-to-compute values that help short circuit recursive algorithm;
				// recall loadInit/require plugin modules are dependencies of modules in dojoRequireModuleStack...
				// which would cause a circular dependency chain that would never be resolved if checked here
				// notice all dependencies of any particular loadInit/require plugin module will already
				// be checked since those are pushed into dojoRequireModuleStack explicitly by the
				// plugin...so if a particular loadInitPlugin module's dependencies are not really
				// on board, that *will* be detected elsewhere in the traversal.
				var module, mid;
				touched = {};
				for(mid in modules){
					module = modules[mid];
					if(module.executed || module.noReqPluginCheck){
						touched[mid] = 1;
					}else{
						if(module.noReqPluginCheck!==0){
							// tag the module as either a loadInit or require plugin or not for future reference
							module.noReqPluginCheck = /loadInit\!/.test(mid) || /require\!/.test(mid) ? 1 : 0;
						}
						if(module.noReqPluginCheck){
							touched[mid] = 1;
						}else if(module.injected!==arrived){
							// not executed, has not arrived, and is not a loadInit or require plugin resource
							touched[mid] = 0;
						}// else, leave undefined and we'll traverse the dependencies
					}
				}
				for(var t, i = 0, end = dojoRequireModuleStack.length; i<end; i++){
					module = dojoRequireModuleStack[i];
					if(!(t = touched[module.mid])){
						if(t===0 || !traverse(module)){
							return;
						}
					}
				}
				guardCheckComplete(function(){
					var oldCallbacks = dojoRequireCallbacks;
					dojoRequireCallbacks = [];
					array.forEach(oldCallbacks, function(cb){cb(1);});
				});
			};
		})()),

		dojoLoadInitPlugin = function(mid, require, loaded){
			// mid names a module that defines a "dojo load init" bundle, an object with two properties:
			//
			//	 * names: a vector of module ids that give top-level names to define in the lexical scope of def
			//	 * def: a function that contains some some legacy loader API applications
			//
			// The point of def is to possibly cause some modules to be loaded (but not executed) by dojo/require! where the module
			// ids are possibly-determined at runtime. For example, here is dojox.gfx from v1.6 expressed as an AMD module using the dojo/loadInit
			// and dojo/require plugins.
			//
			// // dojox/gfx:
			//
			//	 define("*loadInit_12, {
			//	   names:["dojo", "dijit", "dojox"],
			//	   def: function(){
			//		 dojo.loadInit(function(){
			//		   var gfx = lang.getObject("dojox.gfx", true);
			//
			//		   //
			//		   // code required to set gfx properties ommitted...
			//		   //
			//
			//		   // now use the calculations to include the runtime-dependent module
			//		   dojo.require("dojox.gfx." + gfx.renderer);
			//		 });
			//	   }
			//	 });
			//
			//	 define(["dojo", "dojo/loadInit!" + id].concat("dojo/require!dojox/gfx/matric,dojox/gfx/_base"), function(dojo){
			//	   // when this AMD factory function is executed, the following modules are guaranteed downloaded but not executed:
			//	   //	"dojox.gfx." + gfx.renderer
			//	   //	dojox.gfx.matrix
			//	   //	dojox.gfx._base
			//	   dojo.provide("dojo.gfx");
			//	   dojo.require("dojox.gfx.matrix");
			//	   dojo.require("dojox.gfx._base");
			//	   dojo.require("dojox.gfx." + gfx.renderer);
			//	   return lang.getObject("dojo.gfx");
			//	 });
			//	})();
			//
			// The idea is to run the legacy loader API with global variables shadowed, which allows these variables to
			// be relocated. For example, dojox and dojo could be relocated to different names by giving a map and the code above will
			// execute properly (because the plugin below resolves the load init bundle.names module with respect to the module that demanded
			// the plugin resource).
			//
			// Note that the relocation is specified in the runtime configuration; relocated names need not be set at build-time.
			//
			// Warning: this is not the best way to express dojox.gfx as and AMD module. In fact, the module has been properly converted in
			// v1.7. However, this technique allows the builder to convert legacy modules into AMD modules and guarantee the codepath is the
			// same in the converted AMD module.
			require([mid], function(bundle){
				// notice how names is resolved with respect to the module that demanded the plugin resource
				require(bundle.names, function(){
					// bring the bundle names into scope
					for(var scopeText = "", args= [], i = 0; i<arguments.length; i++){
						scopeText+= "var " + bundle.names[i] + "= arguments[" + i + "]; ";
						args.push(arguments[i]);
					}
					eval(scopeText);

					var callingModule = require.module,
						// the list of modules that need to be downloaded but not executed before the callingModule can be executed
						requireList = [],

						// the list of i18n bundles that are xdomain; undefined if none
						i18nDeps,

						syncLoaderApi = {
							provide:function(moduleName){
								// mark modules that arrive consequent to multiple provides in this module as arrived since they can't be injected
								moduleName = slashName(moduleName);
								var providedModule = getModule(moduleName, callingModule);
								if(providedModule!==callingModule){
									setArrived(providedModule);
								}
							},
							require:function(moduleName, omitModuleCheck){
								moduleName = slashName(moduleName);
								omitModuleCheck && (getModule(moduleName, callingModule).result = nonmodule);
								requireList.push(moduleName);
							},
							requireLocalization:function(moduleName, bundleName, locale){
								// since we're going to need dojo/i8n, add it to i18nDeps if not already there
								if(!i18nDeps){
									// don't have to map since that will occur when the dependency is resolved
									i18nDeps = ["dojo/i18n"];
								}

								// figure out if the bundle is xdomain; if so, add it to the i18nDepsSet
								locale = (locale || dojo.locale).toLowerCase();
								moduleName = slashName(moduleName) + "/nls/" + (/root/i.test(locale) ? "" : locale + "/") + slashName(bundleName);
								if(getModule(moduleName, callingModule).isXd){
									// don't have to map since that will occur when the dependency is resolved
									i18nDeps.push("dojo/i18n!" + moduleName);
								}// else the bundle will be loaded synchronously when the module is evaluated
							},
							loadInit:function(f){
								f();
							}
						},

						hold = {},
						p;

					// hijack the correct dojo and apply bundle.def
					try{
						for(p in syncLoaderApi){
							hold[p] = dojo[p];
							dojo[p] = syncLoaderApi[p];
						}
						bundle.def.apply(null, args);
					}catch(e){
						signal("error", [makeErrorToken("failedDojoLoadInit"), e]);
					}finally{
						for(p in syncLoaderApi){
							dojo[p] = hold[p];
						}
					}

					if(i18nDeps){
						requireList = requireList.concat(i18nDeps);
					}

					if(requireList.length){
						dojoRequirePlugin(requireList.join(","), require, loaded);
					}else{
						loaded();
					}
				});
			});
		},

		extractApplication = function(
			text,			  // the text to search
			startSearch,	  // the position in text to start looking for the closing paren
			startApplication  // the position in text where the function application expression starts
		){
			// find end of the call by finding the matching end paren
			// Warning: as usual, this will fail in the presense of unmatched right parans contained in strings, regexs, or unremoved comments
			var parenRe = /\(|\)/g,
				matchCount = 1,
				match;
			parenRe.lastIndex = startSearch;
			while((match = parenRe.exec(text))){
				if(match[0] == ")"){
					matchCount -= 1;
				}else{
					matchCount += 1;
				}
				if(matchCount == 0){
					break;
				}
			}

			if(matchCount != 0){
				throw "unmatched paren around character " + parenRe.lastIndex + " in: " + text;
			}

			//Put the master matching string in the results.
			return [dojo.trim(text.substring(startApplication, parenRe.lastIndex))+";\n", parenRe.lastIndex];
		},

		// the following regex is taken from 1.6. It is a very poor technique to remove comments and
		// will fail in some cases; for example, consider the code...
		//
		//	  var message = "Category-1 */* Category-2";
		//
		// The regex that follows will see a /* comment and trash the code accordingly. In fact, there are all
		// kinds of cases like this with strings and regexs that will cause this design to fail miserably.
		//
		// Alternative regex designs exist that will result in less-likely failures, but will still fail in many cases.
		// The only solution guaranteed 100% correct is to parse the code and that seems overkill for this
		// backcompat/unbuilt-xdomain layer. In the end, since it's been this way for a while, we won't change it.
		// See the opening paragraphs of Chapter 7 or ECME-262 which describes the lexical abiguity further.
		removeCommentRe = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,

		syncLoaderApiRe = /(^|\s)dojo\.(loadInit|require|provide|requireLocalization|requireIf|requireAfterIf|platformRequire)\s*\(/mg,

		amdLoaderApiRe = /(^|\s)(require|define)\s*\(/m,

		extractLegacyApiApplications = function(text, noCommentText){
			// scan the noCommentText for any legacy loader API applications. Copy such applications into result (this is
			// used by the builder). Move dojo.loadInit applications to loadInitApplications string. Copy all other applications
			// to otherApplications string. If no applications were found, return 0, signalling an AMD module. Otherwise, return
			// loadInitApplications + otherApplications. Fixup text by replacing
			//
			//	 dojo.loadInit(// etc...
			//
			// with
			//
			//	 \n 0 && dojo.loadInit(// etc...
			//
			// Which results in the dojo.loadInit from *not* being applied. This design goes a long way towards protecting the
			// code from an over-agressive removeCommentRe. However...
			//
			// WARNING: the removeCommentRe will cause an error if a detected comment removes all or part of a legacy-loader application
			// that is not in a comment.

			var match, startSearch, startApplication, application,
				loadInitApplications = [],
				otherApplications = [],
				allApplications = [];

			// noCommentText may be provided by a build app with comments extracted by a better method than regex (hopefully)
			noCommentText = noCommentText || text.replace(removeCommentRe, function(match){
				// remove iff the detected comment has text that looks like a sync loader API application; this helps by
				// removing as little as possible, minimizing the changes the janky regex will kill the module
				syncLoaderApiRe.lastIndex = amdLoaderApiRe.lastIndex = 0;
				return (syncLoaderApiRe.test(match) || amdLoaderApiRe.test(match)) ? "" : match;
			});

			// find and extract all dojo.loadInit applications
			while((match = syncLoaderApiRe.exec(noCommentText))){
				startSearch = syncLoaderApiRe.lastIndex;
				startApplication = startSearch	- match[0].length;
				application = extractApplication(noCommentText, startSearch, startApplication);
				if(match[2]=="loadInit"){
					loadInitApplications.push(application[0]);
				}else{
					otherApplications.push(application[0]);
				}
				syncLoaderApiRe.lastIndex = application[1];
			}
			allApplications = loadInitApplications.concat(otherApplications);
			if(allApplications.length || !amdLoaderApiRe.test(noCommentText)){
				// either there were some legacy loader API applications or there were no AMD API applications
				return [text.replace(/(^|\s)dojo\.loadInit\s*\(/g, "\n0 && dojo.loadInit("), allApplications.join(""), allApplications];
			}else{
				// legacy loader API *was not* detected and AMD API *was* detected; therefore, assume it's an AMD module
				return 0;
			}
		},

		transformToAmd = function(module, text){
			// This is roughly the equivalent of dojo._xdCreateResource in 1.6-; however, it expresses a v1.6- dojo
			// module in terms of AMD define instead of creating the dojo proprietary xdomain module expression.
			// The module could have originated from several sources:
			//
			//	 * amd require() a module, e.g., require(["my/module"])
			//	 * amd require() a nonmodule, e.g., require(["my/resource.js"')
			//	 * amd define() deps vector (always a module)
			//	 * dojo.require() a module, e.g. dojo.require("my.module")
			//	 * dojo.require() a nonmodule, e.g., dojo.require("my.module", true)
			//	 * dojo.requireIf/requireAfterIf/platformRequire a module
			//
			// The module is scanned for legacy loader API applications; if none are found, then assume the module is an
			// AMD module and return 0. Otherwise, a synthetic dojo/loadInit plugin resource is created and the module text
			// is rewritten as an AMD module with the single dependency of this synthetic resource. When the dojo/loadInit
			// plugin loaded the synthetic resource, it will cause all dojo.loadInit's to be executed, find all dojo.require's
			// (either directly consequent to dojo.require or indirectly consequent to dojo.require[After]If or
			// dojo.platformRequire, and finally cause loading of all dojo.required modules with the dojo/require plugin. Thus,
			// when the dojo/loadInit plugin reports it has been loaded, all modules required by the given module are guaranteed
			// loaded (but not executed). This then allows the module to execute it's code path without interupts, thereby
			// following the synchronous code path.
			//
			// Notice that this function behaves the same whether or not it happens to be in a mapped dojo/loader module.

			var extractResult, id, names = [], namesAsStrings = [];
			if(buildDetectRe.test(text) || !(extractResult = extractLegacyApiApplications(text))){
				// buildDetectRe.test(text) => a built module, always AMD
				// extractResult==0 => no sync API
				return 0;
			}

			// manufacture a synthetic module id that can never be a real mdule id (just like require does)
			id = module.mid + "-*loadInit";

			// construct the dojo/loadInit names vector which causes any relocated names to be defined as lexical variables under their not-relocated name
			// the dojo/loadInit plugin assumes the first name in names is "dojo"

			for(var p in getModule("dojo", module).result.scopeMap){
				names.push(p);
				namesAsStrings.push('"' + p + '"');
			}

			// rewrite the module as a synthetic dojo/loadInit plugin resource + the module expressed as an AMD module that depends on this synthetic resource
			// don't have to map dojo/init since that will occur when the dependency is resolved
			return "// xdomain rewrite of " + module.mid + "\n" +
				"define('" + id + "',{\n" +
				"\tnames:" + dojo.toJson(names) + ",\n" +
				"\tdef:function(" + names.join(",") + "){" + extractResult[1] + "}" +
				"});\n\n" +
				"define(" + dojo.toJson(names.concat(["dojo/loadInit!"+id])) + ", function(" + names.join(",") + "){\n" + extractResult[0] + "});";
		},

		loaderVars = require.initSyncLoader(dojoRequirePlugin, checkDojoRequirePlugin, transformToAmd),

		sync =
			loaderVars.sync,

		requested =
			loaderVars.requested,

		arrived =
			loaderVars.arrived,

		nonmodule =
			loaderVars.nonmodule,

		executing =
			loaderVars.executing,

		executed =
			loaderVars.executed,

		syncExecStack =
			loaderVars.syncExecStack,

		modules =
			loaderVars.modules,

		execQ =
			loaderVars.execQ,

		getModule =
			loaderVars.getModule,

		injectModule =
			loaderVars.injectModule,

		setArrived =
			loaderVars.setArrived,

		signal =
			loaderVars.signal,

		finishExec =
			loaderVars.finishExec,

		execModule =
			loaderVars.execModule,

		getLegacyMode =
			loaderVars.getLegacyMode,

		guardCheckComplete =
			loaderVars.guardCheckComplete;

	// there is exactly one dojoRequirePlugin among possibly-many dojo/_base/loader's (owing to mapping)
	dojoRequirePlugin = loaderVars.dojoRequirePlugin;

	dojo.provide = function(mid){
		var executingModule = syncExecStack[0],
			module = lang.mixin(getModule(slashName(mid), require.module), {
				executed:executing,
				result:lang.getObject(mid, true)
			});
		setArrived(module);
		if(executingModule){
			(executingModule.provides || (executingModule.provides = [])).push(function(){
				module.result = lang.getObject(mid);
				delete module.provides;
				module.executed!==executed && finishExec(module);
			});
		}// else dojo.provide called not consequent to loading; therefore, give up trying to publish module value to loader namespace
		return module.result;
	};

	has.add("config-publishRequireResult", 1, 0, 0);

	dojo.require = function(moduleName, omitModuleCheck) {
		// summary:
		//		loads a Javascript module from the appropriate URI
		//
		// moduleName: String
		//		module name to load, using periods for separators,
		//		 e.g. "dojo.date.locale".  Module paths are de-referenced by dojo's
		//		internal mapping of locations to names and are disambiguated by
		//		longest prefix. See `dojo.registerModulePath()` for details on
		//		registering new modules.
		//
		// omitModuleCheck: Boolean?
		//		if `true`, omitModuleCheck skips the step of ensuring that the
		//		loaded file actually defines the symbol it is referenced by.
		//		For example if it called as `dojo.require("a.b.c")` and the
		//		file located at `a/b/c.js` does not define an object `a.b.c`,
		//		and exception will be throws whereas no exception is raised
		//		when called as `dojo.require("a.b.c", true)`
		//
		// description:
		//		Modules are loaded via dojo.require by using one of two loaders: the normal loader
		//		and the xdomain loader. The xdomain loader is used when dojo was built with a
		//		custom build that specified loader=xdomain and the module lives on a modulePath
		//		that is a whole URL, with protocol and a domain. The versions of Dojo that are on
		//		the Google and AOL CDNs use the xdomain loader.
		//
		//		If the module is loaded via the xdomain loader, it is an asynchronous load, since
		//		the module is added via a dynamically created script tag. This
		//		means that dojo.require() can return before the module has loaded. However, this
		//		should only happen in the case where you do dojo.require calls in the top-level
		//		HTML page, or if you purposely avoid the loader checking for dojo.require
		//		dependencies in your module by using a syntax like dojo["require"] to load the module.
		//
		//		Sometimes it is useful to not have the loader detect the dojo.require calls in the
		//		module so that you can dynamically load the modules as a result of an action on the
		//		page, instead of right at module load time.
		//
		//		Also, for script blocks in an HTML page, the loader does not pre-process them, so
		//		it does not know to download the modules before the dojo.require calls occur.
		//
		//		So, in those two cases, when you want on-the-fly module loading or for script blocks
		//		in the HTML page, special care must be taken if the dojo.required code is loaded
		//		asynchronously. To make sure you can execute code that depends on the dojo.required
		//		modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
		//		callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
		//		executing.
		//
		//		This type of syntax works with both xdomain and normal loaders, so it is good
		//		practice to always use this idiom for on-the-fly code loading and in HTML script
		//		blocks. If at some point you change loaders and where the code is loaded from,
		//		it will all still work.
		//
		//		More on how dojo.require
		//		`dojo.require("A.B")` first checks to see if symbol A.B is
		//		defined. If it is, it is simply returned (nothing to do).
		//
		//		If it is not defined, it will look for `A/B.js` in the script root
		//		directory.
		//
		//		`dojo.require` throws an exception if it cannot find a file
		//		to load, or if the symbol `A.B` is not defined after loading.
		//
		//		It returns the object `A.B`, but note the caveats above about on-the-fly loading and
		//		HTML script blocks when the xdomain loader is loading a module.
		//
		//		`dojo.require()` does nothing about importing symbols into
		//		the current namespace.	It is presumed that the caller will
		//		take care of that.
		//
		// example:
		//		To use dojo.require in conjunction with dojo.ready:
		//
		//		|	dojo.require("foo");
		//		|	dojo.require("bar");
		//		|	dojo.addOnLoad(function(){
		//		|		//you can now safely do something with foo and bar
		//		|	});
		//
		// example:
		//		For example, to import all symbols into a local block, you might write:
		//
		//		|	with (dojo.require("A.B")) {
		//		|		...
		//		|	}
		//
		//		And to import just the leaf symbol to a local variable:
		//
		//		|	var B = dojo.require("A.B");
		//		|	...
		//
		// returns:
		//		the required namespace object
		function doRequire(mid, omitModuleCheck){
			var module = getModule(slashName(mid), require.module);
			if(syncExecStack.length && syncExecStack[0].finish){
				// switched to async loading in the middle of evaluating a legacy module; stop
				// applying dojo.require so the remaining dojo.requires are applied in order
				syncExecStack[0].finish.push(mid);
				return undefined;
			}

			// recall module.executed has values {0, executing, executed}; therefore, truthy indicates executing or executed
			if(module.executed){
				return module.result;
			}
			omitModuleCheck && (module.result = nonmodule);

			// rcg...why here and in two lines??
			var currentMode = getLegacyMode();

			// recall, in sync mode to inject is to *eval* the module text
			// if the module is a legacy module, this is the same as executing
			// but if the module is an AMD module, this means defining, not executing
			injectModule(module);
			// the inject may have changed the mode
			currentMode = getLegacyMode();

			// in sync mode to dojo.require is to execute
			if(module.executed!==executed && module.injected===arrived){
				// the module was already here before injectModule was called probably finishing up a xdomain
				// load, but maybe a module given to the loader directly rather than having the loader retrieve it

				loaderVars.guardCheckComplete(function(){
					execModule(module);
				});
			}
			if(module.executed){
				return module.result;
			}

			if(currentMode==sync){
				// the only way to get here is in sync mode and dojo.required a module that
				//	 * was loaded async in the injectModule application a few lines up
				//	 * was an AMD module that had deps that are being loaded async and therefore couldn't execute
				if(module.cjs){
					// the module was an AMD module; unshift, not push, which causes the current traversal to be reattempted from the top
					execQ.unshift(module);
				}else{
					// the module was a legacy module
					syncExecStack.length && (syncExecStack[0].finish= [mid]);
				}
			}else{
				// the loader wasn't in sync mode on entry; probably async mode; therefore, no expectation of getting
				// the module value synchronously; make sure it gets executed though
				execQ.push(module);
			}

			return undefined;
		}

		var result = doRequire(moduleName, omitModuleCheck);
		if(has("config-publishRequireResult") && !lang.exists(moduleName) && result!==undefined){
			lang.setObject(moduleName, result);
		}
		return result;
	};

	dojo.loadInit = function(f) {
		f();
	};

	dojo.registerModulePath = function(/*String*/moduleName, /*String*/prefix){
		// summary:
		//		Maps a module name to a path
		// description:
		//		An unregistered module is given the default path of ../[module],
		//		relative to Dojo root. For example, module acme is mapped to
		//		../acme.  If you want to use a different module name, use
		//		dojo.registerModulePath.
		// example:
		//		If your dojo.js is located at this location in the web root:
		//	|	/myapp/js/dojo/dojo/dojo.js
		//		and your modules are located at:
		//	|	/myapp/js/foo/bar.js
		//	|	/myapp/js/foo/baz.js
		//	|	/myapp/js/foo/thud/xyzzy.js
		//		Your application can tell Dojo to locate the "foo" namespace by calling:
		//	|	dojo.registerModulePath("foo", "../../foo");
		//		At which point you can then use dojo.require() to load the
		//		modules (assuming they provide() the same things which are
		//		required). The full code might be:
		//	|	<script type="text/javascript"
		//	|		src="/myapp/js/dojo/dojo/dojo.js"></script>
		//	|	<script type="text/javascript">
		//	|		dojo.registerModulePath("foo", "../../foo");
		//	|		dojo.require("foo.bar");
		//	|		dojo.require("foo.baz");
		//	|		dojo.require("foo.thud.xyzzy");
		//	|	</script>

		var paths = {};
		paths[moduleName.replace(/\./g, "/")] = prefix;
		require({paths:paths});
	};

	dojo.platformRequire = function(/*Object*/modMap){
		// summary:
		//		require one or more modules based on which host environment
		//		Dojo is currently operating in
		// description:
		//		This method takes a "map" of arrays which one can use to
		//		optionally load dojo modules. The map is indexed by the
		//		possible dojo.name_ values, with two additional values:
		//		"default" and "common". The items in the "default" array will
		//		be loaded if none of the other items have been choosen based on
		//		dojo.name_, set by your host environment. The items in the
		//		"common" array will *always* be loaded, regardless of which
		//		list is chosen.
		// example:
		//		|	dojo.platformRequire({
		//		|		browser: [
		//		|			"foo.sample", // simple module
		//		|			"foo.test",
		//		|			["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
		//		|		],
		//		|		default: [ "foo.sample._base" ],
		//		|		common: [ "important.module.common" ]
		//		|	});

		var result = (modMap.common || []).concat(modMap[dojo._name] || modMap["default"] || []),
			temp;
		while(result.length){
			if(lang.isArray(temp = result.shift())){
				dojo.require.apply(dojo, temp);
			}else{
				dojo.require(temp);
			}
		}
	};

	dojo.requireIf = dojo.requireAfterIf = function(/*Boolean*/ condition, /*String*/ moduleName, /*Boolean?*/omitModuleCheck){
		// summary:
		//		If the condition is true then call `dojo.require()` for the specified
		//		resource
		//
		// example:
		//	|	dojo.requireIf(dojo.isBrowser, "my.special.Module");

		if(condition){
			dojo.require(moduleName, omitModuleCheck);
		}
	};

	dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale){
		require(["../i18n"], function(i18n){
			i18n.getLocalization(moduleName, bundleName, locale);
		});
	};

	return {
		// summary:
		//		This module defines the v1.x synchronous loader API.

		extractLegacyApiApplications:extractLegacyApiApplications,
		require:dojoRequirePlugin,
		loadInit:dojoLoadInitPlugin
	};
});