123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- Object.defineProperty(exports, '__esModule', { value: true });
- const nodeStackTrace = require('./node-stack-trace.js');
- const STACKTRACE_FRAME_LIMIT = 50;
- // Used to sanitize webpack (error: *) wrapped stack errors
- const WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
- const STRIP_FRAME_REGEXP = /captureMessage|captureException/;
- /**
- * Creates a stack parser with the supplied line parsers
- *
- * StackFrames are returned in the correct order for Sentry Exception
- * frames and with Sentry SDK internal frames removed from the top and bottom
- *
- */
- function createStackParser(...parsers) {
- const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
- return (stack, skipFirst = 0) => {
- const frames = [];
- const lines = stack.split('\n');
- for (let i = skipFirst; i < lines.length; i++) {
- const line = lines[i];
- // Ignore lines over 1kb as they are unlikely to be stack frames.
- // Many of the regular expressions use backtracking which results in run time that increases exponentially with
- // input size. Huge strings can result in hangs/Denial of Service:
- // https://github.com/getsentry/sentry-javascript/issues/2286
- if (line.length > 1024) {
- continue;
- }
- // https://github.com/getsentry/sentry-javascript/issues/5459
- // Remove webpack (error: *) wrappers
- const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
- // https://github.com/getsentry/sentry-javascript/issues/7813
- // Skip Error: lines
- if (cleanedLine.match(/\S*Error: /)) {
- continue;
- }
- for (const parser of sortedParsers) {
- const frame = parser(cleanedLine);
- if (frame) {
- frames.push(frame);
- break;
- }
- }
- if (frames.length >= STACKTRACE_FRAME_LIMIT) {
- break;
- }
- }
- return stripSentryFramesAndReverse(frames);
- };
- }
- /**
- * Gets a stack parser implementation from Options.stackParser
- * @see Options
- *
- * If options contains an array of line parsers, it is converted into a parser
- */
- function stackParserFromStackParserOptions(stackParser) {
- if (Array.isArray(stackParser)) {
- return createStackParser(...stackParser);
- }
- return stackParser;
- }
- /**
- * Removes Sentry frames from the top and bottom of the stack if present and enforces a limit of max number of frames.
- * Assumes stack input is ordered from top to bottom and returns the reverse representation so call site of the
- * function that caused the crash is the last frame in the array.
- * @hidden
- */
- function stripSentryFramesAndReverse(stack) {
- if (!stack.length) {
- return [];
- }
- const localStack = Array.from(stack);
- // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
- if (/sentryWrapped/.test(localStack[localStack.length - 1].function || '')) {
- localStack.pop();
- }
- // Reversing in the middle of the procedure allows us to just pop the values off the stack
- localStack.reverse();
- // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
- if (STRIP_FRAME_REGEXP.test(localStack[localStack.length - 1].function || '')) {
- localStack.pop();
- // When using synthetic events, we will have a 2 levels deep stack, as `new Error('Sentry syntheticException')`
- // is produced within the hub itself, making it:
- //
- // Sentry.captureException()
- // getCurrentHub().captureException()
- //
- // instead of just the top `Sentry` call itself.
- // This forces us to possibly strip an additional frame in the exact same was as above.
- if (STRIP_FRAME_REGEXP.test(localStack[localStack.length - 1].function || '')) {
- localStack.pop();
- }
- }
- return localStack.slice(0, STACKTRACE_FRAME_LIMIT).map(frame => ({
- ...frame,
- filename: frame.filename || localStack[localStack.length - 1].filename,
- function: frame.function || '?',
- }));
- }
- const defaultFunctionName = '<anonymous>';
- /**
- * Safely extract function name from itself
- */
- function getFunctionName(fn) {
- try {
- if (!fn || typeof fn !== 'function') {
- return defaultFunctionName;
- }
- return fn.name || defaultFunctionName;
- } catch (e) {
- // Just accessing custom props in some Selenium environments
- // can cause a "Permission denied" exception (see raven-js#495).
- return defaultFunctionName;
- }
- }
- /**
- * Node.js stack line parser
- *
- * This is in @sentry/utils so it can be used from the Electron SDK in the browser for when `nodeIntegration == true`.
- * This allows it to be used without referencing or importing any node specific code which causes bundlers to complain
- */
- function nodeStackLineParser(getModule) {
- return [90, nodeStackTrace.node(getModule)];
- }
- exports.filenameIsInApp = nodeStackTrace.filenameIsInApp;
- exports.createStackParser = createStackParser;
- exports.getFunctionName = getFunctionName;
- exports.nodeStackLineParser = nodeStackLineParser;
- exports.stackParserFromStackParserOptions = stackParserFromStackParserOptions;
- exports.stripSentryFramesAndReverse = stripSentryFramesAndReverse;
- //# sourceMappingURL=stacktrace.js.map
|