loader_xd.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojo._base._loader.loader_xd"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojo._base._loader.loader_xd"] = true;
  8. //Cross-domain resource loader.
  9. dojo.provide("dojo._base._loader.loader_xd");
  10. dojo._xdReset = function(){
  11. //summary: Internal xd loader function. Resets the xd state.
  12. //This flag indicates where or not we have crossed into xdomain territory. Once any resource says
  13. //it is cross domain, then the rest of the resources have to be treated as xdomain because we need
  14. //to evaluate resources in order. If there is a xdomain resource followed by a xhr resource, we can't load
  15. //the xhr resource until the one before it finishes loading. The text of the xhr resource will be converted
  16. //to match the format for a xd resource and put in the xd load queue.
  17. dojo._isXDomain = dojo.config.useXDomain || false;
  18. dojo._xdClearInterval();
  19. dojo._xdInFlight = {};
  20. dojo._xdOrderedReqs = [];
  21. dojo._xdDepMap = {};
  22. dojo._xdContents = [];
  23. dojo._xdDefList = [];
  24. }
  25. dojo._xdClearInterval = function(){
  26. //summary: Internal xd loader function.
  27. //Clears the interval timer used to check on the
  28. //status of in-flight xd module resource requests.
  29. if(dojo._xdTimer){
  30. clearInterval(dojo._xdTimer);
  31. dojo._xdTimer = 0;
  32. }
  33. }
  34. //Call reset immediately to set the state.
  35. dojo._xdReset();
  36. dojo._xdCreateResource = function(/*String*/contents, /*String*/resourceName, /*String*/resourcePath){
  37. //summary: Internal xd loader function. Creates an xd module source given an
  38. //non-xd module contents.
  39. //Remove comments. Not perfect, but good enough for dependency resolution.
  40. var depContents = contents.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg , "");
  41. //Find dependencies.
  42. var deps = [];
  43. var depRegExp = /dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg;
  44. var match;
  45. while((match = depRegExp.exec(depContents)) != null){
  46. if(match[1] == "requireLocalization"){
  47. //Need to load the local bundles asap, since they are not
  48. //part of the list of modules watched for loading.
  49. eval(match[0]);
  50. }else{
  51. deps.push('"' + match[1] + '", ' + match[2]);
  52. }
  53. }
  54. //Create resource object and the call to _xdResourceLoaded.
  55. var output = [];
  56. output.push(dojo._scopeName + "._xdResourceLoaded(function(" + dojo._scopePrefixArgs + "){\n");
  57. //See if there are any dojo.loadInit calls
  58. var loadInitCalls = dojo._xdExtractLoadInits(contents);
  59. if(loadInitCalls){
  60. //Adjust fileContents since extractLoadInits removed something.
  61. contents = loadInitCalls[0];
  62. //Add any loadInit calls to the top of the xd file.
  63. for(var i = 1; i < loadInitCalls.length; i++){
  64. output.push(loadInitCalls[i] + ";\n");
  65. }
  66. }
  67. output.push("return {");
  68. //Add dependencies
  69. if(deps.length > 0){
  70. output.push("depends: [");
  71. for(i = 0; i < deps.length; i++){
  72. if(i > 0){
  73. output.push(",\n");
  74. }
  75. output.push("[" + deps[i] + "]");
  76. }
  77. output.push("],");
  78. }
  79. //Add the contents of the file inside a function.
  80. //Pass in scope arguments so we can support multiple versions of the
  81. //same module on a page.
  82. output.push("\ndefineResource: function(" + dojo._scopePrefixArgs + "){");
  83. //Don't put in the contents in the debugAtAllCosts case
  84. //since the contents may have syntax errors. Let those
  85. //get pushed up when the script tags are added to the page
  86. //in the debugAtAllCosts case.
  87. if(!dojo.config["debugAtAllCosts"] || resourceName == "dojo._base._loader.loader_debug"){
  88. output.push(contents);
  89. }
  90. //Add isLocal property so we know if we have to do something different
  91. //in debugAtAllCosts situations.
  92. output.push("\n}, resourceName: '" + resourceName + "', resourcePath: '" + resourcePath + "'};});");
  93. return output.join(""); //String
  94. }
  95. dojo._xdExtractLoadInits = function(/*String*/fileContents){
  96. //Extracts
  97. var regexp = /dojo.loadInit\s*\(/g;
  98. regexp.lastIndex = 0;
  99. var parenRe = /[\(\)]/g;
  100. parenRe.lastIndex = 0;
  101. var results = [];
  102. var matches;
  103. while((matches = regexp.exec(fileContents))){
  104. //Find end of the call by finding the matching end paren
  105. parenRe.lastIndex = regexp.lastIndex;
  106. var matchCount = 1;
  107. var parenMatch;
  108. while((parenMatch = parenRe.exec(fileContents))){
  109. if(parenMatch[0] == ")"){
  110. matchCount -= 1;
  111. }else{
  112. matchCount += 1;
  113. }
  114. if(matchCount == 0){
  115. break;
  116. }
  117. }
  118. if(matchCount != 0){
  119. throw "unmatched paren around character " + parenRe.lastIndex + " in: " + fileContents;
  120. }
  121. //Put the master matching string in the results.
  122. var startIndex = regexp.lastIndex - matches[0].length;
  123. results.push(fileContents.substring(startIndex, parenRe.lastIndex));
  124. //Remove the matching section.
  125. var remLength = parenRe.lastIndex - startIndex;
  126. fileContents = fileContents.substring(0, startIndex) + fileContents.substring(parenRe.lastIndex, fileContents.length);
  127. //Move the master regexp past the last matching paren point.
  128. regexp.lastIndex = parenRe.lastIndex - remLength;
  129. regexp.lastIndex = parenRe.lastIndex;
  130. }
  131. if(results.length > 0){
  132. results.unshift(fileContents);
  133. }
  134. return (results.length ? results : null);
  135. }
  136. dojo._xdIsXDomainPath = function(/*string*/relpath) {
  137. //summary: Figure out whether the path is local or x-domain
  138. //If there is a colon before the first / then, we have a URL with a protocol.
  139. var colonIndex = relpath.indexOf(":");
  140. var slashIndex = relpath.indexOf("/");
  141. if(colonIndex > 0 && colonIndex < slashIndex || relpath.indexOf("//") === 0){
  142. return true;
  143. }else{
  144. //Is the base script URI-based URL a cross domain URL?
  145. //If so, then the relpath will be evaluated relative to
  146. //baseUrl, and therefore qualify as xdomain.
  147. //Only treat it as xdomain if the page does not have a
  148. //host (file:// url), if the baseUrl does not match the
  149. //current window's domain, or if the baseUrl starts with //.
  150. //If baseUrl starts with // then it probably means that xdomain
  151. //is wanted since it is such a specific path request. This is not completely robust,
  152. //but something more robust would require normalizing the protocol on baseUrl and on the location
  153. //to see if they differ. However, that requires more code, and // as a start path is unusual.
  154. var url = dojo.baseUrl;
  155. colonIndex = url.indexOf(":");
  156. slashIndex = url.indexOf("/");
  157. if(url.indexOf("//") === 0 || (colonIndex > 0 && colonIndex < slashIndex && (!location.host || url.indexOf("http://" + location.host) != 0))){
  158. return true;
  159. }
  160. }
  161. return false;
  162. }
  163. dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
  164. //summary: Internal xd loader function. Overrides loadPath() from loader.js.
  165. //xd loading requires slightly different behavior from loadPath().
  166. var currentIsXDomain = dojo._xdIsXDomainPath(relpath);
  167. dojo._isXDomain |= currentIsXDomain;
  168. var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : dojo.baseUrl) + relpath;
  169. try{
  170. return ((!module || dojo._isXDomain) ? dojo._loadUri(uri, cb, currentIsXDomain, module) : dojo._loadUriAndCheck(uri, module, cb)); //Boolean
  171. }catch(e){
  172. console.error(e);
  173. return false; //Boolean
  174. }
  175. }
  176. dojo._xdCharSet = "utf-8";
  177. dojo._loadUri = function(/*String*/uri, /*Function?*/cb, /*boolean*/currentIsXDomain, /*String?*/module){
  178. //summary: Internal xd loader function. Overrides loadUri() from loader.js.
  179. // xd loading requires slightly different behavior from loadPath().
  180. //description: Wanted to override getText(), but it is used by
  181. // the widget code in too many, synchronous ways right now.
  182. if(dojo._loadedUrls[uri]){
  183. return 1; //Boolean
  184. }
  185. //Add the module (resource) to the list of modules.
  186. //Only do this work if we have a modlue name. Otherwise,
  187. //it is a non-xd i18n bundle, which can load immediately and does not
  188. //need to be tracked. Also, don't track dojo.i18n, since it is a prerequisite
  189. //and will be loaded correctly if we load it right away: it has no dependencies.
  190. if(dojo._isXDomain && module && module != "dojo.i18n"){
  191. dojo._xdOrderedReqs.push(module);
  192. //Add to waiting resources if it is an xdomain resource.
  193. //Don't add non-xdomain i18n bundles, those get evaled immediately.
  194. if(currentIsXDomain || uri.indexOf("/nls/") == -1){
  195. dojo._xdInFlight[module] = true;
  196. //Increment inFlightCount
  197. //This will stop the modulesLoaded from firing all the way.
  198. dojo._inFlightCount++;
  199. }
  200. //Start timer
  201. if(!dojo._xdTimer){
  202. if(dojo.isAIR){
  203. dojo._xdTimer = setInterval(function(){dojo._xdWatchInFlight();}, 100);
  204. }else{
  205. dojo._xdTimer = setInterval(dojo._scopeName + "._xdWatchInFlight();", 100);
  206. }
  207. }
  208. dojo._xdStartTime = (new Date()).getTime();
  209. }
  210. if (currentIsXDomain){
  211. //Fix name to be a .xd.fileextension name.
  212. var lastIndex = uri.lastIndexOf('.');
  213. if(lastIndex <= 0){
  214. lastIndex = uri.length - 1;
  215. }
  216. var xdUri = uri.substring(0, lastIndex) + ".xd";
  217. if(lastIndex != uri.length - 1){
  218. xdUri += uri.substring(lastIndex, uri.length);
  219. }
  220. if (dojo.isAIR){
  221. xdUri = xdUri.replace("app:/", "/");
  222. }
  223. //Add to script src
  224. var element = document.createElement("script");
  225. element.type = "text/javascript";
  226. if(dojo._xdCharSet){
  227. element.charset = dojo._xdCharSet;
  228. }
  229. element.src = xdUri;
  230. if(!dojo.headElement){
  231. dojo._headElement = document.getElementsByTagName("head")[0];
  232. //Head element may not exist, particularly in html
  233. //html 4 or tag soup cases where the page does not
  234. //have a head tag in it. Use html element, since that will exist.
  235. //Seems to be an issue mostly with Opera 9 and to lesser extent Safari 2
  236. if(!dojo._headElement){
  237. dojo._headElement = document.getElementsByTagName("html")[0];
  238. }
  239. }
  240. dojo._headElement.appendChild(element);
  241. }else{
  242. var contents = dojo._getText(uri, null, true);
  243. if(contents == null){ return 0; /*boolean*/}
  244. //If this is not xdomain, or if loading a i18n resource bundle, then send it down
  245. //the normal eval/callback path.
  246. if(dojo._isXDomain
  247. && uri.indexOf("/nls/") == -1
  248. && module != "dojo.i18n"){
  249. var res = dojo._xdCreateResource(contents, module, uri);
  250. dojo.eval(res);
  251. }else{
  252. if(cb){
  253. contents = '('+contents+')';
  254. }else{
  255. //Only do the scoping if no callback. If a callback is specified,
  256. //it is most likely the i18n bundle stuff.
  257. contents = dojo._scopePrefix + contents + dojo._scopeSuffix;
  258. }
  259. var value = dojo["eval"](contents+"\r\n//@ sourceURL="+uri);
  260. if(cb){
  261. cb(value);
  262. }
  263. }
  264. }
  265. //These steps are done in the non-xd loader version of this function.
  266. //Maintain these steps to fit in with the existing system.
  267. dojo._loadedUrls[uri] = true;
  268. dojo._loadedUrls.push(uri);
  269. return true; //Boolean
  270. }
  271. dojo._xdResourceLoaded = function(/*Object*/res){
  272. //summary: Internal xd loader function. Called by an xd module resource when
  273. //it has been loaded via a script tag.
  274. //Evaluate the function with scopeArgs for multiversion support.
  275. res = res.apply(dojo.global, dojo._scopeArgs);
  276. //Work through dependencies.
  277. var deps = res.depends;
  278. var requireList = null;
  279. var requireAfterList = null;
  280. var provideList = [];
  281. if(deps && deps.length > 0){
  282. var dep = null;
  283. var insertHint = 0;
  284. var attachedResource = false;
  285. for(var i = 0; i < deps.length; i++){
  286. dep = deps[i];
  287. //Look for specific dependency indicators.
  288. if (dep[0] == "provide"){
  289. provideList.push(dep[1]);
  290. }else{
  291. if(!requireList){
  292. requireList = [];
  293. }
  294. if(!requireAfterList){
  295. requireAfterList = [];
  296. }
  297. var unpackedDeps = dojo._xdUnpackDependency(dep);
  298. if(unpackedDeps.requires){
  299. requireList = requireList.concat(unpackedDeps.requires);
  300. }
  301. if(unpackedDeps.requiresAfter){
  302. requireAfterList = requireAfterList.concat(unpackedDeps.requiresAfter);
  303. }
  304. }
  305. //Call the dependency indicator to allow for the normal dojo setup.
  306. //Only allow for one dot reference, for the i18n._preloadLocalizations calls
  307. //(and maybe future, one-dot things).
  308. var depType = dep[0];
  309. var objPath = depType.split(".");
  310. if(objPath.length == 2){
  311. dojo[objPath[0]][objPath[1]].apply(dojo[objPath[0]], dep.slice(1));
  312. }else{
  313. dojo[depType].apply(dojo, dep.slice(1));
  314. }
  315. }
  316. //If loading the debugAtAllCosts module, eval it right away since we need
  317. //its functions to properly load the other modules.
  318. if(provideList.length == 1 && provideList[0] == "dojo._base._loader.loader_debug"){
  319. res.defineResource(dojo);
  320. }else{
  321. //Save off the resource contents for definition later.
  322. var contentIndex = dojo._xdContents.push({
  323. content: res.defineResource,
  324. resourceName: res["resourceName"],
  325. resourcePath: res["resourcePath"],
  326. isDefined: false
  327. }) - 1;
  328. //Add provide/requires to dependency map.
  329. for(i = 0; i < provideList.length; i++){
  330. dojo._xdDepMap[provideList[i]] = { requires: requireList, requiresAfter: requireAfterList, contentIndex: contentIndex };
  331. }
  332. }
  333. //Now update the inflight status for any provided resources in this loaded resource.
  334. //Do this at the very end (in a *separate* for loop) to avoid shutting down the
  335. //inflight timer check too soon.
  336. for(i = 0; i < provideList.length; i++){
  337. dojo._xdInFlight[provideList[i]] = false;
  338. }
  339. }
  340. }
  341. dojo._xdLoadFlattenedBundle = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*Object*/bundleData){
  342. //summary: Internal xd loader function. Used when loading
  343. //a flattened localized bundle via a script tag.
  344. locale = locale || "root";
  345. var jsLoc = dojo.i18n.normalizeLocale(locale).replace('-', '_');
  346. var bundleResource = [moduleName, "nls", bundleName].join(".");
  347. var bundle = dojo["provide"](bundleResource);
  348. bundle[jsLoc] = bundleData;
  349. //Assign the bundle for the original locale(s) we wanted.
  350. var mapName = [moduleName, jsLoc, bundleName].join(".");
  351. var bundleMap = dojo._xdBundleMap[mapName];
  352. if(bundleMap){
  353. for(var param in bundleMap){
  354. bundle[param] = bundleData;
  355. }
  356. }
  357. };
  358. dojo._xdInitExtraLocales = function(){
  359. // Simulate the extra locale work that dojo.requireLocalization does.
  360. var extra = dojo.config.extraLocale;
  361. if(extra){
  362. if(!extra instanceof Array){
  363. extra = [extra];
  364. }
  365. dojo._xdReqLoc = dojo.xdRequireLocalization;
  366. dojo.xdRequireLocalization = function(m, b, locale, fLocales){
  367. dojo._xdReqLoc(m,b,locale, fLocales);
  368. if(locale){return;}
  369. for(var i=0; i<extra.length; i++){
  370. dojo._xdReqLoc(m,b,extra[i], fLocales);
  371. }
  372. };
  373. }
  374. }
  375. dojo._xdBundleMap = {};
  376. dojo.xdRequireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
  377. //summary: Internal xd loader function. The xd version of dojo.requireLocalization.
  378. //Account for allowing multiple extra locales. Do this here inside the function
  379. //since dojo._xdInitExtraLocales() depends on djConfig being set up, but that only
  380. //happens after hostenv_browser runs. loader_xd has to come before hostenv_browser
  381. //though since hostenv_browser can do a dojo.require for the debug module.
  382. if(dojo._xdInitExtraLocales){
  383. dojo._xdInitExtraLocales();
  384. dojo._xdInitExtraLocales = null;
  385. dojo.xdRequireLocalization.apply(dojo, arguments);
  386. return;
  387. }
  388. var locales = availableFlatLocales.split(",");
  389. //Find the best-match locale to load.
  390. //Assumes dojo.i18n has already been loaded. This is true for xdomain builds,
  391. //since it is included in dojo.xd.js.
  392. var jsLoc = dojo.i18n.normalizeLocale(locale);
  393. var bestLocale = "";
  394. for(var i = 0; i < locales.length; i++){
  395. //Locale must match from start of string.
  396. if(jsLoc.indexOf(locales[i]) == 0){
  397. if(locales[i].length > bestLocale.length){
  398. bestLocale = locales[i];
  399. }
  400. }
  401. }
  402. var fixedBestLocale = bestLocale.replace('-', '_');
  403. //See if the bundle we are going to use is already loaded.
  404. var bundleResource = dojo.getObject([moduleName, "nls", bundleName].join("."));
  405. if(!bundleResource || !bundleResource[fixedBestLocale]){
  406. //Need to remember what locale we wanted and which one we actually use.
  407. //Then when we load the one we are actually using, use that bundle for the one
  408. //we originally wanted.
  409. var mapName = [moduleName, (fixedBestLocale||"root"), bundleName].join(".");
  410. var bundleMap = dojo._xdBundleMap[mapName];
  411. if(!bundleMap){
  412. bundleMap = dojo._xdBundleMap[mapName] = {};
  413. }
  414. bundleMap[jsLoc.replace('-', '_')] = true;
  415. //Do just a normal dojo.require so the resource tracking stuff works as usual.
  416. dojo.require(moduleName + ".nls" + (bestLocale ? "." + bestLocale : "") + "." + bundleName);
  417. }
  418. }
  419. // Replace dojo.requireLocalization with a wrapper
  420. dojo._xdRealRequireLocalization = dojo.requireLocalization;
  421. dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
  422. // summary: loads a bundle intelligently based on whether the module is
  423. // local or xd. Overrides the local-case implementation.
  424. var modulePath = dojo.moduleUrl(moduleName).toString();
  425. if (dojo._xdIsXDomainPath(modulePath)) {
  426. // call cross-domain loader
  427. return dojo.xdRequireLocalization.apply(dojo, arguments);
  428. } else {
  429. // call local-loader
  430. return dojo._xdRealRequireLocalization.apply(dojo, arguments);
  431. }
  432. }
  433. //This is a bit brittle: it has to know about the dojo methods that deal with dependencies
  434. //It would be ideal to intercept the actual methods and do something fancy at that point,
  435. //but I have concern about knowing which provide to match to the dependency in that case,
  436. //since scripts can load whenever they want, and trigger new calls to dojo._xdResourceLoaded().
  437. dojo._xdUnpackDependency = function(/*Array*/dep){
  438. //summary: Internal xd loader function. Determines what to do with a dependency
  439. //that was listed in an xd version of a module contents.
  440. //Extract the dependency(ies).
  441. var newDeps = null;
  442. var newAfterDeps = null;
  443. switch(dep[0]){
  444. case "requireIf":
  445. case "requireAfterIf":
  446. //First arg (dep[1]) is the test. Depedency is dep[2].
  447. if(dep[1] === true){
  448. newDeps = [{name: dep[2], content: null}];
  449. }
  450. break;
  451. case "platformRequire":
  452. var modMap = dep[1];
  453. var common = modMap["common"]||[];
  454. newDeps = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);
  455. //Flatten the array of arrays into a one-level deep array.
  456. //Each result could be an array of 3 elements (the 3 arguments to dojo.require).
  457. //We only need the first one.
  458. if(newDeps){
  459. for(var i = 0; i < newDeps.length; i++){
  460. if(newDeps[i] instanceof Array){
  461. newDeps[i] = {name: newDeps[i][0], content: null};
  462. }else{
  463. newDeps[i] = {name: newDeps[i], content: null};
  464. }
  465. }
  466. }
  467. break;
  468. case "require":
  469. //Just worry about dep[1]
  470. newDeps = [{name: dep[1], content: null}];
  471. break;
  472. case "i18n._preloadLocalizations":
  473. //We can eval these immediately, since they load i18n bundles.
  474. //Since i18n bundles have no dependencies, whenever they are loaded
  475. //in a script tag, they are evaluated immediately, so we do not have to
  476. //treat them has an explicit dependency for the dependency mapping.
  477. //We can call it immediately since dojo.i18n is part of dojo.xd.js.
  478. dojo.i18n._preloadLocalizations.apply(dojo.i18n._preloadLocalizations, dep.slice(1));
  479. break;
  480. }
  481. //The requireIf and requireAfterIf needs to be evaluated after the current resource is evaluated.
  482. if(dep[0] == "requireAfterIf" || dep[0] == "requireIf"){
  483. newAfterDeps = newDeps;
  484. newDeps = null;
  485. }
  486. return {requires: newDeps, requiresAfter: newAfterDeps}; //Object
  487. }
  488. dojo._xdWalkReqs = function(){
  489. //summary: Internal xd loader function.
  490. //Walks the requires and evaluates module resource contents in
  491. //the right order.
  492. var reqChain = null;
  493. var req;
  494. for(var i = 0; i < dojo._xdOrderedReqs.length; i++){
  495. req = dojo._xdOrderedReqs[i];
  496. if(dojo._xdDepMap[req]){
  497. reqChain = [req];
  498. reqChain[req] = true; //Allow for fast lookup of the req in the array
  499. dojo._xdEvalReqs(reqChain);
  500. }
  501. }
  502. }
  503. dojo._xdEvalReqs = function(/*Array*/reqChain){
  504. //summary: Internal xd loader function.
  505. //Does a depth first, breadth second search and eval of required modules.
  506. while(reqChain.length > 0){
  507. var req = reqChain[reqChain.length - 1];
  508. var res = dojo._xdDepMap[req];
  509. var i, reqs, nextReq;
  510. if(res){
  511. //Trace down any requires for this resource.
  512. //START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  513. reqs = res.requires;
  514. if(reqs && reqs.length > 0){
  515. for(i = 0; i < reqs.length; i++){
  516. nextReq = reqs[i].name;
  517. if(nextReq && !reqChain[nextReq]){
  518. //New req depedency. Follow it down.
  519. reqChain.push(nextReq);
  520. reqChain[nextReq] = true;
  521. dojo._xdEvalReqs(reqChain);
  522. }
  523. }
  524. }
  525. //END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  526. //Evaluate the resource.
  527. var contents = dojo._xdContents[res.contentIndex];
  528. if(!contents.isDefined){
  529. var content = contents.content;
  530. content["resourceName"] = contents["resourceName"];
  531. content["resourcePath"] = contents["resourcePath"];
  532. dojo._xdDefList.push(content);
  533. contents.isDefined = true;
  534. }
  535. dojo._xdDepMap[req] = null;
  536. //Trace down any requireAfters for this resource.
  537. //START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  538. reqs = res.requiresAfter;
  539. if(reqs && reqs.length > 0){
  540. for(i = 0; i < reqs.length; i++){
  541. nextReq = reqs[i].name;
  542. if(nextReq && !reqChain[nextReq]){
  543. //New req depedency. Follow it down.
  544. reqChain.push(nextReq);
  545. reqChain[nextReq] = true;
  546. dojo._xdEvalReqs(reqChain);
  547. }
  548. }
  549. }
  550. //END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  551. }
  552. //Done with that require. Remove it and go to the next one.
  553. reqChain.pop();
  554. }
  555. }
  556. dojo._xdWatchInFlight = function(){
  557. //summary: Internal xd loader function.
  558. //Monitors in-flight requests for xd module resources.
  559. var noLoads = "";
  560. var waitInterval = (dojo.config.xdWaitSeconds || 15) * 1000;
  561. var expired = (dojo._xdStartTime + waitInterval) < (new Date()).getTime();
  562. //If any xdInFlight are true, then still waiting for something to load.
  563. //Come back later. If we timed out, report the things that did not load.
  564. for(var param in dojo._xdInFlight){
  565. if(dojo._xdInFlight[param] === true){
  566. if(expired){
  567. noLoads += param + " ";
  568. }else{
  569. return;
  570. }
  571. }
  572. }
  573. //All done. Clean up and notify.
  574. dojo._xdClearInterval();
  575. if(expired){
  576. throw "Could not load cross-domain resources: " + noLoads;
  577. }
  578. dojo._xdWalkReqs();
  579. var defLength = dojo._xdDefList.length;
  580. for(var i= 0; i < defLength; i++){
  581. var content = dojo._xdDefList[i];
  582. if(dojo.config["debugAtAllCosts"] && content["resourceName"]){
  583. if(!dojo["_xdDebugQueue"]){
  584. dojo._xdDebugQueue = [];
  585. }
  586. dojo._xdDebugQueue.push({resourceName: content.resourceName, resourcePath: content.resourcePath});
  587. }else{
  588. //Evaluate the resource to bring it into being.
  589. //Pass in scope args to allow multiple versions of modules in a page.
  590. content.apply(dojo.global, dojo._scopeArgs);
  591. }
  592. }
  593. //Evaluate any resources that were not evaled before.
  594. //This normally shouldn't happen with proper dojo.provide and dojo.require
  595. //usage, but providing it just in case. Note that these may not be executed
  596. //in the original order that the developer intended.
  597. for(i = 0; i < dojo._xdContents.length; i++){
  598. var current = dojo._xdContents[i];
  599. if(current.content && !current.isDefined){
  600. //Pass in scope args to allow multiple versions of modules in a page.
  601. current.content.apply(dojo.global, dojo._scopeArgs);
  602. }
  603. }
  604. //Clean up for the next round of xd loading.
  605. dojo._xdReset();
  606. if(dojo["_xdDebugQueue"] && dojo._xdDebugQueue.length > 0){
  607. dojo._xdDebugFileLoaded();
  608. }else{
  609. dojo._xdNotifyLoaded();
  610. }
  611. }
  612. dojo._xdNotifyLoaded = function(){
  613. //Clear inflight count so we will finally do finish work.
  614. //Just having a legitimate status (true or false) for an inflight item
  615. //means that it is still being processed. Do the typeof test
  616. //to avoid bad JavaScript that might tinker with Object.prototype.
  617. for(var prop in dojo._xdInFlight){
  618. if(typeof dojo._xdInFlight[prop] == "boolean"){
  619. return;
  620. }
  621. }
  622. dojo._inFlightCount = 0;
  623. //Only trigger call loaded if dj_load_init has run.
  624. if(dojo._initFired && !dojo._loadNotifying){
  625. dojo._callLoaded();
  626. }
  627. }
  628. }