text: //Cross-domain resource loader.
  dojo.provide("dojo._base._loader.loader_xd");
  
  dojo._xdReset = function(){
  	//summary: Internal xd loader function. Resets the xd state.
  
  	//This flag indicates where or not we have crossed into xdomain territory. Once any resource says
  	//it is cross domain, then the rest of the resources have to be treated as xdomain because we need
  	//to evaluate resources in order. If there is a xdomain resource followed by a xhr resource, we can't load
  	//the xhr resource until the one before it finishes loading. The text of the xhr resource will be converted
  	//to match the format for a xd resource and put in the xd load queue.
  	this._isXDomain = dojo.config.useXDomain || false;
  
  	this._xdTimer = 0;
  	this._xdInFlight = {};
  	this._xdOrderedReqs = [];
  	this._xdDepMap = {};
  	this._xdContents = [];
  	this._xdDefList = [];
  }
  
  //Call reset immediately to set the state.
  dojo._xdReset();
  
  dojo._xdCreateResource = function(/*String*/contents, /*String*/resourceName, /*String*/resourcePath){
  	//summary: Internal xd loader function. Creates an xd module source given an
  	//non-xd module contents.
  
  	//Remove comments. Not perfect, but good enough for dependency resolution.
  	var depContents = contents.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg , "");
  
  	//Find dependencies.
  	var deps = [];
      var depRegExp = /dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\(([\w\W]*?)\)/mg;
      var match;
  	while((match = depRegExp.exec(depContents)) != null){
  		if(match[1] == "requireLocalization"){
  			//Need to load the local bundles asap, since they are not
  			//part of the list of modules watched for loading.
  			eval(match[0]);
  		}else{
  			deps.push('"' + match[1] + '", ' + match[2]);
  		}
  	}
  
  	//Create resource object and the call to _xdResourceLoaded.
  	var output = [];
  	output.push(dojo._scopeName + "._xdResourceLoaded({\n");
  
  	//Add dependencies
  	if(deps.length > 0){
  		output.push("depends: [");
  		for(var i = 0; i < deps.length; i++){
  			if(i > 0){
  				output.push(",\n");
  			}
  			output.push("[" + deps[i] + "]");
  		}
  		output.push("],");
  	}
  
  	//Add the contents of the file inside a function.
  	//Pass in scope arguments so we can support multiple versions of the
  	//same module on a page.
  	output.push("\ndefineResource: function(" + dojo._scopePrefixArgs + "){");
  
  	//Don't put in the contents in the debugAtAllCosts case
  	//since the contents may have syntax errors. Let those
  	//get pushed up when the script tags are added to the page
  	//in the debugAtAllCosts case.
  	if(!dojo.config["debugAtAllCosts"] || resourceName == "dojo._base._loader.loader_debug"){
  		output.push(contents);
  	}
  	//Add isLocal property so we know if we have to do something different
  	//in debugAtAllCosts situations.
  	output.push("\n}, resourceName: '" + resourceName + "', resourcePath: '" + resourcePath + "'});");
  	
  	return output.join(""); //String
  }
  
  dojo._xdIsXDomainPath = function(/*string*/relpath) {
      //summary: Figure out whether the path is local or x-domain
  	//If there is a colon before the first / then, we have a URL with a protocol.
      
  	var colonIndex = relpath.indexOf(":");
  	var slashIndex = relpath.indexOf("/");
  
  	if(colonIndex > 0 && colonIndex < slashIndex){
  		return true;
  	}else{
  		//Is the base script URI-based URL a cross domain URL?
  		//If so, then the relpath will be evaluated relative to
  		//baseUrl, and therefore qualify as xdomain.
  		//Only treat it as xdomain if the page does not have a
  		//host (file:// url) or if the baseUrl does not match the
  		//current window's domain.
  		var url = this.baseUrl;
  		colonIndex = url.indexOf(":");
  		slashIndex = url.indexOf("/");
  		if(colonIndex > 0 && colonIndex < slashIndex && (!location.host || url.indexOf("http://" + location.host) != 0)){
  			return true;
  		}
  	}
      return false;     
  }
  
  dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
  	//summary: Internal xd loader function. Overrides loadPath() from loader.js.
  	//xd loading requires slightly different behavior from loadPath().
  
  	var currentIsXDomain = this._xdIsXDomainPath(relpath);
      this._isXDomain |= currentIsXDomain;
  
  	var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : this.baseUrl) + relpath;
  
  	try{
  		return ((!module || this._isXDomain) ? this._loadUri(uri, cb, currentIsXDomain, module) : this._loadUriAndCheck(uri, module, cb)); //Boolean
  	}catch(e){
  		console.debug(e);
  		return false; //Boolean
  	}
  }
  
  dojo._loadUri = function(/*String*/uri, /*Function?*/cb, /*boolean*/currentIsXDomain, /*String?*/module){
  	//summary: Internal xd loader function. Overrides loadUri() from loader.js.
  	//		xd loading requires slightly different behavior from loadPath().
  	//description: Wanted to override getText(), but it is used by
  	//		the widget code in too many, synchronous ways right now.
  	if(this._loadedUrls[uri]){
  		return 1; //Boolean
  	}
  
  	//Add the module (resource) to the list of modules.
  	//Only do this work if we have a modlue name. Otherwise, 
  	//it is a non-xd i18n bundle, which can load immediately and does not 
  	//need to be tracked. Also, don't track dojo.i18n, since it is a prerequisite
  	//and will be loaded correctly if we load it right away: it has no dependencies.
  	if(this._isXDomain && module && module != "dojo.i18n"){
  		this._xdOrderedReqs.push(module);
  
  		//Add to waiting resources if it is an xdomain resource.
  		//Don't add non-xdomain i18n bundles, those get evaled immediately.
  		if(currentIsXDomain || uri.indexOf("/nls/") == -1){
  			this._xdInFlight[module] = true;
  
  			//Increment inFlightCount
  			//This will stop the modulesLoaded from firing all the way.
  			this._inFlightCount++;
  		}
  
  		//Start timer
  		if(!this._xdTimer){
  			if(dojo.isAIR){
  				this._xdTimer = setInterval(function(){dojo._xdWatchInFlight();}, 100);
  			}else{
  				this._xdTimer = setInterval(dojo._scopeName + "._xdWatchInFlight();", 100);
  			}
  		}
  		this._xdStartTime = (new Date()).getTime();
  	}
  
  	if (currentIsXDomain){
  		//Fix name to be a .xd.fileextension name.
  		var lastIndex = uri.lastIndexOf('.');
  		if(lastIndex <= 0){
  			lastIndex = uri.length - 1;
  		}
  
  		var xdUri = uri.substring(0, lastIndex) + ".xd";
  		if(lastIndex != uri.length - 1){
  			xdUri += uri.substring(lastIndex, uri.length);
  		}
  
  		if (dojo.isAIR){
  			xdUri = xdUri.replace("app:/", "/");
  		}
  
  		//Add to script src
  		var element = document.createElement("script");
  		element.type = "text/javascript";
  		element.src = xdUri;
  		if(!this.headElement){
  			this._headElement = document.getElementsByTagName("head")[0];
  
  			//Head element may not exist, particularly in html
  			//html 4 or tag soup cases where the page does not
  			//have a head tag in it. Use html element, since that will exist.
  			//Seems to be an issue mostly with Opera 9 and to lesser extent Safari 2
  			if(!this._headElement){
  				this._headElement = document.getElementsByTagName("html")[0];
  			}
  		}
  		this._headElement.appendChild(element);
  	}else{
  		var contents = this._getText(uri, null, true);
  		if(contents == null){ return 0; /*boolean*/}
  		
  		//If this is not xdomain, or if loading a i18n resource bundle, then send it down
  		//the normal eval/callback path.
  		if(this._isXDomain
  			&& uri.indexOf("/nls/") == -1
  			&& module != "dojo.i18n"){
  			var res = this._xdCreateResource(contents, module, uri);
  			dojo.eval(res);
  		}else{
  			if(cb){
  				contents = '('+contents+')';
  			}else{
  				//Only do the scoping if no callback. If a callback is specified,
  				//it is most likely the i18n bundle stuff.
  				contents = this._scopePrefix + contents + this._scopeSuffix;
  			}
  			var value = dojo["eval"](contents+"\r\n//@ sourceURL="+uri);
  			if(cb){
  				cb(value);
  			}
  		}
  	}
  
  	//These steps are done in the non-xd loader version of this function.
  	//Maintain these steps to fit in with the existing system.
  	this._loadedUrls[uri] = true;
  	this._loadedUrls.push(uri);
  	return true; //Boolean
  }
  
  dojo._xdResourceLoaded = function(/*Object*/res){
  	//summary: Internal xd loader function. Called by an xd module resource when
  	//it has been loaded via a script tag.
  	var deps = res.depends;
  	var requireList = null;
  	var requireAfterList = null;
  	var provideList = [];
  	if(deps && deps.length > 0){
  		var dep = null;
  		var insertHint = 0;
  		var attachedResource = false;
  		for(var i = 0; i < deps.length; i++){
  			dep = deps[i];
  
  			//Look for specific dependency indicators.
  			if (dep[0] == "provide"){
  				provideList.push(dep[1]);
  			}else{
  				if(!requireList){
  					requireList = [];
  				}
  				if(!requireAfterList){
  					requireAfterList = [];
  				}
  
  				var unpackedDeps = this._xdUnpackDependency(dep);
  				if(unpackedDeps.requires){
  					requireList = requireList.concat(unpackedDeps.requires);
  				}
  				if(unpackedDeps.requiresAfter){
  					requireAfterList = requireAfterList.concat(unpackedDeps.requiresAfter);
  				}
  			}
  
  			//Call the dependency indicator to allow for the normal dojo setup.
  			//Only allow for one dot reference, for the i18n._preloadLocalizations calls
  			//(and maybe future, one-dot things).
  			var depType = dep[0];
  			var objPath = depType.split(".");
  			if(objPath.length == 2){
  				dojo[objPath[0]][objPath[1]].apply(dojo[objPath[0]], dep.slice(1));
  			}else{
  				dojo[depType].apply(dojo, dep.slice(1));
  			}
  		}
  
  
  		//If loading the debugAtAllCosts module, eval it right away since we need
  		//its functions to properly load the other modules.
  		if(provideList.length == 1 && provideList[0] == "dojo._base._loader.loader_debug"){
  			res.defineResource(dojo);
  		}else{
  			//Save off the resource contents for definition later.
  			var contentIndex = this._xdContents.push({
  					content: res.defineResource,
  					resourceName: res["resourceName"],
  					resourcePath: res["resourcePath"],
  					isDefined: false
  				}) - 1;
  	
  			//Add provide/requires to dependency map.
  			for(var i = 0; i < provideList.length; i++){
  				this._xdDepMap[provideList[i]] = { requires: requireList, requiresAfter: requireAfterList, contentIndex: contentIndex };
  			}
  		}
  
  		//Now update the inflight status for any provided resources in this loaded resource.
  		//Do this at the very end (in a *separate* for loop) to avoid shutting down the 
  		//inflight timer check too soon.
  		for(var i = 0; i < provideList.length; i++){
  			this._xdInFlight[provideList[i]] = false;
  		}
  	}
  }
  
  dojo._xdLoadFlattenedBundle = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*Object*/bundleData){
  	//summary: Internal xd loader function. Used when loading
  	//a flattened localized bundle via a script tag.
  	locale = locale || "root";
  	var jsLoc = dojo.i18n.normalizeLocale(locale).replace('-', '_');
   	var bundleResource = [moduleName, "nls", bundleName].join(".");
  	var bundle = dojo["provide"](bundleResource);
  	bundle[jsLoc] = bundleData;
  	
  	//Assign the bundle for the original locale(s) we wanted.
  	var mapName = [moduleName, jsLoc, bundleName].join(".");
  	var bundleMap = dojo._xdBundleMap[mapName];
  	if(bundleMap){
  		for(var param in bundleMap){
  			bundle[param] = bundleData;
  		}
  	}
  };
  
  
  dojo._xdInitExtraLocales = function(){
  	// Simulate the extra locale work that dojo.requireLocalization does.
  
  	var extra = dojo.config.extraLocale;
  	if(extra){
  		if(!extra instanceof Array){
  			extra = [extra];
  		}
  
  		dojo._xdReqLoc = dojo.xdRequireLocalization;
  		dojo.xdRequireLocalization = function(m, b, locale, fLocales){
  			dojo._xdReqLoc(m,b,locale, fLocales);
  			if(locale){return;}
  			for(var i=0; i<extra.length; i++){
  				dojo._xdReqLoc(m,b,extra[i], fLocales);
  			}
  		};
  	}
  }
  
  dojo._xdBundleMap = {};
  
  dojo.xdRequireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
  	//summary: Internal xd loader function. The xd version of dojo.requireLocalization.
  	
  
  	//Account for allowing multiple extra locales. Do this here inside the function
  	//since dojo._xdInitExtraLocales() depends on djConfig being set up, but that only
  	//happens after hostenv_browser runs. loader_xd has to come before hostenv_browser
  	//though since hostenv_browser can do a dojo.require for the debug module.
  	if(dojo._xdInitExtraLocales){
  		dojo._xdInitExtraLocales();
  		dojo._xdInitExtraLocales = null;
  		dojo.xdRequireLocalization.apply(dojo, arguments);
  		return;
  	}
  
  	var locales = availableFlatLocales.split(",");
  	
  	//Find the best-match locale to load.
  	//Assumes dojo.i18n has already been loaded. This is true for xdomain builds,
  	//since it is included in dojo.xd.js.
  	var jsLoc = dojo.i18n.normalizeLocale(locale);
  
  	var bestLocale = "";
  	for(var i = 0; i < locales.length; i++){
  		//Locale must match from start of string.
  		if(jsLoc.indexOf(locales[i]) == 0){
  			if(locales[i].length > bestLocale.length){
  				bestLocale = locales[i];
  			}
  		}
  	}
  
  	var fixedBestLocale = bestLocale.replace('-', '_');
  	//See if the bundle we are going to use is already loaded.
   	var bundleResource = dojo.getObject([moduleName, "nls", bundleName].join("."));
  	if(bundleResource && bundleResource[fixedBestLocale]){
  		bundle[jsLoc.replace('-', '_')] = bundleResource[fixedBestLocale];
  	}else{
  		//Need to remember what locale we wanted and which one we actually use.
  		//Then when we load the one we are actually using, use that bundle for the one
  		//we originally wanted.
  		var mapName = [moduleName, (fixedBestLocale||"root"), bundleName].join(".");
  		var bundleMap = dojo._xdBundleMap[mapName];
  		if(!bundleMap){
  			bundleMap = dojo._xdBundleMap[mapName] = {};
  		}
  		bundleMap[jsLoc.replace('-', '_')] = true;
  		
  		//Do just a normal dojo.require so the resource tracking stuff works as usual.
  		dojo.require(moduleName + ".nls" + (bestLocale ? "." + bestLocale : "") + "." + bundleName);
  	}
  }
  
  // Replace dojo.requireLocalization with a wrapper
  dojo._xdRealRequireLocalization = dojo.requireLocalization;
  dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
      // summary: loads a bundle intelligently based on whether the module is 
      // local or xd. Overrides the local-case implementation.
      
      var modulePath = this.moduleUrl(moduleName).toString();
      if (this._xdIsXDomainPath(modulePath)) {
          // call cross-domain loader
          return dojo.xdRequireLocalization.apply(dojo, arguments);
      } else {
          // call local-loader
          return dojo._xdRealRequireLocalization.apply(dojo, arguments);
      }
  }
  
  //This is a bit brittle: it has to know about the dojo methods that deal with dependencies
  //It would be ideal to intercept the actual methods and do something fancy at that point,
  //but I have concern about knowing which provide to match to the dependency in that case,
  //since scripts can load whenever they want, and trigger new calls to dojo._xdResourceLoaded().
  dojo._xdUnpackDependency = function(/*Array*/dep){
  	//summary: Internal xd loader function. Determines what to do with a dependency
  	//that was listed in an xd version of a module contents.
  
  	//Extract the dependency(ies).
  	var newDeps = null;
  	var newAfterDeps = null;
  	switch(dep[0]){
  		case "requireIf":
  		case "requireAfterIf":
  			//First arg (dep[1]) is the test. Depedency is dep[2].
  			if(dep[1] === true){
  				newDeps = [{name: dep[2], content: null}];
  			}
  			break;
  		case "platformRequire":
  			var modMap = dep[1];
  			var common = modMap["common"]||[];
  			var newDeps = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);	
  			//Flatten the array of arrays into a one-level deep array.
  			//Each result could be an array of 3 elements  (the 3 arguments to dojo.require).
  			//We only need the first one.
  			if(newDeps){
  				for(var i = 0; i < newDeps.length; i++){
  					if(newDeps[i] instanceof Array){
  						newDeps[i] = {name: newDeps[i][0], content: null};
  					}else{
  						newDeps[i] = {name: newDeps[i], content: null};
  					}
  				}
  			}
  			break;
  		case "require":
  			//Just worry about dep[1]
  			newDeps = [{name: dep[1], content: null}];
  			break;
  		case "i18n._preloadLocalizations":
  			//We can eval these immediately, since they load i18n bundles.
  			//Since i18n bundles have no dependencies, whenever they are loaded
  			//in a script tag, they are evaluated immediately, so we do not have to
  			//treat them has an explicit dependency for the dependency mapping.
  			//We can call it immediately since dojo.i18n is part of dojo.xd.js.
  			dojo.i18n._preloadLocalizations.apply(dojo.i18n._preloadLocalizations, dep.slice(1));
  			break;
  	}
  
  	//The requireIf and requireAfterIf needs to be evaluated after the current resource is evaluated.
  	if(dep[0] == "requireAfterIf" || dep[0] == "requireIf"){
  		newAfterDeps = newDeps;
  		newDeps = null;
  	}
  	return {requires: newDeps, requiresAfter: newAfterDeps}; //Object
  }
  
  dojo._xdWalkReqs = function(){
  	//summary: Internal xd loader function. 
  	//Walks the requires and evaluates module resource contents in
  	//the right order.
  	var reqChain = null;
  	var req;
  	for(var i = 0; i < this._xdOrderedReqs.length; i++){
  		req = this._xdOrderedReqs[i];
  		if(this._xdDepMap[req]){
  			reqChain = [req];
  			reqChain[req] = true; //Allow for fast lookup of the req in the array
  			this._xdEvalReqs(reqChain);
  		}
  	}
  }
  
  dojo._xdEvalReqs = function(/*Array*/reqChain){
  	//summary: Internal xd loader function. 
  	//Does a depth first, breadth second search and eval of required modules.
  	while(reqChain.length > 0){
  		var req = reqChain[reqChain.length - 1];
  		var res = this._xdDepMap[req];
  		if(res){
  			//Trace down any requires for this resource.
  			//START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  			var reqs = res.requires;
  			if(reqs && reqs.length > 0){
  				var nextReq;
  				for(var i = 0; i < reqs.length; i++){
  					nextReq = reqs[i].name;
  					if(nextReq && !reqChain[nextReq]){
  						//New req depedency. Follow it down.
  						reqChain.push(nextReq);
  						reqChain[nextReq] = true;
  						this._xdEvalReqs(reqChain);
  					}
  				}
  			}
  			//END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  
  			//Evaluate the resource.
  			var contents = this._xdContents[res.contentIndex];
  			if(!contents.isDefined){
  				var content = contents.content;
  				content["resourceName"] = contents["resourceName"];
  				content["resourcePath"] = contents["resourcePath"];
  				this._xdDefList.push(content);
  				contents.isDefined = true;
  			}
  			this._xdDepMap[req] = null;
  
  			//Trace down any requireAfters for this resource.
  			//START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  			var reqs = res.requiresAfter;
  			if(reqs && reqs.length > 0){
  				var nextReq;
  				for(var i = 0; i < reqs.length; i++){
  					nextReq = reqs[i].name;
  					if(nextReq && !reqChain[nextReq]){
  						//New req depedency. Follow it down.
  						reqChain.push(nextReq);
  						reqChain[nextReq] = true;
  						this._xdEvalReqs(reqChain);
  					}
  				}
  			}
  			//END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
  		}
  
  		//Done with that require. Remove it and go to the next one.
  		reqChain.pop();
  	}
  }
  
  dojo._xdClearInterval = function(){
  	//summary: Internal xd loader function.
  	//Clears the interval timer used to check on the
  	//status of in-flight xd module resource requests.
  	clearInterval(this._xdTimer);
  	this._xdTimer = 0;
  }
  
  dojo._xdWatchInFlight = function(){
  	//summary: Internal xd loader function.
  	//Monitors in-flight requests for xd module resources.
  
  	var noLoads = "";
  	var waitInterval = (dojo.config.xdWaitSeconds || 15) * 1000;
  	var expired = (this._xdStartTime + waitInterval) < (new Date()).getTime();
  
  	//If any xdInFlight are true, then still waiting for something to load.
  	//Come back later. If we timed out, report the things that did not load.
  	for(var param in this._xdInFlight){
  		if(this._xdInFlight[param] === true){
  			if(expired){
  				noLoads += param + " ";
  			}else{
  				return;
  			}
  		}
  	}
  
  	//All done. Clean up and notify.
  	this._xdClearInterval();
  
  	if(expired){
  		throw "Could not load cross-domain resources: " + noLoads;
  	}
  
  	this._xdWalkReqs();
  	
  	var defLength = this._xdDefList.length;
  	for(var i= 0; i < defLength; i++){
  		var content = dojo._xdDefList[i];
  		if(dojo.config["debugAtAllCosts"] && content["resourceName"]){
  			if(!this["_xdDebugQueue"]){
  				this._xdDebugQueue = [];
  			}
  			this._xdDebugQueue.push({resourceName: content.resourceName, resourcePath: content.resourcePath});
  		}else{
  			//Evaluate the resource to bring it into being.
  			//Pass in scope args to allow multiple versions of modules in a page.	
  			content.apply(dojo.global, dojo._scopeArgs);
  		}
  	}
  
  	//Evaluate any resources that were not evaled before.
  	//This normally shouldn't happen with proper dojo.provide and dojo.require
  	//usage, but providing it just in case. Note that these may not be executed
  	//in the original order that the developer intended.
  	for(var i = 0; i < this._xdContents.length; i++){
  		var current = this._xdContents[i];
  		if(current.content && !current.isDefined){
  			//Pass in scope args to allow multiple versions of modules in a page.	
  			current.content.apply(dojo.global, dojo._scopeArgs);
  		}
  	}
  
  	//Clean up for the next round of xd loading.
  	this._xdReset();
  
  	if(this["_xdDebugQueue"] && this._xdDebugQueue.length > 0){
  		this._xdDebugFileLoaded();
  	}else{
  		this._xdNotifyLoaded();
  	}
  }
  
  dojo._xdNotifyLoaded = function(){
  	//Clear inflight count so we will finally do finish work.
  	this._inFlightCount = 0; 
  	
  	//Only trigger call loaded if dj_load_init has run. 
  	if(this._initFired && !this._loadNotifying){ 
  		this._callLoaded();
  	}
  }
  