diff options
author | Andrew Dolgov <[email protected]> | 2011-03-04 19:02:28 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-03-04 19:02:59 +0300 |
commit | a089699c8915636ba4f158d77dba9b012bc93208 (patch) | |
tree | b2d7d051f1f55d44a6be07d3ee137e5a7ccfcefb /lib/dojo/_base/_loader/hostenv_ff_ext.js | |
parent | cfad9259a6feacfa8194b1312770ae6db1ecce50 (diff) |
build custom layer of Dojo to speed up loading of tt-rss (refs #293)
Diffstat (limited to 'lib/dojo/_base/_loader/hostenv_ff_ext.js')
-rw-r--r-- | lib/dojo/_base/_loader/hostenv_ff_ext.js | 491 |
1 files changed, 327 insertions, 164 deletions
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? } |