diff --git a/js/tracekit/tracekit.js b/js/tracekit/tracekit.js
index 78bb33be54..7d91404f2b 100644
--- a/js/tracekit/tracekit.js
+++ b/js/tracekit/tracekit.js
@@ -1,10 +1,12 @@
-/*
- TraceKit - Cross brower stack traces - github.com/occ/TraceKit
- MIT license
-*/
-
-;(function(window, undefined) {
-
+/**
+ * https://github.com/csnover/TraceKit
+ * @license MIT
+ * @namespace TraceKit
+ */
+(function(window, undefined) {
+if (!window) {
+ return;
+}
var TraceKit = {};
var _oldTraceKit = window.TraceKit;
@@ -13,25 +15,34 @@ var _oldTraceKit = window.TraceKit;
var _slice = [].slice;
var UNKNOWN_FUNCTION = '?';
-
/**
- * _has, a better form of hasOwnProperty
- * Example: _has(MainHostObject, property) === true/false
+ * A better form of hasOwnProperty
+ * Example: `_has(MainHostObject, property) === true/false`
*
- * @param {Object} host object to check property
+ * @param {Object} object to check property
* @param {string} key to check
+ * @return {Boolean} true if the object has the key and it is not inherited
*/
function _has(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}
+/**
+ * Returns true if the parameter is undefined
+ * Example: `_isUndefined(val) === true/false`
+ *
+ * @param {*} what Value to check
+ * @return {Boolean} true if undefined and false otherwise
+ */
function _isUndefined(what) {
return typeof what === 'undefined';
}
/**
- * TraceKit.noConflict: Export TraceKit out to another variable
- * Example: var TK = TraceKit.noConflict()
+ * Export TraceKit out to another variable
+ * Example: `var TK = TraceKit.noConflict()`
+ * @return {Object} The TraceKit object
+ * @memberof TraceKit
*/
TraceKit.noConflict = function noConflict() {
window.TraceKit = _oldTraceKit;
@@ -39,11 +50,12 @@ TraceKit.noConflict = function noConflict() {
};
/**
- * TraceKit.wrap: Wrap any function in a TraceKit reporter
- * Example: func = TraceKit.wrap(func);
+ * Wrap any function in a TraceKit reporter
+ * Example: `func = TraceKit.wrap(func);`
*
* @param {Function} func Function to be wrapped
* @return {Function} The wrapped func
+ * @memberof TraceKit
*/
TraceKit.wrap = function traceKitWrapper(func) {
function wrapped() {
@@ -58,23 +70,25 @@ TraceKit.wrap = function traceKitWrapper(func) {
};
/**
- * TraceKit.report: cross-browser processing of unhandled exceptions
+ * Cross-browser processing of unhandled exceptions
*
* Syntax:
+ * ```js
* TraceKit.report.subscribe(function(stackInfo) { ... })
* TraceKit.report.unsubscribe(function(stackInfo) { ... })
* TraceKit.report(exception)
* try { ...code... } catch(ex) { TraceKit.report(ex); }
+ * ```
*
* Supports:
* - Firefox: full stack trace with line numbers, plus column number
- * on top frame; column number is not guaranteed
- * - Opera: full stack trace with line and column numbers
- * - Chrome: full stack trace with line and column numbers
- * - Safari: line and column number for the top frame only; some frames
- * may be missing, and column number is not guaranteed
- * - IE: line and column number for the top frame only; some frames
- * may be missing, and column number is not guaranteed
+ * on top frame; column number is not guaranteed
+ * - Opera: full stack trace with line and column numbers
+ * - Chrome: full stack trace with line and column numbers
+ * - Safari: line and column number for the top frame only; some frames
+ * may be missing, and column number is not guaranteed
+ * - IE: line and column number for the top frame only; some frames
+ * may be missing, and column number is not guaranteed
*
* In theory, TraceKit should work on all of the following versions:
* - IE5.5+ (only 8.0 tested)
@@ -93,17 +107,22 @@ TraceKit.wrap = function traceKitWrapper(func) {
* If the exception does not reach the top of the browser, you will only
* get a stack trace from the point where TraceKit.report was called.
*
- * Handlers receive a stackInfo object as described in the
+ * Handlers receive a TraceKit.StackTrace object as described in the
* TraceKit.computeStackTrace docs.
+ *
+ * @memberof TraceKit
+ * @namespace
*/
TraceKit.report = (function reportModuleWrapper() {
var handlers = [],
+ lastArgs = null,
lastException = null,
lastExceptionStack = null;
/**
* Add a crash handler.
* @param {Function} handler
+ * @memberof TraceKit.report
*/
function subscribe(handler) {
installGlobalHandler();
@@ -113,6 +132,7 @@ TraceKit.report = (function reportModuleWrapper() {
/**
* Remove a crash handler.
* @param {Function} handler
+ * @memberof TraceKit.report
*/
function unsubscribe(handler) {
for (var i = handlers.length - 1; i >= 0; --i) {
@@ -124,11 +144,14 @@ TraceKit.report = (function reportModuleWrapper() {
/**
* Dispatch stack information to all handlers.
- * @param {Object.} stack
+ * @param {TraceKit.StackTrace} stack
+ * @param {boolean} isWindowError Is this a top-level window error?
+ * @memberof TraceKit.report
+ * @throws An exception if an error occurs while calling an handler.
*/
- function notifyHandlers(stack, windowError) {
+ function notifyHandlers(stack, isWindowError) {
var exception = null;
- if (windowError && !TraceKit.collectWindowErrors) {
+ if (isWindowError && !TraceKit.collectWindowErrors) {
return;
}
for (var i in handlers) {
@@ -153,34 +176,36 @@ TraceKit.report = (function reportModuleWrapper() {
* Supported by Gecko and IE.
* @param {string} message Error message.
* @param {string} url URL of script that generated the exception.
- * @param {(number|string)} lineNo The line number at which the error
- * occurred.
+ * @param {(number|string)} lineNo The line number at which the error occurred.
+ * @param {(number|string)=} columnNo The column number at which the error occurred.
+ * @param {Error=} errorObj The actual Error object.
+ * @memberof TraceKit.report
*/
- function traceKitWindowOnError(message, url, lineNo) {
+ function traceKitWindowOnError(message, url, lineNo, columnNo, errorObj) {
var stack = null;
if (lastExceptionStack) {
TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
- stack = lastExceptionStack;
- lastExceptionStack = null;
- lastException = null;
+ processLastException();
+ } else if (errorObj) {
+ stack = TraceKit.computeStackTrace(errorObj);
+ notifyHandlers(stack, true);
} else {
var location = {
- 'url': url,
- 'line': lineNo
+ 'url': url,
+ 'line': lineNo,
+ 'column': columnNo
};
location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);
location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);
stack = {
- 'mode': 'onerror',
- 'message': message,
- 'url': document.location.href,
- 'stack': [location],
- 'useragent': navigator.userAgent
+ 'mode': 'onerror',
+ 'message': message,
+ 'stack': [location]
};
- }
- notifyHandlers(stack, 'from window.onerror');
+ notifyHandlers(stack, true);
+ }
if (_oldOnerrorHandler) {
return _oldOnerrorHandler.apply(this, arguments);
@@ -189,8 +214,11 @@ TraceKit.report = (function reportModuleWrapper() {
return false;
}
- function installGlobalHandler ()
- {
+ /**
+ * Install a global onerror handler
+ * @memberof TraceKit.report
+ */
+ function installGlobalHandler () {
if (_onErrorHandlerInstalled === true) {
return;
}
@@ -199,26 +227,38 @@ TraceKit.report = (function reportModuleWrapper() {
_onErrorHandlerInstalled = true;
}
+ /**
+ * Process the most recent exception
+ * @memberof TraceKit.report
+ */
+ function processLastException() {
+ var _lastExceptionStack = lastExceptionStack,
+ _lastArgs = lastArgs;
+ lastArgs = null;
+ lastExceptionStack = null;
+ lastException = null;
+ notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));
+ }
+
/**
* Reports an unhandled Error to TraceKit.
* @param {Error} ex
+ * @memberof TraceKit.report
+ * @throws An exception if an incomplete stack trace is detected (old IE browsers).
*/
function report(ex) {
- var args = _slice.call(arguments, 1);
if (lastExceptionStack) {
if (lastException === ex) {
return; // already caught by an inner catch block, ignore
} else {
- var s = lastExceptionStack;
- lastExceptionStack = null;
- lastException = null;
- notifyHandlers.apply(null, [s, null].concat(args));
+ processLastException();
}
}
var stack = TraceKit.computeStackTrace(ex);
lastExceptionStack = stack;
lastException = ex;
+ lastArgs = _slice.call(arguments, 1);
// If the stack trace is incomplete, wait for 2 seconds for
// slow slow IE to see if onerror occurs or not before reporting
@@ -226,9 +266,7 @@ TraceKit.report = (function reportModuleWrapper() {
// stack trace
window.setTimeout(function () {
if (lastException === ex) {
- lastExceptionStack = null;
- lastException = null;
- notifyHandlers.apply(null, [stack, null].concat(args));
+ processLastException();
}
}, (stack.incomplete ? 2000 : 0));
@@ -240,22 +278,36 @@ TraceKit.report = (function reportModuleWrapper() {
return report;
}());
+/**
+ * An object representing a single stack frame.
+ * @typedef {Object} StackFrame
+ * @property {string} url The JavaScript or HTML file URL.
+ * @property {string} func The function name, or empty for anonymous functions (if guessing did not work).
+ * @property {string[]?} args The arguments passed to the function, if known.
+ * @property {number=} line The line number, if known.
+ * @property {number=} column The column number, if known.
+ * @property {string[]} context An array of source code lines; the middle element corresponds to the correct line#.
+ * @memberof TraceKit
+ */
+
+/**
+ * An object representing a JavaScript stack trace.
+ * @typedef {Object} StackTrace
+ * @property {string} name The name of the thrown exception.
+ * @property {string} message The exception error message.
+ * @property {TraceKit.StackFrame[]} stack An array of stack frames.
+ * @property {string} mode 'stack', 'stacktrace', 'multiline', 'callers', 'onerror', or 'failed' -- method used to collect the stack trace.
+ * @memberof TraceKit
+ */
+
/**
* TraceKit.computeStackTrace: cross-browser stack traces in JavaScript
*
* Syntax:
+ * ```js
* s = TraceKit.computeStackTrace.ofCaller([depth])
* s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)
- * Returns:
- * s.name - exception name
- * s.message - exception message
- * s.stack[i].url - JavaScript or HTML file URL
- * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)
- * s.stack[i].args - arguments passed to the function, if known
- * s.stack[i].line - line number, if known
- * s.stack[i].column - column number, if known
- * s.stack[i].context - an array of source code lines; the middle element corresponds to the correct line#
- * s.mode - 'stack', 'stacktrace', 'multiline', 'callers', 'onerror', or 'failed' -- method used to collect the stack trace
+ * ```
*
* Supports:
* - Firefox: full stack trace with line numbers and unreliable column
@@ -294,6 +346,7 @@ TraceKit.report = (function reportModuleWrapper() {
* inner function that actually caused the exception).
*
* Tracing example:
+ * ```js
* function trace(message) {
* var stackInfo = TraceKit.computeStackTrace.ofCaller();
* var data = message + "\n";
@@ -306,6 +359,9 @@ TraceKit.report = (function reportModuleWrapper() {
* else
* alert(data);
* }
+ * ```
+ * @memberof TraceKit
+ * @namespace
*/
TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
var debug = false,
@@ -316,20 +372,21 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* to look up anonymous function names.
* @param {string} url URL of source code.
* @return {string} Source contents.
+ * @memberof TraceKit.computeStackTrace
*/
function loadSource(url) {
if (!TraceKit.remoteFetching) { //Only attempt request if remoteFetching is on.
return '';
}
try {
- function getXHR() {
+ var getXHR = function() {
try {
return new window.XMLHttpRequest();
} catch (e) {
// explicitly bubble up the exception if not found
return new window.ActiveXObject('Microsoft.XMLHTTP');
}
- }
+ };
var request = getXHR();
request.open('GET', url, false);
@@ -344,13 +401,29 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* Retrieves source code from the source code cache.
* @param {string} url URL of source code.
* @return {Array.} Source contents.
+ * @memberof TraceKit.computeStackTrace
*/
function getSource(url) {
+ if (typeof url !== 'string') {
+ return [];
+ }
+
if (!_has(sourceCache, url)) {
// URL needs to be able to fetched within the acceptable domain. Otherwise,
// cross-domain errors will be triggered.
+ /*
+ Regex matches:
+ 0 - Full Url
+ 1 - Protocol
+ 2 - Domain
+ 3 - Port (Useful for internal applications)
+ 4 - Path
+ */
var source = '';
- if (url.indexOf(document.domain) !== -1) {
+ var domain = '';
+ try { domain = window.document.domain; } catch (e) { }
+ var match = /(.*)\:\/\/([^:\/]+)([:\d]*)\/{0,1}([\s\S]*)/.exec(url);
+ if (match && match[2] === domain) {
source = loadSource(url);
}
sourceCache[url] = source ? source.split('\n') : [];
@@ -366,6 +439,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* @param {string} url URL of source code.
* @param {(string|number)} lineNo Line number in source code.
* @return {string} The function name, if discoverable.
+ * @memberof TraceKit.computeStackTrace
*/
function guessFunctionName(url, lineNo) {
var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/,
@@ -402,6 +476,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* @param {(string|number)} line Line number in source code to centre
* around for context.
* @return {?Array.} Lines of source code.
+ * @memberof TraceKit.computeStackTrace
*/
function gatherContext(url, line) {
var source = getSource(url);
@@ -436,6 +511,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* used inside a regular expression as a string literal.
* @param {string} text The string.
* @return {string} The escaped string literal.
+ * @memberof TraceKit.computeStackTrace
*/
function escapeRegExp(text) {
return text.replace(/[\-\[\]{}()*+?.,\\\^$|#]/g, '\\$&');
@@ -447,6 +523,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* be matched the same as their literal friends.
* @param {string} body The string.
* @return {string} The escaped string.
+ * @memberof TraceKit.computeStackTrace
*/
function escapeCodeAsRegExpForMatchingInsideHTML(body) {
return escapeRegExp(body).replace('<', '(?:<|<)').replace('>', '(?:>|>)').replace('&', '(?:&|&)').replace('"', '(?:"|")').replace(/\s+/g, '\\s+');
@@ -458,6 +535,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* @param {Array.} urls A list of URLs to search.
* @return {?Object.} An object containing
* the url, line, and column number of the defined function.
+ * @memberof TraceKit.computeStackTrace
*/
function findSourceInUrls(re, urls) {
var source, m;
@@ -489,6 +567,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* @param {string} url The URL to search.
* @param {(string|number)} line The line number to examine.
* @return {?number} The column number.
+ * @memberof TraceKit.computeStackTrace
*/
function findSourceInLine(fragment, url, line) {
var source = getSource(url),
@@ -510,10 +589,15 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* function definition.
* @return {?Object.} An object containing
* the url, line, and column number of the defined function.
+ * @memberof TraceKit.computeStackTrace
*/
function findSourceByFunctionBody(func) {
+ if (_isUndefined(window && window.document)) {
+ return;
+ }
+
var urls = [window.location.href],
- scripts = document.getElementsByTagName('script'),
+ scripts = window.document.getElementsByTagName('script'),
body,
code = '' + func,
codeRE = /^function(?:\s+([\w$]+))?\s*\(([\w\s,]*)\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,
@@ -587,6 +671,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
// ex.message = qq is not defined
// ex.fileName = http://...
// ex.lineNumber = 59
+ // ex.columnNumber = 69
// ex.stack = ...stack trace... (see the example below)
// ex.name = ReferenceError
//
@@ -611,15 +696,17 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* Computes stack trace information from the stack property.
* Chrome and Gecko use this property.
* @param {Error} ex
- * @return {?Object.} Stack trace information.
+ * @return {?TraceKit.StackTrace} Stack trace information.
+ * @memberof TraceKit.computeStackTrace
*/
function computeStackTraceFromStackProp(ex) {
if (!ex.stack) {
return null;
}
- var chrome = /^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
- gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i,
+ var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|webpack|eval).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,
+ gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|\[native).*?)(?::(\d+))?(?::(\d+))?\s*$/i,
+ winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
lines = ex.stack.split('\n'),
stack = [],
parts,
@@ -627,21 +714,31 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
reference = /^(.*) is undefined$/.exec(ex.message);
for (var i = 0, j = lines.length; i < j; ++i) {
- if ((parts = gecko.exec(lines[i]))) {
+ if ((parts = chrome.exec(lines[i]))) {
+ var isNative = parts[2] && parts[2].indexOf('native') !== -1;
element = {
- 'url': parts[3],
+ 'url': !isNative ? parts[2] : null,
'func': parts[1] || UNKNOWN_FUNCTION,
- 'args': parts[2] ? parts[2].split(',') : '',
- 'line': +parts[4],
- 'column': parts[5] ? +parts[5] : null
+ 'args': isNative ? [parts[2]] : [],
+ 'line': parts[3] ? +parts[3] : null,
+ 'column': parts[4] ? +parts[4] : null
};
- } else if ((parts = chrome.exec(lines[i]))) {
+ } else if ( parts = winjs.exec(lines[i]) ) {
element = {
'url': parts[2],
'func': parts[1] || UNKNOWN_FUNCTION,
+ 'args': [],
'line': +parts[3],
'column': parts[4] ? +parts[4] : null
};
+ } else if ((parts = gecko.exec(lines[i]))) {
+ element = {
+ 'url': parts[3],
+ 'func': parts[1] || UNKNOWN_FUNCTION,
+ 'args': parts[2] ? parts[2].split(',') : [],
+ 'line': parts[4] ? +parts[4] : null,
+ 'column': parts[5] ? +parts[5] : null
+ };
} else {
continue;
}
@@ -657,51 +754,70 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
stack.push(element);
}
- if (stack[0] && stack[0].line && !stack[0].column && reference) {
- stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);
- }
-
if (!stack.length) {
return null;
}
+ if (stack[0] && stack[0].line && !stack[0].column && reference) {
+ stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);
+ } else if (!stack[0].column && !_isUndefined(ex.columnNumber)) {
+ // FireFox uses this awesome columnNumber property for its top frame
+ // Also note, Firefox's column number is 0-based and everything else expects 1-based,
+ // so adding 1
+ stack[0].column = ex.columnNumber + 1;
+ }
+
return {
'mode': 'stack',
'name': ex.name,
'message': ex.message,
- 'url': document.location.href,
- 'stack': stack,
- 'useragent': navigator.userAgent
+ 'stack': stack
};
}
/**
* Computes stack trace information from the stacktrace property.
- * Opera 10 uses this property.
+ * Opera 10+ uses this property.
* @param {Error} ex
- * @return {?Object.} Stack trace information.
+ * @return {?TraceKit.StackTrace} Stack trace information.
+ * @memberof TraceKit.computeStackTrace
*/
function computeStackTraceFromStacktraceProp(ex) {
// Access and store the stacktrace property before doing ANYTHING
// else to it because Opera is not very good at providing it
// reliably in other circumstances.
var stacktrace = ex.stacktrace;
+ if (!stacktrace) {
+ return;
+ }
- var testRE = / line (\d+), column (\d+) in (?:]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i,
+ var opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i,
+ opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:]+)>|([^\)]+))\((.*)\))? in (.*):\s*$/i,
lines = stacktrace.split('\n'),
stack = [],
parts;
- for (var i = 0, j = lines.length; i < j; i += 2) {
- if ((parts = testRE.exec(lines[i]))) {
- var element = {
+ for (var line = 0; line < lines.length; line += 2) {
+ var element = null;
+ if ((parts = opera10Regex.exec(lines[line]))) {
+ element = {
+ 'url': parts[2],
+ 'line': +parts[1],
+ 'column': null,
+ 'func': parts[3],
+ 'args':[]
+ };
+ } else if ((parts = opera11Regex.exec(lines[line]))) {
+ element = {
+ 'url': parts[6],
'line': +parts[1],
'column': +parts[2],
'func': parts[3] || parts[4],
- 'args': parts[5] ? parts[5].split(',') : [],
- 'url': parts[6]
+ 'args': parts[5] ? parts[5].split(',') : []
};
+ }
+ if (element) {
if (!element.func && element.line) {
element.func = guessFunctionName(element.url, element.line);
}
@@ -712,7 +828,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
}
if (!element.context) {
- element.context = [lines[i + 1]];
+ element.context = [lines[line + 1]];
}
stack.push(element);
@@ -727,9 +843,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
'mode': 'stacktrace',
'name': ex.name,
'message': ex.message,
- 'url': document.location.href,
- 'stack': stack,
- 'useragent': navigator.userAgent
+ 'stack': stack
};
}
@@ -740,9 +854,11 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
* Opera 9 and earlier use this method if the option to show stack
* traces is turned on in opera:config.
* @param {Error} ex
- * @return {?Object.} Stack information.
+ * @return {?TraceKit.StackTrace} Stack information.
+ * @memberof TraceKit.computeStackTrace
*/
function computeStackTraceFromOperaMultiLineMessage(ex) {
+ // TODO: Clean this function up
// Opera includes a stack trace into the exception message. An example is:
//
// Statement on line 3: Undefined variable: undefinedFunc
@@ -762,40 +878,42 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
return null;
}
- var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
- lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
+ var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|https?|blob)\S+)(?:: in function (\S+))?\s*$/i,
+ lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|https?|blob)\S+)(?:: in function (\S+))?\s*$/i,
lineRE3 = /^\s*Line (\d+) of function script\s*$/i,
stack = [],
- scripts = document.getElementsByTagName('script'),
+ scripts = (window && window.document && window.document.getElementsByTagName('script')),
inlineScriptBlocks = [],
- parts,
- i,
- len,
- source;
+ parts;
- for (i in scripts) {
- if (_has(scripts, i) && !scripts[i].src) {
- inlineScriptBlocks.push(scripts[i]);
+ for (var s in scripts) {
+ if (_has(scripts, s) && !scripts[s].src) {
+ inlineScriptBlocks.push(scripts[s]);
}
}
- for (i = 2, len = lines.length; i < len; i += 2) {
+ for (var line = 2; line < lines.length; line += 2) {
var item = null;
- if ((parts = lineRE1.exec(lines[i]))) {
+ if ((parts = lineRE1.exec(lines[line]))) {
item = {
'url': parts[2],
'func': parts[3],
- 'line': +parts[1]
+ 'args': [],
+ 'line': +parts[1],
+ 'column': null
};
- } else if ((parts = lineRE2.exec(lines[i]))) {
+ } else if ((parts = lineRE2.exec(lines[line]))) {
item = {
'url': parts[3],
- 'func': parts[4]
+ 'func': parts[4],
+ 'args': [],
+ 'line': +parts[1],
+ 'column': null // TODO: Check to see if inline#1 (+parts[2]) points to the script number or column number.
};
var relativeLine = (+parts[1]); // relative to the start of the