diff --git a/chrome/content/zotero/xpcom/debug.js b/chrome/content/zotero/xpcom/debug.js index 3e9eb64f8..a635045c2 100644 --- a/chrome/content/zotero/xpcom/debug.js +++ b/chrome/content/zotero/xpcom/debug.js @@ -46,23 +46,6 @@ Zotero.Debug = new function () { return; } - // Properly display thrown Error objects - if (message && message.constructor) { - switch (message.constructor.name) { - case 'Error': - case 'EvalError': - case 'RangeError': - case 'ReferenceError': - case 'SyntaxError': - case 'TypeError': - case 'URIError': - message = "'message' => \"" + message.message + "\"\n" - + Zotero.Utilities.varDump(message) + "\n" - + message.stack; - break; - } - } - if (typeof message != 'string') { message = Zotero.Utilities.varDump(message); } diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js index e143dce7e..ef4bd2446 100644 --- a/chrome/content/zotero/xpcom/utilities.js +++ b/chrome/content/zotero/xpcom/utilities.js @@ -1159,96 +1159,133 @@ Zotero.Utilities = { * * Adapted from http://binnyva.blogspot.com/2005/10/dump-function-javascript-equivalent-of.html */ - "varDump":function(arr,level,maxLevel,parentObjects,path) { - var dumped_text = ""; - if (level === undefined){ + "varDump": function(obj,level,maxLevel,parentObjects,path) { + // Simple dump + var type = typeof obj; + if (type == 'number' || type == 'undefined' || type == 'boolean' || obj === null) { + if (!level) { + // When dumping these directly, make sure to distinguish them from regular + // strings as output by Zotero.debug (i.e. no quotes) + return '===>' + obj + '<=== (' + type + ')'; + } + else { + return '' + obj; + } + } + else if (type == 'string') { + return JSON.stringify(obj); + } + else if (type == 'function') { + var funcStr = ('' + obj).trim(); + if (!level) { + // Dump function contents as well if only dumping function + return funcStr; + } + + // Display [native code] label for native functions, but make it one line + if (/^[^{]+{\s*\[native code\]\s*}$/i.test(funcStr)) { + return funcStr.replace(/\s*(\[native code\])\s*/i, ' $1 '); + } + + // For non-native functions, display an elipsis + return ('' + obj).replace(/{[\s\S]*}/, '{...}'); + } + else if (type != 'object') { + return '<> ' + obj; + } + + // More complex dump with indentation for objects + if (level === undefined) { level = 0; } - + if (maxLevel === undefined) { maxLevel = 4; } - - // The padding given at the beginning of the line. - var level_padding = ""; - for (var j=0;j maxLevel){ - return dumped_text + level_padding + "<>...\n"; + + var objType = Object.prototype.toString.call(obj); + + if (level > maxLevel) { + return objType + " <>"; } - if (typeof(arr) == 'object') { // Array/Hashes/Objects - var isRequest = Zotero.isFx && !Zotero.isBookmarklet - && arr instanceof Components.interfaces.nsIRequest; - - //array for checking recursion - //initialise at first itteration - if(!parentObjects) { - parentObjects = [arr]; - path = ['ROOT']; + // The padding given at the beginning of the line. + var level_padding = ""; + for (var j=0; j <>\n"; - continue; - } - - var value = arr[item]; - } catch(e) { - dumped_text += level_padding + "'" + item + "' => <>\n"; + } + if (isError) { + return (obj.constructor.name ? obj.constructor.name : 'Error') + ': ' + + (obj.message ? ('' + obj.message).replace(/^/gm, level_padding).trim() : '') + + '\n' + level_padding + "===== Stack Trace =====\n" + + (obj.stack ? obj.stack.trim().replace(/^(?=.)/gm, level_padding) : '') + + '\n' + level_padding + "======================="; + } + + // Only dump single level for nsIDOMNode objects (including document) + if (Zotero.isFx && !Zotero.isBookmarklet + && obj instanceof Components.interfaces.nsIDOMNode + ) { + level = maxLevel; + } + + // Recursion checking + if(!parentObjects) { + parentObjects = [obj]; + path = ['ROOT']; + } + + var isArray = objType == '[object Array]' + var dumpedText = isArray ? '[' : objType + ' {'; + for (var prop in obj) { + dumpedText += '\n' + level_padding + JSON.stringify(prop) + ": "; + + try { + var value = obj[prop]; + } catch(e) { + dumpedText += "<>"; + continue; + } + + // Check for recursion + if (typeof(value) == 'object') { + var i = parentObjects.indexOf(value); + if(i != -1) { + var parentName = path.slice(0,i+1).join('->'); + dumpedText += "<>"; continue; } - - if (typeof(value) == 'object') { // If it is an array - //check for recursion - var i = parentObjects.indexOf(value); - if(i != -1) { - var parentName = path.slice(0,i+1).join('->'); - dumped_text += level_padding + "'" + item + "' => <>\n"; - continue; - } - - var openBrace = '{', closeBrace = '}'; - var type = Object.prototype.toString.call(value); - if(type == '[object Array]') { - openBrace = '['; - closeBrace = ']'; - } - - dumped_text += level_padding + "'" + item + "' => " + type + ' ' + openBrace; - //only recurse if there's anything in the object, purely cosmetical - try { - for(var i in value) { - dumped_text += "\n" + Zotero.Utilities.varDump(value,level+1,maxLevel,parentObjects.concat([value]),path.concat([item])) + level_padding; - break; - } - } catch(e) { - dumped_text += "<>\n"; - } - dumped_text += closeBrace + "\n"; - } - else { - if (typeof value == 'function'){ - dumped_text += level_padding + "'" + item + "' => function(...){...} \n"; - } - else if (typeof value == 'number') { - dumped_text += level_padding + "'" + item + "' => " + value + "\n"; - } - else { - dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n"; - } - } + } + + try { + dumpedText += Zotero.Utilities.varDump(value,level+1,maxLevel,parentObjects.concat([value]),path.concat([prop])); + } catch(e) { + dumpedText += "<>"; } } - else { // Stings/Chars/Numbers etc. - dumped_text = "===>"+arr+"<===("+typeof(arr)+")"; + + var lastChar = dumpedText.charAt(dumpedText.length - 1); + if (lastChar != '[' && lastChar != '{') { + dumpedText += '\n' + level_padding.substr(4); } - return dumped_text; + dumpedText += isArray ? ']' : '}'; + + return dumpedText; }, /**