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