|
|
|
"use strict";
|
|
|
|
|
|
|
|
// FIXME: Move this into its own package!
|
|
|
|
|
|
|
|
const execall = require("execall");
|
|
|
|
const defaultValue = require("default-value");
|
|
|
|
|
|
|
|
// I'm so, so sorry...
|
|
|
|
let lineRegex = /\s+at\s+(?:(?:((?:[^\[$\n]|$)+)\[as ([^\]]+)\] |((?:[^\(\n]|$)+))\(([^\)\n]+)\)|([^\n]+))(?:\n|$)/gm;
|
|
|
|
let positionRegex = /(.+):(\d+):(\d+)/;
|
|
|
|
|
|
|
|
function maybeTrim(value) {
|
|
|
|
if (value != null) {
|
|
|
|
return value.trim();
|
|
|
|
} else {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseLocation(locationString) {
|
|
|
|
if (locationString === "<anonymous>") {
|
|
|
|
return { anonymous: true };
|
|
|
|
} else {
|
|
|
|
let match = positionRegex.exec(locationString);
|
|
|
|
|
|
|
|
if (match != null) {
|
|
|
|
return {
|
|
|
|
path: match[1],
|
|
|
|
line: parseInt(match[2]),
|
|
|
|
column: parseInt(match[3])
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
throw new Error(`Could not parse location from string: ${locationString}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function extractFrames(stack) {
|
|
|
|
// TODO: Maybe make this code even more cautious, and match each stacktrace line individually, aborting as soon as any one line cannot be parsed?
|
|
|
|
let matches = execall(lineRegex, stack);
|
|
|
|
|
|
|
|
return matches.map((match) => {
|
|
|
|
let groups = match.subMatches;
|
|
|
|
|
|
|
|
return {
|
|
|
|
functionName: maybeTrim(defaultValue(groups[0], groups[2])),
|
|
|
|
alias: groups[1],
|
|
|
|
location: parseLocation(defaultValue(groups[3], groups[4]))
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = function parseStackTrace(error) {
|
|
|
|
let stack = error.stack;
|
|
|
|
let lines = stack.split("\n");
|
|
|
|
|
|
|
|
let firstStackLine = lines
|
|
|
|
.map((line) => line.trim())
|
|
|
|
.findIndex((line) => line.startsWith("at ") && positionRegex.test(line));
|
|
|
|
|
|
|
|
if (firstStackLine !== -1) {
|
|
|
|
let cleanStack = lines
|
|
|
|
.slice(firstStackLine)
|
|
|
|
.join("\n");
|
|
|
|
|
|
|
|
return extractFrames(cleanStack);
|
|
|
|
} else {
|
|
|
|
throw new Error(`Could not find a stacktrace frame`);
|
|
|
|
}
|
|
|
|
};
|