From 540fbac6de77721fcf65cb2c103d31fe6348465f Mon Sep 17 00:00:00 2001 From: Sander Rijken Date: Fri, 5 Jun 2015 17:01:27 +0200 Subject: [PATCH 1/2] Make sure createLog roks with null sourceOrMessage --- dist/exceptionless.js | 4 ++-- dist/exceptionless.js.map | 2 +- dist/exceptionless.min.js | 2 +- dist/exceptionless.min.js.map | 2 +- dist/exceptionless.node.js | 4 ++-- dist/exceptionless.node.js.map | 2 +- src/ExceptionlessClient-spec.ts | 9 +++++++++ src/ExceptionlessClient.ts | 8 ++++---- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/dist/exceptionless.js b/dist/exceptionless.js index 28961390..203c6c00 100644 --- a/dist/exceptionless.js +++ b/dist/exceptionless.js @@ -2065,8 +2065,8 @@ var ExceptionlessClient = (function () { builder = builder.setSource(sourceOrMessage).setMessage(message); } else { - var source = (arguments.callee.caller).name; - builder = builder.setSource(source).setMessage(sourceOrMessage); + var caller = (arguments.callee.caller); + builder = builder.setSource(caller && caller.name).setMessage(sourceOrMessage); } return builder; }; diff --git a/dist/exceptionless.js.map b/dist/exceptionless.js.map index 25c9ff5c..bc96fc7d 100644 --- a/dist/exceptionless.js.map +++ b/dist/exceptionless.js.map @@ -1 +1 @@ -{"version":3,"sources":["tracekit.js","/source/exceptionless.ts"],"names":["getDefaultsSettingsFromScriptTag","processUnhandledException","processJQueryAjaxError"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/nCA,8BAA8B,+BAA+B,CAAC,CAAA;AAqC9D,mCAAmC,+BAA+B,CAAC,CAAA;AACnE,uCAAuC,mCAAmC,CAAC,CAAA;AAC3E,4CAA4C,wCAAwC,CAAC,CAAA;AAIrF,wCAAwC,sCAAsC,CAAC,CAAA;AAK/E,oCAAoC,qBAAqB,CAAC,CAAA;AAC1D,sBAAsB,OAAO,CAAC,CAAA;AAE9B;IACEA,EAAEA,CAACA,CAACA,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","file":"exceptionless.js","sourcesContent":["/*\r\n TraceKit - Cross brower stack traces - github.com/csnover/TraceKit\r\n MIT license\r\n*/\r\n\r\n(function(window, undefined) {\r\nif (!window) {\r\n return;\r\n}\r\n\r\nvar TraceKit = {};\r\nvar _oldTraceKit = window.TraceKit;\r\n\r\n// global reference to slice\r\nvar _slice = [].slice;\r\nvar UNKNOWN_FUNCTION = '?';\r\n\r\n\r\n/**\r\n * _has, a better form of hasOwnProperty\r\n * Example: _has(MainHostObject, property) === true/false\r\n *\r\n * @param {Object} object to check property\r\n * @param {string} key to check\r\n */\r\nfunction _has(object, key) {\r\n return Object.prototype.hasOwnProperty.call(object, key);\r\n}\r\n\r\nfunction _isUndefined(what) {\r\n return typeof what === 'undefined';\r\n}\r\n\r\n/**\r\n * TraceKit.noConflict: Export TraceKit out to another variable\r\n * Example: var TK = TraceKit.noConflict()\r\n */\r\nTraceKit.noConflict = function noConflict() {\r\n window.TraceKit = _oldTraceKit;\r\n return TraceKit;\r\n};\r\n\r\n/**\r\n * TraceKit.wrap: Wrap any function in a TraceKit reporter\r\n * Example: func = TraceKit.wrap(func);\r\n *\r\n * @param {Function} func Function to be wrapped\r\n * @return {Function} The wrapped func\r\n */\r\nTraceKit.wrap = function traceKitWrapper(func) {\r\n function wrapped() {\r\n try {\r\n return func.apply(this, arguments);\r\n } catch (e) {\r\n TraceKit.report(e);\r\n throw e;\r\n }\r\n }\r\n return wrapped;\r\n};\r\n\r\n/**\r\n * TraceKit.report: cross-browser processing of unhandled exceptions\r\n *\r\n * Syntax:\r\n * TraceKit.report.subscribe(function(stackInfo) { ... })\r\n * TraceKit.report.unsubscribe(function(stackInfo) { ... })\r\n * TraceKit.report(exception)\r\n * try { ...code... } catch(ex) { TraceKit.report(ex); }\r\n *\r\n * Supports:\r\n * - Firefox: full stack trace with line numbers, plus column number\r\n * on top frame; column number is not guaranteed\r\n * - Opera: full stack trace with line and column numbers\r\n * - Chrome: full stack trace with line and column numbers\r\n * - Safari: line and column number for the top frame only; some frames\r\n * may be missing, and column number is not guaranteed\r\n * - IE: line and column number for the top frame only; some frames\r\n * may be missing, and column number is not guaranteed\r\n *\r\n * In theory, TraceKit should work on all of the following versions:\r\n * - IE5.5+ (only 8.0 tested)\r\n * - Firefox 0.9+ (only 3.5+ tested)\r\n * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require\r\n * Exceptions Have Stacktrace to be enabled in opera:config)\r\n * - Safari 3+ (only 4+ tested)\r\n * - Chrome 1+ (only 5+ tested)\r\n * - Konqueror 3.5+ (untested)\r\n *\r\n * Requires TraceKit.computeStackTrace.\r\n *\r\n * Tries to catch all unhandled exceptions and report them to the\r\n * subscribed handlers. Please note that TraceKit.report will rethrow the\r\n * exception. This is REQUIRED in order to get a useful stack trace in IE.\r\n * If the exception does not reach the top of the browser, you will only\r\n * get a stack trace from the point where TraceKit.report was called.\r\n *\r\n * Handlers receive a stackInfo object as described in the\r\n * TraceKit.computeStackTrace docs.\r\n */\r\nTraceKit.report = (function reportModuleWrapper() {\r\n var handlers = [],\r\n lastException = null,\r\n lastExceptionStack = null;\r\n\r\n /**\r\n * Add a crash handler.\r\n * @param {Function} handler\r\n */\r\n function subscribe(handler) {\r\n installGlobalHandler();\r\n handlers.push(handler);\r\n }\r\n\r\n /**\r\n * Remove a crash handler.\r\n * @param {Function} handler\r\n */\r\n function unsubscribe(handler) {\r\n for (var i = handlers.length - 1; i >= 0; --i) {\r\n if (handlers[i] === handler) {\r\n handlers.splice(i, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Dispatch stack information to all handlers.\r\n * @param {Object.} stack\r\n */\r\n function notifyHandlers(stack, isWindowError) {\r\n var exception = null;\r\n if (isWindowError && !TraceKit.collectWindowErrors) {\r\n return;\r\n }\r\n for (var i in handlers) {\r\n if (_has(handlers, i)) {\r\n try {\r\n handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));\r\n } catch (inner) {\r\n exception = inner;\r\n }\r\n }\r\n }\r\n\r\n if (exception) {\r\n throw exception;\r\n }\r\n }\r\n\r\n var _oldOnerrorHandler, _onErrorHandlerInstalled;\r\n\r\n /**\r\n * Ensures all global unhandled exceptions are recorded.\r\n * Supported by Gecko and IE.\r\n * @param {string} message Error message.\r\n * @param {string} url URL of script that generated the exception.\r\n * @param {(number|string)} lineNo The line number at which the error\r\n * occurred.\r\n * @param {?(number|string)} columnNo The column number at which the error\r\n * occurred.\r\n * @param {?Error} errorObj The actual Error object.\r\n */\r\n function traceKitWindowOnError(message, url, lineNo, columnNo, errorObj) {\r\n var stack = null;\r\n\r\n if (errorObj) {\r\n stack = TraceKit.computeStackTrace(errorObj);\r\n }\r\n else\r\n {\r\n if (lastExceptionStack) {\r\n TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);\r\n stack = lastExceptionStack;\r\n lastExceptionStack = null;\r\n lastException = null;\r\n } else {\r\n var location = {\r\n 'url': url,\r\n 'line': lineNo,\r\n 'column': columnNo\r\n };\r\n location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);\r\n location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);\r\n stack = {\r\n 'mode': 'onerror',\r\n 'message': message,\r\n 'url': document.location.href,\r\n 'stack': [location],\r\n 'useragent': navigator.userAgent\r\n };\r\n }\r\n }\r\n\r\n notifyHandlers(stack, 'from window.onerror');\r\n\r\n if (_oldOnerrorHandler) {\r\n return _oldOnerrorHandler.apply(this, arguments);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function installGlobalHandler ()\r\n {\r\n if (_onErrorHandlerInstalled === true) {\r\n return;\r\n }\r\n _oldOnerrorHandler = window.onerror;\r\n window.onerror = traceKitWindowOnError;\r\n _onErrorHandlerInstalled = true;\r\n }\r\n\r\n /**\r\n * Reports an unhandled Error to TraceKit.\r\n * @param {Error} ex\r\n */\r\n function report(ex) {\r\n var args = _slice.call(arguments, 1);\r\n if (lastExceptionStack) {\r\n if (lastException === ex) {\r\n return; // already caught by an inner catch block, ignore\r\n } else {\r\n var s = lastExceptionStack;\r\n lastExceptionStack = null;\r\n lastException = null;\r\n notifyHandlers.apply(null, [s, null].concat(args));\r\n }\r\n }\r\n\r\n var stack = TraceKit.computeStackTrace(ex);\r\n lastExceptionStack = stack;\r\n lastException = ex;\r\n\r\n // If the stack trace is incomplete, wait for 2 seconds for\r\n // slow slow IE to see if onerror occurs or not before reporting\r\n // this exception; otherwise, we will end up with an incomplete\r\n // stack trace\r\n window.setTimeout(function () {\r\n if (lastException === ex) {\r\n lastExceptionStack = null;\r\n lastException = null;\r\n notifyHandlers.apply(null, [stack, null].concat(args));\r\n }\r\n }, (stack.incomplete ? 2000 : 0));\r\n\r\n throw ex; // re-throw to propagate to the top level (and cause window.onerror)\r\n }\r\n\r\n report.subscribe = subscribe;\r\n report.unsubscribe = unsubscribe;\r\n return report;\r\n}());\r\n\r\n/**\r\n * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript\r\n *\r\n * Syntax:\r\n * s = TraceKit.computeStackTrace.ofCaller([depth])\r\n * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)\r\n * Returns:\r\n * s.name - exception name\r\n * s.message - exception message\r\n * s.stack[i].url - JavaScript or HTML file URL\r\n * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)\r\n * s.stack[i].args - arguments passed to the function, if known\r\n * s.stack[i].line - line number, if known\r\n * s.stack[i].column - column number, if known\r\n * s.stack[i].context - an array of source code lines; the middle element corresponds to the correct line#\r\n * s.mode - 'stack', 'stacktrace', 'multiline', 'callers', 'onerror', or 'failed' -- method used to collect the stack trace\r\n *\r\n * Supports:\r\n * - Firefox: full stack trace with line numbers and unreliable column\r\n * number on top frame\r\n * - Opera 10: full stack trace with line and column numbers\r\n * - Opera 9-: full stack trace with line numbers\r\n * - Chrome: full stack trace with line and column numbers\r\n * - Safari: line and column number for the topmost stacktrace element\r\n * only\r\n * - IE: no line numbers whatsoever\r\n *\r\n * Tries to guess names of anonymous functions by looking for assignments\r\n * in the source code. In IE and Safari, we have to guess source file names\r\n * by searching for function bodies inside all page scripts. This will not\r\n * work for scripts that are loaded cross-domain.\r\n * Here be dragons: some function names may be guessed incorrectly, and\r\n * duplicate functions may be mismatched.\r\n *\r\n * TraceKit.computeStackTrace should only be used for tracing purposes.\r\n * Logging of unhandled exceptions should be done with TraceKit.report,\r\n * which builds on top of TraceKit.computeStackTrace and provides better\r\n * IE support by utilizing the window.onerror event to retrieve information\r\n * about the top of the stack.\r\n *\r\n * Note: In IE and Safari, no stack trace is recorded on the Error object,\r\n * so computeStackTrace instead walks its *own* chain of callers.\r\n * This means that:\r\n * * in Safari, some methods may be missing from the stack trace;\r\n * * in IE, the topmost function in the stack trace will always be the\r\n * caller of computeStackTrace.\r\n *\r\n * This is okay for tracing (because you are likely to be calling\r\n * computeStackTrace from the function you want to be the topmost element\r\n * of the stack trace anyway), but not okay for logging unhandled\r\n * exceptions (because your catch block will likely be far away from the\r\n * inner function that actually caused the exception).\r\n *\r\n * Tracing example:\r\n * function trace(message) {\r\n * var stackInfo = TraceKit.computeStackTrace.ofCaller();\r\n * var data = message + \"\\n\";\r\n * for(var i in stackInfo.stack) {\r\n * var item = stackInfo.stack[i];\r\n * data += (item.func || '[anonymous]') + \"() in \" + item.url + \":\" + (item.line || '0') + \"\\n\";\r\n * }\r\n * if (window.console)\r\n * console.info(data);\r\n * else\r\n * alert(data);\r\n * }\r\n */\r\nTraceKit.computeStackTrace = (function computeStackTraceWrapper() {\r\n var debug = false,\r\n sourceCache = {};\r\n\r\n /**\r\n * Attempts to retrieve source code via XMLHttpRequest, which is used\r\n * to look up anonymous function names.\r\n * @param {string} url URL of source code.\r\n * @return {string} Source contents.\r\n */\r\n function loadSource(url) {\r\n if (!TraceKit.remoteFetching) { //Only attempt request if remoteFetching is on.\r\n return '';\r\n }\r\n try {\r\n var getXHR = function() {\r\n try {\r\n return new window.XMLHttpRequest();\r\n } catch (e) {\r\n // explicitly bubble up the exception if not found\r\n return new window.ActiveXObject('Microsoft.XMLHTTP');\r\n }\r\n };\r\n\r\n var request = getXHR();\r\n request.open('GET', url, false);\r\n request.send('');\r\n return request.responseText;\r\n } catch (e) {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Retrieves source code from the source code cache.\r\n * @param {string} url URL of source code.\r\n * @return {Array.} Source contents.\r\n */\r\n function getSource(url) {\r\n if (typeof url !== 'string') {\r\n return [];\r\n }\r\n\r\n if (!_has(sourceCache, url)) {\r\n // URL needs to be able to fetched within the acceptable domain. Otherwise,\r\n // cross-domain errors will be triggered.\r\n var source = '';\r\n\r\n url = url || '';\r\n if (url.indexOf && url.indexOf(document.domain) !== -1) {\r\n source = loadSource(url);\r\n }\r\n sourceCache[url] = source ? source.split('\\n') : [];\r\n }\r\n\r\n return sourceCache[url];\r\n }\r\n\r\n /**\r\n * Tries to use an externally loaded copy of source code to determine\r\n * the name of a function by looking at the name of the variable it was\r\n * assigned to, if any.\r\n * @param {string} url URL of source code.\r\n * @param {(string|number)} lineNo Line number in source code.\r\n * @return {string} The function name, if discoverable.\r\n */\r\n function guessFunctionName(url, lineNo) {\r\n var reFunctionArgNames = /function ([^(]*)\\(([^)]*)\\)/,\r\n reGuessFunction = /['\"]?([0-9A-Za-z$_]+)['\"]?\\s*[:=]\\s*(function|eval|new Function)/,\r\n line = '',\r\n maxLines = 10,\r\n source = getSource(url),\r\n m;\r\n\r\n if (!source.length) {\r\n return UNKNOWN_FUNCTION;\r\n }\r\n\r\n // Walk backwards from the first line in the function until we find the line which\r\n // matches the pattern above, which is the function definition\r\n for (var i = 0; i < maxLines; ++i) {\r\n line = source[lineNo - i] + line;\r\n\r\n if (!_isUndefined(line)) {\r\n if ((m = reGuessFunction.exec(line))) {\r\n return m[1];\r\n } else if ((m = reFunctionArgNames.exec(line))) {\r\n return m[1];\r\n }\r\n }\r\n }\r\n\r\n return UNKNOWN_FUNCTION;\r\n }\r\n\r\n /**\r\n * Retrieves the surrounding lines from where an exception occurred.\r\n * @param {string} url URL of source code.\r\n * @param {(string|number)} line Line number in source code to centre\r\n * around for context.\r\n * @return {?Array.} Lines of source code.\r\n */\r\n function gatherContext(url, line) {\r\n var source = getSource(url);\r\n\r\n if (!source.length) {\r\n return null;\r\n }\r\n\r\n var context = [],\r\n // linesBefore & linesAfter are inclusive with the offending line.\r\n // if linesOfContext is even, there will be one extra line\r\n // *before* the offending line.\r\n linesBefore = Math.floor(TraceKit.linesOfContext / 2),\r\n // Add one extra line if linesOfContext is odd\r\n linesAfter = linesBefore + (TraceKit.linesOfContext % 2),\r\n start = Math.max(0, line - linesBefore - 1),\r\n end = Math.min(source.length, line + linesAfter - 1);\r\n\r\n line -= 1; // convert to 0-based index\r\n\r\n for (var i = start; i < end; ++i) {\r\n if (!_isUndefined(source[i])) {\r\n context.push(source[i]);\r\n }\r\n }\r\n\r\n return context.length > 0 ? context : null;\r\n }\r\n\r\n /**\r\n * Escapes special characters, except for whitespace, in a string to be\r\n * used inside a regular expression as a string literal.\r\n * @param {string} text The string.\r\n * @return {string} The escaped string literal.\r\n */\r\n function escapeRegExp(text) {\r\n return text.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#]/g, '\\\\$&');\r\n }\r\n\r\n /**\r\n * Escapes special characters in a string to be used inside a regular\r\n * expression as a string literal. Also ensures that HTML entities will\r\n * be matched the same as their literal friends.\r\n * @param {string} body The string.\r\n * @return {string} The escaped string.\r\n */\r\n function escapeCodeAsRegExpForMatchingInsideHTML(body) {\r\n return escapeRegExp(body).replace('<', '(?:<|<)').replace('>', '(?:>|>)').replace('&', '(?:&|&)').replace('\"', '(?:\"|")').replace(/\\s+/g, '\\\\s+');\r\n }\r\n\r\n /**\r\n * Determines where a code fragment occurs in the source code.\r\n * @param {RegExp} re The function definition.\r\n * @param {Array.} urls A list of URLs to search.\r\n * @return {?Object.} An object containing\r\n * the url, line, and column number of the defined function.\r\n */\r\n function findSourceInUrls(re, urls) {\r\n var source, m;\r\n for (var i = 0, j = urls.length; i < j; ++i) {\r\n // console.log('searching', urls[i]);\r\n if ((source = getSource(urls[i])).length) {\r\n source = source.join('\\n');\r\n if ((m = re.exec(source))) {\r\n // console.log('Found function in ' + urls[i]);\r\n\r\n return {\r\n 'url': urls[i],\r\n 'line': source.substring(0, m.index).split('\\n').length,\r\n 'column': m.index - source.lastIndexOf('\\n', m.index) - 1\r\n };\r\n }\r\n }\r\n }\r\n\r\n // console.log('no match');\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Determines at which column a code fragment occurs on a line of the\r\n * source code.\r\n * @param {string} fragment The code fragment.\r\n * @param {string} url The URL to search.\r\n * @param {(string|number)} line The line number to examine.\r\n * @return {?number} The column number.\r\n */\r\n function findSourceInLine(fragment, url, line) {\r\n var source = getSource(url),\r\n re = new RegExp('\\\\b' + escapeRegExp(fragment) + '\\\\b'),\r\n m;\r\n\r\n line -= 1;\r\n\r\n if (source && source.length > line && (m = re.exec(source[line]))) {\r\n return m.index;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Determines where a function was defined within the source code.\r\n * @param {(Function|string)} func A function reference or serialized\r\n * function definition.\r\n * @return {?Object.} An object containing\r\n * the url, line, and column number of the defined function.\r\n */\r\n function findSourceByFunctionBody(func) {\r\n var urls = [window.location.href],\r\n scripts = document.getElementsByTagName('script'),\r\n body,\r\n code = '' + func,\r\n codeRE = /^function(?:\\s+([\\w$]+))?\\s*\\(([\\w\\s,]*)\\)\\s*\\{\\s*(\\S[\\s\\S]*\\S)\\s*\\}\\s*$/,\r\n eventRE = /^function on([\\w$]+)\\s*\\(event\\)\\s*\\{\\s*(\\S[\\s\\S]*\\S)\\s*\\}\\s*$/,\r\n re,\r\n parts,\r\n result;\r\n\r\n for (var i = 0; i < scripts.length; ++i) {\r\n var script = scripts[i];\r\n if (script.src) {\r\n urls.push(script.src);\r\n }\r\n }\r\n\r\n if (!(parts = codeRE.exec(code))) {\r\n re = new RegExp(escapeRegExp(code).replace(/\\s+/g, '\\\\s+'));\r\n }\r\n\r\n // not sure if this is really necessary, but I don’t have a test\r\n // corpus large enough to confirm that and it was in the original.\r\n else {\r\n var name = parts[1] ? '\\\\s+' + parts[1] : '',\r\n args = parts[2].split(',').join('\\\\s*,\\\\s*');\r\n\r\n body = escapeRegExp(parts[3]).replace(/;$/, ';?'); // semicolon is inserted if the function ends with a comment.replace(/\\s+/g, '\\\\s+');\r\n re = new RegExp('function' + name + '\\\\s*\\\\(\\\\s*' + args + '\\\\s*\\\\)\\\\s*{\\\\s*' + body + '\\\\s*}');\r\n }\r\n\r\n // look for a normal function definition\r\n if ((result = findSourceInUrls(re, urls))) {\r\n return result;\r\n }\r\n\r\n // look for an old-school event handler function\r\n if ((parts = eventRE.exec(code))) {\r\n var event = parts[1];\r\n body = escapeCodeAsRegExpForMatchingInsideHTML(parts[2]);\r\n\r\n // look for a function defined in HTML as an onXXX handler\r\n re = new RegExp('on' + event + '=[\\\\\\'\"]\\\\s*' + body + '\\\\s*[\\\\\\'\"]', 'i');\r\n\r\n if ((result = findSourceInUrls(re, urls[0]))) {\r\n return result;\r\n }\r\n\r\n // look for ???\r\n re = new RegExp(body);\r\n\r\n if ((result = findSourceInUrls(re, urls))) {\r\n return result;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // Contents of Exception in various browsers.\r\n //\r\n // SAFARI:\r\n // ex.message = Can't find variable: qq\r\n // ex.line = 59\r\n // ex.sourceId = 580238192\r\n // ex.sourceURL = http://...\r\n // ex.expressionBeginOffset = 96\r\n // ex.expressionCaretOffset = 98\r\n // ex.expressionEndOffset = 98\r\n // ex.name = ReferenceError\r\n //\r\n // FIREFOX:\r\n // ex.message = qq is not defined\r\n // ex.fileName = http://...\r\n // ex.lineNumber = 59\r\n // ex.columnNumber = 69\r\n // ex.stack = ...stack trace... (see the example below)\r\n // ex.name = ReferenceError\r\n //\r\n // CHROME:\r\n // ex.message = qq is not defined\r\n // ex.name = ReferenceError\r\n // ex.type = not_defined\r\n // ex.arguments = ['aa']\r\n // ex.stack = ...stack trace...\r\n //\r\n // INTERNET EXPLORER:\r\n // ex.message = ...\r\n // ex.name = ReferenceError\r\n //\r\n // OPERA:\r\n // ex.message = ...message... (see the example below)\r\n // ex.name = ReferenceError\r\n // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)\r\n // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'\r\n\r\n /**\r\n * Computes stack trace information from the stack property.\r\n * Chrome and Gecko use this property.\r\n * @param {Error} ex\r\n * @return {?Object.} Stack trace information.\r\n */\r\n function computeStackTraceFromStackProp(ex) {\r\n if (!ex.stack) {\r\n return null;\r\n }\r\n\r\n var chrome = /^\\s*at (.*?) ?\\(?((?:file|https?|chrome-extension):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i,\r\n gecko = /^\\s*(.*?)(?:\\((.*?)\\))?@?((?:file|https?|chrome):.*?):(\\d+)(?::(\\d+))?\\s*$/i,\r\n winjs = /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:ms-appx|http|https):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i,\r\n lines = ex.stack.split('\\n'),\r\n stack = [],\r\n parts,\r\n element,\r\n reference = /^(.*) is undefined$/.exec(ex.message);\r\n\r\n for (var i = 0, j = lines.length; i < j; ++i) {\r\n if ((parts = gecko.exec(lines[i]))) {\r\n element = {\r\n 'url': parts[3],\r\n 'func': parts[1] || UNKNOWN_FUNCTION,\r\n 'args': parts[2] ? parts[2].split(',') : '',\r\n 'line': +parts[4],\r\n 'column': parts[5] ? +parts[5] : null\r\n };\r\n } else if ((parts = chrome.exec(lines[i]))) {\r\n element = {\r\n 'url': parts[2],\r\n 'func': parts[1] || UNKNOWN_FUNCTION,\r\n 'line': +parts[3],\r\n 'column': parts[4] ? +parts[4] : null\r\n };\r\n } else if ((parts = winjs.exec(lines[i]))) {\r\n element = {\r\n 'url': parts[2],\r\n 'func': parts[1] || UNKNOWN_FUNCTION,\r\n 'line': +parts[3],\r\n 'column': parts[4] ? +parts[4] : null\r\n };\r\n } else {\r\n continue;\r\n }\r\n\r\n if (!element.func && element.line) {\r\n element.func = guessFunctionName(element.url, element.line);\r\n }\r\n\r\n if (element.line) {\r\n element.context = gatherContext(element.url, element.line);\r\n }\r\n\r\n stack.push(element);\r\n }\r\n\r\n if (!stack.length) {\r\n return null;\r\n }\r\n\r\n if (stack[0] && stack[0].line && !stack[0].column && reference) {\r\n stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);\r\n } else if (!stack[0].column && !_isUndefined(ex.columnNumber)) {\r\n // FireFox uses this awesome columnNumber property for its top frame\r\n // Also note, Firefox's column number is 0-based and everything else expects 1-based,\r\n // so adding 1\r\n stack[0].column = ex.columnNumber + 1;\r\n }\r\n\r\n return {\r\n 'mode': 'stack',\r\n 'name': ex.name,\r\n 'message': ex.message,\r\n 'url': document.location.href,\r\n 'stack': stack,\r\n 'useragent': navigator.userAgent\r\n };\r\n }\r\n\r\n /**\r\n * Computes stack trace information from the stacktrace property.\r\n * Opera 10 uses this property.\r\n * @param {Error} ex\r\n * @return {?Object.} Stack trace information.\r\n */\r\n function computeStackTraceFromStacktraceProp(ex) {\r\n // Access and store the stacktrace property before doing ANYTHING\r\n // else to it because Opera is not very good at providing it\r\n // reliably in other circumstances.\r\n var stacktrace = ex.stacktrace;\r\n\r\n var testRE = / line (\\d+), column (\\d+) in (?:]+)>|([^\\)]+))\\((.*)\\) in (.*):\\s*$/i,\r\n lines = stacktrace.split('\\n'),\r\n stack = [],\r\n parts;\r\n\r\n for (var i = 0, j = lines.length; i < j; i += 2) {\r\n if ((parts = testRE.exec(lines[i]))) {\r\n var element = {\r\n 'line': +parts[1],\r\n 'column': +parts[2],\r\n 'func': parts[3] || parts[4],\r\n 'args': parts[5] ? parts[5].split(',') : [],\r\n 'url': parts[6]\r\n };\r\n\r\n if (!element.func && element.line) {\r\n element.func = guessFunctionName(element.url, element.line);\r\n }\r\n if (element.line) {\r\n try {\r\n element.context = gatherContext(element.url, element.line);\r\n } catch (exc) {}\r\n }\r\n\r\n if (!element.context) {\r\n element.context = [lines[i + 1]];\r\n }\r\n\r\n stack.push(element);\r\n }\r\n }\r\n\r\n if (!stack.length) {\r\n return null;\r\n }\r\n\r\n return {\r\n 'mode': 'stacktrace',\r\n 'name': ex.name,\r\n 'message': ex.message,\r\n 'url': document.location.href,\r\n 'stack': stack,\r\n 'useragent': navigator.userAgent\r\n };\r\n }\r\n\r\n /**\r\n * NOT TESTED.\r\n * Computes stack trace information from an error message that includes\r\n * the stack trace.\r\n * Opera 9 and earlier use this method if the option to show stack\r\n * traces is turned on in opera:config.\r\n * @param {Error} ex\r\n * @return {?Object.} Stack information.\r\n */\r\n function computeStackTraceFromOperaMultiLineMessage(ex) {\r\n // Opera includes a stack trace into the exception message. An example is:\r\n //\r\n // Statement on line 3: Undefined variable: undefinedFunc\r\n // Backtrace:\r\n // Line 3 of linked script file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.js: In function zzz\r\n // undefinedFunc(a);\r\n // Line 7 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function yyy\r\n // zzz(x, y, z);\r\n // Line 3 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function xxx\r\n // yyy(a, a, a);\r\n // Line 1 of function script\r\n // try { xxx('hi'); return false; } catch(ex) { TraceKit.report(ex); }\r\n // ...\r\n\r\n var lines = ex.message.split('\\n');\r\n if (lines.length < 4) {\r\n return null;\r\n }\r\n\r\n var lineRE1 = /^\\s*Line (\\d+) of linked script ((?:file|https?)\\S+)(?:: in function (\\S+))?\\s*$/i,\r\n lineRE2 = /^\\s*Line (\\d+) of inline#(\\d+) script in ((?:file|https?)\\S+)(?:: in function (\\S+))?\\s*$/i,\r\n lineRE3 = /^\\s*Line (\\d+) of function script\\s*$/i,\r\n stack = [],\r\n scripts = document.getElementsByTagName('script'),\r\n inlineScriptBlocks = [],\r\n parts,\r\n i,\r\n len,\r\n source;\r\n\r\n for (i in scripts) {\r\n if (_has(scripts, i) && !scripts[i].src) {\r\n inlineScriptBlocks.push(scripts[i]);\r\n }\r\n }\r\n\r\n for (i = 2, len = lines.length; i < len; i += 2) {\r\n var item = null;\r\n if ((parts = lineRE1.exec(lines[i]))) {\r\n item = {\r\n 'url': parts[2],\r\n 'func': parts[3],\r\n 'line': +parts[1]\r\n };\r\n } else if ((parts = lineRE2.exec(lines[i]))) {\r\n item = {\r\n 'url': parts[3],\r\n 'func': parts[4]\r\n };\r\n var relativeLine = (+parts[1]); // relative to the start of the