var ErrorStackParser = require('error-stack-parser'); var UNKNOWN_FUNCTION = '?'; var ERR_CLASS_REGEXP = new RegExp('^(([a-zA-Z0-9-_$ ]*): *)?(Uncaught )?([a-zA-Z0-9-_$ ]*): '); function guessFunctionName() { return UNKNOWN_FUNCTION; } function gatherContext() { return null; } function Frame(stackFrame) { var data = {}; data._stackFrame = stackFrame; data.url = stackFrame.fileName; data.line = stackFrame.lineNumber; data.func = stackFrame.functionName; data.column = stackFrame.columnNumber; data.args = stackFrame.args; data.context = gatherContext(); return data; } function Stack(exception, skip) { function getStack() { var parserStack = []; skip = skip || 0; try { parserStack = ErrorStackParser.parse(exception); } catch(e) { parserStack = []; } var stack = []; for (var i = skip; i < parserStack.length; i++) { stack.push(new Frame(parserStack[i])); } return stack; } return { stack: getStack(), message: exception.message, name: _mostSpecificErrorName(exception), rawStack: exception.stack, rawException: exception }; } function parse(e, skip) { var err = e; if (err.nested || err.cause) { var traceChain = []; while (err) { traceChain.push(new Stack(err, skip)); err = err.nested || err.cause; skip = 0; // Only apply skip value to primary error } // Return primary error with full trace chain attached. traceChain[0].traceChain = traceChain; return traceChain[0]; } else { return new Stack(err, skip); } } function guessErrorClass(errMsg) { if (!errMsg || !errMsg.match) { return ['Unknown error. There was no error message to display.', '']; } var errClassMatch = errMsg.match(ERR_CLASS_REGEXP); var errClass = '(unknown)'; if (errClassMatch) { errClass = errClassMatch[errClassMatch.length - 1]; errMsg = errMsg.replace((errClassMatch[errClassMatch.length - 2] || '') + errClass + ':', ''); errMsg = errMsg.replace(/(^[\s]+|[\s]+$)/g, ''); } return [errClass, errMsg]; } // * Prefers any value over an empty string // * Prefers any value over 'Error' where possible // * Prefers name over constructor.name when both are more specific than 'Error' function _mostSpecificErrorName(error) { var name = error.name && error.name.length && error.name; var constructorName = error.constructor.name && error.constructor.name.length && error.constructor.name; if (!name || !constructorName) { return name || constructorName; } if (name === 'Error') { return constructorName; } return name; } module.exports = { guessFunctionName: guessFunctionName, guessErrorClass: guessErrorClass, gatherContext: gatherContext, parse: parse, Stack: Stack, Frame: Frame };