From 3d569f117326ab9bf880cfe877b83d4f1f0ad754 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 14 Jan 2017 18:01:51 -0500 Subject: [PATCH] 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`). --- chrome/content/zotero/browser.js | 2 +- chrome/content/zotero/xpcom/db.js | 4 +++- chrome/content/zotero/xpcom/schema.js | 5 +++-- chrome/content/zotero/zoteroPane.js | 32 +++++++++++++++++++-------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/chrome/content/zotero/browser.js b/chrome/content/zotero/browser.js index 96695a22c..20acf816f 100644 --- 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 index 77d31b9dd..e63ba7ab7 100644 --- 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 index 02e9ffd71..c6425416d 100644 --- 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 index b3b044b1a..fd6f30279 100644 --- 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");