diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index fec534de72..806e8beb15 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -246,10 +246,8 @@ Zotero.HTTP = new function() { // Don't cache GET requests xmlhttp.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone, responseCharset); }; @@ -334,10 +332,8 @@ Zotero.HTTP = new function() { xmlhttp.setRequestHeader(header, headers[header]); } - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone, responseCharset); }; @@ -398,10 +394,8 @@ Zotero.HTTP = new function() { // Don't cache HEAD requests xmlhttp.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone); }; @@ -437,10 +431,8 @@ Zotero.HTTP = new function() { xmlhttp.mozBackgroundRequest = true; xmlhttp.open('OPTIONS', uri.spec, true); - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); @@ -479,10 +471,8 @@ Zotero.HTTP = new function() { xmlhttp.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, function (xmlhttp) { Zotero.debug("Proxy auth request completed with status " + xmlhttp.status + ": " + xmlhttp.responseText); @@ -558,10 +548,8 @@ Zotero.HTTP = new function() { xmlhttp.setRequestHeader("Content-Type", 'text/xml; charset="utf-8"'); - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; @@ -594,10 +582,8 @@ Zotero.HTTP = new function() { // Prevent certificate/authentication dialogs from popping up xmlhttp.mozBackgroundRequest = true; xmlhttp.open('MKCOL', uri.spec, true); - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); @@ -639,10 +625,8 @@ Zotero.HTTP = new function() { // with Content-Length: 0, which triggers a "no element found" error // in Firefox, so we override to text xmlhttp.overrideMimeType("text/plain"); - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(body); @@ -678,10 +662,8 @@ Zotero.HTTP = new function() { // Firefox 3 throws a "no element found" error even with a // 204 ("No Content") response, so we override to text xmlhttp.overrideMimeType("text/plain"); - var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { - Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 70c786e179..6dc724552f 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -186,28 +186,20 @@ Components.utils.import("resource://gre/modules/Services.jsm"); // whether we are waiting for another Zotero process to release its DB lock var _waitingForDBLock = false; - /** - * Maintains nsITimers to be used when Zotero.wait() completes (to reduce performance penalty - * of initializing new objects) - */ - var _waitTimers = []; - /** * Maintains nsITimerCallbacks to be used when Zotero.wait() completes */ var _waitTimerCallbacks = []; - /** - * Maintains running nsITimers in global scope, so that they don't disappear randomly - */ - var _runningTimers = []; - // Errors that were in the console at startup var _startupErrors = []; // Number of errors to maintain in the recent errors buffer const ERROR_BUFFER_SIZE = 25; // A rolling buffer of the last ERROR_BUFFER_SIZE errors var _recentErrors = []; + + // The hidden DOM window + var _hiddenDOMWindow; /** * Initialize the extension @@ -247,14 +239,12 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } // OS platform - var win = Components.classes["@mozilla.org/appshell/appShellService;1"] - .getService(Components.interfaces.nsIAppShellService) - .hiddenDOMWindow; - this.platform = win.navigator.platform; + _hiddenDOMWindow = Services.appShell.hiddenDOMWindow; + this.platform = _hiddenDOMWindow.navigator.platform; this.isMac = (this.platform.substr(0, 3) == "Mac"); this.isWin = (this.platform.substr(0, 3) == "Win"); this.isLinux = (this.platform.substr(0, 5) == "Linux"); - this.oscpu = win.navigator.oscpu; + this.oscpu = _hiddenDOMWindow.navigator.oscpu; // Browser Zotero.browser = "g"; @@ -1521,10 +1511,9 @@ Components.utils.import("resource://gre/modules/Services.jsm"); _waiting--; // requeue nsITimerCallbacks that came up during Zotero.wait() but couldn't execute - for(var i in _waitTimers) { - _waitTimers[i].initWithCallback(_waitTimerCallbacks[i], 0, Components.interfaces.nsITimer.TYPE_ONE_SHOT); + for(var i=0; i<_waitTimerCallbacks.length; i++) { + Zotero.setTimeout(_waitTimerCallbacks[i], 0); } - _waitTimers = []; _waitTimerCallbacks = []; //Zotero.debug("Waited " + cycles + " cycles"); @@ -1540,13 +1529,8 @@ Components.utils.import("resource://gre/modules/Services.jsm"); this.pumpGenerator = function(generator, ms, errorHandler, doneHandler) { _waiting++; - var timer = Components.classes["@mozilla.org/timer;1"]. - createInstance(Components.interfaces.nsITimer), - yielded, - useJIT = Components.utils.methodjit; - var timerCallback = {"notify":function() { - Components.utils.methodjit = useJIT; - + var yielded; + var interval = _hiddenDOMWindow.setInterval(function() { var err = false; _waiting--; try { @@ -1560,14 +1544,12 @@ Components.utils.import("resource://gre/modules/Services.jsm"); err = e; } - timer.cancel(); - _runningTimers.splice(_runningTimers.indexOf(timer), 1); + _hiddenDOMWindow.clearInterval(interval); // requeue nsITimerCallbacks that came up during generator pumping but couldn't execute - for(var i in _waitTimers) { - _waitTimers[i].initWithCallback(_waitTimerCallbacks[i], 0, Components.interfaces.nsITimer.TYPE_ONE_SHOT); + for(var i=0; i<_waitTimerCallbacks.length; i++) { + Zotero.setTimeout(_waitTimerCallbacks[i], 0); } - _waitTimers = []; _waitTimerCallbacks = []; if(err) { @@ -1579,10 +1561,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } else if(doneHandler) { doneHandler(yielded); } - }} - timer.initWithCallback(timerCallback, ms ? ms : 0, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); - // add timer to global scope so that it doesn't get garbage collected before it completes - _runningTimers.push(timer); + }, 0); }; /** @@ -1606,27 +1585,17 @@ Components.utils.import("resource://gre/modules/Services.jsm"); * is executing */ this.setTimeout = function(func, ms, runWhenWaiting) { - var timer = Components.classes["@mozilla.org/timer;1"]. - createInstance(Components.interfaces.nsITimer), - useJIT = Components.utils.methodjit; - var timerCallback = {"notify":function() { - Components.utils.methodjit = useJIT; - + var timerCallback = function() { if(_waiting && !runWhenWaiting) { // if our callback gets called during Zotero.wait(), queue it to be set again // when Zotero.wait() completes - _waitTimers.push(timer); _waitTimerCallbacks.push(timerCallback); } else { // execute callback function func(); - // remove timer from global scope, so it can be garbage collected - _runningTimers.splice(_runningTimers.indexOf(timer), 1); } - }} - timer.initWithCallback(timerCallback, ms, Components.interfaces.nsITimer.TYPE_ONE_SHOT); - // add timer to global scope so that it doesn't get garbage collected before it completes - _runningTimers.push(timer); + }; + _hiddenDOMWindow.setTimeout(timerCallback, ms); } /** diff --git a/resource/q.js b/resource/q.js index 029b5beddc..b2b94d1325 100644 --- a/resource/q.js +++ b/resource/q.js @@ -58,49 +58,11 @@ // Mozilla JSM } else if (~String(this).indexOf('BackstagePass')) { EXPORTED_SYMBOLS = ["Q"]; + Components.utils.import("resource://gre/modules/Services.jsm"); + var hiddenDOMWindow = Services.appShell.hiddenDOMWindow; // Q expects an implementation of setTimeout - setTimeout = new function() { - // We need to maintain references to running nsITimers. Otherwise, they can - // get garbage collected before they fire. - var _runningTimers = []; - - return function setTimeout(func, ms) { - var useMethodjit = Components.utils.methodjit, - timer = Components.classes["@mozilla.org/timer;1"]. - createInstance(Components.interfaces.nsITimer); - timer.initWithCallback({"notify":function() { - Components.utils.methodjit = useMethodjit; - - // Remove timer from array so it can be garbage collected - _runningTimers.splice(_runningTimers.indexOf(timer), 1); - - // Execute callback function - try { - func(); - } catch(err) { - // Rethrow errors that occur so that they appear in the error - // console with the appropriate name and line numbers. While the - // the errors appear without this, the line numbers get eaten. - var scriptError = Components.classes["@mozilla.org/scripterror;1"] - .createInstance(Components.interfaces.nsIScriptError); - scriptError.init( - err.message || err.toString(), - err.fileName || err.filename || null, - null, - err.lineNumber || null, - null, - scriptError.errorFlag, - 'component javascript' - ); - Components.classes["@mozilla.org/consoleservice;1"] - .getService(Components.interfaces.nsIConsoleService) - .logMessage(scriptError); - } - }}, ms, Components.interfaces.nsITimer.TYPE_ONE_SHOT); - _runningTimers.push(timer); - } - }; + setTimeout = hiddenDOMWindow.setTimeout; Q = definition(); //