commit 3d569f117326ab9bf880cfe877b83d4f1f0ad754
parent 7e30afb2a56b8c4296548fd6782619ae0719c612
Author: Dan Stillman <dstillman@zotero.org>
Date: Sat, 14 Jan 2017 18:01:51 -0500
Compatibility fixes for Bluebird >=3.4.2
Before 3.4.2, `yield` in a Bluebird `coroutine()` released Zalgo if an
already-resolved promise (e.g., from `Promise.resolve()`) was yielded,
continuing immediately instead of on the next turn of the event loop. We
apparently relied on that broken behavior in a few places, particularly from
`Zotero.DB.waitForTransaction()`. All the transaction-queueing stuff probably
needs to be reevaluated in general, but for now, mirror the previous possibly
ill-advised behavior by checking explicitly for a transaction before yielding
on `waitForTransaction()` (as well as the result of a 'load' event from
`libraryTreeView`).
Diffstat:
4 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/chrome/content/zotero/browser.js b/chrome/content/zotero/browser.js
@@ -605,7 +605,7 @@ var Zotero_Browser = new function() {
return;
}
- if (!Zotero.isConnector) {
+ if (!Zotero.isConnector && Zotero.DB.inTransaction()) {
yield Zotero.DB.waitForTransaction();
}
diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js
@@ -953,7 +953,9 @@ Zotero.DBConnection.prototype.backupDatabase = Zotero.Promise.coroutine(function
// Start a promise that will be resolved when the backup is finished
var resolveBackupPromise;
- yield this.waitForTransaction();
+ if (this.inTransaction()) {
+ yield this.waitForTransaction();
+ }
this._backupPromise = new Zotero.Promise(function () {
resolveBackupPromise = arguments[0];
});
diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js
@@ -1010,8 +1010,9 @@ Zotero.Schema = new function(){
return;
}
- // If transaction already in progress, delay by ten minutes
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
// Get the last timestamp we got from the server
var lastUpdated = yield this.getDBVersion('repository');
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
@@ -947,7 +947,9 @@ var ZoteroPane = new function()
this.newSearch = Zotero.Promise.coroutine(function* () {
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
var s = new Zotero.Search();
s.libraryID = this.getSelectedLibraryID();
@@ -1011,7 +1013,9 @@ var ZoteroPane = new function()
this.openLookupWindow = Zotero.Promise.coroutine(function* () {
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
if (!this.canEdit()) {
this.displayCannotEditLibraryMessage();
@@ -1379,8 +1383,10 @@ var ZoteroPane = new function()
* be a better test for whether the item pane changed)
*/
this.itemSelected = function (event) {
- return Zotero.spawn(function* () {
- yield Zotero.DB.waitForTransaction();
+ return Zotero.Promise.coroutine(function* () {
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
// Don't select item until items list has loaded
//
@@ -1389,7 +1395,9 @@ var ZoteroPane = new function()
this.itemsView.addEventListener('load', function () {
deferred.resolve();
});
- yield deferred.promise;
+ if (deferred.promise.isPending()) {
+ yield deferred.promise;
+ }
if (!this.itemsView || !this.itemsView.selection) {
Zotero.debug("Items view not available in itemSelected", 2);
@@ -1592,7 +1600,7 @@ var ZoteroPane = new function()
}
return true;
- }, this)
+ }.bind(this))()
.finally(function () {
return this.itemsView.onSelect();
}.bind(this));
@@ -3686,7 +3694,9 @@ var ZoteroPane = new function()
//
// Duplicate newItem() checks here
//
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
// Currently selected row
if (row === undefined && this.collectionsView && this.collectionsView.selection) {
@@ -3806,7 +3816,9 @@ var ZoteroPane = new function()
//
// Duplicate newItem() checks here
//
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
// Currently selected row
if (row === undefined) {
@@ -3894,7 +3906,9 @@ var ZoteroPane = new function()
* |link| -- create web link instead of snapshot
*/
this.addAttachmentFromPage = Zotero.Promise.coroutine(function* (link, itemID) {
- yield Zotero.DB.waitForTransaction();
+ if (Zotero.DB.inTransaction()) {
+ yield Zotero.DB.waitForTransaction();
+ }
if (typeof itemID != 'number') {
throw new Error("itemID must be an integer");