@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
125 lines (103 loc) • 3.93 kB
JavaScript
import { UNKNOWN_FUNCTION } from './stacktrace.js';
/**
* Does this filename look like it's part of the app code?
*/
function filenameIsInApp(filename, isNative = false) {
const isInternal =
isNative ||
(filename &&
// It's not internal if it's an absolute linux path
!filename.startsWith('/') &&
// It's not internal if it's an absolute windows path
!filename.match(/^[A-Z]:/) &&
// It's not internal if the path is starting with a dot
!filename.startsWith('.') &&
// It's not internal if the frame has a protocol. In node, this is usually the case if the file got pre-processed with a bundler like webpack
!filename.match(/^[a-zA-Z]([a-zA-Z0-9.\-+])*:\/\//)); // Schema from: https://stackoverflow.com/a/3641782
// in_app is all that's not an internal Node function or a module within node_modules
// note that isNative appears to return true even for node core libraries
// see https://github.com/getsentry/raven-node/issues/176
return !isInternal && filename !== undefined && !filename.includes('node_modules/');
}
/** Node Stack line parser */
function node(getModule) {
const FILENAME_MATCH = /^\s*[-]{4,}$/;
const FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/;
// eslint-disable-next-line complexity
return (line) => {
const lineMatch = line.match(FULL_MATCH);
if (lineMatch) {
let object;
let method;
let functionName;
let typeName;
let methodName;
if (lineMatch[1]) {
functionName = lineMatch[1];
let methodStart = functionName.lastIndexOf('.');
if (functionName[methodStart - 1] === '.') {
methodStart--;
}
if (methodStart > 0) {
object = functionName.slice(0, methodStart);
method = functionName.slice(methodStart + 1);
const objectEnd = object.indexOf('.Module');
if (objectEnd > 0) {
functionName = functionName.slice(objectEnd + 1);
object = object.slice(0, objectEnd);
}
}
typeName = undefined;
}
if (method) {
typeName = object;
methodName = method;
}
if (method === '<anonymous>') {
methodName = undefined;
functionName = undefined;
}
if (functionName === undefined) {
methodName = methodName || UNKNOWN_FUNCTION;
functionName = typeName ? `${typeName}.${methodName}` : methodName;
}
let filename = lineMatch[2]?.startsWith('file://') ? lineMatch[2].slice(7) : lineMatch[2];
const isNative = lineMatch[5] === 'native';
// If it's a Windows path, trim the leading slash so that `/C:/foo` becomes `C:/foo`
if (filename?.match(/\/[A-Z]:/)) {
filename = filename.slice(1);
}
if (!filename && lineMatch[5] && !isNative) {
filename = lineMatch[5];
}
return {
filename: filename ? decodeURI(filename) : undefined,
module: getModule ? getModule(filename) : undefined,
function: functionName,
lineno: _parseIntOrUndefined(lineMatch[3]),
colno: _parseIntOrUndefined(lineMatch[4]),
in_app: filenameIsInApp(filename || '', isNative),
};
}
if (line.match(FILENAME_MATCH)) {
return {
filename: line,
};
}
return undefined;
};
}
/**
* Node.js stack line parser
*
* This is in @sentry/core 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, node(getModule)];
}
function _parseIntOrUndefined(input) {
return parseInt(input || '', 10) || undefined;
}
export { filenameIsInApp, node, nodeStackLineParser };
//# sourceMappingURL=node-stack-trace.js.map