diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index f0bf02260..3fc2521a8 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -14,6 +14,7 @@ Zotero.HTTP = new function() { this.status = xmlhttp.status; this.channel = xmlhttp.channel; this.message = msg; + this.stack = new Error().stack; // Hide password from debug output // @@ -40,9 +41,6 @@ Zotero.HTTP = new function() { this.UnexpectedStatusException.prototype.is5xx = function () { return this.status >= 500 && this.status < 600; } - this.UnexpectedStatusException.prototype.toString = function() { - return this.message; - }; /** * Exception returned if the browser is offline when promise* is used @@ -50,19 +48,15 @@ Zotero.HTTP = new function() { */ this.BrowserOfflineException = function() { this.message = "XMLHttpRequest could not complete because the browser is offline"; + this.stack = new Error().stack; }; this.BrowserOfflineException.prototype = Object.create(Error.prototype); - this.BrowserOfflineException.prototype.toString = function() { - return this.message; - }; this.TimeoutException = function(ms) { this.message = "XMLHttpRequest has timed out after " + ms + "ms"; + this.stack = new Error().stack; }; this.TimeoutException.prototype = Object.create(Error.prototype); - this.TimeoutException.prototype.toString = function() { - return this.message; - }; this.promise = function () { Zotero.debug("Zotero.HTTP.promise() is deprecated -- use Zotero.HTTP.request()", 2); diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js index 2f00a2380..15a91dda9 100644 --- a/chrome/content/zotero/xpcom/utilities.js +++ b/chrome/content/zotero/xpcom/utilities.js @@ -1431,10 +1431,24 @@ Zotero.Utilities = { header = (obj.name ? obj.name + ' ' : '') + 'Exception'; } - return header + ': ' - + (obj.message ? ('' + obj.message).replace(/^/gm, level_padding).trim() : '') - + '\n\n' - + (obj.stack ? obj.stack.trim().replace(/^(?=.)/gm, level_padding) : ''); + let msg = (obj.message ? ('' + obj.message).replace(/^/gm, level_padding).trim() : ''); + if (obj.stack) { + let stack = obj.stack.trim().replace(/^(?=.)/gm, level_padding); + + msg += '\n\n'; + + // At least with Zotero.HTTP.UnexpectedStatusException, the stack contains "Error:" + // and the message in addition to the trace. I'm not sure what's causing that + // (Bluebird?), but fix it here. + if (obj.stack.startsWith('Error:')) { + msg += obj.stack.replace('Error: ' + obj.message + '\n', ''); + } + else { + msg += stack; + } + } + + return header + ': ' + msg; } // Only dump single level for nsIDOMNode objects (including document)