diff --git a/chrome/content/zotero/tools/testTranslators/testTranslators.js b/chrome/content/zotero/tools/testTranslators/testTranslators.js index bd170febe..f91b8de6f 100644 --- a/chrome/content/zotero/tools/testTranslators/testTranslators.js +++ b/chrome/content/zotero/tools/testTranslators/testTranslators.js @@ -24,8 +24,9 @@ */ const NUM_CONCURRENT_TESTS = 6; -const TRANSLATOR_TYPES = ["Web", "Import", "Export", "Search"]; const TABLE_COLUMNS = ["Translator", "Supported", "Status", "Pending", "Succeeded", "Failed", "Mismatch", "Issues"]; +// Not using const to prevent const collisions in connectors +var TRANSLATOR_TYPES = ["Web", "Import", "Export", "Search"]; var translatorTables = {}, translatorTestViews = {}, translatorTestViewsToRun = {}, diff --git a/chrome/content/zotero/tools/testTranslators/translatorTester.js b/chrome/content/zotero/tools/testTranslators/translatorTester.js index cbeab693d..298f16815 100644 --- a/chrome/content/zotero/tools/testTranslators/translatorTester.js +++ b/chrome/content/zotero/tools/testTranslators/translatorTester.js @@ -36,7 +36,7 @@ try { var Zotero; } -Zotero_TranslatorTesters = new function() { +var Zotero_TranslatorTesters = new function() { const TEST_TYPES = ["web", "import", "export", "search"]; var collectedResults = {}; @@ -190,7 +190,7 @@ Zotero_TranslatorTesters = new function() { * @param {Function} [debugCallback] A function to call to write debug output. If not present, * Zotero.debug will be used. */ -Zotero_TranslatorTester = function(translator, type, debugCallback) { +var Zotero_TranslatorTester = function(translator, type, debugCallback) { this.type = type; this.translator = translator; this.output = ""; diff --git a/chrome/content/zotero/xpcom/connector/repo.js b/chrome/content/zotero/xpcom/connector/repo.js index b747f6d1e..1b5080fdd 100644 --- a/chrome/content/zotero/xpcom/connector/repo.js +++ b/chrome/content/zotero/xpcom/connector/repo.js @@ -56,7 +56,7 @@ Zotero.Repo = new function() { * Get translator code from repository * @param {String} translatorID ID of the translator to retrieve code for */ - this.getTranslatorCode = Zotero.Promise.method(function (translatorID) { + this.getTranslatorCode = Zotero.Promise.method(function (translatorID, debugMode) { var deferred = Zotero.Promise.defer(); // try standalone @@ -72,6 +72,11 @@ Zotero.Repo = new function() { ); return; } + // Don't fetch from repo in debug mode + if (debugMode) { + deferred.resolve([false, Zotero.Repo.SOURCE_ZOTERO_STANDALONE]); + return; + } // then try repo diff --git a/chrome/content/zotero/xpcom/connector/translator.js b/chrome/content/zotero/xpcom/connector/translator.js index 3cf970b04..467f1dc50 100644 --- a/chrome/content/zotero/xpcom/connector/translator.js +++ b/chrome/content/zotero/xpcom/connector/translator.js @@ -130,7 +130,9 @@ Zotero.Translators = new function() { if(!_initialized) Zotero.Translators.init() var translators = _cache[type].slice(0); var codeGetter = new Zotero.Translators.CodeGetter(translators, debugMode); - return codeGetter.getAll(); + return codeGetter.getAll().then(function() { + return translators; + });; }); /** @@ -326,24 +328,36 @@ Zotero.Translators = new function() { Zotero.Translators.CodeGetter = function(translators, debugMode) { this._translators = translators; this._debugMode = debugMode; -} + this._concurrency = 1; +}; -Zotero.Translators.CodeGetter.prototype.getAll = Zotero.Promise.method(function () { - var translators = []; - for (let translator of this._translators) { - // retrieve code if no code and translator is supported locally - if((translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER && !translator.hasOwnProperty("code")) - // or if debug mode is enabled (even if unsupported locally) - || (this._debugMode && (!translator.hasOwnProperty("code") - // or if in debug mode and the code we have came from the repo (which doesn't - // include test cases) - || (Zotero.Repo && translator.codeSource === Zotero.Repo.SOURCE_REPO)))) { - // get next translator - translators.push(translator.getCode()); +Zotero.Translators.CodeGetter.prototype.getCodeFor = Zotero.Promise.method(function(i) { + let translator = this._translators[i]; + // retrieve code if no code and translator is supported locally + if((translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER && !translator.hasOwnProperty("code")) + // or if debug mode is enabled (even if unsupported locally) + || (this._debugMode && (!translator.hasOwnProperty("code") + // or if in debug mode and the code we have came from the repo (which doesn't + // include test cases) + || (Zotero.Repo && translator.codeSource === Zotero.Repo.SOURCE_REPO)))) { + // get code + return translator.getCode(); + } +}); + +Zotero.Translators.CodeGetter.prototype.getAll = function () { + var codes = []; + // Chain promises with some level of concurrency. If unchained, fires + // off hundreds of xhttprequests on connectors and crashes the extension + for (let i = 0; i < this._translators.length; i++) { + if (i < this._concurrency) { + codes.push(this.getCodeFor(i)); + } else { + codes.push(codes[i-this._concurrency].then(() => this.getCodeFor(i))); } } - return Zotero.Promise.all(translators); -}); + return Promise.all(codes); +}; var TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator", "target", "priority", "lastUpdated"]; @@ -428,8 +442,8 @@ Zotero.Translator.prototype.init = function(info) { * * @return {Promise} - Promise for translator code or false if none */ -Zotero.Translator.prototype.getCode = function () { - return Zotero.Repo.getTranslatorCode(this.translatorID) +Zotero.Translator.prototype.getCode = function (debugMode) { + return Zotero.Repo.getTranslatorCode(this.translatorID, debugMode) .then(function (args) { var code = args[0]; var source = args[1]; diff --git a/chrome/content/zotero/xpcom/server_connector.js b/chrome/content/zotero/xpcom/server_connector.js index bb6a33799..a7f0ac050 100644 --- a/chrome/content/zotero/xpcom/server_connector.js +++ b/chrome/content/zotero/xpcom/server_connector.js @@ -618,7 +618,9 @@ Zotero.Server.Connector.GetTranslatorCode.prototype = { */ "init":function(postData, sendResponseCallback) { var translator = Zotero.Translators.get(postData.translatorID); - sendResponseCallback(200, "application/javascript", translator.code); + translator.getCode().then(function(code) { + sendResponseCallback(200, "application/javascript", code); + }); } } diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index b6b855076..4b8e11fbe 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -1264,7 +1264,7 @@ Zotero.Translate.Base.prototype = { // Zotero.Translators.get() returns a promise in the connectors, but we don't expect it to // otherwise - if (!this.isConnector && this.translator[0].then) { + if (!Zotero.isConnector && this.translator[0].then) { throw new Error("Translator should not be a promise in non-connector mode"); } @@ -1741,9 +1741,12 @@ Zotero.Translate.Base.prototype = { this._sandboxManager = new Zotero.Translate.SandboxManager(this._sandboxLocation); } const createArrays = "['creators', 'notes', 'tags', 'seeAlso', 'attachments']"; - var src = "var Zotero = {};"+ - "Zotero.Item = function (itemType) {"+ - "const createArrays = "+createArrays+";"+ + var src = ""; + if (Zotero.isFx && !Zotero.isBookmarklet) { + src = "var Zotero = {};"; + } + src += "Zotero.Item = function (itemType) {"+ + "var createArrays = "+createArrays+";"+ "this.itemType = itemType;"+ "for(var i=0, n=createArrays.length; i