From a089699c8915636ba4f158d77dba9b012bc93208 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 4 Mar 2011 19:02:28 +0300 Subject: build custom layer of Dojo to speed up loading of tt-rss (refs #293) --- lib/dojo/_base/_loader/bootstrap.js | 604 ++++++++++--- lib/dojo/_base/_loader/hostenv_browser.js | 684 +++++++++----- lib/dojo/_base/_loader/hostenv_ff_ext.js | 491 ++++++---- lib/dojo/_base/_loader/hostenv_rhino.js | 313 ++++--- lib/dojo/_base/_loader/hostenv_spidermonkey.js | 101 ++- lib/dojo/_base/_loader/loader.js | 1084 ++++++++++++++++------ lib/dojo/_base/_loader/loader_debug.js | 123 ++- lib/dojo/_base/_loader/loader_xd.js | 1136 +++++++++++++++--------- 8 files changed, 3097 insertions(+), 1439 deletions(-) (limited to 'lib/dojo/_base/_loader') diff --git a/lib/dojo/_base/_loader/bootstrap.js b/lib/dojo/_base/_loader/bootstrap.js index 7cc168e5d..3ef3012a2 100644 --- a/lib/dojo/_base/_loader/bootstrap.js +++ b/lib/dojo/_base/_loader/bootstrap.js @@ -5,116 +5,500 @@ */ -(function(){ -if(typeof this["loadFirebugConsole"]=="function"){ -this["loadFirebugConsole"](); -}else{ -this.console=this.console||{}; -var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"]; -var i=0,tn; -while((tn=cn[i++])){ -if(!console[tn]){ -(function(){ -var _1=tn+""; -console[_1]=("log" in console)?function(){ -var a=Array.apply({},arguments); -a.unshift(_1+":"); -console["log"](a.join(" ")); -}:function(){ -}; -console[_1]._fake=true; -})(); -} -} -} -if(typeof dojo=="undefined"){ -dojo={_scopeName:"dojo",_scopePrefix:"",_scopePrefixArgs:"",_scopeSuffix:"",_scopeMap:{},_scopeMapRev:{}}; -} -var d=dojo; -if(typeof dijit=="undefined"){ -dijit={_scopeName:"dijit"}; -} -if(typeof dojox=="undefined"){ -dojox={_scopeName:"dojox"}; -} -if(!d._scopeArgs){ -d._scopeArgs=[dojo,dijit,dojox]; -} -d.global=this; -d.config={isDebug:false,debugAtAllCosts:false}; -if(typeof djConfig!="undefined"){ -for(var _2 in djConfig){ -d.config[_2]=djConfig[_2]; -} -} -dojo.locale=d.config.locale; -var _3="$Rev: 22487 $".match(/\d+/); -dojo.version={major:1,minor:5,patch:0,flag:"",revision:_3?+_3[0]:NaN,toString:function(){ -with(d.version){ -return major+"."+minor+"."+patch+flag+" ("+revision+")"; -} -}}; -if(typeof OpenAjax!="undefined"){ -OpenAjax.hub.registerLibrary(dojo._scopeName,"http://dojotoolkit.org",d.version.toString()); -} -var _4,_5,_6={}; -for(var i in {toString:1}){ -_4=[]; -break; -} -dojo._extraNames=_4=_4||["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"]; -_5=_4.length; -dojo._mixin=function(_7,_8){ -var _9,s,i; -for(_9 in _8){ -s=_8[_9]; -if(!(_9 in _7)||(_7[_9]!==s&&(!(_9 in _6)||_6[_9]!==s))){ -_7[_9]=s; -} -} -if(_5&&_8){ -for(i=0;i<_5;++i){ -_9=_4[i]; -s=_8[_9]; -if(!(_9 in _7)||(_7[_9]!==s&&(!(_9 in _6)||_6[_9]!==s))){ -_7[_9]=s; -} -} -} -return _7; -}; -dojo.mixin=function(_a,_b){ -if(!_a){ -_a={}; -} -for(var i=1,l=arguments.length;i` tag inclusion. This may double-request resources and + // cause problems with scripts which expect `dojo.require()` to + // preform synchronously. `debugAtAllCosts` can be an invaluable + // debugging aid, but when using it, ensure that all code which + // depends on Dojo modules is wrapped in `dojo.addOnLoad()` handlers. + // Due to the somewhat unpredictable side-effects of using + // `debugAtAllCosts`, it is strongly recommended that you enable this + // flag as a last resort. `debugAtAllCosts` has no effect when loading + // resources across domains. For usage information, see the + // [Dojo Book](http://dojotoolkit.org/book/book-dojo/part-4-meta-dojo-making-your-dojo-code-run-faster-and-better/debugging-facilities/deb) + debugAtAllCosts: false, + // locale: String + // The locale to assume for loading localized resources in this page, + // specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt). + // Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`. + // See the documentation for `dojo.i18n` and `dojo.requireLocalization` + // for details on loading localized resources. If no locale is specified, + // Dojo assumes the locale of the user agent, according to `navigator.userLanguage` + // or `navigator.language` properties. + locale: undefined, + // extraLocale: Array + // No default value. Specifies additional locales whose + // resources should also be loaded alongside the default locale when + // calls to `dojo.requireLocalization()` are processed. + extraLocale: undefined, + // baseUrl: String + // The directory in which `dojo.js` is located. Under normal + // conditions, Dojo auto-detects the correct location from which it + // was loaded. You may need to manually configure `baseUrl` in cases + // where you have renamed `dojo.js` or in which `` tags confuse + // some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned + // either the value of `djConfig.baseUrl` if one is provided or the + // auto-detected root if not. Other modules are located relative to + // this path. The path should end in a slash. + baseUrl: undefined, + // modulePaths: Object + // A map of module names to paths relative to `dojo.baseUrl`. The + // key/value pairs correspond directly to the arguments which + // `dojo.registerModulePath` accepts. Specifiying + // `djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent + // of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple + // modules may be configured via `djConfig.modulePaths`. + modulePaths: {}, + // afterOnLoad: Boolean + // Indicates Dojo was added to the page after the page load. In this case + // Dojo will not wait for the page DOMContentLoad/load events and fire + // its dojo.addOnLoad callbacks after making sure all outstanding + // dojo.required modules have loaded. Only works with a built dojo.js, + // it does not work the dojo.js directly from source control. + afterOnLoad: false, + // addOnLoad: Function or Array + // Adds a callback via dojo.addOnLoad. Useful when Dojo is added after + // the page loads and djConfig.afterOnLoad is true. Supports the same + // arguments as dojo.addOnLoad. When using a function reference, use + // `djConfig.addOnLoad = function(){};`. For object with function name use + // `djConfig.addOnLoad = [myObject, "functionName"];` and for object with + // function reference use + // `djConfig.addOnLoad = [myObject, function(){}];` + addOnLoad: null, + // require: Array + // An array of module names to be loaded immediately after dojo.js has been included + // in a page. + require: [], + // defaultDuration: Array + // Default duration, in milliseconds, for wipe and fade animations within dijits. + // Assigned to dijit.defaultDuration. + defaultDuration: 200, + // dojoBlankHtmlUrl: String + // Used by some modules to configure an empty iframe. Used by dojo.io.iframe and + // dojo.back, and dijit popup support in IE where an iframe is needed to make sure native + // controls do not bleed through the popups. Normally this configuration variable + // does not need to be set, except when using cross-domain/CDN Dojo builds. + // Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl` + // to the path on your domain your copy of blank.html. + dojoBlankHtmlUrl: undefined, + // ioPublish: Boolean? + // Set this to true to enable publishing of topics for the different phases of + // IO operations. Publishing is done via dojo.publish. See dojo.__IoPublish for a list + // of topics that are published. + ioPublish: false, + // useCustomLogger: Anything? + // If set to a value that evaluates to true such as a string or array and + // isDebug is true and Firebug is not available or running, then it bypasses + // the creation of Firebug Lite allowing you to define your own console object. + useCustomLogger: undefined, + // transparentColor: Array + // Array containing the r, g, b components used as transparent color in dojo.Color; + // if undefined, [255,255,255] (white) will be used. + transparentColor: undefined, + // skipIeDomLoaded: Boolean + // For IE only, skip the DOMContentLoaded hack used. Sometimes it can cause an Operation + // Aborted error if the rest of the page triggers script defers before the DOM is ready. + // If this is config value is set to true, then dojo.addOnLoad callbacks will not be + // triggered until the page load event, which is after images and iframes load. If you + // want to trigger the callbacks sooner, you can put a script block in the bottom of + // your HTML that calls dojo._loadInit();. If you are using multiversion support, change + // "dojo." to the appropriate scope name for dojo. + skipIeDomLoaded: false } -_f=(p in _f?_f[p]:(_d?_f[p]={}:undefined)); +=====*/ + +(function(){ + // firebug stubs + + if(typeof this["loadFirebugConsole"] == "function"){ + // for Firebug 1.2 + this["loadFirebugConsole"](); + }else{ + this.console = this.console || {}; + + // Be careful to leave 'log' always at the end + var cn = [ + "assert", "count", "debug", "dir", "dirxml", "error", "group", + "groupEnd", "info", "profile", "profileEnd", "time", "timeEnd", + "trace", "warn", "log" + ]; + var i=0, tn; + while((tn=cn[i++])){ + if(!console[tn]){ + (function(){ + var tcn = tn+""; + console[tcn] = ('log' in console) ? function(){ + var a = Array.apply({}, arguments); + a.unshift(tcn+":"); + console["log"](a.join(" ")); + } : function(){} + console[tcn]._fake = true; + })(); + } + } + } + + //TODOC: HOW TO DOC THIS? + // dojo is the root variable of (almost all) our public symbols -- make sure it is defined. + if(typeof dojo == "undefined"){ + dojo = { + _scopeName: "dojo", + _scopePrefix: "", + _scopePrefixArgs: "", + _scopeSuffix: "", + _scopeMap: {}, + _scopeMapRev: {} + }; + } + + var d = dojo; + + //Need placeholders for dijit and dojox for scoping code. + if(typeof dijit == "undefined"){ + dijit = {_scopeName: "dijit"}; + } + if(typeof dojox == "undefined"){ + dojox = {_scopeName: "dojox"}; + } + + if(!d._scopeArgs){ + d._scopeArgs = [dojo, dijit, dojox]; + } + +/*===== +dojo.global = { + // summary: + // Alias for the global scope + // (e.g. the window object in a browser). + // description: + // Refer to 'dojo.global' rather than referring to window to ensure your + // code runs correctly in contexts other than web browsers (e.g. Rhino on a server). } -return _f; -}; -dojo.setObject=function(_10,_11,_12){ -var _13=_10.split("."),p=_13.pop(),obj=d._getProp(_13,true,_12); -return obj&&p?(obj[p]=_11):undefined; -}; -dojo.getObject=function(_14,_15,_16){ -return d._getProp(_14.split("."),_15,_16); -}; -dojo.exists=function(_17,obj){ -return !!d.getObject(_17,false,obj); -}; -dojo["eval"]=function(_18){ -return d.global.eval?d.global.eval(_18):eval(_18); -}; -d.deprecated=d.experimental=function(){ -}; +=====*/ + d.global = this; + + d.config =/*===== djConfig = =====*/{ + isDebug: false, + debugAtAllCosts: false + }; + + if(typeof djConfig != "undefined"){ + for(var opt in djConfig){ + d.config[opt] = djConfig[opt]; + } + } + +/*===== + // Override locale setting, if specified + dojo.locale = { + // summary: the locale as defined by Dojo (read-only) + }; +=====*/ + dojo.locale = d.config.locale; + + var rev = "$Rev: 22487 $".match(/\d+/); + +/*===== + dojo.version = function(){ + // summary: + // Version number of the Dojo Toolkit + // major: Integer + // Major version. If total version is "1.2.0beta1", will be 1 + // minor: Integer + // Minor version. If total version is "1.2.0beta1", will be 2 + // patch: Integer + // Patch version. If total version is "1.2.0beta1", will be 0 + // flag: String + // Descriptor flag. If total version is "1.2.0beta1", will be "beta1" + // revision: Number + // The SVN rev from which dojo was pulled + this.major = 0; + this.minor = 0; + this.patch = 0; + this.flag = ""; + this.revision = 0; + } +=====*/ + dojo.version = { + major: 1, minor: 5, patch: 0, flag: "", + revision: rev ? +rev[0] : NaN, + toString: function(){ + with(d.version){ + return major + "." + minor + "." + patch + flag + " (" + revision + ")"; // String + } + } + } + + // Register with the OpenAjax hub + if(typeof OpenAjax != "undefined"){ + OpenAjax.hub.registerLibrary(dojo._scopeName, "http://dojotoolkit.org", d.version.toString()); + } + + var extraNames, extraLen, empty = {}; + for(var i in {toString: 1}){ extraNames = []; break; } + dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf", + "propertyIsEnumerable", "toLocaleString", "toString", "constructor"]; + extraLen = extraNames.length; + + dojo._mixin = function(/*Object*/ target, /*Object*/ source){ + // summary: + // Adds all properties and methods of source to target. This addition + // is "prototype extension safe", so that instances of objects + // will not pass along prototype defaults. + var name, s, i; + for(name in source){ + // the "tobj" condition avoid copying properties in "source" + // inherited from Object.prototype. For example, if target has a custom + // toString() method, don't overwrite it with the toString() method + // that source inherited from Object.prototype + s = source[name]; + if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){ + target[name] = s; + } + } + // IE doesn't recognize some custom functions in for..in + if(extraLen && source){ + for(i = 0; i < extraLen; ++i){ + name = extraNames[i]; + s = source[name]; + if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){ + target[name] = s; + } + } + } + return target; // Object + } + + dojo.mixin = function(/*Object*/obj, /*Object...*/props){ + // summary: + // Adds all properties and methods of props to obj and returns the + // (now modified) obj. + // description: + // `dojo.mixin` can mix multiple source objects into a + // destination object which is then returned. Unlike regular + // `for...in` iteration, `dojo.mixin` is also smart about avoiding + // extensions which other toolkits may unwisely add to the root + // object prototype + // obj: + // The object to mix properties into. Also the return value. + // props: + // One or more objects whose values are successively copied into + // obj. If more than one of these objects contain the same value, + // the one specified last in the function call will "win". + // example: + // make a shallow copy of an object + // | var copy = dojo.mixin({}, source); + // example: + // many class constructors often take an object which specifies + // values to be configured on the object. In this case, it is + // often simplest to call `dojo.mixin` on the `this` object: + // | dojo.declare("acme.Base", null, { + // | constructor: function(properties){ + // | // property configuration: + // | dojo.mixin(this, properties); + // | + // | console.log(this.quip); + // | // ... + // | }, + // | quip: "I wasn't born yesterday, you know - I've seen movies.", + // | // ... + // | }); + // | + // | // create an instance of the class and configure it + // | var b = new acme.Base({quip: "That's what it does!" }); + // example: + // copy in properties from multiple objects + // | var flattened = dojo.mixin( + // | { + // | name: "Frylock", + // | braces: true + // | }, + // | { + // | name: "Carl Brutanananadilewski" + // | } + // | ); + // | + // | // will print "Carl Brutanananadilewski" + // | console.log(flattened.name); + // | // will print "true" + // | console.log(flattened.braces); + if(!obj){ obj = {}; } + for(var i=1, l=arguments.length; i=0){ -d.isOpera=tv; -} -if(_6.indexOf("AdobeAIR")>=0){ -d.isAIR=1; -} -d.isKhtml=(_7.indexOf("Konqueror")>=0)?tv:0; -d.isWebKit=parseFloat(_6.split("WebKit/")[1])||undefined; -d.isChrome=parseFloat(_6.split("Chrome/")[1])||undefined; -d.isMac=_7.indexOf("Macintosh")>=0; -var _8=Math.max(_7.indexOf("WebKit"),_7.indexOf("Safari"),0); -if(_8&&!dojo.isChrome){ -d.isSafari=parseFloat(_7.split("Version/")[1]); -if(!d.isSafari||parseFloat(_7.substr(_8+7))<=419.3){ -d.isSafari=2; -} -} -if(_6.indexOf("Gecko")>=0&&!d.isKhtml&&!d.isWebKit){ -d.isMozilla=d.isMoz=tv; -} -if(d.isMoz){ -d.isFF=parseFloat(_6.split("Firefox/")[1]||_6.split("Minefield/")[1])||undefined; -} -if(document.all&&!d.isOpera){ -d.isIE=parseFloat(_7.split("MSIE ")[1])||undefined; -var _9=document.documentMode; -if(_9&&_9!=5&&Math.floor(d.isIE)!=_9){ -d.isIE=_9; -} -} -if(dojo.isIE&&window.location.protocol==="file:"){ -dojo.config.ieForceActiveXXhr=true; -} -d.isQuirks=document.compatMode=="BackCompat"; -d.locale=dojo.config.locale||(d.isIE?n.userLanguage:n.language).toLowerCase(); -d._XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"]; -d._xhrObj=function(){ -var _a,_b; -if(!dojo.isIE||!dojo.config.ieForceActiveXXhr){ -try{ -_a=new XMLHttpRequest(); -} -catch(e){ -} -} -if(!_a){ -for(var i=0;i<3;++i){ -var _c=d._XMLHTTP_PROGIDS[i]; -try{ -_a=new ActiveXObject(_c); -} -catch(e){ -_b=e; -} -if(_a){ -d._XMLHTTP_PROGIDS=[_c]; -break; -} -} -} -if(!_a){ -throw new Error("XMLHTTP not available: "+_b); -} -return _a; -}; -d._isDocumentOk=function(_d){ -var _e=_d.status||0,lp=location.protocol; -return (_e>=200&&_e<300)||_e==304||_e==1223||(!_e&&(lp=="file:"||lp=="chrome:"||lp=="chrome-extension:"||lp=="app:")); +/*===== +dojo.isBrowser = { + // example: + // | if(dojo.isBrowser){ ... } }; -var _f=window.location+""; -var _10=document.getElementsByTagName("base"); -var _11=(_10&&_10.length>0); -d._getText=function(uri,_12){ -var _13=d._xhrObj(); -if(!_11&&dojo._Url){ -uri=(new dojo._Url(_f,uri)).toString(); -} -if(d.config.cacheBust){ -uri+=""; -uri+=(uri.indexOf("?")==-1?"?":"&")+String(d.config.cacheBust).replace(/\W+/g,""); -} -_13.open("GET",uri,false); -try{ -_13.send(null); -if(!d._isDocumentOk(_13)){ -var err=Error("Unable to load "+uri+" status:"+_13.status); -err.status=_13.status; -err.responseText=_13.responseText; -throw err; -} -} -catch(e){ -if(_12){ -return null; -} -throw e; -} -return _13.responseText; -}; -var _14=window; -var _15=function(_16,fp){ -var _17=_14.attachEvent||_14.addEventListener; -_16=_14.attachEvent?_16:_16.substring(2); -_17(_16,function(){ -fp.apply(_14,arguments); -},false); -}; -d._windowUnloaders=[]; -d.windowUnloaded=function(){ -var mll=d._windowUnloaders; -while(mll.length){ -(mll.pop())(); -} -d=null; -}; -var _18=0; -d.addOnWindowUnload=function(obj,_19){ -d._onto(d._windowUnloaders,obj,_19); -if(!_18){ -_18=1; -_15("onunload",d.windowUnloaded); -} + +dojo.isFF = { + // example: + // | if(dojo.isFF > 1){ ... } }; -var _1a=0; -d.addOnUnload=function(obj,_1b){ -d._onto(d._unloaders,obj,_1b); -if(!_1a){ -_1a=1; -_15("onbeforeunload",dojo.unloaded); -} + +dojo.isIE = { + // example: + // | if(dojo.isIE > 6){ + // | // we are IE7 + // | } }; -})(); -dojo._initFired=false; -dojo._loadInit=function(e){ -if(dojo._scrollIntervalId){ -clearInterval(dojo._scrollIntervalId); -dojo._scrollIntervalId=0; -} -if(!dojo._initFired){ -dojo._initFired=true; -if(!dojo.config.afterOnLoad&&window.detachEvent){ -window.detachEvent("onload",dojo._loadInit); -} -if(dojo._inFlightCount==0){ -dojo._modulesLoaded(); -} -} + +dojo.isSafari = { + // example: + // | if(dojo.isSafari){ ... } + // example: + // Detect iPhone: + // | if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ + // | // we are iPhone. Note, iPod touch reports "iPod" above and fails this test. + // | } }; -if(!dojo.config.afterOnLoad){ -if(document.addEventListener){ -document.addEventListener("DOMContentLoaded",dojo._loadInit,false); -window.addEventListener("load",dojo._loadInit,false); -}else{ -if(window.attachEvent){ -window.attachEvent("onload",dojo._loadInit); -if(!dojo.config.skipIeDomLoaded&&self===self.top){ -dojo._scrollIntervalId=setInterval(function(){ -try{ -if(document.body){ -document.documentElement.doScroll("left"); -dojo._loadInit(); -} -} -catch(e){ -} -},30); -} -} -} -} -if(dojo.isIE){ -try{ -(function(){ -document.namespaces.add("v","urn:schemas-microsoft-com:vml"); -var _1c=["*","group","roundrect","oval","shape","rect","imagedata","path","textpath","text"],i=0,l=1,s=document.createStyleSheet(); -if(dojo.isIE>=8){ -i=1; -l=_1c.length; -} -for(;i= 0){ d.isOpera = tv; } + if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; } + d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0; + d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; + d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; + d.isMac = dav.indexOf("Macintosh") >= 0; + + // safari detection derived from: + // http://developer.apple.com/internet/safari/faq.html#anchor2 + // http://developer.apple.com/internet/safari/uamatrix.html + var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); + if(index && !dojo.isChrome){ + // try to grab the explicit Safari version first. If we don't get + // one, look for less than 419.3 as the indication that we're on something + // "Safari 2-ish". + d.isSafari = parseFloat(dav.split("Version/")[1]); + if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ + d.isSafari = 2; + } + } + + if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; } + if(d.isMoz){ + //We really need to get away from this. Consider a sane isGecko approach for the future. + d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined; + } + if(document.all && !d.isOpera){ + d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined; + //In cases where the page has an HTTP header or META tag with + //X-UA-Compatible, then it is in emulation mode. + //Make sure isIE reflects the desired version. + //document.documentMode of 5 means quirks mode. + //Only switch the value if documentMode's major version + //is different from isIE's major version. + var mode = document.documentMode; + if(mode && mode != 5 && Math.floor(d.isIE) != mode){ + d.isIE = mode; + } + } + + //Workaround to get local file loads of dojo to work on IE 7 + //by forcing to not use native xhr. + if(dojo.isIE && window.location.protocol === "file:"){ + dojo.config.ieForceActiveXXhr=true; + } + + d.isQuirks = document.compatMode == "BackCompat"; + + // TODO: is the HTML LANG attribute relevant? + d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase(); + + // These are in order of decreasing likelihood; this will change in time. + d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; + + d._xhrObj = function(){ + // summary: + // does the work of portably generating a new XMLHTTPRequest object. + var http, last_e; + if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){ + try{ http = new XMLHttpRequest(); }catch(e){} + } + if(!http){ + for(var i=0; i<3; ++i){ + var progid = d._XMLHTTP_PROGIDS[i]; + try{ + http = new ActiveXObject(progid); + }catch(e){ + last_e = e; + } + + if(http){ + d._XMLHTTP_PROGIDS = [progid]; // so faster next time + break; + } + } + } + + if(!http){ + throw new Error("XMLHTTP not available: "+last_e); + } + + return http; // XMLHTTPRequest instance + } + + d._isDocumentOk = function(http){ + var stat = http.status || 0, + lp = location.protocol; + return (stat >= 200 && stat < 300) || // Boolean + stat == 304 || // allow any 2XX response code + stat == 1223 || // get it out of the cache + // Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file + (!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:") ); + } + + //See if base tag is in use. + //This is to fix http://trac.dojotoolkit.org/ticket/3973, + //but really, we need to find out how to get rid of the dojo._Url reference + //below and still have DOH work with the dojo.i18n test following some other + //test that uses the test frame to load a document (trac #2757). + //Opera still has problems, but perhaps a larger issue of base tag support + //with XHR requests (hasBase is true, but the request is still made to document + //path, not base path). + var owloc = window.location+""; + var base = document.getElementsByTagName("base"); + var hasBase = (base && base.length > 0); + + d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ + // summary: Read the contents of the specified uri and return those contents. + // uri: + // A relative or absolute uri. If absolute, it still must be in + // the same "domain" as we are. + // fail_ok: + // Default false. If fail_ok and loading fails, return null + // instead of throwing. + // returns: The response text. null is returned when there is a + // failure and failure is okay (an exception otherwise) + + // NOTE: must be declared before scope switches ie. this._xhrObj() + var http = d._xhrObj(); + + if(!hasBase && dojo._Url){ + uri = (new dojo._Url(owloc, uri)).toString(); + } + + if(d.config.cacheBust){ + //Make sure we have a string before string methods are used on uri + uri += ""; + uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,""); + } + + http.open('GET', uri, false); + try{ + http.send(null); + if(!d._isDocumentOk(http)){ + var err = Error("Unable to load "+uri+" status:"+ http.status); + err.status = http.status; + err.responseText = http.responseText; + throw err; + } + }catch(e){ + if(fail_ok){ return null; } // null + // rethrow the exception + throw e; + } + return http.responseText; // String + } + + + var _w = window; + var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){ + // summary: + // non-destructively adds the specified function to the node's + // evtName handler. + // evtName: should be in the form "onclick" for "onclick" handlers. + // Make sure you pass in the "on" part. + var _a = _w.attachEvent || _w.addEventListener; + evtName = _w.attachEvent ? evtName : evtName.substring(2); + _a(evtName, function(){ + fp.apply(_w, arguments); + }, false); + }; + + + d._windowUnloaders = []; + + d.windowUnloaded = function(){ + // summary: + // signal fired by impending window destruction. You may use + // dojo.addOnWindowUnload() to register a listener for this + // event. NOTE: if you wish to dojo.connect() to this method + // to perform page/application cleanup, be aware that this + // event WILL NOT fire if no handler has been registered with + // dojo.addOnWindowUnload. This behavior started in Dojo 1.3. + // Previous versions always triggered dojo.windowUnloaded. See + // dojo.addOnWindowUnload for more info. + var mll = d._windowUnloaders; + while(mll.length){ + (mll.pop())(); + } + d = null; + }; + + var _onWindowUnloadAttached = 0; + d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when window.onunload + // fires. + // description: + // The first time that addOnWindowUnload is called Dojo + // will register a page listener to trigger your unload + // handler with. Note that registering these handlers may + // destory "fastback" page caching in browsers that support + // it. Be careful trying to modify the DOM or access + // JavaScript properties during this phase of page unloading: + // they may not always be available. Consider + // dojo.addOnUnload() if you need to modify the DOM or do + // heavy JavaScript work since it fires at the eqivalent of + // the page's "onbeforeunload" event. + // example: + // | dojo.addOnWindowUnload(functionPointer) + // | dojo.addOnWindowUnload(object, "functionName"); + // | dojo.addOnWindowUnload(object, function(){ /* ... */}); + + d._onto(d._windowUnloaders, obj, functionName); + if(!_onWindowUnloadAttached){ + _onWindowUnloadAttached = 1; + _handleNodeEvent("onunload", d.windowUnloaded); + } + }; + + var _onUnloadAttached = 0; + d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when the page unloads. + // description: + // The first time that addOnUnload is called Dojo will + // register a page listener to trigger your unload handler + // with. + // + // In a browser enviroment, the functions will be triggered + // during the window.onbeforeunload event. Be careful of doing + // too much work in an unload handler. onbeforeunload can be + // triggered if a link to download a file is clicked, or if + // the link is a javascript: link. In these cases, the + // onbeforeunload event fires, but the document is not + // actually destroyed. So be careful about doing destructive + // operations in a dojo.addOnUnload callback. + // + // Further note that calling dojo.addOnUnload will prevent + // browsers from using a "fast back" cache to make page + // loading via back button instantaneous. + // example: + // | dojo.addOnUnload(functionPointer) + // | dojo.addOnUnload(object, "functionName") + // | dojo.addOnUnload(object, function(){ /* ... */}); + + d._onto(d._unloaders, obj, functionName); + if(!_onUnloadAttached){ + _onUnloadAttached = 1; + _handleNodeEvent("onbeforeunload", dojo.unloaded); + } + }; + + })(); + + //START DOMContentLoaded + dojo._initFired = false; + dojo._loadInit = function(e){ + if(dojo._scrollIntervalId){ + clearInterval(dojo._scrollIntervalId); + dojo._scrollIntervalId = 0; + } + + if(!dojo._initFired){ + dojo._initFired = true; + + //Help out IE to avoid memory leak. + if(!dojo.config.afterOnLoad && window.detachEvent){ + window.detachEvent("onload", dojo._loadInit); + } + + if(dojo._inFlightCount == 0){ + dojo._modulesLoaded(); + } + } + } + + if(!dojo.config.afterOnLoad){ + if(document.addEventListener){ + //Standards. Hooray! Assumption here that if standards based, + //it knows about DOMContentLoaded. It is OK if it does not, the fall through + //to window onload should be good enough. + document.addEventListener("DOMContentLoaded", dojo._loadInit, false); + window.addEventListener("load", dojo._loadInit, false); + }else if(window.attachEvent){ + window.attachEvent("onload", dojo._loadInit); + + //DOMContentLoaded approximation. Diego Perini found this MSDN article + //that indicates doScroll is available after DOM ready, so do a setTimeout + //to check when it is available. + //http://msdn.microsoft.com/en-us/library/ms531426.aspx + if(!dojo.config.skipIeDomLoaded && self === self.top){ + dojo._scrollIntervalId = setInterval(function (){ + try{ + //When dojo is loaded into an iframe in an IE HTML Application + //(HTA), such as in a selenium test, javascript in the iframe + //can't see anything outside of it, so self===self.top is true, + //but the iframe is not the top window and doScroll will be + //available before document.body is set. Test document.body + //before trying the doScroll trick + if(document.body){ + document.documentElement.doScroll("left"); + dojo._loadInit(); + } + }catch (e){} + }, 30); + } + } + } + + if(dojo.isIE){ + try{ + (function(){ + document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); + var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"], + i = 0, l = 1, s = document.createStyleSheet(); + if(dojo.isIE >= 8){ + i = 1; + l = vmlElems.length; + } + for(; i < l; ++i){ + s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block"); + } + })(); + }catch(e){} + } + //END DOMContentLoaded + + + /* + OpenAjax.subscribe("OpenAjax", "onload", function(){ + if(dojo._inFlightCount == 0){ + dojo._modulesLoaded(); + } + }); + + OpenAjax.subscribe("OpenAjax", "onunload", function(){ + dojo.unloaded(); + }); + */ +} //if (typeof window != 'undefined') + +//Register any module paths set up in djConfig. Need to do this +//in the hostenvs since hostenv_browser can read djConfig from a +//script tag's attribute. (function(){ -var mp=dojo.config["modulePaths"]; -if(mp){ -for(var _1d in mp){ -dojo.registerModulePath(_1d,mp[_1d]); -} -} + var mp = dojo.config["modulePaths"]; + if(mp){ + for(var param in mp){ + dojo.registerModulePath(param, mp[param]); + } + } })(); + +//Load debug code if necessary. if(dojo.config.isDebug){ -dojo.require("dojo._firebug.firebug"); + dojo.require("dojo._firebug.firebug"); } + if(dojo.config.debugAtAllCosts){ -dojo.config.useXDomain=true; -dojo.require("dojo._base._loader.loader_xd"); -dojo.require("dojo._base._loader.loader_debug"); -dojo.require("dojo.i18n"); + dojo.config.useXDomain = true; + dojo.require("dojo._base._loader.loader_xd"); + dojo.require("dojo._base._loader.loader_debug"); + dojo.require("dojo.i18n"); } diff --git a/lib/dojo/_base/_loader/hostenv_ff_ext.js b/lib/dojo/_base/_loader/hostenv_ff_ext.js index 08242393d..94a0a8046 100644 --- a/lib/dojo/_base/_loader/hostenv_ff_ext.js +++ b/lib/dojo/_base/_loader/hostenv_ff_ext.js @@ -5,171 +5,334 @@ */ -if(typeof window!="undefined"){ -dojo.isBrowser=true; -dojo._name="browser"; -(function(){ -var d=dojo; -d.baseUrl=d.config.baseUrl; -var n=navigator; -var _1=n.userAgent; -var _2=n.appVersion; -var tv=parseFloat(_2); -d.isMozilla=d.isMoz=tv; -if(d.isMoz){ -d.isFF=parseFloat(_1.split("Firefox/")[1])||undefined; -} -d.isQuirks=document.compatMode=="BackCompat"; -d.locale=dojo.config.locale||n.language.toLowerCase(); -d._xhrObj=function(){ -return new XMLHttpRequest(); -}; -var _3=d._loadUri; -d._loadUri=function(_4,cb){ -var _5=["file:","chrome:","resource:"].some(function(_6){ -return String(_4).indexOf(_6)==0; -}); -if(_5){ -var l=Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader); -var _7=l.loadSubScript(_4,d.global); -if(cb){ -cb(_7); -} -return true; -}else{ -return _3.apply(d,arguments); -} -}; -d._isDocumentOk=function(_8){ -var _9=_8.status||0; -return (_9>=200&&_9<300)||_9==304||_9==1223||(!_9&&(location.protocol=="file:"||location.protocol=="chrome:")); -}; -var _a=false; -d._getText=function(_b,_c){ -var _d=d._xhrObj(); -if(!_a&&dojo._Url){ -_b=(new dojo._Url(_b)).toString(); -} -if(d.config.cacheBust){ -_b+=""; -_b+=(_b.indexOf("?")==-1?"?":"&")+String(d.config.cacheBust).replace(/\W+/g,""); -} -var _e=["file:","chrome:","resource:"].some(function(_f){ -return String(_b).indexOf(_f)==0; -}); -if(_e){ -var _10=Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); -var _11=Components.classes["@mozilla.org/scriptableinputstream;1"].getService(Components.interfaces.nsIScriptableInputStream); -var _12=_10.newChannel(_b,null,null); -var _13=_12.open(); -_11.init(_13); -var str=_11.read(_13.available()); -_11.close(); -_13.close(); -return str; -}else{ -_d.open("GET",_b,false); -try{ -_d.send(null); -if(!d._isDocumentOk(_d)){ -var err=Error("Unable to load "+_b+" status:"+_d.status); -err.status=_d.status; -err.responseText=_d.responseText; -throw err; -} -} -catch(e){ -if(_c){ -return null; -} -throw e; -} -return _d.responseText; -} -}; -d._windowUnloaders=[]; -d.windowUnloaded=function(){ -var mll=d._windowUnloaders; -while(mll.length){ -(mll.pop())(); -} -}; -d.addOnWindowUnload=function(obj,_14){ -d._onto(d._windowUnloaders,obj,_14); -}; -var _15=[]; -var _16=null; -dojo._defaultContext=[window,document]; -dojo.pushContext=function(g,d){ -var old=[dojo.global,dojo.doc]; -_15.push(old); -var n; -if(!g&&!d){ -n=dojo._defaultContext; -}else{ -n=[g,d]; -if(!d&&dojo.isString(g)){ -var t=document.getElementById(g); -if(t.contentDocument){ -n=[t.contentWindow,t.contentDocument]; -} -} -} -_16=n; -dojo.setContext.apply(dojo,n); -return old; -}; -dojo.popContext=function(){ -var oc=_16; -if(!_15.length){ -return oc; -} -dojo.setContext.apply(dojo,_15.pop()); -return oc; -}; -dojo._inContext=function(g,d,f){ -var a=dojo._toArray(arguments); -f=a.pop(); -if(a.length==1){ -d=null; -} -dojo.pushContext(g,d); -var r=f(); -dojo.popContext(); -return r; -}; -})(); -dojo._initFired=false; -dojo._loadInit=function(e){ -dojo._initFired=true; -var _17=(e&&e.type)?e.type.toLowerCase():"load"; -if(arguments.callee.initialized||(_17!="domcontentloaded"&&_17!="load")){ -return; -} -arguments.callee.initialized=true; -if(dojo._inFlightCount==0){ -dojo._modulesLoaded(); -} -}; -if(!dojo.config.afterOnLoad){ -window.addEventListener("DOMContentLoaded",function(e){ -dojo._loadInit(e); -},false); -} -} +// a host environment specifically built for Mozilla extensions, but derived +// from the browser host environment +if(typeof window != 'undefined'){ + dojo.isBrowser = true; + dojo._name = "browser"; + + + // FIXME: PORTME + // http://developer.mozilla.org/en/mozIJSSubScriptLoader + + + // attempt to figure out the path to dojo if it isn't set in the config + (function(){ + var d = dojo; + // this is a scope protection closure. We set browser versions and grab + // the URL we were loaded from here. + + // FIXME: need to probably use a different reference to "document" to get the hosting XUL environment + + d.baseUrl = d.config.baseUrl; + + // fill in the rendering support information in dojo.render.* + var n = navigator; + var dua = n.userAgent; + var dav = n.appVersion; + var tv = parseFloat(dav); + + d.isMozilla = d.isMoz = tv; + if(d.isMoz){ + d.isFF = parseFloat(dua.split("Firefox/")[1]) || undefined; + } + + // FIXME + d.isQuirks = document.compatMode == "BackCompat"; + + // FIXME + // TODO: is the HTML LANG attribute relevant? + d.locale = dojo.config.locale || n.language.toLowerCase(); + + d._xhrObj = function(){ + return new XMLHttpRequest(); + } + + // monkey-patch _loadUri to handle file://, chrome://, and resource:// url's + var oldLoadUri = d._loadUri; + d._loadUri = function(uri, cb){ + var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){ + return String(uri).indexOf(prefix) == 0; + }); + if(handleLocal){ + // see: + // http://developer.mozilla.org/en/mozIJSSubScriptLoader + var l = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Components.interfaces.mozIJSSubScriptLoader); + var value = l.loadSubScript(uri, d.global) + if(cb){ cb(value); } + return true; + }else{ + // otherwise, call the pre-existing version + return oldLoadUri.apply(d, arguments); + } + } + + // FIXME: PORTME + d._isDocumentOk = function(http){ + var stat = http.status || 0; + return (stat >= 200 && stat < 300) || // Boolean + stat == 304 || // allow any 2XX response code + stat == 1223 || // get it out of the cache + (!stat && (location.protocol=="file:" || location.protocol=="chrome:") ); + } + + // FIXME: PORTME + // var owloc = window.location+""; + // var base = document.getElementsByTagName("base"); + // var hasBase = (base && base.length > 0); + var hasBase = false; + + d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ + // summary: Read the contents of the specified uri and return those contents. + // uri: + // A relative or absolute uri. If absolute, it still must be in + // the same "domain" as we are. + // fail_ok: + // Default false. If fail_ok and loading fails, return null + // instead of throwing. + // returns: The response text. null is returned when there is a + // failure and failure is okay (an exception otherwise) + + // alert("_getText: " + uri); + + // NOTE: must be declared before scope switches ie. this._xhrObj() + var http = d._xhrObj(); + + if(!hasBase && dojo._Url){ + uri = (new dojo._Url(uri)).toString(); + } + if(d.config.cacheBust){ + //Make sure we have a string before string methods are used on uri + uri += ""; + uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,""); + } + var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){ + return String(uri).indexOf(prefix) == 0; + }); + if(handleLocal){ + // see: + // http://forums.mozillazine.org/viewtopic.php?p=921150#921150 + var ioService = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + var scriptableStream=Components + .classes["@mozilla.org/scriptableinputstream;1"] + .getService(Components.interfaces.nsIScriptableInputStream); + + var channel = ioService.newChannel(uri, null, null); + var input = channel.open(); + scriptableStream.init(input); + var str = scriptableStream.read(input.available()); + scriptableStream.close(); + input.close(); + return str; + }else{ + http.open('GET', uri, false); + try{ + http.send(null); + // alert(http); + if(!d._isDocumentOk(http)){ + var err = Error("Unable to load "+uri+" status:"+ http.status); + err.status = http.status; + err.responseText = http.responseText; + throw err; + } + }catch(e){ + if(fail_ok){ return null; } // null + // rethrow the exception + throw e; + } + return http.responseText; // String + } + } + + d._windowUnloaders = []; + + // FIXME: PORTME + d.windowUnloaded = function(){ + // summary: + // signal fired by impending window destruction. You may use + // dojo.addOnWIndowUnload() or dojo.connect() to this method to perform + // page/application cleanup methods. See dojo.addOnWindowUnload for more info. + var mll = d._windowUnloaders; + while(mll.length){ + (mll.pop())(); + } + } + + // FIXME: PORTME + d.addOnWindowUnload = function(/*Object?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when window.onunload fires. + // Be careful trying to modify the DOM or access JavaScript properties + // during this phase of page unloading: they may not always be available. + // Consider dojo.addOnUnload() if you need to modify the DOM or do heavy + // JavaScript work. + // example: + // | dojo.addOnWindowUnload(functionPointer) + // | dojo.addOnWindowUnload(object, "functionName") + // | dojo.addOnWindowUnload(object, function(){ /* ... */}); + + d._onto(d._windowUnloaders, obj, functionName); + } + + // XUL specific APIs + var contexts = []; + var current = null; + dojo._defaultContext = [ window, document ]; + + dojo.pushContext = function(/*Object|String?*/g, /*MDocumentElement?*/d){ + // summary: + // causes subsequent calls to Dojo methods to assume the + // passed object and, optionally, document as the default + // scopes to use. A 2-element array of the previous global and + // document are returned. + // description: + // dojo.pushContext treats contexts as a stack. The + // auto-detected contexts which are initially provided using + // dojo.setContext() require authors to keep state in order to + // "return" to a previous context, whereas the + // dojo.pushContext and dojo.popContext methods provide a more + // natural way to augment blocks of code to ensure that they + // execute in a different window or frame without issue. If + // called without any arguments, the default context (the + // context when Dojo is first loaded) is instead pushed into + // the stack. If only a single string is passed, a node in the + // intitial context's document is looked up and its + // contextWindow and contextDocument properties are used as + // the context to push. This means that iframes can be given + // an ID and code can be executed in the scope of the iframe's + // document in subsequent calls easily. + // g: + // The global context. If a string, the id of the frame to + // search for a context and document. + // d: + // The document element to execute subsequent code with. + var old = [dojo.global, dojo.doc]; + contexts.push(old); + var n; + if(!g && !d){ + n = dojo._defaultContext; + }else{ + n = [ g, d ]; + if(!d && dojo.isString(g)){ + var t = document.getElementById(g); + if(t.contentDocument){ + n = [t.contentWindow, t.contentDocument]; + } + } + } + current = n; + dojo.setContext.apply(dojo, n); + return old; // Array + }; + + dojo.popContext = function(){ + // summary: + // If the context stack contains elements, ensure that + // subsequent code executes in the *previous* context to the + // current context. The current context set ([global, + // document]) is returned. + var oc = current; + if(!contexts.length){ + return oc; + } + dojo.setContext.apply(dojo, contexts.pop()); + return oc; + }; + + // FIXME: + // don't really like the current arguments and order to + // _inContext, so don't make it public until it's right! + dojo._inContext = function(g, d, f){ + var a = dojo._toArray(arguments); + f = a.pop(); + if(a.length == 1){ + d = null; + } + dojo.pushContext(g, d); + var r = f(); + dojo.popContext(); + return r; + }; + + })(); + + dojo._initFired = false; + // BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/) + dojo._loadInit = function(e){ + dojo._initFired = true; + // allow multiple calls, only first one will take effect + // A bug in khtml calls events callbacks for document for event which isnt supported + // for example a created contextmenu event calls DOMContentLoaded, workaround + var type = (e && e.type) ? e.type.toLowerCase() : "load"; + if(arguments.callee.initialized || (type != "domcontentloaded" && type != "load")){ return; } + arguments.callee.initialized = true; + if(dojo._inFlightCount == 0){ + dojo._modulesLoaded(); + } + } + + /* + (function(){ + var _w = window; + var _handleNodeEvent = function(evtName, fp){ + // summary: + // non-destructively adds the specified function to the node's + // evtName handler. + // evtName: should be in the form "onclick" for "onclick" handlers. + // Make sure you pass in the "on" part. + var oldHandler = _w[evtName] || function(){}; + _w[evtName] = function(){ + fp.apply(_w, arguments); + oldHandler.apply(_w, arguments); + }; + }; + // FIXME: PORT + // FIXME: dojo.unloaded requires dojo scope, so using anon function wrapper. + _handleNodeEvent("onbeforeunload", function() { dojo.unloaded(); }); + _handleNodeEvent("onunload", function() { dojo.windowUnloaded(); }); + })(); + */ + + + // FIXME: PORTME + // this event fires a lot, namely for all plugin XUL overlays and for + // all iframes (in addition to window navigations). We only want + // Dojo's to fire once..but we might care if pages navigate. We'll + // probably need an extension-specific API + if(!dojo.config.afterOnLoad){ + window.addEventListener("DOMContentLoaded",function(e){ + dojo._loadInit(e); + // console.log("DOM content loaded", e); + }, false); + } + +} //if (typeof window != 'undefined') + +//Register any module paths set up in djConfig. Need to do this +//in the hostenvs since hostenv_browser can read djConfig from a +//script tag's attribute. (function(){ -var mp=dojo.config["modulePaths"]; -if(mp){ -for(var _18 in mp){ -dojo.registerModulePath(_18,mp[_18]); -} -} + var mp = dojo.config["modulePaths"]; + if(mp){ + for(var param in mp){ + dojo.registerModulePath(param, mp[param]); + } + } })(); + +//Load debug code if necessary. if(dojo.config.isDebug){ -console.log=function(m){ -var s=Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService); -s.logStringMessage(m); -}; -console.debug=function(){ -}; + // logging stub for extension logging + console.log = function(m){ + var s = Components.classes["@mozilla.org/consoleservice;1"].getService( + Components.interfaces.nsIConsoleService + ); + s.logStringMessage(m); + } + console.debug = function(){ + console.log(dojo._toArray(arguments).join(" ")); + } + // FIXME: what about the rest of the console.* methods? And is there any way to reach into firebug and log into it directly? } diff --git a/lib/dojo/_base/_loader/hostenv_rhino.js b/lib/dojo/_base/_loader/hostenv_rhino.js index 9cd882713..ee9ad8b43 100644 --- a/lib/dojo/_base/_loader/hostenv_rhino.js +++ b/lib/dojo/_base/_loader/hostenv_rhino.js @@ -5,149 +5,204 @@ */ +/* +* Rhino host environment +*/ + if(dojo.config["baseUrl"]){ -dojo.baseUrl=dojo.config["baseUrl"]; + dojo.baseUrl = dojo.config["baseUrl"]; }else{ -dojo.baseUrl="./"; + dojo.baseUrl = "./"; } -dojo.locale=dojo.locale||String(java.util.Locale.getDefault().toString().replace("_","-").toLowerCase()); -dojo._name="rhino"; -dojo.isRhino=true; -if(typeof print=="function"){ -console.debug=print; + +dojo.locale = dojo.locale || String(java.util.Locale.getDefault().toString().replace('_','-').toLowerCase()); +dojo._name = 'rhino'; +dojo.isRhino = true; + +if(typeof print == "function"){ + console.debug = print; } + if(!("byId" in dojo)){ -dojo.byId=function(id,_1){ -if(id&&(typeof id=="string"||id instanceof String)){ -if(!_1){ -_1=document; -} -return _1.getElementById(id); -} -return id; -}; -} -dojo._isLocalUrl=function(_2){ -var _3=(new java.io.File(_2)).exists(); -if(!_3){ -var _4; -try{ -_4=(new java.net.URL(_2)).openStream(); -_4.close(); -} -finally{ -if(_4&&_4.close){ -_4.close(); -} -} -} -return _3; -}; -dojo._loadUri=function(_5,cb){ -try{ -var _6; -try{ -_6=dojo._isLocalUrl(_5); -} -catch(e){ -return false; -} -if(cb){ -var _7=(_6?readText:readUri)(_5,"UTF-8"); -if(!eval("'‏'").length){ -_7=String(_7).replace(/[\u200E\u200F\u202A-\u202E]/g,function(_8){ -return "\\u"+_8.charCodeAt(0).toString(16); -}); -} -cb(eval("("+_7+")")); -}else{ -load(_5); -} -return true; -} -catch(e){ -return false; -} -}; -dojo.exit=function(_9){ -quit(_9); -}; -function readText(_a,_b){ -_b=_b||"utf-8"; -var jf=new java.io.File(_a); -var is=new java.io.FileInputStream(jf); -return dj_readInputStream(is,_b); -}; -function readUri(_c,_d){ -var _e=(new java.net.URL(_c)).openConnection(); -_d=_d||_e.getContentEncoding()||"utf-8"; -var is=_e.getInputStream(); -return dj_readInputStream(is,_d); -}; -function dj_readInputStream(is,_f){ -var _10=new java.io.BufferedReader(new java.io.InputStreamReader(is,_f)); -try{ -var sb=new java.lang.StringBuffer(); -var _11=""; -while((_11=_10.readLine())!==null){ -sb.append(_11); -sb.append(java.lang.System.getProperty("line.separator")); -} -return sb.toString(); + dojo.byId = function(id, doc){ + if(id && (typeof id == "string" || id instanceof String)){ + if(!doc){ doc = document; } + return doc.getElementById(id); + } + return id; // assume it's a node + } } -finally{ -_10.close(); -} -}; -dojo._getText=function(uri,_12){ -try{ -var _13=dojo._isLocalUrl(uri); -var _14=(_13?readText:readUri)(uri,"UTF-8"); -if(_14!==null){ -_14+=""; + +dojo._isLocalUrl = function(/*String*/ uri) { + // summary: + // determines if URI is local or not. + + var local = (new java.io.File(uri)).exists(); + if(!local){ + var stream; + //Try remote URL. Allow this method to throw, + //but still do cleanup. + try{ + // try it as a file first, URL second + stream = (new java.net.URL(uri)).openStream(); + // close the stream so we don't leak resources + stream.close(); + }finally{ + if(stream && stream.close){ + stream.close(); + } + } + } + return local; } -return _14; + +// see comments in spidermonkey loadUri +dojo._loadUri = function(uri, cb){ + try{ + var local; + try{ + local = dojo._isLocalUrl(uri); + }catch(e){ + // no debug output; this failure just means the uri was not found. + return false; + } + + //FIXME: Use Rhino 1.6 native readFile/readUrl if available? + if(cb){ + var contents = (local ? readText : readUri)(uri, "UTF-8"); + + // patch up the input to eval until https://bugzilla.mozilla.org/show_bug.cgi?id=471005 is fixed. + if(!eval("'\u200f'").length){ + contents = String(contents).replace(/[\u200E\u200F\u202A-\u202E]/g, function(match){ + return "\\u" + match.charCodeAt(0).toString(16); + }) + } + + cb(eval('('+contents+')')); + }else{ + load(uri); + } + return true; + }catch(e){ + console.debug("rhino load('" + uri + "') failed. Exception: " + e); + return false; + } } -catch(e){ -if(_12){ -return null; -}else{ -throw e; + +dojo.exit = function(exitcode){ + quit(exitcode); } + +// reading a file from disk in Java is a humiliating experience by any measure. +// Lets avoid that and just get the freaking text +function readText(path, encoding){ + encoding = encoding || "utf-8"; + // NOTE: we intentionally avoid handling exceptions, since the caller will + // want to know + var jf = new java.io.File(path); + var is = new java.io.FileInputStream(jf); + return dj_readInputStream(is, encoding); } -}; -dojo.doc=typeof document!="undefined"?document:null; -dojo.body=function(){ -return document.body; -}; -if(typeof setTimeout=="undefined"||typeof clearTimeout=="undefined"){ -dojo._timeouts=[]; -clearTimeout=function(idx){ -if(!dojo._timeouts[idx]){ -return; + +function readUri(uri, encoding){ + var conn = (new java.net.URL(uri)).openConnection(); + encoding = encoding || conn.getContentEncoding() || "utf-8"; + var is = conn.getInputStream(); + return dj_readInputStream(is, encoding); } -dojo._timeouts[idx].stop(); -}; -setTimeout=function(_15,_16){ -var def={sleepTime:_16,hasSlept:false,run:function(){ -if(!this.hasSlept){ -this.hasSlept=true; -java.lang.Thread.currentThread().sleep(this.sleepTime); + +function dj_readInputStream(is, encoding){ + var input = new java.io.BufferedReader(new java.io.InputStreamReader(is, encoding)); + try { + var sb = new java.lang.StringBuffer(); + var line = ""; + while((line = input.readLine()) !== null){ + sb.append(line); + sb.append(java.lang.System.getProperty("line.separator")); + } + return sb.toString(); + } finally { + input.close(); + } } -try{ -_15(); + +dojo._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ + // summary: Read the contents of the specified uri and return those contents. + // uri: + // A relative or absolute uri. + // fail_ok: + // Default false. If fail_ok and loading fails, return null + // instead of throwing. + // returns: The response text. null is returned when there is a + // failure and failure is okay (an exception otherwise) + try{ + var local = dojo._isLocalUrl(uri); + var text = (local ? readText : readUri)(uri, "UTF-8"); + if(text !== null){ + //Force JavaScript string. + text += ""; + } + return text; + }catch(e){ + if(fail_ok){ + return null; + }else{ + throw e; + } + } } -catch(e){ + +// summary: +// return the document object associated with the dojo.global +dojo.doc = typeof document != "undefined" ? document : null; + +dojo.body = function(){ + return document.body; } -}}; -var _17=new java.lang.Runnable(def); -var _18=new java.lang.Thread(_17); -_18.start(); -return dojo._timeouts.push(_18)-1; -}; + +// Supply setTimeout/clearTimeout implementations if they aren't already there +// Note: this assumes that we define both if one is not provided... there might +// be a better way to do this if there is a use case where one is defined but +// not the other +if(typeof setTimeout == "undefined" || typeof clearTimeout == "undefined"){ + dojo._timeouts = []; + clearTimeout = function(idx){ + if(!dojo._timeouts[idx]){ return; } + dojo._timeouts[idx].stop(); + } + + setTimeout = function(func, delay){ + // summary: provides timed callbacks using Java threads + + var def={ + sleepTime:delay, + hasSlept:false, + + run:function(){ + if(!this.hasSlept){ + this.hasSlept=true; + java.lang.Thread.currentThread().sleep(this.sleepTime); + } + try{ + func(); + }catch(e){ + console.debug("Error running setTimeout thread:" + e); + } + } + }; + + var runnable = new java.lang.Runnable(def); + var thread = new java.lang.Thread(runnable); + thread.start(); + return dojo._timeouts.push(thread)-1; + } } + +//Register any module paths set up in djConfig. Need to do this +//in the hostenvs since hostenv_browser can read djConfig from a +//script tag's attribute. if(dojo.config["modulePaths"]){ -for(var param in dojo.config["modulePaths"]){ -dojo.registerModulePath(param,dojo.config["modulePaths"][param]); -} + for(var param in dojo.config["modulePaths"]){ + dojo.registerModulePath(param, dojo.config["modulePaths"][param]); + } } diff --git a/lib/dojo/_base/_loader/hostenv_spidermonkey.js b/lib/dojo/_base/_loader/hostenv_spidermonkey.js index ca63f16ce..17b21f5f0 100644 --- a/lib/dojo/_base/_loader/hostenv_spidermonkey.js +++ b/lib/dojo/_base/_loader/hostenv_spidermonkey.js @@ -5,46 +5,83 @@ */ +/* + * SpiderMonkey host environment + */ + if(dojo.config["baseUrl"]){ -dojo.baseUrl=dojo.config["baseUrl"]; + dojo.baseUrl = dojo.config["baseUrl"]; }else{ -dojo.baseUrl="./"; + dojo.baseUrl = "./"; } -dojo._name="spidermonkey"; -dojo.isSpidermonkey=true; -dojo.exit=function(_1){ -quit(_1); + +dojo._name = 'spidermonkey'; + +/*===== +dojo.isSpidermonkey = { + // summary: Detect spidermonkey }; -if(typeof print=="function"){ -console.debug=print; -} -if(typeof line2pc=="undefined"){ -throw new Error("attempt to use SpiderMonkey host environment when no 'line2pc' global"); +=====*/ + +dojo.isSpidermonkey = true; +dojo.exit = function(exitcode){ + quit(exitcode); } -dojo._spidermonkeyCurrentFile=function(_2){ -var s=""; -try{ -throw Error("whatever"); + +if(typeof print == "function"){ + console.debug = print; } -catch(e){ -s=e.stack; + +if(typeof line2pc == 'undefined'){ + throw new Error("attempt to use SpiderMonkey host environment when no 'line2pc' global"); } -var _3=s.match(/[^@]*\.js/gi); -if(!_3){ -throw Error("could not parse stack string: '"+s+"'"); + +dojo._spidermonkeyCurrentFile = function(depth){ + // + // This is a hack that determines the current script file by parsing a + // generated stack trace (relying on the non-standard "stack" member variable + // of the SpiderMonkey Error object). + // + // If param depth is passed in, it'll return the script file which is that far down + // the stack, but that does require that you know how deep your stack is when you are + // calling. + // + var s = ''; + try{ + throw Error("whatever"); + }catch(e){ + s = e.stack; + } + // lines are like: bu_getCurrentScriptURI_spidermonkey("ScriptLoader.js")@burst/Runtime.js:101 + var matches = s.match(/[^@]*\.js/gi); + if(!matches){ + throw Error("could not parse stack string: '" + s + "'"); + } + var fname = (typeof depth != 'undefined' && depth) ? matches[depth + 1] : matches[matches.length - 1]; + if(!fname){ + throw Error("could not find file name in stack string '" + s + "'"); + } + //print("SpiderMonkeyRuntime got fname '" + fname + "' from stack string '" + s + "'"); + return fname; } -var _4=(typeof _2!="undefined"&&_2)?_3[_2+1]:_3[_3.length-1]; -if(!_4){ -throw Error("could not find file name in stack string '"+s+"'"); + +// print(dojo._spidermonkeyCurrentFile(0)); + +dojo._loadUri = function(uri){ + // spidermonkey load() evaluates the contents into the global scope (which + // is what we want). + // TODO: sigh, load() does not return a useful value. + // Perhaps it is returning the value of the last thing evaluated? + var ok = load(uri); + // console.log("spidermonkey load(", uri, ") returned ", ok); + return 1; } -return _4; -}; -dojo._loadUri=function(_5){ -var ok=load(_5); -return 1; -}; + +//Register any module paths set up in djConfig. Need to do this +//in the hostenvs since hostenv_browser can read djConfig from a +//script tag's attribute. if(dojo.config["modulePaths"]){ -for(var param in dojo.config["modulePaths"]){ -dojo.registerModulePath(param,dojo.config["modulePaths"][param]); -} + for(var param in dojo.config["modulePaths"]){ + dojo.registerModulePath(param, dojo.config["modulePaths"][param]); + } } diff --git a/lib/dojo/_base/_loader/loader.js b/lib/dojo/_base/_loader/loader.js index 3f31040a1..9206de888 100644 --- a/lib/dojo/_base/_loader/loader.js +++ b/lib/dojo/_base/_loader/loader.js @@ -5,296 +5,800 @@ */ -if(!dojo._hasResource["dojo.foo"]){ -dojo._hasResource["dojo.foo"]=true; +if(!dojo._hasResource["dojo.foo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.foo"] = true; +/* + * loader.js - A bootstrap module. Runs before the hostenv_*.js file. Contains + * all of the package loading methods. + */ + (function(){ -var d=dojo; -d.mixin(d,{_loadedModules:{},_inFlightCount:0,_hasResource:{},_modulePrefixes:{dojo:{name:"dojo",value:"."},doh:{name:"doh",value:"../util/doh"},tests:{name:"tests",value:"tests"}},_moduleHasPrefix:function(_1){ -var mp=d._modulePrefixes; -return !!(mp[_1]&&mp[_1].value); -},_getModulePrefix:function(_2){ -var mp=d._modulePrefixes; -if(d._moduleHasPrefix(_2)){ -return mp[_2].value; -} -return _2; -},_loadedUrls:[],_postLoad:false,_loaders:[],_unloaders:[],_loadNotifying:false}); -dojo._loadPath=function(_3,_4,cb){ -var _5=((_3.charAt(0)=="/"||_3.match(/^\w+:/))?"":d.baseUrl)+_3; -try{ -return !_4?d._loadUri(_5,cb):d._loadUriAndCheck(_5,_4,cb); -} -catch(e){ -console.error(e); -return false; -} -}; -dojo._loadUri=function(_6,cb){ -if(d._loadedUrls[_6]){ -return true; -} -d._inFlightCount++; -var _7=d._getText(_6,true); -if(_7){ -d._loadedUrls[_6]=true; -d._loadedUrls.push(_6); -if(cb){ -_7="("+_7+")"; -}else{ -_7=d._scopePrefix+_7+d._scopeSuffix; -} -if(!d.isIE){ -_7+="\r\n//@ sourceURL="+_6; -} -var _8=d["eval"](_7); -if(cb){ -cb(_8); -} -} -if(--d._inFlightCount==0&&d._postLoad&&d._loaders.length){ -setTimeout(function(){ -if(d._inFlightCount==0){ -d._callLoaded(); -} -},0); -} -return !!_7; -}; -dojo._loadUriAndCheck=function(_9,_a,cb){ -var ok=false; -try{ -ok=d._loadUri(_9,cb); -} -catch(e){ -console.error("failed loading "+_9+" with error: "+e); -} -return !!(ok&&d._loadedModules[_a]); -}; -dojo.loaded=function(){ -d._loadNotifying=true; -d._postLoad=true; -var _b=d._loaders; -d._loaders=[]; -for(var x=0;x<_b.length;x++){ -_b[x](); -} -d._loadNotifying=false; -if(d._postLoad&&d._inFlightCount==0&&_b.length){ -d._callLoaded(); -} -}; -dojo.unloaded=function(){ -var _c=d._unloaders; -while(_c.length){ -(_c.pop())(); -} -}; -d._onto=function(_d,_e,fn){ -if(!fn){ -_d.push(_e); -}else{ -if(fn){ -var _f=(typeof fn=="string")?_e[fn]:fn; -_d.push(function(){ -_f.call(_e); -}); -} -} -}; -dojo.ready=dojo.addOnLoad=function(obj,_10){ -d._onto(d._loaders,obj,_10); -if(d._postLoad&&d._inFlightCount==0&&!d._loadNotifying){ -d._callLoaded(); -} -}; -var dca=d.config.addOnLoad; -if(dca){ -d.addOnLoad[(dca instanceof Array?"apply":"call")](d,dca); -} -dojo._modulesLoaded=function(){ -if(d._postLoad){ -return; -} -if(d._inFlightCount>0){ -console.warn("files still in flight!"); -return; -} -d._callLoaded(); -}; -dojo._callLoaded=function(){ -if(typeof setTimeout=="object"||(d.config.useXDomain&&d.isOpera)){ -setTimeout(d.isAIR?function(){ -d.loaded(); -}:d._scopeName+".loaded();",0); -}else{ -d.loaded(); -} -}; -dojo._getModuleSymbols=function(_11){ -var _12=_11.split("."); -for(var i=_12.length;i>0;i--){ -var _13=_12.slice(0,i).join("."); -if(i==1&&!d._moduleHasPrefix(_13)){ -_12[0]="../"+_12[0]; -}else{ -var _14=d._getModulePrefix(_13); -if(_14!=_13){ -_12.splice(0,i,_14); -break; -} -} -} -return _12; -}; -dojo._global_omit_module_check=false; -dojo.loadInit=function(_15){ -_15(); -}; -dojo._loadModule=dojo.require=function(_16,_17){ -_17=d._global_omit_module_check||_17; -var _18=d._loadedModules[_16]; -if(_18){ -return _18; -} -var _19=d._getModuleSymbols(_16).join("/")+".js"; -var _1a=!_17?_16:null; -var ok=d._loadPath(_19,_1a); -if(!ok&&!_17){ -throw new Error("Could not load '"+_16+"'; last tried '"+_19+"'"); -} -if(!_17&&!d._isXDomain){ -_18=d._loadedModules[_16]; -if(!_18){ -throw new Error("symbol '"+_16+"' is not defined after loading '"+_19+"'"); -} -} -return _18; -}; -dojo.provide=function(_1b){ -_1b=_1b+""; -return (d._loadedModules[_1b]=d.getObject(_1b,true)); -}; -dojo.platformRequire=function(_1c){ -var _1d=_1c.common||[]; -var _1e=_1d.concat(_1c[d._name]||_1c["default"]||[]); -for(var x=0;x<_1e.length;x++){ -var _1f=_1e[x]; -if(_1f.constructor==Array){ -d._loadModule.apply(d,_1f); -}else{ -d._loadModule(_1f); -} -} -}; -dojo.requireIf=function(_20,_21){ -if(_20===true){ -var _22=[]; -for(var i=1;i0&&!(j==1&&_2d[0]=="")&&_2d[j]==".."&&_2d[j-1]!=".."){ -if(j==(_2d.length-1)){ -_2d.splice(j,1); -_2d[j-1]=""; -}else{ -_2d.splice(j-1,2); -j-=2; -} -} -} -} -_2a.path=_2d.join("/"); -} -} -} -} -uri=[]; -if(_2a.scheme){ -uri.push(_2a.scheme,":"); -} -if(_2a.authority){ -uri.push("//",_2a.authority); -} -uri.push(_2a.path); -if(_2a.query){ -uri.push("?",_2a.query); -} -if(_2a.fragment){ -uri.push("#",_2a.fragment); -} -} -this.uri=uri.join(""); -var r=this.uri.match(ore); -this.scheme=r[2]||(r[1]?"":n); -this.authority=r[4]||(r[3]?"":n); -this.path=r[5]; -this.query=r[7]||(r[6]?"":n); -this.fragment=r[9]||(r[8]?"":n); -if(this.authority!=n){ -r=this.authority.match(ire); -this.user=r[3]||n; -this.password=r[4]||n; -this.host=r[6]||r[7]; -this.port=r[9]||n; -} -}; -dojo._Url.prototype.toString=function(){ -return this.uri; -}; -dojo.moduleUrl=function(_2e,url){ -var loc=d._getModuleSymbols(_2e).join("/"); -if(!loc){ -return null; -} -if(loc.lastIndexOf("/")!=loc.length-1){ -loc+="/"; -} -var _2f=loc.indexOf(":"); -if(loc.charAt(0)!="/"&&(_2f==-1||_2f>loc.indexOf("/"))){ -loc=d.baseUrl+loc; -} -return new d._Url(loc,url); -}; + var d = dojo; + + d.mixin(d, { + _loadedModules: {}, + _inFlightCount: 0, + _hasResource: {}, + + _modulePrefixes: { + dojo: { name: "dojo", value: "." }, + // dojox: { name: "dojox", value: "../dojox" }, + // dijit: { name: "dijit", value: "../dijit" }, + doh: { name: "doh", value: "../util/doh" }, + tests: { name: "tests", value: "tests" } + }, + + _moduleHasPrefix: function(/*String*/module){ + // summary: checks to see if module has been established + var mp = d._modulePrefixes; + return !!(mp[module] && mp[module].value); // Boolean + }, + + _getModulePrefix: function(/*String*/module){ + // summary: gets the prefix associated with module + var mp = d._modulePrefixes; + if(d._moduleHasPrefix(module)){ + return mp[module].value; // String + } + return module; // String + }, + + _loadedUrls: [], + + //WARNING: + // This variable is referenced by packages outside of bootstrap: + // FloatingPane.js and undo/browser.js + _postLoad: false, + + //Egad! Lots of test files push on this directly instead of using dojo.addOnLoad. + _loaders: [], + _unloaders: [], + _loadNotifying: false + }); + + + dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){ + // summary: + // Load a Javascript module given a relative path + // + // description: + // Loads and interprets the script located at relpath, which is + // relative to the script root directory. If the script is found but + // its interpretation causes a runtime exception, that exception is + // not caught by us, so the caller will see it. We return a true + // value if and only if the script is found. + // + // relpath: + // A relative path to a script (no leading '/', and typically ending + // in '.js'). + // module: + // A module whose existance to check for after loading a path. Can be + // used to determine success or failure of the load. + // cb: + // a callback function to pass the result of evaluating the script + + var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : d.baseUrl) + relpath; + try{ + return !module ? d._loadUri(uri, cb) : d._loadUriAndCheck(uri, module, cb); // Boolean + }catch(e){ + console.error(e); + return false; // Boolean + } + } + + dojo._loadUri = function(/*String*/uri, /*Function?*/cb){ + // summary: + // Loads JavaScript from a URI + // description: + // Reads the contents of the URI, and evaluates the contents. This is + // used to load modules as well as resource bundles. Returns true if + // it succeeded. Returns false if the URI reading failed. Throws if + // the evaluation throws. + // uri: a uri which points at the script to be loaded + // cb: + // a callback function to process the result of evaluating the script + // as an expression, typically used by the resource bundle loader to + // load JSON-style resources + + if(d._loadedUrls[uri]){ + return true; // Boolean + } + d._inFlightCount++; // block addOnLoad calls that arrive while we're busy downloading + var contents = d._getText(uri, true); + if(contents){ // not 404, et al + d._loadedUrls[uri] = true; + d._loadedUrls.push(uri); + 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 = d._scopePrefix + contents + d._scopeSuffix; + } + if(!d.isIE){ contents += "\r\n//@ sourceURL=" + uri; } // debugging assist for Firebug + var value = d["eval"](contents); + if(cb){ cb(value); } + } + // Check to see if we need to call _callLoaded() due to an addOnLoad() that arrived while we were busy downloading + if(--d._inFlightCount == 0 && d._postLoad && d._loaders.length){ + // We shouldn't be allowed to get here but Firefox allows an event + // (mouse, keybd, async xhrGet) to interrupt a synchronous xhrGet. + // If the current script block contains multiple require() statements, then after each + // require() returns, inFlightCount == 0, but we want to hold the _callLoaded() until + // all require()s are done since the out-of-sequence addOnLoad() presumably needs them all. + // setTimeout allows the next require() to start (if needed), and then we check this again. + setTimeout(function(){ + // If inFlightCount > 0, then multiple require()s are running sequentially and + // the next require() started after setTimeout() was executed but before we got here. + if(d._inFlightCount == 0){ + d._callLoaded(); + } + }, 0); + } + return !!contents; // Boolean: contents? true : false + } + + // FIXME: probably need to add logging to this method + dojo._loadUriAndCheck = function(/*String*/uri, /*String*/moduleName, /*Function?*/cb){ + // summary: calls loadUri then findModule and returns true if both succeed + var ok = false; + try{ + ok = d._loadUri(uri, cb); + }catch(e){ + console.error("failed loading " + uri + " with error: " + e); + } + return !!(ok && d._loadedModules[moduleName]); // Boolean + } + + dojo.loaded = function(){ + // summary: + // signal fired when initial environment and package loading is + // complete. You should use dojo.addOnLoad() instead of doing a + // direct dojo.connect() to this method in order to handle + // initialization tasks that require the environment to be + // initialized. In a browser host, declarative widgets will + // be constructed when this function finishes runing. + d._loadNotifying = true; + d._postLoad = true; + var mll = d._loaders; + + //Clear listeners so new ones can be added + //For other xdomain package loads after the initial load. + d._loaders = []; + + for(var x = 0; x < mll.length; x++){ + mll[x](); + } + + d._loadNotifying = false; + + //Make sure nothing else got added to the onload queue + //after this first run. If something did, and we are not waiting for any + //more inflight resources, run again. + if(d._postLoad && d._inFlightCount == 0 && mll.length){ + d._callLoaded(); + } + } + + dojo.unloaded = function(){ + // summary: + // signal fired by impending environment destruction. You should use + // dojo.addOnUnload() instead of doing a direct dojo.connect() to this + // method to perform page/application cleanup methods. See + // dojo.addOnUnload for more info. + var mll = d._unloaders; + while(mll.length){ + (mll.pop())(); + } + } + + d._onto = function(arr, obj, fn){ + if(!fn){ + arr.push(obj); + }else if(fn){ + var func = (typeof fn == "string") ? obj[fn] : fn; + arr.push(function(){ func.call(obj); }); + } + } + + dojo.ready = dojo.addOnLoad = function(/*Object*/obj, /*String|Function?*/functionName){ + // summary: + // Registers a function to be triggered after the DOM and dojo.require() calls + // have finished loading. + // + // description: + // Registers a function to be triggered after the DOM has finished + // loading and `dojo.require` modules have loaded. Widgets declared in markup + // have been instantiated if `djConfig.parseOnLoad` is true when this fires. + // + // Images and CSS files may or may not have finished downloading when + // the specified function is called. (Note that widgets' CSS and HTML + // code is guaranteed to be downloaded before said widgets are + // instantiated, though including css resouces BEFORE any script elements + // is highly recommended). + // + // example: + // Register an anonymous function to run when everything is ready + // | dojo.addOnLoad(function(){ doStuff(); }); + // + // example: + // Register a function to run when everything is ready by pointer: + // | var init = function(){ doStuff(); } + // | dojo.addOnLoad(init); + // + // example: + // Register a function to run scoped to `object`, either by name or anonymously: + // | dojo.addOnLoad(object, "functionName"); + // | dojo.addOnLoad(object, function(){ doStuff(); }); + + d._onto(d._loaders, obj, functionName); + + //Added for xdomain loading. dojo.addOnLoad is used to + //indicate callbacks after doing some dojo.require() statements. + //In the xdomain case, if all the requires are loaded (after initial + //page load), then immediately call any listeners. + if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){ + d._callLoaded(); + } + } + + //Support calling dojo.addOnLoad via djConfig.addOnLoad. Support all the + //call permutations of dojo.addOnLoad. Mainly useful when dojo is added + //to the page after the page has loaded. + var dca = d.config.addOnLoad; + if(dca){ + d.addOnLoad[(dca instanceof Array ? "apply" : "call")](d, dca); + } + + dojo._modulesLoaded = function(){ + if(d._postLoad){ return; } + if(d._inFlightCount > 0){ + console.warn("files still in flight!"); + return; + } + d._callLoaded(); + } + + dojo._callLoaded = function(){ + + // The "object" check is for IE, and the other opera check fixes an + // issue in Opera where it could not find the body element in some + // widget test cases. For 0.9, maybe route all browsers through the + // setTimeout (need protection still for non-browser environments + // though). This might also help the issue with FF 2.0 and freezing + // issues where we try to do sync xhr while background css images are + // being loaded (trac #2572)? Consider for 0.9. + if(typeof setTimeout == "object" || (d.config.useXDomain && d.isOpera)){ + setTimeout( + d.isAIR ? function(){ d.loaded(); } : d._scopeName + ".loaded();", + 0); + }else{ + d.loaded(); + } + } + + dojo._getModuleSymbols = function(/*String*/modulename){ + // summary: + // Converts a module name in dotted JS notation to an array + // representing the path in the source tree + var syms = modulename.split("."); + for(var i = syms.length; i>0; i--){ + var parentModule = syms.slice(0, i).join("."); + if(i == 1 && !d._moduleHasPrefix(parentModule)){ + // Support default module directory (sibling of dojo) for top-level modules + syms[0] = "../" + syms[0]; + }else{ + var parentModulePath = d._getModulePrefix(parentModule); + if(parentModulePath != parentModule){ + syms.splice(0, i, parentModulePath); + break; + } + } + } + return syms; // Array + } + + dojo._global_omit_module_check = false; + + dojo.loadInit = function(/*Function*/init){ + // summary: + // Executes a function that needs to be executed for the loader's dojo.requireIf + // resolutions to work. This is needed mostly for the xdomain loader case where + // a function needs to be executed to set up the possible values for a dojo.requireIf + // call. + // init: + // a function reference. Executed immediately. + // description: This function is mainly a marker for the xdomain loader to know parts of + // code that needs be executed outside the function wrappper that is placed around modules. + // The init function could be executed more than once, and it should make no assumptions + // on what is loaded, or what modules are available. Only the functionality in Dojo Base + // is allowed to be used. Avoid using this method. For a valid use case, + // see the source for dojox.gfx. + init(); + } + + dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){ + // summary: + // loads a Javascript module from the appropriate URI + // moduleName: + // module name to load, using periods for separators, + // e.g. "dojo.date.locale". Module paths are de-referenced by dojo's + // internal mapping of locations to names and are disambiguated by + // longest prefix. See `dojo.registerModulePath()` for details on + // registering new modules. + // omitModuleCheck: + // if `true`, omitModuleCheck skips the step of ensuring that the + // loaded file actually defines the symbol it is referenced by. + // For example if it called as `dojo.require("a.b.c")` and the + // file located at `a/b/c.js` does not define an object `a.b.c`, + // and exception will be throws whereas no exception is raised + // when called as `dojo.require("a.b.c", true)` + // description: + // Modules are loaded via dojo.require by using one of two loaders: the normal loader + // and the xdomain loader. The xdomain loader is used when dojo was built with a + // custom build that specified loader=xdomain and the module lives on a modulePath + // that is a whole URL, with protocol and a domain. The versions of Dojo that are on + // the Google and AOL CDNs use the xdomain loader. + // + // If the module is loaded via the xdomain loader, it is an asynchronous load, since + // the module is added via a dynamically created script tag. This + // means that dojo.require() can return before the module has loaded. However, this + // should only happen in the case where you do dojo.require calls in the top-level + // HTML page, or if you purposely avoid the loader checking for dojo.require + // dependencies in your module by using a syntax like dojo["require"] to load the module. + // + // Sometimes it is useful to not have the loader detect the dojo.require calls in the + // module so that you can dynamically load the modules as a result of an action on the + // page, instead of right at module load time. + // + // Also, for script blocks in an HTML page, the loader does not pre-process them, so + // it does not know to download the modules before the dojo.require calls occur. + // + // So, in those two cases, when you want on-the-fly module loading or for script blocks + // in the HTML page, special care must be taken if the dojo.required code is loaded + // asynchronously. To make sure you can execute code that depends on the dojo.required + // modules, be sure to add the code that depends on the modules in a dojo.addOnLoad() + // callback. dojo.addOnLoad waits for all outstanding modules to finish loading before + // executing. Example: + // + // | + // + // This type of syntax works with both xdomain and normal loaders, so it is good + // practice to always use this idiom for on-the-fly code loading and in HTML script + // blocks. If at some point you change loaders and where the code is loaded from, + // it will all still work. + // + // More on how dojo.require + // `dojo.require("A.B")` first checks to see if symbol A.B is + // defined. If it is, it is simply returned (nothing to do). + // + // If it is not defined, it will look for `A/B.js` in the script root + // directory. + // + // `dojo.require` throws an excpetion if it cannot find a file + // to load, or if the symbol `A.B` is not defined after loading. + // + // It returns the object `A.B`, but note the caveats above about on-the-fly loading and + // HTML script blocks when the xdomain loader is loading a module. + // + // `dojo.require()` does nothing about importing symbols into + // the current namespace. It is presumed that the caller will + // take care of that. For example, to import all symbols into a + // local block, you might write: + // + // | with (dojo.require("A.B")) { + // | ... + // | } + // + // And to import just the leaf symbol to a local variable: + // + // | var B = dojo.require("A.B"); + // | ... + // returns: the required namespace object + omitModuleCheck = d._global_omit_module_check || omitModuleCheck; + + //Check if it is already loaded. + var module = d._loadedModules[moduleName]; + if(module){ + return module; + } + + // convert periods to slashes + var relpath = d._getModuleSymbols(moduleName).join("/") + '.js'; + + var modArg = !omitModuleCheck ? moduleName : null; + var ok = d._loadPath(relpath, modArg); + + if(!ok && !omitModuleCheck){ + throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'"); + } + + // check that the symbol was defined + // Don't bother if we're doing xdomain (asynchronous) loading. + if(!omitModuleCheck && !d._isXDomain){ + // pass in false so we can give better error + module = d._loadedModules[moduleName]; + if(!module){ + throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'"); + } + } + + return module; + } + + dojo.provide = function(/*String*/ resourceName){ + // summary: + // Register a resource with the package system. Works in conjunction with `dojo.require` + // + // description: + // Each javascript source file is called a resource. When a + // resource is loaded by the browser, `dojo.provide()` registers + // that it has been loaded. + // + // Each javascript source file must have at least one + // `dojo.provide()` call at the top of the file, corresponding to + // the file name. For example, `js/dojo/foo.js` must have + // `dojo.provide("dojo.foo");` before any calls to + // `dojo.require()` are made. + // + // For backwards compatibility reasons, in addition to registering + // the resource, `dojo.provide()` also ensures that the javascript + // object for the module exists. For example, + // `dojo.provide("dojox.data.FlickrStore")`, in addition to + // registering that `FlickrStore.js` is a resource for the + // `dojox.data` module, will ensure that the `dojox.data` + // javascript object exists, so that calls like + // `dojo.data.foo = function(){ ... }` don't fail. + // + // In the case of a build where multiple javascript source files + // are combined into one bigger file (similar to a .lib or .jar + // file), that file may contain multiple dojo.provide() calls, to + // note that it includes multiple resources. + // + // resourceName: String + // A dot-sperated string identifying a resource. + // + // example: + // Safely create a `my` object, and make dojo.require("my.CustomModule") work + // | dojo.provide("my.CustomModule"); + + //Make sure we have a string. + resourceName = resourceName + ""; + return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object + } + + //Start of old bootstrap2: + + dojo.platformRequire = function(/*Object*/modMap){ + // summary: + // require one or more modules based on which host environment + // Dojo is currently operating in + // description: + // This method takes a "map" of arrays which one can use to + // optionally load dojo modules. The map is indexed by the + // possible dojo.name_ values, with two additional values: + // "default" and "common". The items in the "default" array will + // be loaded if none of the other items have been choosen based on + // dojo.name_, set by your host environment. The items in the + // "common" array will *always* be loaded, regardless of which + // list is chosen. + // example: + // | dojo.platformRequire({ + // | browser: [ + // | "foo.sample", // simple module + // | "foo.test", + // | ["foo.bar.baz", true] // skip object check in _loadModule (dojo.require) + // | ], + // | default: [ "foo.sample._base" ], + // | common: [ "important.module.common" ] + // | }); + + var common = modMap.common || []; + var result = common.concat(modMap[d._name] || modMap["default"] || []); + + for(var x=0; x + // | + d._modulePrefixes[module] = { name: module, value: prefix }; + } + + dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){ + // summary: + // Declares translated resources and loads them if necessary, in the + // same style as dojo.require. Contents of the resource bundle are + // typically strings, but may be any name/value pair, represented in + // JSON format. See also `dojo.i18n.getLocalization`. + // + // description: + // Load translated resource bundles provided underneath the "nls" + // directory within a package. Translated resources may be located in + // different packages throughout the source tree. + // + // Each directory is named for a locale as specified by RFC 3066, + // (http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase. + // Note that the two bundles in the example do not define all the + // same variants. For a given locale, bundles will be loaded for + // that locale and all more general locales above it, including a + // fallback at the root directory. For example, a declaration for + // the "de-at" locale will first load `nls/de-at/bundleone.js`, + // then `nls/de/bundleone.js` and finally `nls/bundleone.js`. The + // data will be flattened into a single Object so that lookups + // will follow this cascading pattern. An optional build step can + // preload the bundles to avoid data redundancy and the multiple + // network hits normally required to load these resources. + // + // moduleName: + // name of the package containing the "nls" directory in which the + // bundle is found + // + // bundleName: + // bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a + // a bundle name is not supported, since "nls" is the name of the folder + // that holds bundles. Using "nls" as the bundle name will cause problems + // with the custom build. + // + // locale: + // the locale to load (optional) By default, the browser's user + // locale as defined by dojo.locale + // + // availableFlatLocales: + // A comma-separated list of the available, flattened locales for this + // bundle. This argument should only be set by the build process. + // + // example: + // A particular widget may define one or more resource bundles, + // structured in a program as follows, where moduleName is + // mycode.mywidget and bundleNames available include bundleone and + // bundletwo: + // | ... + // | mycode/ + // | mywidget/ + // | nls/ + // | bundleone.js (the fallback translation, English in this example) + // | bundletwo.js (also a fallback translation) + // | de/ + // | bundleone.js + // | bundletwo.js + // | de-at/ + // | bundleone.js + // | en/ + // | (empty; use the fallback translation) + // | en-us/ + // | bundleone.js + // | en-gb/ + // | bundleone.js + // | es/ + // | bundleone.js + // | bundletwo.js + // | ...etc + // | ... + // + + d.require("dojo.i18n"); + d.i18n._requireLocalization.apply(d.hostenv, arguments); + }; + + + var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"), + ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"); + + dojo._Url = function(/*dojo._Url|String...*/){ + // summary: + // Constructor to create an object representing a URL. + // It is marked as private, since we might consider removing + // or simplifying it. + // description: + // Each argument is evaluated in order relative to the next until + // a canonical uri is produced. To get an absolute Uri relative to + // the current document use: + // new dojo._Url(document.baseURI, url) + + var n = null, + _a = arguments, + uri = [_a[0]]; + // resolve uri components relative to each other + for(var i = 1; i<_a.length; i++){ + if(!_a[i]){ continue; } + + // Safari doesn't support this.constructor so we have to be explicit + // FIXME: Tracked (and fixed) in Webkit bug 3537. + // http://bugs.webkit.org/show_bug.cgi?id=3537 + var relobj = new d._Url(_a[i]+""), + uriobj = new d._Url(uri[0]+""); + + if( + relobj.path == "" && + !relobj.scheme && + !relobj.authority && + !relobj.query + ){ + if(relobj.fragment != n){ + uriobj.fragment = relobj.fragment; + } + relobj = uriobj; + }else if(!relobj.scheme){ + relobj.scheme = uriobj.scheme; + + if(!relobj.authority){ + relobj.authority = uriobj.authority; + + if(relobj.path.charAt(0) != "/"){ + var path = uriobj.path.substring(0, + uriobj.path.lastIndexOf("/") + 1) + relobj.path; + + var segs = path.split("/"); + for(var j = 0; j < segs.length; j++){ + if(segs[j] == "."){ + // flatten "./" references + if(j == segs.length - 1){ + segs[j] = ""; + }else{ + segs.splice(j, 1); + j--; + } + }else if(j > 0 && !(j == 1 && segs[0] == "") && + segs[j] == ".." && segs[j-1] != ".."){ + // flatten "../" references + if(j == (segs.length - 1)){ + segs.splice(j, 1); + segs[j - 1] = ""; + }else{ + segs.splice(j - 1, 2); + j -= 2; + } + } + } + relobj.path = segs.join("/"); + } + } + } + + uri = []; + if(relobj.scheme){ + uri.push(relobj.scheme, ":"); + } + if(relobj.authority){ + uri.push("//", relobj.authority); + } + uri.push(relobj.path); + if(relobj.query){ + uri.push("?", relobj.query); + } + if(relobj.fragment){ + uri.push("#", relobj.fragment); + } + } + + this.uri = uri.join(""); + + // break the uri into its main components + var r = this.uri.match(ore); + + this.scheme = r[2] || (r[1] ? "" : n); + this.authority = r[4] || (r[3] ? "" : n); + this.path = r[5]; // can never be undefined + this.query = r[7] || (r[6] ? "" : n); + this.fragment = r[9] || (r[8] ? "" : n); + + if(this.authority != n){ + // server based naming authority + r = this.authority.match(ire); + + this.user = r[3] || n; + this.password = r[4] || n; + this.host = r[6] || r[7]; // ipv6 || ipv4 + this.port = r[9] || n; + } + } + + dojo._Url.prototype.toString = function(){ return this.uri; }; + + dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){ + // summary: + // Returns a `dojo._Url` object relative to a module. + // example: + // | var pngPath = dojo.moduleUrl("acme","images/small.png"); + // | console.dir(pngPath); // list the object properties + // | // create an image and set it's source to pngPath's value: + // | var img = document.createElement("img"); + // | // NOTE: we assign the string representation of the url object + // | img.src = pngPath.toString(); + // | // add our image to the document + // | dojo.body().appendChild(img); + // example: + // you may de-reference as far as you like down the package + // hierarchy. This is sometimes handy to avoid lenghty relative + // urls or for building portable sub-packages. In this example, + // the `acme.widget` and `acme.util` directories may be located + // under different roots (see `dojo.registerModulePath`) but the + // the modules which reference them can be unaware of their + // relative locations on the filesystem: + // | // somewhere in a configuration block + // | dojo.registerModulePath("acme.widget", "../../acme/widget"); + // | dojo.registerModulePath("acme.util", "../../util"); + // | + // | // ... + // | + // | // code in a module using acme resources + // | var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html"); + // | var dataPath = dojo.moduleUrl("acme.util","resources/data.json"); + + var loc = d._getModuleSymbols(module).join('/'); + if(!loc){ return null; } + if(loc.lastIndexOf("/") != loc.length-1){ + loc += "/"; + } + + //If the path is an absolute path (starts with a / or is on another + //domain/xdomain) then don't add the baseUrl. + var colonIndex = loc.indexOf(":"); + if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){ + loc = d.baseUrl + loc; + } + + return new d._Url(loc, url); // dojo._Url + } })(); + } diff --git a/lib/dojo/_base/_loader/loader_debug.js b/lib/dojo/_base/_loader/loader_debug.js index a28040f58..fa26d8efb 100644 --- a/lib/dojo/_base/_loader/loader_debug.js +++ b/lib/dojo/_base/_loader/loader_debug.js @@ -5,55 +5,82 @@ */ -if(!dojo._hasResource["dojo._base._loader.loader_debug"]){ -dojo._hasResource["dojo._base._loader.loader_debug"]=true; +if(!dojo._hasResource["dojo._base._loader.loader_debug"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base._loader.loader_debug"] = true; dojo.provide("dojo._base._loader.loader_debug"); -dojo.nonDebugProvide=dojo.provide; -dojo.provide=function(_1){ -var _2=dojo["_xdDebugQueue"]; -if(_2&&_2.length>0&&_1==_2["currentResourceName"]){ -if(dojo.isAIR){ -window.setTimeout(function(){ -dojo._xdDebugFileLoaded(_1); -},1); -}else{ -window.setTimeout(dojo._scopeName+"._xdDebugFileLoaded('"+_1+"')",1); -} -} -return dojo.nonDebugProvide.apply(dojo,arguments); -}; -dojo._xdDebugFileLoaded=function(_3){ -if(!dojo._xdDebugScopeChecked){ -if(dojo._scopeName!="dojo"){ -window.dojo=window[dojo.config.scopeMap[0][1]]; -window.dijit=window[dojo.config.scopeMap[1][1]]; -window.dojox=window[dojo.config.scopeMap[2][1]]; -} -dojo._xdDebugScopeChecked=true; -} -var _4=dojo._xdDebugQueue; -if(_3&&_3==_4.currentResourceName){ -_4.shift(); -} -if(_4.length==0){ -dojo._xdWatchInFlight(); -} -if(_4.length==0){ -_4.currentResourceName=null; -for(var _5 in dojo._xdInFlight){ -if(dojo._xdInFlight[_5]===true){ -return; -} -} -dojo._xdNotifyLoaded(); -}else{ -if(_3==_4.currentResourceName){ -_4.currentResourceName=_4[0].resourceName; -var _6=document.createElement("script"); -_6.type="text/javascript"; -_6.src=_4[0].resourcePath; -document.getElementsByTagName("head")[0].appendChild(_6); + +//Override dojo.provide, so we can trigger the next +//script tag for the next local module. We can only add one +//at a time because there are browsers that execute script tags +//in the order that the code is received, and not in the DOM order. +dojo.nonDebugProvide = dojo.provide; + +dojo.provide = function(resourceName){ + var dbgQueue = dojo["_xdDebugQueue"]; + if(dbgQueue && dbgQueue.length > 0 && resourceName == dbgQueue["currentResourceName"]){ + //Set a timeout so the module can be executed into existence. Normally the + //dojo.provide call in a module is the first line. Don't want to risk attaching + //another script tag until the current one finishes executing. + if(dojo.isAIR){ + window.setTimeout(function(){dojo._xdDebugFileLoaded(resourceName);}, 1); + }else{ + window.setTimeout(dojo._scopeName + "._xdDebugFileLoaded('" + resourceName + "')", 1); + } + } + + return dojo.nonDebugProvide.apply(dojo, arguments); } + +dojo._xdDebugFileLoaded = function(resourceName){ + + if(!dojo._xdDebugScopeChecked){ + //If using a scoped dojo, we need to expose dojo as a real global + //for the debugAtAllCosts stuff to work. + if(dojo._scopeName != "dojo"){ + window.dojo = window[dojo.config.scopeMap[0][1]]; + window.dijit = window[dojo.config.scopeMap[1][1]]; + window.dojox = window[dojo.config.scopeMap[2][1]]; + } + + dojo._xdDebugScopeChecked = true; + } + + var dbgQueue = dojo._xdDebugQueue; + + if(resourceName && resourceName == dbgQueue.currentResourceName){ + dbgQueue.shift(); + } + + if(dbgQueue.length == 0){ + //Check for more modules that need debug loading. + //dojo._xdWatchInFlight will add more things to the debug + //queue if they just recently loaded but it was not detected + //between the dojo._xdWatchInFlight intervals. + dojo._xdWatchInFlight(); + } + + if(dbgQueue.length == 0){ + dbgQueue.currentResourceName = null; + + //Make sure nothing else is in flight. + //If something is still in flight, then it still + //needs to be added to debug queue after it loads. + for(var param in dojo._xdInFlight){ + if(dojo._xdInFlight[param] === true){ + return; + } + } + + dojo._xdNotifyLoaded(); + }else{ + if(resourceName == dbgQueue.currentResourceName){ + dbgQueue.currentResourceName = dbgQueue[0].resourceName; + var element = document.createElement("script"); + element.type = "text/javascript"; + element.src = dbgQueue[0].resourcePath; + document.getElementsByTagName("head")[0].appendChild(element); + } + } } -}; + } diff --git a/lib/dojo/_base/_loader/loader_xd.js b/lib/dojo/_base/_loader/loader_xd.js index 2ecab3db6..c60b86b05 100644 --- a/lib/dojo/_base/_loader/loader_xd.js +++ b/lib/dojo/_base/_loader/loader_xd.js @@ -5,461 +5,719 @@ */ -if(!dojo._hasResource["dojo._base._loader.loader_xd"]){ -dojo._hasResource["dojo._base._loader.loader_xd"]=true; +if(!dojo._hasResource["dojo._base._loader.loader_xd"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo._base._loader.loader_xd"] = true; +//Cross-domain resource loader. dojo.provide("dojo._base._loader.loader_xd"); -dojo._xdReset=function(){ -dojo._isXDomain=dojo.config.useXDomain||false; -dojo._xdClearInterval(); -dojo._xdInFlight={}; -dojo._xdOrderedReqs=[]; -dojo._xdDepMap={}; -dojo._xdContents=[]; -dojo._xdDefList=[]; -}; -dojo._xdClearInterval=function(){ -if(dojo._xdTimer){ -clearInterval(dojo._xdTimer); -dojo._xdTimer=0; -} -}; -dojo._xdReset(); -dojo._xdCreateResource=function(_1,_2,_3){ -var _4=_1.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,""); -var _5=[]; -var _6=/dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg; -var _7; -while((_7=_6.exec(_4))!=null){ -if(_7[1]=="requireLocalization"){ -eval(_7[0]); -}else{ -_5.push("\""+_7[1]+"\", "+_7[2]); -} -} -var _8=[]; -_8.push(dojo._scopeName+"._xdResourceLoaded(function("+dojo._scopePrefixArgs+"){\n"); -var _9=dojo._xdExtractLoadInits(_1); -if(_9){ -_1=_9[0]; -for(var i=1;i<_9.length;i++){ -_8.push(_9[i]+";\n"); -} -} -_8.push("return {"); -if(_5.length>0){ -_8.push("depends: ["); -for(i=0;i<_5.length;i++){ -if(i>0){ -_8.push(",\n"); -} -_8.push("["+_5[i]+"]"); -} -_8.push("],"); -} -_8.push("\ndefineResource: function("+dojo._scopePrefixArgs+"){"); -if(!dojo.config["debugAtAllCosts"]||_2=="dojo._base._loader.loader_debug"){ -_8.push(_1); -} -_8.push("\n}, resourceName: '"+_2+"', resourcePath: '"+_3+"'};});"); -return _8.join(""); -}; -dojo._xdExtractLoadInits=function(_a){ -var _b=/dojo.loadInit\s*\(/g; -_b.lastIndex=0; -var _c=/[\(\)]/g; -_c.lastIndex=0; -var _d=[]; -var _e; -while((_e=_b.exec(_a))){ -_c.lastIndex=_b.lastIndex; -var _f=1; -var _10; -while((_10=_c.exec(_a))){ -if(_10[0]==")"){ -_f-=1; -}else{ -_f+=1; -} -if(_f==0){ -break; -} -} -if(_f!=0){ -throw "unmatched paren around character "+_c.lastIndex+" in: "+_a; -} -var _11=_b.lastIndex-_e[0].length; -_d.push(_a.substring(_11,_c.lastIndex)); -var _12=_c.lastIndex-_11; -_a=_a.substring(0,_11)+_a.substring(_c.lastIndex,_a.length); -_b.lastIndex=_c.lastIndex-_12; -_b.lastIndex=_c.lastIndex; -} -if(_d.length>0){ -_d.unshift(_a); -} -return (_d.length?_d:null); -}; -dojo._xdIsXDomainPath=function(_13){ -var _14=_13.indexOf(":"); -var _15=_13.indexOf("/"); -if(_14>0&&_14<_15){ -return true; -}else{ -var url=dojo.baseUrl; -_14=url.indexOf(":"); -_15=url.indexOf("/"); -if(_14>0&&_14<_15&&(!location.host||url.indexOf("http://"+location.host)!=0)){ -return true; -} -} -return false; -}; -dojo._loadPath=function(_16,_17,cb){ -var _18=dojo._xdIsXDomainPath(_16); -dojo._isXDomain|=_18; -var uri=((_16.charAt(0)=="/"||_16.match(/^\w+:/))?"":dojo.baseUrl)+_16; -try{ -return ((!_17||dojo._isXDomain)?dojo._loadUri(uri,cb,_18,_17):dojo._loadUriAndCheck(uri,_17,cb)); -} -catch(e){ -console.error(e); -return false; -} -}; -dojo._xdCharSet="utf-8"; -dojo._loadUri=function(uri,cb,_19,_1a){ -if(dojo._loadedUrls[uri]){ -return 1; -} -if(dojo._isXDomain&&_1a&&_1a!="dojo.i18n"){ -dojo._xdOrderedReqs.push(_1a); -if(_19||uri.indexOf("/nls/")==-1){ -dojo._xdInFlight[_1a]=true; -dojo._inFlightCount++; -} -if(!dojo._xdTimer){ -if(dojo.isAIR){ -dojo._xdTimer=setInterval(function(){ -dojo._xdWatchInFlight(); -},100); -}else{ -dojo._xdTimer=setInterval(dojo._scopeName+"._xdWatchInFlight();",100); -} -} -dojo._xdStartTime=(new Date()).getTime(); -} -if(_19){ -var _1b=uri.lastIndexOf("."); -if(_1b<=0){ -_1b=uri.length-1; -} -var _1c=uri.substring(0,_1b)+".xd"; -if(_1b!=uri.length-1){ -_1c+=uri.substring(_1b,uri.length); -} -if(dojo.isAIR){ -_1c=_1c.replace("app:/","/"); -} -var _1d=document.createElement("script"); -_1d.type="text/javascript"; -if(dojo._xdCharSet){ -_1d.charset=dojo._xdCharSet; -} -_1d.src=_1c; -if(!dojo.headElement){ -dojo._headElement=document.getElementsByTagName("head")[0]; -if(!dojo._headElement){ -dojo._headElement=document.getElementsByTagName("html")[0]; -} -} -dojo._headElement.appendChild(_1d); -}else{ -var _1e=dojo._getText(uri,null,true); -if(_1e==null){ -return 0; -} -if(dojo._isXDomain&&uri.indexOf("/nls/")==-1&&_1a!="dojo.i18n"){ -var res=dojo._xdCreateResource(_1e,_1a,uri); -dojo.eval(res); -}else{ -if(cb){ -_1e="("+_1e+")"; -}else{ -_1e=dojo._scopePrefix+_1e+dojo._scopeSuffix; -} -var _1f=dojo["eval"](_1e+"\r\n//@ sourceURL="+uri); -if(cb){ -cb(_1f); -} -} -} -dojo._loadedUrls[uri]=true; -dojo._loadedUrls.push(uri); -return true; -}; -dojo._xdResourceLoaded=function(res){ -res=res.apply(dojo.global,dojo._scopeArgs); -var _20=res.depends; -var _21=null; -var _22=null; -var _23=[]; -if(_20&&_20.length>0){ -var dep=null; -var _24=0; -var _25=false; -for(var i=0;i<_20.length;i++){ -dep=_20[i]; -if(dep[0]=="provide"){ -_23.push(dep[1]); -}else{ -if(!_21){ -_21=[]; -} -if(!_22){ -_22=[]; -} -var _26=dojo._xdUnpackDependency(dep); -if(_26.requires){ -_21=_21.concat(_26.requires); -} -if(_26.requiresAfter){ -_22=_22.concat(_26.requiresAfter); -} -} -var _27=dep[0]; -var _28=_27.split("."); -if(_28.length==2){ -dojo[_28[0]][_28[1]].apply(dojo[_28[0]],dep.slice(1)); -}else{ -dojo[_27].apply(dojo,dep.slice(1)); -} -} -if(_23.length==1&&_23[0]=="dojo._base._loader.loader_debug"){ -res.defineResource(dojo); -}else{ -var _29=dojo._xdContents.push({content:res.defineResource,resourceName:res["resourceName"],resourcePath:res["resourcePath"],isDefined:false})-1; -for(i=0;i<_23.length;i++){ -dojo._xdDepMap[_23[i]]={requires:_21,requiresAfter:_22,contentIndex:_29}; -} -} -for(i=0;i<_23.length;i++){ -dojo._xdInFlight[_23[i]]=false; -} -} -}; -dojo._xdLoadFlattenedBundle=function(_2a,_2b,_2c,_2d){ -_2c=_2c||"root"; -var _2e=dojo.i18n.normalizeLocale(_2c).replace("-","_"); -var _2f=[_2a,"nls",_2b].join("."); -var _30=dojo["provide"](_2f); -_30[_2e]=_2d; -var _31=[_2a,_2e,_2b].join("."); -var _32=dojo._xdBundleMap[_31]; -if(_32){ -for(var _33 in _32){ -_30[_33]=_2d; -} -} -}; -dojo._xdInitExtraLocales=function(){ -var _34=dojo.config.extraLocale; -if(_34){ -if(!_34 instanceof Array){ -_34=[_34]; -} -dojo._xdReqLoc=dojo.xdRequireLocalization; -dojo.xdRequireLocalization=function(m,b,_35,_36){ -dojo._xdReqLoc(m,b,_35,_36); -if(_35){ -return; -} -for(var i=0;i<_34.length;i++){ -dojo._xdReqLoc(m,b,_34[i],_36); -} -}; -} -}; -dojo._xdBundleMap={}; -dojo.xdRequireLocalization=function(_37,_38,_39,_3a){ -if(dojo._xdInitExtraLocales){ -dojo._xdInitExtraLocales(); -dojo._xdInitExtraLocales=null; -dojo.xdRequireLocalization.apply(dojo,arguments); -return; -} -var _3b=_3a.split(","); -var _3c=dojo.i18n.normalizeLocale(_39); -var _3d=""; -for(var i=0;i<_3b.length;i++){ -if(_3c.indexOf(_3b[i])==0){ -if(_3b[i].length>_3d.length){ -_3d=_3b[i]; -} -} -} -var _3e=_3d.replace("-","_"); -var _3f=dojo.getObject([_37,"nls",_38].join(".")); -if(!_3f||!_3f[_3e]){ -var _40=[_37,(_3e||"root"),_38].join("."); -var _41=dojo._xdBundleMap[_40]; -if(!_41){ -_41=dojo._xdBundleMap[_40]={}; -} -_41[_3c.replace("-","_")]=true; -dojo.require(_37+".nls"+(_3d?"."+_3d:"")+"."+_38); -} -}; -dojo._xdRealRequireLocalization=dojo.requireLocalization; -dojo.requireLocalization=function(_42,_43,_44,_45){ -var _46=dojo.moduleUrl(_42).toString(); -if(dojo._xdIsXDomainPath(_46)){ -return dojo.xdRequireLocalization.apply(dojo,arguments); -}else{ -return dojo._xdRealRequireLocalization.apply(dojo,arguments); -} -}; -dojo._xdUnpackDependency=function(dep){ -var _47=null; -var _48=null; -switch(dep[0]){ -case "requireIf": -case "requireAfterIf": -if(dep[1]===true){ -_47=[{name:dep[2],content:null}]; -} -break; -case "platformRequire": -var _49=dep[1]; -var _4a=_49["common"]||[]; -_47=(_49[dojo.hostenv.name_])?_4a.concat(_49[dojo.hostenv.name_]||[]):_4a.concat(_49["default"]||[]); -if(_47){ -for(var i=0;i<_47.length;i++){ -if(_47[i] instanceof Array){ -_47[i]={name:_47[i][0],content:null}; -}else{ -_47[i]={name:_47[i],content:null}; -} -} -} -break; -case "require": -_47=[{name:dep[1],content:null}]; -break; -case "i18n._preloadLocalizations": -dojo.i18n._preloadLocalizations.apply(dojo.i18n._preloadLocalizations,dep.slice(1)); -break; -} -if(dep[0]=="requireAfterIf"||dep[0]=="requireIf"){ -_48=_47; -_47=null; -} -return {requires:_47,requiresAfter:_48}; -}; -dojo._xdWalkReqs=function(){ -var _4b=null; -var req; -for(var i=0;i0){ -var req=_4c[_4c.length-1]; -var res=dojo._xdDepMap[req]; -var i,_4d,_4e; -if(res){ -_4d=res.requires; -if(_4d&&_4d.length>0){ -for(i=0;i<_4d.length;i++){ -_4e=_4d[i].name; -if(_4e&&!_4c[_4e]){ -_4c.push(_4e); -_4c[_4e]=true; -dojo._xdEvalReqs(_4c); -} + +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. + dojo._isXDomain = dojo.config.useXDomain || false; + + dojo._xdClearInterval(); + dojo._xdInFlight = {}; + dojo._xdOrderedReqs = []; + dojo._xdDepMap = {}; + dojo._xdContents = []; + dojo._xdDefList = []; } + +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. + if(dojo._xdTimer){ + clearInterval(dojo._xdTimer); + dojo._xdTimer = 0; + } } -var _4f=dojo._xdContents[res.contentIndex]; -if(!_4f.isDefined){ -var _50=_4f.content; -_50["resourceName"]=_4f["resourceName"]; -_50["resourcePath"]=_4f["resourcePath"]; -dojo._xdDefList.push(_50); -_4f.isDefined=true; + + +//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)\s*\(([\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(function(" + dojo._scopePrefixArgs + "){\n"); + + //See if there are any dojo.loadInit calls + var loadInitCalls = dojo._xdExtractLoadInits(contents); + if(loadInitCalls){ + //Adjust fileContents since extractLoadInits removed something. + contents = loadInitCalls[0]; + + //Add any loadInit calls to the top of the xd file. + for(var i = 1; i < loadInitCalls.length; i++){ + output.push(loadInitCalls[i] + ";\n"); + } + } + + output.push("return {"); + + //Add dependencies + if(deps.length > 0){ + output.push("depends: ["); + for(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._xdDepMap[req]=null; -_4d=res.requiresAfter; -if(_4d&&_4d.length>0){ -for(i=0;i<_4d.length;i++){ -_4e=_4d[i].name; -if(_4e&&!_4c[_4e]){ -_4c.push(_4e); -_4c[_4e]=true; -dojo._xdEvalReqs(_4c); + +dojo._xdExtractLoadInits = function(/*String*/fileContents){ + //Extracts + var regexp = /dojo.loadInit\s*\(/g; + regexp.lastIndex = 0; + + var parenRe = /[\(\)]/g; + parenRe.lastIndex = 0; + + var results = []; + var matches; + while((matches = regexp.exec(fileContents))){ + //Find end of the call by finding the matching end paren + parenRe.lastIndex = regexp.lastIndex; + var matchCount = 1; + var parenMatch; + while((parenMatch = parenRe.exec(fileContents))){ + if(parenMatch[0] == ")"){ + matchCount -= 1; + }else{ + matchCount += 1; + } + if(matchCount == 0){ + break; + } + } + + if(matchCount != 0){ + throw "unmatched paren around character " + parenRe.lastIndex + " in: " + fileContents; + } + + //Put the master matching string in the results. + var startIndex = regexp.lastIndex - matches[0].length; + results.push(fileContents.substring(startIndex, parenRe.lastIndex)); + + //Remove the matching section. + var remLength = parenRe.lastIndex - startIndex; + fileContents = fileContents.substring(0, startIndex) + fileContents.substring(parenRe.lastIndex, fileContents.length); + + //Move the master regexp past the last matching paren point. + regexp.lastIndex = parenRe.lastIndex - remLength; + + regexp.lastIndex = parenRe.lastIndex; + } + + if(results.length > 0){ + results.unshift(fileContents); + } + + return (results.length ? results : null); } + +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 = dojo.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 = dojo._xdIsXDomainPath(relpath); + dojo._isXDomain |= currentIsXDomain; + + var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : dojo.baseUrl) + relpath; + + try{ + return ((!module || dojo._isXDomain) ? dojo._loadUri(uri, cb, currentIsXDomain, module) : dojo._loadUriAndCheck(uri, module, cb)); //Boolean + }catch(e){ + console.error(e); + return false; //Boolean + } } + +dojo._xdCharSet = "utf-8"; + +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(dojo._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(dojo._isXDomain && module && module != "dojo.i18n"){ + dojo._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){ + dojo._xdInFlight[module] = true; + + //Increment inFlightCount + //This will stop the modulesLoaded from firing all the way. + dojo._inFlightCount++; + } + + //Start timer + if(!dojo._xdTimer){ + if(dojo.isAIR){ + dojo._xdTimer = setInterval(function(){dojo._xdWatchInFlight();}, 100); + }else{ + dojo._xdTimer = setInterval(dojo._scopeName + "._xdWatchInFlight();", 100); + } + } + dojo._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"; + if(dojo._xdCharSet){ + element.charset = dojo._xdCharSet; + } + element.src = xdUri; + if(!dojo.headElement){ + dojo._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(!dojo._headElement){ + dojo._headElement = document.getElementsByTagName("html")[0]; + } + } + dojo._headElement.appendChild(element); + }else{ + var contents = dojo._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(dojo._isXDomain + && uri.indexOf("/nls/") == -1 + && module != "dojo.i18n"){ + var res = dojo._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 = dojo._scopePrefix + contents + dojo._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. + dojo._loadedUrls[uri] = true; + dojo._loadedUrls.push(uri); + return true; //Boolean } -_4c.pop(); + +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. + + //Evaluate the function with scopeArgs for multiversion support. + res = res.apply(dojo.global, dojo._scopeArgs); + + //Work through dependencies. + 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 = dojo._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 = dojo._xdContents.push({ + content: res.defineResource, + resourceName: res["resourceName"], + resourcePath: res["resourcePath"], + isDefined: false + }) - 1; + + //Add provide/requires to dependency map. + for(i = 0; i < provideList.length; i++){ + dojo._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(i = 0; i < provideList.length; i++){ + dojo._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._xdWatchInFlight=function(){ -var _51=""; -var _52=(dojo.config.xdWaitSeconds||15)*1000; -var _53=(dojo._xdStartTime+_52)<(new Date()).getTime(); -for(var _54 in dojo._xdInFlight){ -if(dojo._xdInFlight[_54]===true){ -if(_53){ -_51+=_54+" "; -}else{ -return; -} -} -} -dojo._xdClearInterval(); -if(_53){ -throw "Could not load cross-domain resources: "+_51; -} -dojo._xdWalkReqs(); -var _55=dojo._xdDefList.length; -for(var i=0;i<_55;i++){ -var _56=dojo._xdDefList[i]; -if(dojo.config["debugAtAllCosts"]&&_56["resourceName"]){ -if(!dojo["_xdDebugQueue"]){ -dojo._xdDebugQueue=[]; -} -dojo._xdDebugQueue.push({resourceName:_56.resourceName,resourcePath:_56.resourcePath}); -}else{ -_56.apply(dojo.global,dojo._scopeArgs); + + +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 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]){ + //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); + } } -for(i=0;i0){ -dojo._xdDebugFileLoaded(); -}else{ -dojo._xdNotifyLoaded(); + +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 < dojo._xdOrderedReqs.length; i++){ + req = dojo._xdOrderedReqs[i]; + if(dojo._xdDepMap[req]){ + reqChain = [req]; + reqChain[req] = true; //Allow for fast lookup of the req in the array + dojo._xdEvalReqs(reqChain); + } + } } -}; -dojo._xdNotifyLoaded=function(){ -for(var _58 in dojo._xdInFlight){ -if(typeof dojo._xdInFlight[_58]=="boolean"){ -return; + +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 = dojo._xdDepMap[req]; + var i, reqs, nextReq; + if(res){ + //Trace down any requires for this resource. + //START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack + reqs = res.requires; + if(reqs && reqs.length > 0){ + for(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; + dojo._xdEvalReqs(reqChain); + } + } + } + //END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack + + //Evaluate the resource. + var contents = dojo._xdContents[res.contentIndex]; + if(!contents.isDefined){ + var content = contents.content; + content["resourceName"] = contents["resourceName"]; + content["resourcePath"] = contents["resourcePath"]; + dojo._xdDefList.push(content); + contents.isDefined = true; + } + dojo._xdDepMap[req] = null; + + //Trace down any requireAfters for this resource. + //START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack + reqs = res.requiresAfter; + if(reqs && reqs.length > 0){ + for(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; + dojo._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._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 = (dojo._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 dojo._xdInFlight){ + if(dojo._xdInFlight[param] === true){ + if(expired){ + noLoads += param + " "; + }else{ + return; + } + } + } + + //All done. Clean up and notify. + dojo._xdClearInterval(); + + if(expired){ + throw "Could not load cross-domain resources: " + noLoads; + } + + dojo._xdWalkReqs(); + + var defLength = dojo._xdDefList.length; + for(var i= 0; i < defLength; i++){ + var content = dojo._xdDefList[i]; + if(dojo.config["debugAtAllCosts"] && content["resourceName"]){ + if(!dojo["_xdDebugQueue"]){ + dojo._xdDebugQueue = []; + } + dojo._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(i = 0; i < dojo._xdContents.length; i++){ + var current = dojo._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. + dojo._xdReset(); + + if(dojo["_xdDebugQueue"] && dojo._xdDebugQueue.length > 0){ + dojo._xdDebugFileLoaded(); + }else{ + dojo._xdNotifyLoaded(); + } } -dojo._inFlightCount=0; -if(dojo._initFired&&!dojo._loadNotifying){ -dojo._callLoaded(); + +dojo._xdNotifyLoaded = function(){ + //Clear inflight count so we will finally do finish work. + + //Just having a legitimate status (true or false) for an inflight item + //means that it is still being processed. Do the typeof test + //to avoid bad JavaScript that might tinker with Object.prototype. + for(var prop in dojo._xdInFlight){ + if(typeof dojo._xdInFlight[prop] == "boolean"){ + return; + } + } + + dojo._inFlightCount = 0; + + //Only trigger call loaded if dj_load_init has run. + if(dojo._initFired && !dojo._loadNotifying){ + dojo._callLoaded(); + } } -}; + } -- cgit v1.2.3