commit da4e7dd4f165d5cd52156d0367ea032e203544f4
parent aecdf99482134788a17db31a698f87ee29e3178b
Author: Simon Kornblith <simon@simonster.com>
Date: Thu, 13 Jun 2013 14:20:06 -0400
Merge branch '4.0'
Diffstat:
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>