dojo.js 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026
  1. (function(
  2. userConfig,
  3. defaultConfig
  4. ){
  5. // summary:
  6. // This is the "source loader" and is the entry point for Dojo during development. You may also load Dojo with
  7. // any AMD-compliant loader via the package main module dojo/main.
  8. // description:
  9. // This is the "source loader" for Dojo. It provides an AMD-compliant loader that can be configured
  10. // to operate in either synchronous or asynchronous modes. After the loader is defined, dojo is loaded
  11. // IAW the package main module dojo/main. In the event you wish to use a foreign loader, you may load dojo as a package
  12. // via the package main module dojo/main and this loader is not required; see dojo/package.json for details.
  13. //
  14. // In order to keep compatibility with the v1.x line, this loader includes additional machinery that enables
  15. // the dojo.provide, dojo.require et al API. This machinery is loaded by default, but may be dynamically removed
  16. // via the has.js API and statically removed via the build system.
  17. //
  18. // This loader includes sniffing machinery to determine the environment; the following environments are supported:
  19. //
  20. // - browser
  21. // - node.js
  22. // - rhino
  23. //
  24. // This is the so-called "source loader". As such, it includes many optional features that may be discarded by
  25. // building a customized version with the build system.
  26. // Design and Implementation Notes
  27. //
  28. // This is a dojo-specific adaption of bdLoad, donated to the dojo foundation by Altoviso LLC.
  29. //
  30. // This function defines an AMD-compliant (http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition)
  31. // loader that can be configured to operate in either synchronous or asynchronous modes.
  32. //
  33. // Since this machinery implements a loader, it does not have the luxury of using a load system and/or
  34. // leveraging a utility library. This results in an unpleasantly long file; here is a road map of the contents:
  35. //
  36. // 1. Small library for use implementing the loader.
  37. // 2. Define the has.js API; this is used throughout the loader to bracket features.
  38. // 3. Define the node.js and rhino sniffs and sniff.
  39. // 4. Define the loader's data.
  40. // 5. Define the configuration machinery.
  41. // 6. Define the script element sniffing machinery and sniff for configuration data.
  42. // 7. Configure the loader IAW the provided user, default, and sniffing data.
  43. // 8. Define the global require function.
  44. // 9. Define the module resolution machinery.
  45. // 10. Define the module and plugin module definition machinery
  46. // 11. Define the script injection machinery.
  47. // 12. Define the window load detection.
  48. // 13. Define the logging API.
  49. // 14. Define the tracing API.
  50. // 16. Define the AMD define function.
  51. // 17. Define the dojo v1.x provide/require machinery--so called "legacy" modes.
  52. // 18. Publish global variables.
  53. //
  54. // Language and Acronyms and Idioms
  55. //
  56. // moduleId: a CJS module identifier, (used for public APIs)
  57. // mid: moduleId (used internally)
  58. // packageId: a package identifier (used for public APIs)
  59. // pid: packageId (used internally); the implied system or default package has pid===""
  60. // pack: package is used internally to reference a package object (since javascript has reserved words including "package")
  61. // prid: plugin resource identifier
  62. // The integer constant 1 is used in place of true and 0 in place of false.
  63. // define a minimal library to help build the loader
  64. var noop = function(){
  65. },
  66. isEmpty = function(it){
  67. for(var p in it){
  68. return 0;
  69. }
  70. return 1;
  71. },
  72. toString = {}.toString,
  73. isFunction = function(it){
  74. return toString.call(it) == "[object Function]";
  75. },
  76. isString = function(it){
  77. return toString.call(it) == "[object String]";
  78. },
  79. isArray = function(it){
  80. return toString.call(it) == "[object Array]";
  81. },
  82. forEach = function(vector, callback){
  83. if(vector){
  84. for(var i = 0; i < vector.length;){
  85. callback(vector[i++]);
  86. }
  87. }
  88. },
  89. mix = function(dest, src){
  90. for(var p in src){
  91. dest[p] = src[p];
  92. }
  93. return dest;
  94. },
  95. makeError = function(error, info){
  96. return mix(new Error(error), {src:"dojoLoader", info:info});
  97. },
  98. uidSeed = 1,
  99. uid = function(){
  100. // Returns a unique identifier (within the lifetime of the document) of the form /_d+/.
  101. return "_" + uidSeed++;
  102. },
  103. // FIXME: how to doc window.require() api
  104. // this will be the global require function; define it immediately so we can start hanging things off of it
  105. req = function(
  106. config, //(object, optional) hash of configuration properties
  107. dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before applying callback
  108. callback //(function, optional) lambda expression to apply to module values implied by dependencies
  109. ){
  110. return contextRequire(config, dependencies, callback, 0, req);
  111. },
  112. // the loader uses the has.js API to control feature inclusion/exclusion; define then use throughout
  113. global = this,
  114. doc = global.document,
  115. element = doc && doc.createElement("DiV"),
  116. has = req.has = function(name){
  117. return isFunction(hasCache[name]) ? (hasCache[name] = hasCache[name](global, doc, element)) : hasCache[name];
  118. },
  119. hasCache = has.cache = defaultConfig.hasCache;
  120. has.add = function(name, test, now, force){
  121. (hasCache[name]===undefined || force) && (hasCache[name] = test);
  122. return now && has(name);
  123. };
  124. has.add("host-node", userConfig.has && "host-node" in userConfig.has ?
  125. userConfig.has["host-node"] :
  126. (typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
  127. if(has("host-node")){
  128. // fixup the default config for node.js environment
  129. require("./_base/configNode.js").config(defaultConfig);
  130. // remember node's require (with respect to baseUrl==dojo's root)
  131. defaultConfig.loaderPatch.nodeRequire = require;
  132. }
  133. has.add("host-rhino", userConfig.has && "host-rhino" in userConfig.has ?
  134. userConfig.has["host-rhino"] :
  135. (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
  136. if(has("host-rhino")){
  137. // owing to rhino's lame feature that hides the source of the script, give the user a way to specify the baseUrl...
  138. for(var baseUrl = userConfig.baseUrl || ".", arg, rhinoArgs = this.arguments, i = 0; i < rhinoArgs.length;){
  139. arg = (rhinoArgs[i++] + "").split("=");
  140. if(arg[0] == "baseUrl"){
  141. baseUrl = arg[1];
  142. break;
  143. }
  144. }
  145. load(baseUrl + "/_base/configRhino.js");
  146. rhinoDojoConfig(defaultConfig, baseUrl, rhinoArgs);
  147. }
  148. has.add("host-webworker", ((typeof WorkerGlobalScope !== 'undefined') && (self instanceof WorkerGlobalScope)));
  149. if(has("host-webworker")){
  150. mix(defaultConfig.hasCache, {
  151. "host-browser": 0,
  152. "dom": 0,
  153. "dojo-dom-ready-api": 0,
  154. "dojo-sniff": 0,
  155. "dojo-inject-api": 1,
  156. "host-webworker": 1
  157. });
  158. defaultConfig.loaderPatch = {
  159. injectUrl: function(url, callback){
  160. // TODO:
  161. // This is not async, nor can it be in Webworkers. It could be made better by passing
  162. // the entire require array into importScripts at. This way the scripts are loaded in
  163. // async mode; even if the callbacks are ran in sync. It is not a major issue as webworkers
  164. // tend to be long running where initial startup is not a major factor.
  165. try{
  166. importScripts(url);
  167. callback();
  168. }catch(e){
  169. console.info("failed to load resource (" + url + ")");
  170. console.error(e);
  171. }
  172. }
  173. };
  174. }
  175. // userConfig has tests override defaultConfig has tests; do this after the environment detection because
  176. // the environment detection usually sets some has feature values in the hasCache.
  177. for(var p in userConfig.has){
  178. has.add(p, userConfig.has[p], 0, 1);
  179. }
  180. //
  181. // define the loader data
  182. //
  183. // the loader will use these like symbols if the loader has the traceApi; otherwise
  184. // define magic numbers so that modules can be provided as part of defaultConfig
  185. var requested = 1,
  186. arrived = 2,
  187. nonmodule = 3,
  188. executing = 4,
  189. executed = 5;
  190. if(has("dojo-trace-api")){
  191. // these make debugging nice; but using strings for symbols is a gross rookie error; don't do it for production code
  192. requested = "requested";
  193. arrived = "arrived";
  194. nonmodule = "not-a-module";
  195. executing = "executing";
  196. executed = "executed";
  197. }
  198. var legacyMode = 0,
  199. sync = "sync",
  200. xd = "xd",
  201. syncExecStack = [],
  202. dojoRequirePlugin = 0,
  203. checkDojoRequirePlugin = noop,
  204. transformToAmd = noop,
  205. getXhr;
  206. if(has("dojo-sync-loader")){
  207. req.isXdUrl = noop;
  208. req.initSyncLoader = function(dojoRequirePlugin_, checkDojoRequirePlugin_, transformToAmd_){
  209. // the first dojo/_base/loader loaded gets to define these variables; they are designed to work
  210. // in the presence of zero to many mapped dojo/_base/loaders
  211. if(!dojoRequirePlugin){
  212. dojoRequirePlugin = dojoRequirePlugin_;
  213. checkDojoRequirePlugin = checkDojoRequirePlugin_;
  214. transformToAmd = transformToAmd_;
  215. }
  216. return {
  217. sync:sync,
  218. requested:requested,
  219. arrived:arrived,
  220. nonmodule:nonmodule,
  221. executing:executing,
  222. executed:executed,
  223. syncExecStack:syncExecStack,
  224. modules:modules,
  225. execQ:execQ,
  226. getModule:getModule,
  227. injectModule:injectModule,
  228. setArrived:setArrived,
  229. signal:signal,
  230. finishExec:finishExec,
  231. execModule:execModule,
  232. dojoRequirePlugin:dojoRequirePlugin,
  233. getLegacyMode:function(){return legacyMode;},
  234. guardCheckComplete:guardCheckComplete
  235. };
  236. };
  237. if(has("dom") || has("host-webworker")){
  238. // in legacy sync mode, the loader needs a minimal XHR library
  239. var locationProtocol = location.protocol,
  240. locationHost = location.host;
  241. req.isXdUrl = function(url){
  242. if(/^\./.test(url)){
  243. // begins with a dot is always relative to page URL; therefore not xdomain
  244. return false;
  245. }
  246. if(/^\/\//.test(url)){
  247. // for v1.6- backcompat, url starting with // indicates xdomain
  248. return true;
  249. }
  250. // get protocol and host
  251. // \/+ takes care of the typical file protocol that looks like file:///drive/path/to/file
  252. // locationHost is falsy if file protocol => if locationProtocol matches and is "file:", || will return false
  253. var match = url.match(/^([^\/\:]+\:)\/+([^\/]+)/);
  254. return match && (match[1] != locationProtocol || (locationHost && match[2] != locationHost));
  255. };
  256. // note: to get the file:// protocol to work in FF, you must set security.fileuri.strict_origin_policy to false in about:config
  257. has.add("dojo-xhr-factory", 1);
  258. has.add("dojo-force-activex-xhr", has("host-browser") && !doc.addEventListener && window.location.protocol == "file:");
  259. has.add("native-xhr", typeof XMLHttpRequest != "undefined");
  260. if(has("native-xhr") && !has("dojo-force-activex-xhr")){
  261. getXhr = function(){
  262. return new XMLHttpRequest();
  263. };
  264. }else{
  265. // if in the browser an old IE; find an xhr
  266. for(var XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], progid, i = 0; i < 3;){
  267. try{
  268. progid = XMLHTTP_PROGIDS[i++];
  269. if(new ActiveXObject(progid)){
  270. // this progid works; therefore, use it from now on
  271. break;
  272. }
  273. }catch(e){
  274. // squelch; we're just trying to find a good ActiveX progid
  275. // if they all fail, then progid ends up as the last attempt and that will signal the error
  276. // the first time the client actually tries to exec an xhr
  277. }
  278. }
  279. getXhr = function(){
  280. return new ActiveXObject(progid);
  281. };
  282. }
  283. req.getXhr = getXhr;
  284. has.add("dojo-gettext-api", 1);
  285. req.getText = function(url, async, onLoad){
  286. var xhr = getXhr();
  287. xhr.open('GET', fixupUrl(url), false);
  288. xhr.send(null);
  289. if(xhr.status == 200 || (!location.host && !xhr.status)){
  290. if(onLoad){
  291. onLoad(xhr.responseText, async);
  292. }
  293. }else{
  294. throw makeError("xhrFailed", xhr.status);
  295. }
  296. return xhr.responseText;
  297. };
  298. }
  299. }else{
  300. req.async = 1;
  301. }
  302. //
  303. // loader eval
  304. //
  305. var eval_ =
  306. // use the function constructor so our eval is scoped close to (but not in) in the global space with minimal pollution
  307. new Function('return eval(arguments[0]);');
  308. req.eval =
  309. function(text, hint){
  310. return eval_(text + "\r\n//# sourceURL=" + hint);
  311. };
  312. //
  313. // loader micro events API
  314. //
  315. var listenerQueues = {},
  316. error = "error",
  317. signal = req.signal = function(type, args){
  318. var queue = listenerQueues[type];
  319. // notice we run a copy of the queue; this allows listeners to add/remove
  320. // other listeners without affecting this particular signal
  321. forEach(queue && queue.slice(0), function(listener){
  322. listener.apply(null, isArray(args) ? args : [args]);
  323. });
  324. },
  325. on = req.on = function(type, listener){
  326. // notice a queue is not created until a client actually connects
  327. var queue = listenerQueues[type] || (listenerQueues[type] = []);
  328. queue.push(listener);
  329. return {
  330. remove:function(){
  331. for(var i = 0; i<queue.length; i++){
  332. if(queue[i]===listener){
  333. queue.splice(i, 1);
  334. return;
  335. }
  336. }
  337. }
  338. };
  339. };
  340. // configuration machinery; with an optimized/built defaultConfig, all configuration machinery can be discarded
  341. // lexical variables hold key loader data structures to help with minification; these may be completely,
  342. // one-time initialized by defaultConfig for optimized/built versions
  343. var
  344. aliases
  345. // a vector of pairs of [regexs or string, replacement] => (alias, actual)
  346. = [],
  347. paths
  348. // CommonJS paths
  349. = {},
  350. pathsMapProg
  351. // list of (from-path, to-path, regex, length) derived from paths;
  352. // a "program" to apply paths; see computeMapProg
  353. = [],
  354. packs
  355. // a map from packageId to package configuration object; see fixupPackageInfo
  356. = {},
  357. map = req.map
  358. // AMD map config variable; dojo/_base/kernel needs req.map to figure out the scope map
  359. = {},
  360. mapProgs
  361. // vector of quads as described by computeMapProg; map-key is AMD map key, map-value is AMD map value
  362. = [],
  363. modules
  364. // A hash:(mid) --> (module-object) the module namespace
  365. //
  366. // pid: the package identifier to which the module belongs (e.g., "dojo"); "" indicates the system or default package
  367. // mid: the fully-resolved (i.e., mappings have been applied) module identifier without the package identifier (e.g., "dojo/io/script")
  368. // url: the URL from which the module was retrieved
  369. // pack: the package object of the package to which the module belongs
  370. // executed: 0 => not executed; executing => in the process of traversing deps and running factory; executed => factory has been executed
  371. // deps: the dependency vector for this module (vector of modules objects)
  372. // def: the factory for this module
  373. // result: the result of the running the factory for this module
  374. // injected: (0 | requested | arrived) the status of the module; nonmodule means the resource did not call define
  375. // load: plugin load function; applicable only for plugins
  376. //
  377. // Modules go through several phases in creation:
  378. //
  379. // 1. Requested: some other module's definition or a require application contained the requested module in
  380. // its dependency vector or executing code explicitly demands a module via req.require.
  381. //
  382. // 2. Injected: a script element has been appended to the insert-point element demanding the resource implied by the URL
  383. //
  384. // 3. Loaded: the resource injected in [2] has been evaluated.
  385. //
  386. // 4. Defined: the resource contained a define statement that advised the loader about the module. Notice that some
  387. // resources may just contain a bundle of code and never formally define a module via define
  388. //
  389. // 5. Evaluated: the module was defined via define and the loader has evaluated the factory and computed a result.
  390. = {},
  391. cacheBust
  392. // query string to append to module URLs to bust browser cache
  393. = "",
  394. cache
  395. // hash:(mid | url)-->(function | string)
  396. //
  397. // A cache of resources. The resources arrive via a config.cache object, which is a hash from either mid --> function or
  398. // url --> string. The url key is distinguished from the mid key by always containing the prefix "url:". url keys as provided
  399. // by config.cache always have a string value that represents the contents of the resource at the given url. mid keys as provided
  400. // by configl.cache always have a function value that causes the same code to execute as if the module was script injected.
  401. //
  402. // Both kinds of key-value pairs are entered into cache via the function consumePendingCache, which may relocate keys as given
  403. // by any mappings *iff* the config.cache was received as part of a module resource request.
  404. //
  405. // Further, for mid keys, the implied url is computed and the value is entered into that key as well. This allows mapped modules
  406. // to retrieve cached items that may have arrived consequent to another namespace.
  407. //
  408. = {},
  409. urlKeyPrefix
  410. // the prefix to prepend to a URL key in the cache.
  411. = "url:",
  412. pendingCacheInsert
  413. // hash:(mid)-->(function)
  414. //
  415. // Gives a set of cache modules pending entry into cache. When cached modules are published to the loader, they are
  416. // entered into pendingCacheInsert; modules are then pressed into cache upon (1) AMD define or (2) upon receiving another
  417. // independent set of cached modules. (1) is the usual case, and this case allows normalizing mids given in the pending
  418. // cache for the local configuration, possibly relocating modules.
  419. = {},
  420. dojoSniffConfig
  421. // map of configuration variables
  422. // give the data-dojo-config as sniffed from the document (if any)
  423. = {},
  424. insertPointSibling
  425. // the nodes used to locate where scripts are injected into the document
  426. = 0;
  427. if(has("dojo-config-api")){
  428. var consumePendingCacheInsert = function(referenceModule){
  429. var p, item, match, now, m;
  430. for(p in pendingCacheInsert){
  431. item = pendingCacheInsert[p];
  432. match = p.match(/^url\:(.+)/);
  433. if(match){
  434. cache[urlKeyPrefix + toUrl(match[1], referenceModule)] = item;
  435. }else if(p=="*now"){
  436. now = item;
  437. }else if(p!="*noref"){
  438. m = getModuleInfo(p, referenceModule, true);
  439. cache[m.mid] = cache[urlKeyPrefix + m.url] = item;
  440. }
  441. }
  442. if(now){
  443. now(createRequire(referenceModule));
  444. }
  445. pendingCacheInsert = {};
  446. },
  447. escapeString = function(s){
  448. return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(c){ return "\\" + c; });
  449. },
  450. computeMapProg = function(map, dest){
  451. // This routine takes a map as represented by a JavaScript object and initializes dest, a vector of
  452. // quads of (map-key, map-value, refex-for-map-key, length-of-map-key), sorted decreasing by length-
  453. // of-map-key. The regex looks for the map-key followed by either "/" or end-of-string at the beginning
  454. // of a the search source. Notice the map-value is irrelevant to the algorithm
  455. dest.splice(0, dest.length);
  456. for(var p in map){
  457. dest.push([
  458. p,
  459. map[p],
  460. new RegExp("^" + escapeString(p) + "(\/|$)"),
  461. p.length]);
  462. }
  463. dest.sort(function(lhs, rhs){ return rhs[3] - lhs[3]; });
  464. return dest;
  465. },
  466. computeAliases = function(config, dest){
  467. forEach(config, function(pair){
  468. // take a fixed-up copy...
  469. dest.push([isString(pair[0]) ? new RegExp("^" + escapeString(pair[0]) + "$") : pair[0], pair[1]]);
  470. });
  471. },
  472. fixupPackageInfo = function(packageInfo){
  473. // calculate the precise (name, location, main, mappings) for a package
  474. var name = packageInfo.name;
  475. if(!name){
  476. // packageInfo must be a string that gives the name
  477. name = packageInfo;
  478. packageInfo = {name:name};
  479. }
  480. packageInfo = mix({main:"main"}, packageInfo);
  481. packageInfo.location = packageInfo.location ? packageInfo.location : name;
  482. // packageMap is deprecated in favor of AMD map
  483. if(packageInfo.packageMap){
  484. map[name] = packageInfo.packageMap;
  485. }
  486. if(!packageInfo.main.indexOf("./")){
  487. packageInfo.main = packageInfo.main.substring(2);
  488. }
  489. // now that we've got a fully-resolved package object, push it into the configuration
  490. packs[name] = packageInfo;
  491. },
  492. delayedModuleConfig
  493. // module config cannot be consumed until the loader is completely initialized; therefore, all
  494. // module config detected during booting is memorized and applied at the end of loader initialization
  495. // TODO: this is a bit of a kludge; all config should be moved to end of loader initialization, but
  496. // we'll delay this chore and do it with a final loader 1.x cleanup after the 2.x loader prototyping is complete
  497. = [],
  498. config = function(config, booting, referenceModule){
  499. for(var p in config){
  500. if(p=="waitSeconds"){
  501. req.waitms = (config[p] || 0) * 1000;
  502. }
  503. if(p=="cacheBust"){
  504. cacheBust = config[p] ? (isString(config[p]) ? config[p] : (new Date()).getTime() + "") : "";
  505. }
  506. if(p=="baseUrl" || p=="combo"){
  507. req[p] = config[p];
  508. }
  509. if(has("dojo-sync-loader") && p=="async"){
  510. // falsy or "sync" => legacy sync loader
  511. // "xd" => sync but loading xdomain tree and therefore loading asynchronously (not configurable, set automatically by the loader)
  512. // "legacyAsync" => permanently in "xd" by choice
  513. // "debugAtAllCosts" => trying to load everything via script injection (not implemented)
  514. // otherwise, must be truthy => AMD
  515. // legacyMode: sync | legacyAsync | xd | false
  516. var mode = config[p];
  517. req.legacyMode = legacyMode = (isString(mode) && /sync|legacyAsync/.test(mode) ? mode : (!mode ? sync : false));
  518. req.async = !legacyMode;
  519. }
  520. if(config[p]!==hasCache){
  521. // accumulate raw config info for client apps which can use this to pass their own config
  522. req.rawConfig[p] = config[p];
  523. p!="has" && has.add("config-"+p, config[p], 0, booting);
  524. }
  525. }
  526. // make sure baseUrl exists
  527. if(!req.baseUrl){
  528. req.baseUrl = "./";
  529. }
  530. // make sure baseUrl ends with a slash
  531. if(!/\/$/.test(req.baseUrl)){
  532. req.baseUrl += "/";
  533. }
  534. // now do the special work for has, packages, packagePaths, paths, aliases, and cache
  535. for(p in config.has){
  536. has.add(p, config.has[p], 0, booting);
  537. }
  538. // for each package found in any packages config item, augment the packs map owned by the loader
  539. forEach(config.packages, fixupPackageInfo);
  540. // for each packagePath found in any packagePaths config item, augment the packageConfig
  541. // packagePaths is deprecated; remove in 2.0
  542. for(var baseUrl in config.packagePaths){
  543. forEach(config.packagePaths[baseUrl], function(packageInfo){
  544. var location = baseUrl + "/" + packageInfo;
  545. if(isString(packageInfo)){
  546. packageInfo = {name:packageInfo};
  547. }
  548. packageInfo.location = location;
  549. fixupPackageInfo(packageInfo);
  550. });
  551. }
  552. // notice that computeMapProg treats the dest as a reference; therefore, if/when that variable
  553. // is published (see dojo-publish-privates), the published variable will always hold a valid value.
  554. // this must come after all package processing since package processing may mutate map
  555. computeMapProg(mix(map, config.map), mapProgs);
  556. forEach(mapProgs, function(item){
  557. item[1] = computeMapProg(item[1], []);
  558. if(item[0]=="*"){
  559. mapProgs.star = item;
  560. }
  561. });
  562. // push in any paths and recompute the internal pathmap
  563. computeMapProg(mix(paths, config.paths), pathsMapProg);
  564. // aliases
  565. computeAliases(config.aliases, aliases);
  566. if(booting){
  567. delayedModuleConfig.push({config:config.config});
  568. }else{
  569. for(p in config.config){
  570. var module = getModule(p, referenceModule);
  571. module.config = mix(module.config || {}, config.config[p]);
  572. }
  573. }
  574. // push in any new cache values
  575. if(config.cache){
  576. consumePendingCacheInsert();
  577. pendingCacheInsert = config.cache;
  578. if(config.cache["*noref"]){
  579. consumePendingCacheInsert();
  580. }
  581. }
  582. signal("config", [config, req.rawConfig]);
  583. };
  584. //
  585. // execute the various sniffs; userConfig can override and value
  586. //
  587. if(has("dojo-cdn") || has("dojo-sniff")){
  588. // the sniff regex looks for a src attribute ending in dojo.js, optionally preceded with a path.
  589. // match[3] returns the path to dojo.js (if any) without the trailing slash. This is used for the
  590. // dojo location on CDN deployments and baseUrl when either/both of these are not provided
  591. // explicitly in the config data; this is the 1.6- behavior.
  592. var scripts = doc.getElementsByTagName("script"),
  593. i = 0,
  594. script, dojoDir, src, match;
  595. while(i < scripts.length){
  596. script = scripts[i++];
  597. if((src = script.getAttribute("src")) && (match = src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){
  598. // sniff dojoDir and baseUrl
  599. dojoDir = match[3] || "";
  600. defaultConfig.baseUrl = defaultConfig.baseUrl || dojoDir;
  601. // remember an insertPointSibling
  602. insertPointSibling = script;
  603. }
  604. // sniff configuration on attribute in script element
  605. if((src = (script.getAttribute("data-dojo-config") || script.getAttribute("djConfig")))){
  606. dojoSniffConfig = req.eval("({ " + src + " })", "data-dojo-config");
  607. // remember an insertPointSibling
  608. insertPointSibling = script;
  609. }
  610. // sniff requirejs attribute
  611. if(has("dojo-requirejs-api")){
  612. if((src = script.getAttribute("data-main"))){
  613. dojoSniffConfig.deps = dojoSniffConfig.deps || [src];
  614. }
  615. }
  616. }
  617. }
  618. if(has("dojo-test-sniff")){
  619. // pass down doh.testConfig from parent as if it were a data-dojo-config
  620. try{
  621. if(window.parent != window && window.parent.require){
  622. var doh = window.parent.require("doh");
  623. doh && mix(dojoSniffConfig, doh.testConfig);
  624. }
  625. }catch(e){}
  626. }
  627. // configure the loader; let the user override defaults
  628. req.rawConfig = {};
  629. config(defaultConfig, 1);
  630. // do this before setting userConfig/sniffConfig to allow userConfig/sniff overrides
  631. if(has("dojo-cdn")){
  632. packs.dojo.location = dojoDir;
  633. if(dojoDir){
  634. dojoDir += "/";
  635. }
  636. packs.dijit.location = dojoDir + "../dijit/";
  637. packs.dojox.location = dojoDir + "../dojox/";
  638. }
  639. config(userConfig, 1);
  640. config(dojoSniffConfig, 1);
  641. }else{
  642. // no config API, assume defaultConfig has everything the loader needs...for the entire lifetime of the application
  643. paths = defaultConfig.paths;
  644. pathsMapProg = defaultConfig.pathsMapProg;
  645. packs = defaultConfig.packs;
  646. aliases = defaultConfig.aliases;
  647. mapProgs = defaultConfig.mapProgs;
  648. modules = defaultConfig.modules;
  649. cache = defaultConfig.cache;
  650. cacheBust = defaultConfig.cacheBust;
  651. // remember the default config for other processes (e.g., dojo/config)
  652. req.rawConfig = defaultConfig;
  653. }
  654. if(has("dojo-combo-api")){
  655. req.combo = req.combo || {add:noop};
  656. var comboPending = 0,
  657. combosPending = [],
  658. comboPendingTimer = null;
  659. }
  660. // build the loader machinery iaw configuration, including has feature tests
  661. var injectDependencies = function(module){
  662. // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
  663. guardCheckComplete(function(){
  664. forEach(module.deps, injectModule);
  665. if(has("dojo-combo-api") && comboPending && !comboPendingTimer){
  666. comboPendingTimer = setTimeout(function() {
  667. comboPending = 0;
  668. comboPendingTimer = null;
  669. req.combo.done(function(mids, url) {
  670. var onLoadCallback= function(){
  671. // defQ is a vector of module definitions 1-to-1, onto mids
  672. runDefQ(0, mids);
  673. checkComplete();
  674. };
  675. combosPending.push(mids);
  676. injectingModule = mids;
  677. req.injectUrl(url, onLoadCallback, mids);
  678. injectingModule = 0;
  679. }, req);
  680. }, 0);
  681. }
  682. });
  683. },
  684. contextRequire = function(a1, a2, a3, referenceModule, contextRequire){
  685. var module, syntheticMid;
  686. if(isString(a1)){
  687. // signature is (moduleId)
  688. module = getModule(a1, referenceModule, true);
  689. if(module && module.executed){
  690. return module.result;
  691. }
  692. throw makeError("undefinedModule", a1);
  693. }
  694. if(!isArray(a1)){
  695. // a1 is a configuration
  696. config(a1, 0, referenceModule);
  697. // juggle args; (a2, a3) may be (dependencies, callback)
  698. a1 = a2;
  699. a2 = a3;
  700. }
  701. if(isArray(a1)){
  702. // signature is (requestList [,callback])
  703. if(!a1.length){
  704. a2 && a2();
  705. }else{
  706. syntheticMid = "require*" + uid();
  707. // resolve the request list with respect to the reference module
  708. for(var mid, deps = [], i = 0; i < a1.length;){
  709. mid = a1[i++];
  710. deps.push(getModule(mid, referenceModule));
  711. }
  712. // construct a synthetic module to control execution of the requestList, and, optionally, callback
  713. module = mix(makeModuleInfo("", syntheticMid, 0, ""), {
  714. injected: arrived,
  715. deps: deps,
  716. def: a2 || noop,
  717. require: referenceModule ? referenceModule.require : req,
  718. gc: 1 //garbage collect
  719. });
  720. modules[module.mid] = module;
  721. // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
  722. injectDependencies(module);
  723. // try to immediately execute
  724. // if already traversing a factory tree, then strict causes circular dependency to abort the execution; maybe
  725. // it's possible to execute this require later after the current traversal completes and avoid the circular dependency.
  726. // ...but *always* insist on immediate in synch mode
  727. var strict = checkCompleteGuard && legacyMode!=sync;
  728. guardCheckComplete(function(){
  729. execModule(module, strict);
  730. });
  731. if(!module.executed){
  732. // some deps weren't on board or circular dependency detected and strict; therefore, push into the execQ
  733. execQ.push(module);
  734. }
  735. checkComplete();
  736. }
  737. }
  738. return contextRequire;
  739. },
  740. createRequire = function(module){
  741. if(!module){
  742. return req;
  743. }
  744. var result = module.require;
  745. if(!result){
  746. result = function(a1, a2, a3){
  747. return contextRequire(a1, a2, a3, module, result);
  748. };
  749. module.require = mix(result, req);
  750. result.module = module;
  751. result.toUrl = function(name){
  752. return toUrl(name, module);
  753. };
  754. result.toAbsMid = function(mid){
  755. return toAbsMid(mid, module);
  756. };
  757. if(has("dojo-undef-api")){
  758. result.undef = function(mid){
  759. req.undef(mid, module);
  760. };
  761. }
  762. if(has("dojo-sync-loader")){
  763. result.syncLoadNls = function(mid){
  764. var nlsModuleInfo = getModuleInfo(mid, module),
  765. nlsModule = modules[nlsModuleInfo.mid];
  766. if(!nlsModule || !nlsModule.executed){
  767. cached = cache[nlsModuleInfo.mid] || cache[urlKeyPrefix + nlsModuleInfo.url];
  768. if(cached){
  769. evalModuleText(cached);
  770. nlsModule = modules[nlsModuleInfo.mid];
  771. }
  772. }
  773. return nlsModule && nlsModule.executed && nlsModule.result;
  774. };
  775. }
  776. }
  777. return result;
  778. },
  779. execQ =
  780. // The list of modules that need to be evaluated.
  781. [],
  782. defQ =
  783. // The queue of define arguments sent to loader.
  784. [],
  785. waiting =
  786. // The set of modules upon which the loader is waiting for definition to arrive
  787. {},
  788. setRequested = function(module){
  789. module.injected = requested;
  790. waiting[module.mid] = 1;
  791. if(module.url){
  792. waiting[module.url] = module.pack || 1;
  793. }
  794. startTimer();
  795. },
  796. setArrived = function(module){
  797. module.injected = arrived;
  798. delete waiting[module.mid];
  799. if(module.url){
  800. delete waiting[module.url];
  801. }
  802. if(isEmpty(waiting)){
  803. clearTimer();
  804. has("dojo-sync-loader") && legacyMode==xd && (legacyMode = sync);
  805. }
  806. },
  807. execComplete = req.idle =
  808. // says the loader has completed (or not) its work
  809. function(){
  810. return !defQ.length && isEmpty(waiting) && !execQ.length && !checkCompleteGuard;
  811. },
  812. runMapProg = function(targetMid, map){
  813. // search for targetMid in map; return the map item if found; falsy otherwise
  814. if(map){
  815. for(var i = 0; i < map.length; i++){
  816. if(map[i][2].test(targetMid)){
  817. return map[i];
  818. }
  819. }
  820. }
  821. return 0;
  822. },
  823. compactPath = function(path){
  824. var result = [],
  825. segment, lastSegment;
  826. path = path.replace(/\\/g, '/').split('/');
  827. while(path.length){
  828. segment = path.shift();
  829. if(segment==".." && result.length && lastSegment!=".."){
  830. result.pop();
  831. lastSegment = result[result.length - 1];
  832. }else if(segment!="."){
  833. result.push(lastSegment= segment);
  834. } // else ignore "."
  835. }
  836. return result.join("/");
  837. },
  838. makeModuleInfo = function(pid, mid, pack, url){
  839. if(has("dojo-sync-loader")){
  840. var xd= req.isXdUrl(url);
  841. return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0, isXd:xd, isAmd:!!(xd || (packs[pid] && packs[pid].isAmd))};
  842. }else{
  843. return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0};
  844. }
  845. },
  846. getModuleInfo_ = function(mid, referenceModule, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate){
  847. // arguments are passed instead of using lexical variables so that this function my be used independent of the loader (e.g., the builder)
  848. // alwaysCreate is useful in this case so that getModuleInfo never returns references to real modules owned by the loader
  849. var pid, pack, midInPackage, mapItem, url, result, isRelative, requestedMid;
  850. requestedMid = mid;
  851. isRelative = /^\./.test(mid);
  852. if(/(^\/)|(\:)|(\.js$)/.test(mid) || (isRelative && !referenceModule)){
  853. // absolute path or protocol of .js filetype, or relative path but no reference module and therefore relative to page
  854. // whatever it is, it's not a module but just a URL of some sort
  855. // note: pid===0 indicates the routine is returning an unmodified mid
  856. return makeModuleInfo(0, mid, 0, mid);
  857. }else{
  858. // relative module ids are relative to the referenceModule; get rid of any dots
  859. mid = compactPath(isRelative ? (referenceModule.mid + "/../" + mid) : mid);
  860. if(/^\./.test(mid)){
  861. throw makeError("irrationalPath", mid);
  862. }
  863. // at this point, mid is an absolute mid
  864. // map the mid
  865. if(referenceModule){
  866. mapItem = runMapProg(referenceModule.mid, mapProgs);
  867. }
  868. mapItem = mapItem || mapProgs.star;
  869. mapItem = mapItem && runMapProg(mid, mapItem[1]);
  870. if(mapItem){
  871. mid = mapItem[1] + mid.substring(mapItem[3]);
  872. }
  873. match = mid.match(/^([^\/]+)(\/(.+))?$/);
  874. pid = match ? match[1] : "";
  875. if((pack = packs[pid])){
  876. mid = pid + "/" + (midInPackage = (match[3] || pack.main));
  877. }else{
  878. pid = "";
  879. }
  880. // search aliases
  881. var candidateLength = 0,
  882. candidate = 0;
  883. forEach(aliases, function(pair){
  884. var match = mid.match(pair[0]);
  885. if(match && match.length>candidateLength){
  886. candidate = isFunction(pair[1]) ? mid.replace(pair[0], pair[1]) : pair[1];
  887. }
  888. });
  889. if(candidate){
  890. return getModuleInfo_(candidate, 0, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate);
  891. }
  892. result = modules[mid];
  893. if(result){
  894. return alwaysCreate ? makeModuleInfo(result.pid, result.mid, result.pack, result.url) : modules[mid];
  895. }
  896. }
  897. // get here iff the sought-after module does not yet exist; therefore, we need to compute the URL given the
  898. // fully resolved (i.e., all relative indicators and package mapping resolved) module id
  899. // note: pid!==0 indicates the routine is returning a url that has .js appended unmodified mid
  900. mapItem = runMapProg(mid, pathsMapProg);
  901. if(mapItem){
  902. url = mapItem[1] + mid.substring(mapItem[3]);
  903. }else if(pid){
  904. url = pack.location + "/" + midInPackage;
  905. }else if(has("config-tlmSiblingOfDojo")){
  906. url = "../" + mid;
  907. }else{
  908. url = mid;
  909. }
  910. // if result is not absolute, add baseUrl
  911. if(!(/(^\/)|(\:)/.test(url))){
  912. url = baseUrl + url;
  913. }
  914. url += ".js";
  915. return makeModuleInfo(pid, mid, pack, compactPath(url));
  916. },
  917. getModuleInfo = function(mid, referenceModule, fromPendingCache){
  918. return getModuleInfo_(mid, referenceModule, packs, modules, req.baseUrl, fromPendingCache ? [] : mapProgs, fromPendingCache ? [] : pathsMapProg, fromPendingCache ? [] : aliases);
  919. },
  920. resolvePluginResourceId = function(plugin, prid, referenceModule){
  921. return plugin.normalize ? plugin.normalize(prid, function(mid){return toAbsMid(mid, referenceModule);}) : toAbsMid(prid, referenceModule);
  922. },
  923. dynamicPluginUidGenerator = 0,
  924. getModule = function(mid, referenceModule, immediate){
  925. // compute and optionally construct (if necessary) the module implied by the mid with respect to referenceModule
  926. var match, plugin, prid, result;
  927. match = mid.match(/^(.+?)\!(.*)$/);
  928. if(match){
  929. // name was <plugin-module>!<plugin-resource-id>
  930. plugin = getModule(match[1], referenceModule, immediate);
  931. if(has("dojo-sync-loader") && legacyMode == sync && !plugin.executed){
  932. injectModule(plugin);
  933. if(plugin.injected===arrived && !plugin.executed){
  934. guardCheckComplete(function(){
  935. execModule(plugin);
  936. });
  937. }
  938. if(plugin.executed){
  939. promoteModuleToPlugin(plugin);
  940. }else{
  941. // we are in xdomain mode for some reason
  942. execQ.unshift(plugin);
  943. }
  944. }
  945. if(plugin.executed === executed && !plugin.load){
  946. // executed the module not knowing it was a plugin
  947. promoteModuleToPlugin(plugin);
  948. }
  949. // if the plugin has not been loaded, then can't resolve the prid and must assume this plugin is dynamic until we find out otherwise
  950. if(plugin.load){
  951. prid = resolvePluginResourceId(plugin, match[2], referenceModule);
  952. mid = (plugin.mid + "!" + (plugin.dynamic ? ++dynamicPluginUidGenerator + "!" : "") + prid);
  953. }else{
  954. prid = match[2];
  955. mid = plugin.mid + "!" + (++dynamicPluginUidGenerator) + "!waitingForPlugin";
  956. }
  957. result = {plugin:plugin, mid:mid, req:createRequire(referenceModule), prid:prid};
  958. }else{
  959. result = getModuleInfo(mid, referenceModule);
  960. }
  961. return modules[result.mid] || (!immediate && (modules[result.mid] = result));
  962. },
  963. toAbsMid = req.toAbsMid = function(mid, referenceModule){
  964. return getModuleInfo(mid, referenceModule).mid;
  965. },
  966. toUrl = req.toUrl = function(name, referenceModule){
  967. var moduleInfo = getModuleInfo(name+"/x", referenceModule),
  968. url= moduleInfo.url;
  969. return fixupUrl(moduleInfo.pid===0 ?
  970. // if pid===0, then name had a protocol or absolute path; either way, toUrl is the identify function in such cases
  971. name :
  972. // "/x.js" since getModuleInfo automatically appends ".js" and we appended "/x" to make name look like a module id
  973. url.substring(0, url.length-5)
  974. );
  975. },
  976. nonModuleProps = {
  977. injected: arrived,
  978. executed: executed,
  979. def: nonmodule,
  980. result: nonmodule
  981. },
  982. makeCjs = function(mid){
  983. return modules[mid] = mix({mid:mid}, nonModuleProps);
  984. },
  985. cjsRequireModule = makeCjs("require"),
  986. cjsExportsModule = makeCjs("exports"),
  987. cjsModuleModule = makeCjs("module"),
  988. runFactory = function(module, args){
  989. req.trace("loader-run-factory", [module.mid]);
  990. var factory = module.def,
  991. result;
  992. has("dojo-sync-loader") && syncExecStack.unshift(module);
  993. if(has("config-dojo-loader-catches")){
  994. try{
  995. result= isFunction(factory) ? factory.apply(null, args) : factory;
  996. }catch(e){
  997. signal(error, module.result = makeError("factoryThrew", [module, e]));
  998. }
  999. }else{
  1000. result= isFunction(factory) ? factory.apply(null, args) : factory;
  1001. }
  1002. module.result = result===undefined && module.cjs ? module.cjs.exports : result;
  1003. has("dojo-sync-loader") && syncExecStack.shift(module);
  1004. },
  1005. abortExec = {},
  1006. defOrder = 0,
  1007. promoteModuleToPlugin = function(pluginModule){
  1008. var plugin = pluginModule.result;
  1009. pluginModule.dynamic = plugin.dynamic;
  1010. pluginModule.normalize = plugin.normalize;
  1011. pluginModule.load = plugin.load;
  1012. return pluginModule;
  1013. },
  1014. resolvePluginLoadQ = function(plugin){
  1015. // plugins is a newly executed module that has a loadQ waiting to run
  1016. // step 1: traverse the loadQ and fixup the mid and prid; remember the map from original mid to new mid
  1017. // recall the original mid was created before the plugin was on board and therefore it was impossible to
  1018. // compute the final mid; accordingly, prid may or may not change, but the mid will definitely change
  1019. var map = {};
  1020. forEach(plugin.loadQ, function(pseudoPluginResource){
  1021. // manufacture and insert the real module in modules
  1022. var prid = resolvePluginResourceId(plugin, pseudoPluginResource.prid, pseudoPluginResource.req.module),
  1023. mid = plugin.dynamic ? pseudoPluginResource.mid.replace(/waitingForPlugin$/, prid) : (plugin.mid + "!" + prid),
  1024. pluginResource = mix(mix({}, pseudoPluginResource), {mid:mid, prid:prid, injected:0});
  1025. if(!modules[mid]){
  1026. // create a new (the real) plugin resource and inject it normally now that the plugin is on board
  1027. injectPlugin(modules[mid] = pluginResource);
  1028. } // else this was a duplicate request for the same (plugin, rid) for a nondynamic plugin
  1029. // pluginResource is really just a placeholder with the wrong mid (because we couldn't calculate it until the plugin was on board)
  1030. // mark is as arrived and delete it from modules; the real module was requested above
  1031. map[pseudoPluginResource.mid] = modules[mid];
  1032. setArrived(pseudoPluginResource);
  1033. delete modules[pseudoPluginResource.mid];
  1034. });
  1035. plugin.loadQ = 0;
  1036. // step2: replace all references to any placeholder modules with real modules
  1037. var substituteModules = function(module){
  1038. for(var replacement, deps = module.deps || [], i = 0; i<deps.length; i++){
  1039. replacement = map[deps[i].mid];
  1040. if(replacement){
  1041. deps[i] = replacement;
  1042. }
  1043. }
  1044. };
  1045. for(var p in modules){
  1046. substituteModules(modules[p]);
  1047. }
  1048. forEach(execQ, substituteModules);
  1049. },
  1050. finishExec = function(module){
  1051. req.trace("loader-finish-exec", [module.mid]);
  1052. module.executed = executed;
  1053. module.defOrder = defOrder++;
  1054. has("dojo-sync-loader") && forEach(module.provides, function(cb){ cb(); });
  1055. if(module.loadQ){
  1056. // the module was a plugin
  1057. promoteModuleToPlugin(module);
  1058. resolvePluginLoadQ(module);
  1059. }
  1060. // remove all occurrences of this module from the execQ
  1061. for(i = 0; i < execQ.length;){
  1062. if(execQ[i] === module){
  1063. execQ.splice(i, 1);
  1064. }else{
  1065. i++;
  1066. }
  1067. }
  1068. // delete references to synthetic modules
  1069. if (/^require\*/.test(module.mid)) {
  1070. delete modules[module.mid];
  1071. }
  1072. },
  1073. circleTrace = [],
  1074. execModule = function(module, strict){
  1075. // run the dependency vector, then run the factory for module
  1076. if(module.executed === executing){
  1077. req.trace("loader-circular-dependency", [circleTrace.concat(module.mid).join("->")]);
  1078. return (!module.def || strict) ? abortExec : (module.cjs && module.cjs.exports);
  1079. }
  1080. // at this point the module is either not executed or fully executed
  1081. if(!module.executed){
  1082. if(!module.def){
  1083. return abortExec;
  1084. }
  1085. var mid = module.mid,
  1086. deps = module.deps || [],
  1087. arg, argResult,
  1088. args = [],
  1089. i = 0;
  1090. if(has("dojo-trace-api")){
  1091. circleTrace.push(mid);
  1092. req.trace("loader-exec-module", ["exec", circleTrace.length, mid]);
  1093. }
  1094. // for circular dependencies, assume the first module encountered was executed OK
  1095. // modules that circularly depend on a module that has not run its factory will get
  1096. // the pre-made cjs.exports===module.result. They can take a reference to this object and/or
  1097. // add properties to it. When the module finally runs its factory, the factory can
  1098. // read/write/replace this object. Notice that so long as the object isn't replaced, any
  1099. // reference taken earlier while walking the deps list is still valid.
  1100. module.executed = executing;
  1101. while((arg = deps[i++])){
  1102. argResult = ((arg === cjsRequireModule) ? createRequire(module) :
  1103. ((arg === cjsExportsModule) ? module.cjs.exports :
  1104. ((arg === cjsModuleModule) ? module.cjs :
  1105. execModule(arg, strict))));
  1106. if(argResult === abortExec){
  1107. module.executed = 0;
  1108. req.trace("loader-exec-module", ["abort", mid]);
  1109. has("dojo-trace-api") && circleTrace.pop();
  1110. return abortExec;
  1111. }
  1112. args.push(argResult);
  1113. }
  1114. runFactory(module, args);
  1115. finishExec(module);
  1116. has("dojo-trace-api") && circleTrace.pop();
  1117. }
  1118. // at this point the module is guaranteed fully executed
  1119. return module.result;
  1120. },
  1121. checkCompleteGuard = 0,
  1122. guardCheckComplete = function(proc){
  1123. try{
  1124. checkCompleteGuard++;
  1125. proc();
  1126. }finally{
  1127. checkCompleteGuard--;
  1128. }
  1129. if(execComplete()){
  1130. signal("idle", []);
  1131. }
  1132. },
  1133. checkComplete = function(){
  1134. // keep going through the execQ as long as at least one factory is executed
  1135. // plugins, recursion, cached modules all make for many execution path possibilities
  1136. if(checkCompleteGuard){
  1137. return;
  1138. }
  1139. guardCheckComplete(function(){
  1140. checkDojoRequirePlugin();
  1141. for(var currentDefOrder, module, i = 0; i < execQ.length;){
  1142. currentDefOrder = defOrder;
  1143. module = execQ[i];
  1144. execModule(module);
  1145. if(currentDefOrder!=defOrder){
  1146. // defOrder was bumped one or more times indicating something was executed (note, this indicates
  1147. // the execQ was modified, maybe a lot (for example a later module causes an earlier module to execute)
  1148. checkDojoRequirePlugin();
  1149. i = 0;
  1150. }else{
  1151. // nothing happened; check the next module in the exec queue
  1152. i++;
  1153. }
  1154. }
  1155. });
  1156. };
  1157. if(has("dojo-undef-api")){
  1158. req.undef = function(moduleId, referenceModule){
  1159. // In order to reload a module, it must be undefined (this routine) and then re-requested.
  1160. // This is useful for testing frameworks (at least).
  1161. var module = getModule(moduleId, referenceModule);
  1162. setArrived(module);
  1163. mix(module, {def:0, executed:0, injected:0, node:0});
  1164. };
  1165. }
  1166. if(has("dojo-inject-api")){
  1167. if(has("dojo-loader-eval-hint-url")===undefined){
  1168. has.add("dojo-loader-eval-hint-url", 1);
  1169. }
  1170. var fixupUrl= typeof userConfig.fixupUrl == "function" ? userConfig.fixupUrl : function(url){
  1171. url += ""; // make sure url is a Javascript string (some paths may be a Java string)
  1172. return url + (cacheBust ? ((/\?/.test(url) ? "&" : "?") + cacheBust) : "");
  1173. },
  1174. injectPlugin = function(
  1175. module
  1176. ){
  1177. // injects the plugin module given by module; may have to inject the plugin itself
  1178. var plugin = module.plugin;
  1179. if(plugin.executed === executed && !plugin.load){
  1180. // executed the module not knowing it was a plugin
  1181. promoteModuleToPlugin(plugin);
  1182. }
  1183. var onLoad = function(def){
  1184. module.result = def;
  1185. setArrived(module);
  1186. finishExec(module);
  1187. checkComplete();
  1188. };
  1189. if(plugin.load){
  1190. plugin.load(module.prid, module.req, onLoad);
  1191. }else if(plugin.loadQ){
  1192. plugin.loadQ.push(module);
  1193. }else{
  1194. // the unshift instead of push is important: we don't want plugins to execute as
  1195. // dependencies of some other module because this may cause circles when the plugin
  1196. // loadQ is run; also, generally, we want plugins to run early since they may load
  1197. // several other modules and therefore can potentially unblock many modules
  1198. plugin.loadQ = [module];
  1199. execQ.unshift(plugin);
  1200. injectModule(plugin);
  1201. }
  1202. },
  1203. // for IE, injecting a module may result in a recursive execution if the module is in the cache
  1204. cached = 0,
  1205. injectingModule = 0,
  1206. injectingCachedModule = 0,
  1207. evalModuleText = function(text, module){
  1208. // see def() for the injectingCachedModule bracket; it simply causes a short, safe circuit
  1209. if(has("config-stripStrict")){
  1210. text = text.replace(/"use strict"/g, '');
  1211. }
  1212. injectingCachedModule = 1;
  1213. if(has("config-dojo-loader-catches")){
  1214. try{
  1215. if(text===cached){
  1216. cached.call(null);
  1217. }else{
  1218. req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
  1219. }
  1220. }catch(e){
  1221. signal(error, makeError("evalModuleThrew", module));
  1222. }
  1223. }else{
  1224. if(text===cached){
  1225. cached.call(null);
  1226. }else{
  1227. req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
  1228. }
  1229. }
  1230. injectingCachedModule = 0;
  1231. },
  1232. injectModule = function(module){
  1233. // Inject the module. In the browser environment, this means appending a script element into
  1234. // the document; in other environments, it means loading a file.
  1235. //
  1236. // If in synchronous mode, then get the module synchronously if it's not xdomainLoading.
  1237. var mid = module.mid,
  1238. url = module.url;
  1239. if(module.executed || module.injected || waiting[mid] || (module.url && ((module.pack && waiting[module.url]===module.pack) || waiting[module.url]==1))){
  1240. return;
  1241. }
  1242. setRequested(module);
  1243. if(has("dojo-combo-api")){
  1244. var viaCombo = 0;
  1245. if(module.plugin && module.plugin.isCombo){
  1246. // a combo plugin; therefore, must be handled by combo service
  1247. // the prid should have already been converted to a URL (if required by the plugin) during
  1248. // the normalize process; in any event, there is no way for the loader to know how to
  1249. // to the conversion; therefore the third argument is zero
  1250. req.combo.add(module.plugin.mid, module.prid, 0, req);
  1251. viaCombo = 1;
  1252. }else if(!module.plugin){
  1253. viaCombo = req.combo.add(0, module.mid, module.url, req);
  1254. }
  1255. if(viaCombo){
  1256. comboPending= 1;
  1257. return;
  1258. }
  1259. }
  1260. if(module.plugin){
  1261. injectPlugin(module);
  1262. return;
  1263. } // else a normal module (not a plugin)
  1264. var onLoadCallback = function(){
  1265. runDefQ(module);
  1266. if(module.injected !== arrived){
  1267. // the script that contained the module arrived and has been executed yet
  1268. // nothing was added to the defQ (so it wasn't an AMD module) and the module
  1269. // wasn't marked as arrived by dojo.provide (so it wasn't a v1.6- module);
  1270. // therefore, it must not have been a module; adjust state accordingly
  1271. if(has("dojo-enforceDefine")){
  1272. signal(error, makeError("noDefine", module));
  1273. return;
  1274. }
  1275. setArrived(module);
  1276. mix(module, nonModuleProps);
  1277. req.trace("loader-define-nonmodule", [module.url]);
  1278. }
  1279. if(has("dojo-sync-loader") && legacyMode){
  1280. // must call checkComplete even in for sync loader because we may be in xdomainLoading mode;
  1281. // but, if xd loading, then don't call checkComplete until out of the current sync traversal
  1282. // in order to preserve order of execution of the dojo.required modules
  1283. !syncExecStack.length && checkComplete();
  1284. }else{
  1285. checkComplete();
  1286. }
  1287. };
  1288. cached = cache[mid] || cache[urlKeyPrefix + module.url];
  1289. if(cached){
  1290. req.trace("loader-inject", ["cache", module.mid, url]);
  1291. evalModuleText(cached, module);
  1292. onLoadCallback();
  1293. return;
  1294. }
  1295. if(has("dojo-sync-loader") && legacyMode){
  1296. if(module.isXd){
  1297. // switch to async mode temporarily; if current legacyMode!=sync, then is must be one of {legacyAsync, xd, false}
  1298. legacyMode==sync && (legacyMode = xd);
  1299. // fall through and load via script injection
  1300. }else if(module.isAmd && legacyMode!=sync){
  1301. // fall through and load via script injection
  1302. }else{
  1303. // mode may be sync, xd/legacyAsync, or async; module may be AMD or legacy; but module is always located on the same domain
  1304. var xhrCallback = function(text){
  1305. if(legacyMode==sync){
  1306. // the top of syncExecStack gives the current synchronously executing module; the loader needs
  1307. // to know this if it has to switch to async loading in the middle of evaluating a legacy module
  1308. // this happens when a modules dojo.require's a module that must be loaded async because it's xdomain
  1309. // (using unshift/shift because there is no back() methods for Javascript arrays)
  1310. syncExecStack.unshift(module);
  1311. evalModuleText(text, module);
  1312. syncExecStack.shift();
  1313. // maybe the module was an AMD module
  1314. runDefQ(module);
  1315. // legacy modules never get to defineModule() => cjs and injected never set; also evaluation implies executing
  1316. if(!module.cjs){
  1317. setArrived(module);
  1318. finishExec(module);
  1319. }
  1320. if(module.finish){
  1321. // while synchronously evaluating this module, dojo.require was applied referencing a module
  1322. // that had to be loaded async; therefore, the loader stopped answering all dojo.require
  1323. // requests so they could be answered completely in the correct sequence; module.finish gives
  1324. // the list of dojo.requires that must be re-applied once all target modules are available;
  1325. // make a synthetic module to execute the dojo.require's in the correct order
  1326. // compute a guaranteed-unique mid for the synthetic finish module; remember the finish vector; remove it from the reference module
  1327. // TODO: can we just leave the module.finish...what's it hurting?
  1328. var finishMid = mid + "*finish",
  1329. finish = module.finish;
  1330. delete module.finish;
  1331. def(finishMid, ["dojo", ("dojo/require!" + finish.join(",")).replace(/\./g, "/")], function(dojo){
  1332. forEach(finish, function(mid){ dojo.require(mid); });
  1333. });
  1334. // unshift, not push, which causes the current traversal to be reattempted from the top
  1335. execQ.unshift(getModule(finishMid));
  1336. }
  1337. onLoadCallback();
  1338. }else{
  1339. text = transformToAmd(module, text);
  1340. if(text){
  1341. evalModuleText(text, module);
  1342. onLoadCallback();
  1343. }else{
  1344. // if transformToAmd returned falsy, then the module was already AMD and it can be script-injected
  1345. // do so to improve debugability(even though it means another download...which probably won't happen with a good browser cache)
  1346. injectingModule = module;
  1347. req.injectUrl(fixupUrl(url), onLoadCallback, module);
  1348. injectingModule = 0;
  1349. }
  1350. }
  1351. };
  1352. req.trace("loader-inject", ["xhr", module.mid, url, legacyMode!=sync]);
  1353. if(has("config-dojo-loader-catches")){
  1354. try{
  1355. req.getText(url, legacyMode!=sync, xhrCallback);
  1356. }catch(e){
  1357. signal(error, makeError("xhrInjectFailed", [module, e]));
  1358. }
  1359. }else{
  1360. req.getText(url, legacyMode!=sync, xhrCallback);
  1361. }
  1362. return;
  1363. }
  1364. } // else async mode or fell through in xdomain loading mode; either way, load by script injection
  1365. req.trace("loader-inject", ["script", module.mid, url]);
  1366. injectingModule = module;
  1367. req.injectUrl(fixupUrl(url), onLoadCallback, module);
  1368. injectingModule = 0;
  1369. },
  1370. defineModule = function(module, deps, def){
  1371. req.trace("loader-define-module", [module.mid, deps]);
  1372. if(has("dojo-combo-api") && module.plugin && module.plugin.isCombo){
  1373. // the module is a plugin resource loaded by the combo service
  1374. // note: check for module.plugin should be enough since normal plugin resources should
  1375. // not follow this path; module.plugin.isCombo is future-proofing belt and suspenders
  1376. module.result = isFunction(def) ? def() : def;
  1377. setArrived(module);
  1378. finishExec(module);
  1379. return module;
  1380. }
  1381. var mid = module.mid;
  1382. if(module.injected === arrived){
  1383. signal(error, makeError("multipleDefine", module));
  1384. return module;
  1385. }
  1386. mix(module, {
  1387. deps: deps,
  1388. def: def,
  1389. cjs: {
  1390. id: module.mid,
  1391. uri: module.url,
  1392. exports: (module.result = {}),
  1393. setExports: function(exports){
  1394. module.cjs.exports = exports;
  1395. },
  1396. config:function(){
  1397. return module.config;
  1398. }
  1399. }
  1400. });
  1401. // resolve deps with respect to this module
  1402. for(var i = 0; deps[i]; i++){
  1403. deps[i] = getModule(deps[i], module);
  1404. }
  1405. if(has("dojo-sync-loader") && legacyMode && !waiting[mid]){
  1406. // the module showed up without being asked for; it was probably in a <script> element
  1407. injectDependencies(module);
  1408. execQ.push(module);
  1409. checkComplete();
  1410. }
  1411. setArrived(module);
  1412. if(!isFunction(def) && !deps.length){
  1413. module.result = def;
  1414. finishExec(module);
  1415. }
  1416. return module;
  1417. },
  1418. runDefQ = function(referenceModule, mids){
  1419. // defQ is an array of [id, dependencies, factory]
  1420. // mids (if any) is a vector of mids given by a combo service
  1421. var definedModules = [],
  1422. module, args;
  1423. while(defQ.length){
  1424. args = defQ.shift();
  1425. mids && (args[0]= mids.shift());
  1426. // explicit define indicates possible multiple modules in a single file; delay injecting dependencies until defQ fully
  1427. // processed since modules earlier in the queue depend on already-arrived modules that are later in the queue
  1428. // TODO: what if no args[0] and no referenceModule
  1429. module = (args[0] && getModule(args[0])) || referenceModule;
  1430. definedModules.push([module, args[1], args[2]]);
  1431. }
  1432. consumePendingCacheInsert(referenceModule);
  1433. forEach(definedModules, function(args){
  1434. injectDependencies(defineModule.apply(null, args));
  1435. });
  1436. };
  1437. }
  1438. var timerId = 0,
  1439. clearTimer = noop,
  1440. startTimer = noop;
  1441. if(has("dojo-timeout-api")){
  1442. // Timer machinery that monitors how long the loader is waiting and signals an error when the timer runs out.
  1443. clearTimer = function(){
  1444. timerId && clearTimeout(timerId);
  1445. timerId = 0;
  1446. };
  1447. startTimer = function(){
  1448. clearTimer();
  1449. if(req.waitms){
  1450. timerId = global.setTimeout(function(){
  1451. clearTimer();
  1452. signal(error, makeError("timeout", waiting));
  1453. }, req.waitms);
  1454. }
  1455. };
  1456. }
  1457. if (has("dom")) {
  1458. // Test for IE's different way of signaling when scripts finish loading. Note that according to
  1459. // http://bugs.dojotoolkit.org/ticket/15096#comment:14, IE9 also needs to follow the
  1460. // IE specific code path even though it has an addEventListener() method.
  1461. // Unknown if special path needed on IE10+, which also has a document.attachEvent() method.
  1462. // Should evaluate to false for Opera and Windows 8 apps, even though they document.attachEvent()
  1463. // is defined in both those environments.
  1464. has.add("ie-event-behavior", doc.attachEvent && typeof Windows === "undefined" &&
  1465. (typeof opera === "undefined" || opera.toString() != "[object Opera]"));
  1466. }
  1467. if(has("dom") && (has("dojo-inject-api") || has("dojo-dom-ready-api"))){
  1468. var domOn = function(node, eventName, ieEventName, handler){
  1469. // Add an event listener to a DOM node using the API appropriate for the current browser;
  1470. // return a function that will disconnect the listener.
  1471. if(!has("ie-event-behavior")){
  1472. node.addEventListener(eventName, handler, false);
  1473. return function(){
  1474. node.removeEventListener(eventName, handler, false);
  1475. };
  1476. }else{
  1477. node.attachEvent(ieEventName, handler);
  1478. return function(){
  1479. node.detachEvent(ieEventName, handler);
  1480. };
  1481. }
  1482. },
  1483. windowOnLoadListener = domOn(window, "load", "onload", function(){
  1484. req.pageLoaded = 1;
  1485. doc.readyState!="complete" && (doc.readyState = "complete");
  1486. windowOnLoadListener();
  1487. });
  1488. if(has("dojo-inject-api")){
  1489. // if the loader is on the page, there must be at least one script element
  1490. // getting its parent and then doing insertBefore solves the "Operation Aborted"
  1491. // error in IE from appending to a node that isn't properly closed; see
  1492. // dojo/tests/_base/loader/requirejs/simple-badbase.html for an example
  1493. // don't use scripts with type dojo/... since these may be removed; see #15809
  1494. // prefer to use the insertPoint computed during the config sniff in case a script is removed; see #16958
  1495. var scripts = doc.getElementsByTagName("script"),
  1496. i = 0,
  1497. script;
  1498. while(!insertPointSibling){
  1499. if(!/^dojo/.test((script = scripts[i++]) && script.type)){
  1500. insertPointSibling= script;
  1501. }
  1502. }
  1503. req.injectUrl = function(url, callback, owner){
  1504. // insert a script element to the insert-point element with src=url;
  1505. // apply callback upon detecting the script has loaded.
  1506. var node = owner.node = doc.createElement("script"),
  1507. onLoad = function(e){
  1508. e = e || window.event;
  1509. var node = e.target || e.srcElement;
  1510. if(e.type === "load" || /complete|loaded/.test(node.readyState)){
  1511. loadDisconnector();
  1512. errorDisconnector();
  1513. callback && callback();
  1514. }
  1515. },
  1516. loadDisconnector = domOn(node, "load", "onreadystatechange", onLoad),
  1517. errorDisconnector = domOn(node, "error", "onerror", function(e){
  1518. loadDisconnector();
  1519. errorDisconnector();
  1520. signal(error, makeError("scriptError", [url, e]));
  1521. });
  1522. node.type = "text/javascript";
  1523. node.charset = "utf-8";
  1524. node.src = url;
  1525. insertPointSibling.parentNode.insertBefore(node, insertPointSibling);
  1526. return node;
  1527. };
  1528. }
  1529. }
  1530. if(has("dojo-log-api")){
  1531. req.log = function(){
  1532. try{
  1533. for(var i = 0; i < arguments.length; i++){
  1534. console.log(arguments[i]);
  1535. }
  1536. }catch(e){}
  1537. };
  1538. }else{
  1539. req.log = noop;
  1540. }
  1541. if(has("dojo-trace-api")){
  1542. var trace = req.trace = function(
  1543. group, // the trace group to which this application belongs
  1544. args // the contents of the trace
  1545. ){
  1546. ///
  1547. // Tracing interface by group.
  1548. //
  1549. // Sends the contents of args to the console iff (req.trace.on && req.trace[group])
  1550. if(trace.on && trace.group[group]){
  1551. signal("trace", [group, args]);
  1552. for(var arg, dump = [], text= "trace:" + group + (args.length ? (":" + args[0]) : ""), i= 1; i<args.length;){
  1553. arg = args[i++];
  1554. if(isString(arg)){
  1555. text += ", " + arg;
  1556. }else{
  1557. dump.push(arg);
  1558. }
  1559. }
  1560. req.log(text);
  1561. dump.length && dump.push(".");
  1562. req.log.apply(req, dump);
  1563. }
  1564. };
  1565. mix(trace, {
  1566. on:1,
  1567. group:{},
  1568. set:function(group, value){
  1569. if(isString(group)){
  1570. trace.group[group]= value;
  1571. }else{
  1572. mix(trace.group, group);
  1573. }
  1574. }
  1575. });
  1576. trace.set(mix(mix(mix({}, defaultConfig.trace), userConfig.trace), dojoSniffConfig.trace));
  1577. on("config", function(config){
  1578. config.trace && trace.set(config.trace);
  1579. });
  1580. }else{
  1581. req.trace = noop;
  1582. }
  1583. var def = function(
  1584. mid, //(commonjs.moduleId, optional)
  1585. dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before running factory
  1586. factory //(any)
  1587. ){
  1588. ///
  1589. // Advises the loader of a module factory. //Implements http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition.
  1590. ///
  1591. //note
  1592. // CommonJS factory scan courtesy of http://requirejs.org
  1593. var arity = arguments.length,
  1594. defaultDeps = ["require", "exports", "module"],
  1595. // the predominate signature...
  1596. args = [0, mid, dependencies];
  1597. if(arity==1){
  1598. args = [0, (isFunction(mid) ? defaultDeps : []), mid];
  1599. }else if(arity==2 && isString(mid)){
  1600. args = [mid, (isFunction(dependencies) ? defaultDeps : []), dependencies];
  1601. }else if(arity==3){
  1602. args = [mid, dependencies, factory];
  1603. }
  1604. if(has("dojo-amd-factory-scan") && args[1]===defaultDeps){
  1605. args[2].toString()
  1606. .replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, "")
  1607. .replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g, function(match, dep){
  1608. args[1].push(dep);
  1609. });
  1610. }
  1611. req.trace("loader-define", args.slice(0, 2));
  1612. var targetModule = args[0] && getModule(args[0]),
  1613. module;
  1614. if(targetModule && !waiting[targetModule.mid]){
  1615. // given a mid that hasn't been requested; therefore, defined through means other than injecting
  1616. // consequent to a require() or define() application; examples include defining modules on-the-fly
  1617. // due to some code path or including a module in a script element. In any case,
  1618. // there is no callback waiting to finish processing and nothing to trigger the defQ and the
  1619. // dependencies are never requested; therefore, do it here.
  1620. injectDependencies(defineModule(targetModule, args[1], args[2]));
  1621. }else if(!has("ie-event-behavior") || !has("host-browser") || injectingCachedModule){
  1622. // not IE path: anonymous module and therefore must have been injected; therefore, onLoad will fire immediately
  1623. // after script finishes being evaluated and the defQ can be run from that callback to detect the module id
  1624. defQ.push(args);
  1625. }else{
  1626. // IE path: possibly anonymous module and therefore injected; therefore, cannot depend on 1-to-1,
  1627. // in-order exec of onLoad with script eval (since it's IE) and must manually detect here
  1628. targetModule = targetModule || injectingModule;
  1629. if(!targetModule){
  1630. for(mid in waiting){
  1631. module = modules[mid];
  1632. if(module && module.node && module.node.readyState === 'interactive'){
  1633. targetModule = module;
  1634. break;
  1635. }
  1636. }
  1637. if(has("dojo-combo-api") && !targetModule){
  1638. for(var i = 0; i<combosPending.length; i++){
  1639. targetModule = combosPending[i];
  1640. if(targetModule.node && targetModule.node.readyState === 'interactive'){
  1641. break;
  1642. }
  1643. targetModule= 0;
  1644. }
  1645. }
  1646. }
  1647. if(has("dojo-combo-api") && isArray(targetModule)){
  1648. injectDependencies(defineModule(getModule(targetModule.shift()), args[1], args[2]));
  1649. if(!targetModule.length){
  1650. combosPending.splice(i, 1);
  1651. }
  1652. }else if(targetModule){
  1653. consumePendingCacheInsert(targetModule);
  1654. injectDependencies(defineModule(targetModule, args[1], args[2]));
  1655. }else{
  1656. signal(error, makeError("ieDefineFailed", args[0]));
  1657. }
  1658. checkComplete();
  1659. }
  1660. };
  1661. def.amd = {
  1662. vendor:"dojotoolkit.org"
  1663. };
  1664. if(has("dojo-requirejs-api")){
  1665. req.def = def;
  1666. }
  1667. // allow config to override default implementation of named functions; this is useful for
  1668. // non-browser environments, e.g., overriding injectUrl, getText, log, etc. in node.js, Rhino, etc.
  1669. // also useful for testing and monkey patching loader
  1670. mix(mix(req, defaultConfig.loaderPatch), userConfig.loaderPatch);
  1671. // now that req is fully initialized and won't change, we can hook it up to the error signal
  1672. on(error, function(arg){
  1673. try{
  1674. console.error(arg);
  1675. if(arg instanceof Error){
  1676. for(var p in arg){
  1677. console.log(p + ":", arg[p]);
  1678. }
  1679. console.log(".");
  1680. }
  1681. }catch(e){}
  1682. });
  1683. // always publish these
  1684. mix(req, {
  1685. uid:uid,
  1686. cache:cache,
  1687. packs:packs
  1688. });
  1689. if(has("dojo-publish-privates")){
  1690. mix(req, {
  1691. // these may be interesting to look at when debugging
  1692. paths:paths,
  1693. aliases:aliases,
  1694. modules:modules,
  1695. legacyMode:legacyMode,
  1696. execQ:execQ,
  1697. defQ:defQ,
  1698. waiting:waiting,
  1699. // these are used for testing
  1700. // TODO: move testing infrastructure to a different has feature
  1701. packs:packs,
  1702. mapProgs:mapProgs,
  1703. pathsMapProg:pathsMapProg,
  1704. listenerQueues:listenerQueues,
  1705. // these are used by the builder (at least)
  1706. computeMapProg:computeMapProg,
  1707. computeAliases:computeAliases,
  1708. runMapProg:runMapProg,
  1709. compactPath:compactPath,
  1710. getModuleInfo:getModuleInfo_
  1711. });
  1712. }
  1713. // the loader can be defined exactly once; look for global define which is the symbol AMD loaders are
  1714. // *required* to define (as opposed to require, which is optional)
  1715. if(global.define){
  1716. if(has("dojo-log-api")){
  1717. signal(error, makeError("defineAlreadyDefined", 0));
  1718. }
  1719. return;
  1720. }else{
  1721. global.define = def;
  1722. global.require = req;
  1723. if(has("host-node")){
  1724. require = req;
  1725. }
  1726. }
  1727. if(has("dojo-combo-api") && req.combo && req.combo.plugins){
  1728. var plugins = req.combo.plugins,
  1729. pluginName;
  1730. for(pluginName in plugins){
  1731. mix(mix(getModule(pluginName), plugins[pluginName]), {isCombo:1, executed:"executed", load:1});
  1732. }
  1733. }
  1734. if(has("dojo-config-api")){
  1735. forEach(delayedModuleConfig, function(c){ config(c); });
  1736. var bootDeps = dojoSniffConfig.deps || userConfig.deps || defaultConfig.deps,
  1737. bootCallback = dojoSniffConfig.callback || userConfig.callback || defaultConfig.callback;
  1738. req.boot = (bootDeps || bootCallback) ? [bootDeps || [], bootCallback] : 0;
  1739. }
  1740. if(!has("dojo-built")){
  1741. !req.async && req(["dojo"]);
  1742. req.boot && req.apply(null, req.boot);
  1743. }
  1744. })
  1745. //>>excludeStart("replaceLoaderConfig", kwArgs.replaceLoaderConfig);
  1746. (
  1747. // userConfig
  1748. (function(){
  1749. // make sure we're looking at global dojoConfig etc.
  1750. return this.dojoConfig || this.djConfig || this.require || {};
  1751. })(),
  1752. // defaultConfig
  1753. {
  1754. // the default configuration for a browser; this will be modified by other environments
  1755. hasCache:{
  1756. "host-browser":1,
  1757. "dom":1,
  1758. "dojo-amd-factory-scan":1,
  1759. "dojo-loader":1,
  1760. "dojo-has-api":1,
  1761. "dojo-inject-api":1,
  1762. "dojo-timeout-api":1,
  1763. "dojo-trace-api":1,
  1764. "dojo-log-api":1,
  1765. "dojo-dom-ready-api":1,
  1766. "dojo-publish-privates":1,
  1767. "dojo-config-api":1,
  1768. "dojo-sniff":1,
  1769. "dojo-sync-loader":1,
  1770. "dojo-test-sniff":1,
  1771. "config-deferredInstrumentation":1,
  1772. "config-tlmSiblingOfDojo":1
  1773. },
  1774. packages:[{
  1775. // note: like v1.6-, this bootstrap computes baseUrl to be the dojo directory
  1776. name:'dojo',
  1777. location:'.'
  1778. },{
  1779. name:'tests',
  1780. location:'./tests'
  1781. },{
  1782. name:'dijit',
  1783. location:'../dijit'
  1784. },{
  1785. name:'build',
  1786. location:'../util/build'
  1787. },{
  1788. name:'doh',
  1789. location:'../util/doh'
  1790. },{
  1791. name:'dojox',
  1792. location:'../dojox'
  1793. },{
  1794. name:'demos',
  1795. location:'../demos'
  1796. }],
  1797. trace:{
  1798. // these are listed so it's simple to turn them on/off while debugging loading
  1799. "loader-inject":0,
  1800. "loader-define":0,
  1801. "loader-exec-module":0,
  1802. "loader-run-factory":0,
  1803. "loader-finish-exec":0,
  1804. "loader-define-module":0,
  1805. "loader-circular-dependency":0,
  1806. "loader-define-nonmodule":0
  1807. },
  1808. async:0,
  1809. waitSeconds:15
  1810. }
  1811. );
  1812. //>>excludeEnd("replaceLoaderConfig")