import type {ReactStackTrace} from 'shared/ReactTypes';
function prepareStackTrace(
error: Error,
structuredStackTrace: CallSite[],
): string {
const name = error.name || 'Error';
const message = error.message || '';
let stack = name + ': ' + message;
for (let i = 0; i < structuredStackTrace.length; i++) {
stack += '\n at ' + structuredStackTrace[i].toString();
}
return stack;
}
function getStack(error: Error): string {
const previousPrepare = Error.prepareStackTrace;
Error.prepareStackTrace = prepareStackTrace;
try {
return String(error.stack);
} finally {
Error.prepareStackTrace = previousPrepare;
}
}
const frameRegExp =
/^ {3} at (?:(.+) \((.+):(\d+):(\d+)\)|(?:async )?(.+):(\d+):(\d+))$/;
export function parseStackTrace(
error: Error,
skipFrames: number,
): ReactStackTrace {
let stack = getStack(error);
if (stack.startsWith('Error: react-stack-top-frame\n')) {
stack = stack.slice(29);
}
let idx = stack.indexOf('react-stack-bottom-frame');
if (idx !== -1) {
idx = stack.lastIndexOf('\n', idx);
}
if (idx !== -1) {
stack = stack.slice(0, idx);
}
const frames = stack.split('\n');
const parsedFrames: ReactStackTrace = [];
for (let i = skipFrames; i < frames.length; i++) {
const parsed = frameRegExp.exec(frames[i]);
if (!parsed) {
continue;
}
let name = parsed[1] || '';
if (name === '<anonymous>') {
name = '';
}
let filename = parsed[2] || parsed[5] || '';
if (filename === '<anonymous>') {
filename = '';
}
const line = +(parsed[3] || parsed[6]);
const col = +(parsed[4] || parsed[7]);
parsedFrames.push([name, filename, line, col]);
}
return parsedFrames;
}