www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit da4e7dd4f165d5cd52156d0367ea032e203544f4
parent aecdf99482134788a17db31a698f87ee29e3178b
Author: Simon Kornblith <simon@simonster.com>
Date:   Thu, 13 Jun 2013 14:20:06 -0400

Merge branch '4.0'

Diffstat:
Mchrome/content/zotero/browser.js | 13++++++++-----
Mchrome/content/zotero/xpcom/http.js | 27+++++++++++++++++++++++++++
Mchrome/content/zotero/xpcom/translation/translator.js | 2+-
Mchrome/content/zotero/xpcom/zotero.js | 67++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mresource/q.js | 45++++++++++++++++++++++++++++++++++++++++++---
5 files changed, 128 insertions(+), 26 deletions(-)

diff --git a/chrome/content/zotero/browser.js b/chrome/content/zotero/browser.js @@ -812,11 +812,14 @@ Zotero_Browser.Tab.prototype._translatorsAvailable = function(translate, transla //this set of translators is not targeting the same URL as a previous set of translators, // because otherwise we want to use the newer set && this.page.document.location.href != translate.document.location.href - //the previous set of translators targets the top frame or the current one does not either - && (this.page.document.defaultView == this.page.document.defaultView.top - || translate.document.defaultView !== this.page.document.defaultView.top) - //the best translator we had was of higher priority than the new set - && this.page.translators[0].priority <= translators[0].priority + //the best translator we had was of higher priority than the new set + && (this.page.translators[0].priority < translators[0].priority + //or the priority was the same, but... + || (this.page.translators[0].priority == translators[0].priority + //the previous set of translators targets the top frame or the current one does not either + && (this.page.document.defaultView == this.page.document.defaultView.top + || translate.document.defaultView !== this.page.document.defaultView.top) + )) ) { return; //keep what we had } else { diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js @@ -246,8 +246,11 @@ 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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone, responseCharset); }; @@ -332,8 +335,11 @@ Zotero.HTTP = new function() { xmlhttp.setRequestHeader(header, headers[header]); } + var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone, responseCharset); }; @@ -394,8 +400,11 @@ 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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, onDone); }; @@ -431,8 +440,11 @@ Zotero.HTTP = new function() { xmlhttp.mozBackgroundRequest = true; xmlhttp.open('OPTIONS', uri.spec, true); + var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); @@ -471,8 +483,11 @@ Zotero.HTTP = new function() { xmlhttp.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; + var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, function (xmlhttp) { Zotero.debug("Proxy auth request completed with status " + xmlhttp.status + ": " + xmlhttp.responseText); @@ -548,8 +563,11 @@ Zotero.HTTP = new function() { xmlhttp.setRequestHeader("Content-Type", 'text/xml; charset="utf-8"'); + var useMethodjit = Components.utils.methodjit; /** @ignore */ xmlhttp.onreadystatechange = function() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; @@ -582,8 +600,11 @@ 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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); @@ -625,8 +646,11 @@ 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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(body); @@ -662,8 +686,11 @@ 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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) Components.utils.methodjit = useMethodjit; _stateChange(xmlhttp, callback); }; xmlhttp.send(null); diff --git a/chrome/content/zotero/xpcom/translation/translator.js b/chrome/content/zotero/xpcom/translation/translator.js @@ -63,7 +63,7 @@ Zotero.Translators = new function() { while(contents.hasMoreElements()) { var file = contents.getNext().QueryInterface(Components.interfaces.nsIFile); var leafName = file.leafName; - if(!leafName || leafName[0] == ".") continue; + if(!(/[^.].*\.js/.test(leafName))) continue; var lastModifiedTime = file.lastModifiedTime; var dbCacheEntry = false; diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js @@ -184,19 +184,27 @@ Components.utils.import("resource://gre/modules/Services.jsm"); 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 @@ -226,12 +234,14 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } // OS platform - _hiddenDOMWindow = Services.appShell.hiddenDOMWindow; - this.platform = _hiddenDOMWindow.navigator.platform; + var win = Components.classes["@mozilla.org/appshell/appShellService;1"] + .getService(Components.interfaces.nsIAppShellService) + .hiddenDOMWindow; + this.platform = win.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 = _hiddenDOMWindow.navigator.oscpu; + this.oscpu = win.navigator.oscpu; // Browser Zotero.browser = "g"; @@ -1466,9 +1476,10 @@ Components.utils.import("resource://gre/modules/Services.jsm"); _waiting--; // requeue nsITimerCallbacks that came up during Zotero.wait() but couldn't execute - for(var i=0; i<_waitTimerCallbacks.length; i++) { - Zotero.setTimeout(_waitTimerCallbacks[i], 0); + for(var i in _waitTimers) { + _waitTimers[i].initWithCallback(_waitTimerCallbacks[i], 0, Components.interfaces.nsITimer.TYPE_ONE_SHOT); } + _waitTimers = []; _waitTimerCallbacks = []; //Zotero.debug("Waited " + cycles + " cycles"); @@ -1484,8 +1495,14 @@ Components.utils.import("resource://gre/modules/Services.jsm"); this.pumpGenerator = function(generator, ms, errorHandler, doneHandler) { _waiting++; - var yielded; - var interval = _hiddenDOMWindow.setInterval(function() { + var timer = Components.classes["@mozilla.org/timer;1"]. + createInstance(Components.interfaces.nsITimer), + yielded, + useJIT = Components.utils.methodjit; + var timerCallback = {"notify":function() { + // XXX Remove when we drop support for Fx <24 + if(useJIT !== undefined) Components.utils.methodjit = useJIT; + var err = false; _waiting--; try { @@ -1499,12 +1516,14 @@ Components.utils.import("resource://gre/modules/Services.jsm"); err = e; } - _hiddenDOMWindow.clearInterval(interval); + timer.cancel(); + _runningTimers.splice(_runningTimers.indexOf(timer), 1); // requeue nsITimerCallbacks that came up during generator pumping but couldn't execute - for(var i=0; i<_waitTimerCallbacks.length; i++) { - Zotero.setTimeout(_waitTimerCallbacks[i], 0); + for(var i in _waitTimers) { + _waitTimers[i].initWithCallback(_waitTimerCallbacks[i], 0, Components.interfaces.nsITimer.TYPE_ONE_SHOT); } + _waitTimers = []; _waitTimerCallbacks = []; if(err) { @@ -1516,7 +1535,10 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } else if(doneHandler) { doneHandler(yielded); } - }, 0); + }} + 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); }; /** @@ -1540,17 +1562,28 @@ Components.utils.import("resource://gre/modules/Services.jsm"); * is executing */ this.setTimeout = function(func, ms, runWhenWaiting) { - var timerCallback = function() { + var timer = Components.classes["@mozilla.org/timer;1"]. + createInstance(Components.interfaces.nsITimer), + useJIT = Components.utils.methodjit; + var timerCallback = {"notify":function() { + // XXX Remove when we drop support for Fx <24 + if(useJIT !== undefined) Components.utils.methodjit = useJIT; + 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); } - }; - _hiddenDOMWindow.setTimeout(timerCallback, ms); + }} + 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); } /** diff --git a/resource/q.js b/resource/q.js @@ -58,11 +58,50 @@ // 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 = hiddenDOMWindow.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() { + // XXX Remove when we drop support for Fx <24 + if(useMethodjit !== undefined) 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); + } + }; Q = definition(); // <script>