@visulima/error 5.0.2 → 5.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -1
- package/LICENSE.md +1 -1
- package/dist/code-frame/index.js +125 -6
- package/dist/error/index.js +8 -1
- package/dist/index.js +16 -1
- package/dist/packem_shared/NonError-D5FGLYKY.js +8 -0
- package/dist/packem_shared/addKnownErrorConstructor-s_3SsXtQ.js +30 -0
- package/dist/packem_shared/aiFinder-HftEgsry.js +277 -0
- package/dist/packem_shared/aiSolutionResponse-CJBMLS9t.js +34 -0
- package/dist/packem_shared/captureRawStackTrace-ySw7cU0U.js +10 -0
- package/dist/packem_shared/deserializeError-E0VQnnm0.js +116 -0
- package/dist/packem_shared/errorHintFinder-DEaeRnRW.js +21 -0
- package/dist/packem_shared/formatStackFrameLine-D3_6oSWZ.js +24 -0
- package/dist/packem_shared/getErrorCauses-DpUsmuqw.js +43 -0
- package/dist/packem_shared/index-y_UPkY2Z.js +9 -0
- package/dist/packem_shared/indexToLineColumn-Bg8UW1bU.js +50 -0
- package/dist/packem_shared/isVisulimaError-DA7QsCxH.js +34 -0
- package/dist/packem_shared/parseStacktrace-oQvk7wYp.js +273 -0
- package/dist/packem_shared/renderError-C30PRFtU.js +206 -0
- package/dist/packem_shared/ruleBasedFinder-C2F8rQ30.js +207 -0
- package/dist/packem_shared/serializeError-BZ62KiYZ.js +142 -0
- package/dist/solution/ai/ai-prompt.js +13 -7
- package/dist/solution/ai/index.js +3 -1
- package/dist/solution/index.js +2 -1
- package/dist/stacktrace/index.js +2 -1
- package/package.json +1 -1
- package/dist/packem_shared/NonError-CS10kwil.js +0 -1
- package/dist/packem_shared/addKnownErrorConstructor-BqqnTSZp.js +0 -1
- package/dist/packem_shared/aiFinder-McmYwPGR.js +0 -1
- package/dist/packem_shared/aiSolutionResponse-RD0AK1jh.js +0 -10
- package/dist/packem_shared/captureRawStackTrace-CQPNHvBG.js +0 -1
- package/dist/packem_shared/deserializeError-BJM8Kd6G.js +0 -1
- package/dist/packem_shared/errorHintFinder-C_g0nvml.js +0 -2
- package/dist/packem_shared/formatStackFrameLine-iU54KA81.js +0 -2
- package/dist/packem_shared/getErrorCauses-geeK5cwE.js +0 -1
- package/dist/packem_shared/index-CLFYRLyq.js +0 -1
- package/dist/packem_shared/indexToLineColumn-B1F7aNZh.js +0 -1
- package/dist/packem_shared/isVisulimaError-jVZgumOU.js +0 -1
- package/dist/packem_shared/parseStacktrace-Dnxnc4PL.js +0 -2
- package/dist/packem_shared/renderError-ZMlMvw1N.js +0 -18
- package/dist/packem_shared/ruleBasedFinder-P88d0gpK.js +0 -34
- package/dist/packem_shared/serializeError-CTpDr3CL.js +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { i as isPlainObject } from './index-y_UPkY2Z.js';
|
|
2
|
+
import { isErrorLike, getErrorConstructor } from './addKnownErrorConstructor-s_3SsXtQ.js';
|
|
3
|
+
import NonError from './NonError-D5FGLYKY.js';
|
|
4
|
+
|
|
5
|
+
const defaultOptions = {
|
|
6
|
+
maxDepth: Number.POSITIVE_INFINITY
|
|
7
|
+
};
|
|
8
|
+
const deserializePlainObject = (object, options, depth = 0) => {
|
|
9
|
+
if (isErrorLike(object)) {
|
|
10
|
+
return reconstructError(object, options, depth);
|
|
11
|
+
}
|
|
12
|
+
if (options.maxDepth !== void 0 && depth >= options.maxDepth) {
|
|
13
|
+
return new NonError(JSON.stringify(object));
|
|
14
|
+
}
|
|
15
|
+
return new NonError(JSON.stringify(object));
|
|
16
|
+
};
|
|
17
|
+
const reconstructAggregateError = (Constructor, errors, message, options, depth) => {
|
|
18
|
+
const reconstructedErrors = errors.map((error_) => deserializeValue(error_, options, depth + 1));
|
|
19
|
+
return new Constructor(reconstructedErrors, message);
|
|
20
|
+
};
|
|
21
|
+
const reconstructError = (serialized, options, depth) => {
|
|
22
|
+
if (options.maxDepth !== void 0 && depth >= options.maxDepth) {
|
|
23
|
+
return new NonError(JSON.stringify(serialized));
|
|
24
|
+
}
|
|
25
|
+
const { cause, errors, message, name, stack, ...properties } = serialized;
|
|
26
|
+
const Constructor = getErrorConstructor(name) || Error;
|
|
27
|
+
const error = name === "AggregateError" && Array.isArray(errors) ? reconstructAggregateError(Constructor, errors, message, options, depth) : new Constructor(message);
|
|
28
|
+
if (!error.name && name) {
|
|
29
|
+
error.name = name;
|
|
30
|
+
}
|
|
31
|
+
if (message !== void 0) {
|
|
32
|
+
error.message = message;
|
|
33
|
+
}
|
|
34
|
+
if (stack) {
|
|
35
|
+
error.stack = stack;
|
|
36
|
+
}
|
|
37
|
+
restoreErrorProperties(error, properties, cause, name, options, depth);
|
|
38
|
+
if (cause !== void 0) {
|
|
39
|
+
error.cause = deserializeValue(cause, options, depth + 1);
|
|
40
|
+
}
|
|
41
|
+
makePropertiesEnumerable(error, serialized);
|
|
42
|
+
return error;
|
|
43
|
+
};
|
|
44
|
+
const deserializeValue = (value, options, depth) => {
|
|
45
|
+
if (isPlainObject(value)) {
|
|
46
|
+
return deserializePlainObject(value, options, depth);
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
return value.map((item) => deserializeValue(item, options, depth));
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
};
|
|
53
|
+
const restoreErrorProperties = (error, properties, cause, name, options, depth) => {
|
|
54
|
+
const errorCopy = error;
|
|
55
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
56
|
+
if (key === "cause" && cause !== void 0) {
|
|
57
|
+
continue;
|
|
58
|
+
} else if (key === "errors" && name === "AggregateError") {
|
|
59
|
+
continue;
|
|
60
|
+
} else {
|
|
61
|
+
errorCopy[key] = deserializeValue(value, options, depth + 1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const makePropertiesEnumerable = (error, serialized) => {
|
|
66
|
+
const errorProperties = /* @__PURE__ */ new Set();
|
|
67
|
+
errorProperties.add("name");
|
|
68
|
+
errorProperties.add("message");
|
|
69
|
+
errorProperties.add("stack");
|
|
70
|
+
for (const key of Object.keys(serialized)) {
|
|
71
|
+
errorProperties.add(key);
|
|
72
|
+
}
|
|
73
|
+
for (const key of errorProperties) {
|
|
74
|
+
if (key in error) {
|
|
75
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, key);
|
|
76
|
+
if (descriptor && !descriptor.enumerable) {
|
|
77
|
+
Object.defineProperty(error, key, {
|
|
78
|
+
...descriptor,
|
|
79
|
+
enumerable: true
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const handlePrimitive = (value) => new NonError(JSON.stringify(value));
|
|
86
|
+
const handleArray = (value) => new NonError(JSON.stringify(value));
|
|
87
|
+
const handlePlainObject = (value, config) => {
|
|
88
|
+
if (isErrorLike(value)) {
|
|
89
|
+
return reconstructError(value, config, 0);
|
|
90
|
+
}
|
|
91
|
+
return deserializePlainObject(value, config);
|
|
92
|
+
};
|
|
93
|
+
const deserialize = (value, options = {}) => {
|
|
94
|
+
const config = { ...defaultOptions, ...options };
|
|
95
|
+
if (value instanceof Error) {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
if (value === null) {
|
|
99
|
+
return handlePrimitive(null);
|
|
100
|
+
}
|
|
101
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
102
|
+
return handlePrimitive(value);
|
|
103
|
+
}
|
|
104
|
+
if (Array.isArray(value)) {
|
|
105
|
+
return handleArray(value);
|
|
106
|
+
}
|
|
107
|
+
if (isErrorLike(value)) {
|
|
108
|
+
return reconstructError(value, config, 0);
|
|
109
|
+
}
|
|
110
|
+
if (isPlainObject(value)) {
|
|
111
|
+
return handlePlainObject(value, config);
|
|
112
|
+
}
|
|
113
|
+
return new NonError(JSON.stringify(value));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { deserialize as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const errorHintFinder = {
|
|
2
|
+
handle: async (error) => {
|
|
3
|
+
if (error.hint === void 0 || error.hint === null) {
|
|
4
|
+
return void 0;
|
|
5
|
+
}
|
|
6
|
+
if (typeof error.hint === "string" && error.hint !== "") {
|
|
7
|
+
return { body: error.hint };
|
|
8
|
+
}
|
|
9
|
+
if (typeof error.hint === "object" && typeof error.hint.body === "string") {
|
|
10
|
+
return error.hint;
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(error.hint)) {
|
|
13
|
+
return { body: error.hint.join("\n") };
|
|
14
|
+
}
|
|
15
|
+
return void 0;
|
|
16
|
+
},
|
|
17
|
+
name: "errorHint",
|
|
18
|
+
priority: 1
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { errorHintFinder as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const formatStackFrameLine = (frame) => {
|
|
2
|
+
const method = frame.methodName && frame.methodName !== "<unknown>" ? `${frame.methodName} ` : "";
|
|
3
|
+
const file = frame.file ?? "<unknown>";
|
|
4
|
+
const line = frame.line ?? 0;
|
|
5
|
+
const column = frame.column ?? 0;
|
|
6
|
+
if (method.trim()) {
|
|
7
|
+
return ` at ${method}(${file}:${line}:${column})`;
|
|
8
|
+
}
|
|
9
|
+
return ` at ${file}:${line}:${column}`;
|
|
10
|
+
};
|
|
11
|
+
const formatStacktrace = (frames, options) => {
|
|
12
|
+
const lines = [];
|
|
13
|
+
if (options?.header && (options.header.name || options.header.message)) {
|
|
14
|
+
const headerName = String(options.header.name || "Error");
|
|
15
|
+
const headerMessage = String(options.header.message || "");
|
|
16
|
+
lines.push(`${headerName}${headerMessage ? ": " : ""}${headerMessage}`);
|
|
17
|
+
}
|
|
18
|
+
for (const frame of frames) {
|
|
19
|
+
lines.push(formatStackFrameLine(frame));
|
|
20
|
+
}
|
|
21
|
+
return lines.join("\n");
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { formatStackFrameLine, formatStacktrace };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRequire as __cjs_createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const __cjs_require = __cjs_createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
|
|
6
|
+
|
|
7
|
+
const __cjs_getBuiltinModule = (module) => {
|
|
8
|
+
// Check if we're in Node.js and version supports getBuiltinModule
|
|
9
|
+
if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
|
|
10
|
+
const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
|
|
11
|
+
// Node.js 20.16.0+ and 22.3.0+
|
|
12
|
+
if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
|
|
13
|
+
return __cjs_getProcess.getBuiltinModule(module);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// Fallback to createRequire
|
|
17
|
+
return __cjs_require(module);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
inspect
|
|
22
|
+
} = __cjs_getBuiltinModule("node:util");
|
|
23
|
+
|
|
24
|
+
const getErrorCauses = (error) => {
|
|
25
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26
|
+
const causes = [];
|
|
27
|
+
let currentError = error;
|
|
28
|
+
while (currentError) {
|
|
29
|
+
if (seen.has(currentError)) {
|
|
30
|
+
console.error(`Circular reference detected in error causes: ${inspect(error)}`);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
causes.push(currentError);
|
|
34
|
+
seen.add(currentError);
|
|
35
|
+
if (!currentError.cause) {
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
currentError = currentError.cause;
|
|
39
|
+
}
|
|
40
|
+
return causes;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { getErrorCauses as default };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
function isPlainObject(value) {
|
|
2
|
+
if (typeof value !== "object" || value === null) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
const prototype = Object.getPrototypeOf(value);
|
|
6
|
+
return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { isPlainObject as i };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const binarySearch = (element, array) => {
|
|
2
|
+
let m = 0;
|
|
3
|
+
let n = array.length - 2;
|
|
4
|
+
while (m < n) {
|
|
5
|
+
const key = m + (n - m >> 1);
|
|
6
|
+
if (element < array[key]) {
|
|
7
|
+
n = key - 1;
|
|
8
|
+
} else if (element >= array[key + 1]) {
|
|
9
|
+
m = key + 1;
|
|
10
|
+
} else {
|
|
11
|
+
m = key;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return m;
|
|
16
|
+
};
|
|
17
|
+
const getLineStartIndexes = (string_) => (
|
|
18
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
19
|
+
string_.split(/\n|\r(?!\n)/).reduce(
|
|
20
|
+
(accumulator, current) => {
|
|
21
|
+
accumulator.push(accumulator.at(-1) + current.length + 1);
|
|
22
|
+
return accumulator;
|
|
23
|
+
},
|
|
24
|
+
[0]
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
const indexToLineColumn = (input, index, options) => {
|
|
28
|
+
const skipChecks = options?.skipChecks ?? false;
|
|
29
|
+
if (!skipChecks && (!Array.isArray(input) && typeof input !== "string" || (typeof input === "string" || Array.isArray(input)) && input.length === 0)) {
|
|
30
|
+
return { column: 0, line: 0 };
|
|
31
|
+
}
|
|
32
|
+
if (!skipChecks && (typeof index !== "number" || typeof input === "string" && index >= input.length || Array.isArray(input) && index + 1 >= input.at(-1))) {
|
|
33
|
+
return { column: 0, line: 0 };
|
|
34
|
+
}
|
|
35
|
+
if (typeof input === "string") {
|
|
36
|
+
const startIndexesOfEachLine = getLineStartIndexes(input);
|
|
37
|
+
const line2 = binarySearch(index, startIndexesOfEachLine);
|
|
38
|
+
return {
|
|
39
|
+
column: index - startIndexesOfEachLine[line2] + 1,
|
|
40
|
+
line: line2 + 1
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const line = binarySearch(index, input);
|
|
44
|
+
return {
|
|
45
|
+
column: index - input[line] + 1,
|
|
46
|
+
line: line + 1
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { indexToLineColumn as default };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const isVisulimaError = (error) => error instanceof Error && error.type === "VisulimaError";
|
|
2
|
+
class VisulimaError extends Error {
|
|
3
|
+
loc;
|
|
4
|
+
title;
|
|
5
|
+
/**
|
|
6
|
+
* A message that explains to the user how they can fix the error.
|
|
7
|
+
*/
|
|
8
|
+
hint;
|
|
9
|
+
type = "VisulimaError";
|
|
10
|
+
constructor({ cause, hint, location, message, name, stack, title }) {
|
|
11
|
+
super(message, {
|
|
12
|
+
cause
|
|
13
|
+
});
|
|
14
|
+
this.title = title;
|
|
15
|
+
this.name = name;
|
|
16
|
+
this.stack = stack ?? this.stack;
|
|
17
|
+
this.loc = location;
|
|
18
|
+
this.hint = hint;
|
|
19
|
+
}
|
|
20
|
+
setLocation(location) {
|
|
21
|
+
this.loc = location;
|
|
22
|
+
}
|
|
23
|
+
setName(name) {
|
|
24
|
+
this.name = name;
|
|
25
|
+
}
|
|
26
|
+
setMessage(message) {
|
|
27
|
+
this.message = message;
|
|
28
|
+
}
|
|
29
|
+
setHint(hint) {
|
|
30
|
+
this.hint = hint;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { VisulimaError, isVisulimaError };
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
const debugLog = (message, ...arguments_) => {
|
|
2
|
+
if (process.env.DEBUG && String(process.env.DEBUG) === "true") {
|
|
3
|
+
console.debug(`error:parse-stacktrace: ${message}`, ...arguments_);
|
|
4
|
+
}
|
|
5
|
+
};
|
|
6
|
+
const UNKNOWN_FUNCTION = "<unknown>";
|
|
7
|
+
const CHROMIUM_REGEX = /^.*?\s*at\s(?:(.+?\)(?:\s\[.+\])?|\(?.*?)\s?\((?:address\sat\s)?)?(?:async\s)?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
8
|
+
const CHROMIUM_EVAL_REGEX = /\((\S+)\),\s(<[^>]+>)?:(\d+)?:(\d+)?\)?/;
|
|
9
|
+
const CHROMIUM_MAPPED = /(.*?):(\d+):(\d+)(\s<-\s(.+):(\d+):(\d+))?/;
|
|
10
|
+
const WINDOWS_EVAL_REGEX = /(eval)\sat\s(<anonymous>)\s\((.*)\)?:(\d+)?:(\d+)\),\s*(<anonymous>)?:(\d+)?:(\d+)/;
|
|
11
|
+
const NODE_REGEX = /^\s*in\s(?:([^\\/]+(?:\s\[as\s\S+\])?)\s\(?)?\(at?\s?(.*?):(\d+)(?::(\d+))?\)?\s*$/;
|
|
12
|
+
const NODE_NESTED_REGEX = /in\s(.*)\s\(at\s(.+)\)\sat/;
|
|
13
|
+
const REACT_ANDROID_NATIVE_REGEX = /^(?:.*@)?(.*):(\d+):(\d+)$/;
|
|
14
|
+
const GECKO_REGEX = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. \/=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
15
|
+
const GECKO_EVAL_REGEX = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
16
|
+
const FIREFOX_REGEX = /(\S[^\s[]*\[.*\]|.*?)@(.*):(\d+):(\d+)/;
|
|
17
|
+
const WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
|
|
18
|
+
const extractSafariExtensionDetails = (methodName, url) => {
|
|
19
|
+
const isSafariExtension = methodName.includes("safari-extension");
|
|
20
|
+
const isSafariWebExtension = methodName.includes("safari-web-extension");
|
|
21
|
+
return isSafariExtension || isSafariWebExtension ? [
|
|
22
|
+
methodName.includes("@") ? methodName.split("@")[0] : UNKNOWN_FUNCTION,
|
|
23
|
+
isSafariExtension ? `safari-extension:${url}` : `safari-web-extension:${url}`
|
|
24
|
+
] : [methodName, url];
|
|
25
|
+
};
|
|
26
|
+
const parseMapped = (trace, maybeMapped) => {
|
|
27
|
+
const match = CHROMIUM_MAPPED.exec(maybeMapped);
|
|
28
|
+
if (match) {
|
|
29
|
+
trace.file = match[1];
|
|
30
|
+
trace.line = +match[2];
|
|
31
|
+
trace.column = +match[3];
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const parseNode = (line) => {
|
|
35
|
+
const nestedNode = NODE_NESTED_REGEX.exec(line);
|
|
36
|
+
if (nestedNode) {
|
|
37
|
+
debugLog(`parse nested node error stack line: "${line}"`, `found: ${JSON.stringify(nestedNode)}`);
|
|
38
|
+
const split = nestedNode[2].split(":");
|
|
39
|
+
return {
|
|
40
|
+
column: split[2] ? +split[2] : void 0,
|
|
41
|
+
file: split[0],
|
|
42
|
+
line: split[1] ? +split[1] : void 0,
|
|
43
|
+
methodName: nestedNode[1] || UNKNOWN_FUNCTION,
|
|
44
|
+
raw: line,
|
|
45
|
+
type: void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const node = NODE_REGEX.exec(line);
|
|
49
|
+
if (node) {
|
|
50
|
+
debugLog(`parse node error stack line: "${line}"`, `found: ${JSON.stringify(node)}`);
|
|
51
|
+
const trace = {
|
|
52
|
+
column: node[4] ? +node[4] : void 0,
|
|
53
|
+
file: node[2] ? node[2].replace(/at\s/, "") : void 0,
|
|
54
|
+
line: node[3] ? +node[3] : void 0,
|
|
55
|
+
methodName: node[1] || UNKNOWN_FUNCTION,
|
|
56
|
+
raw: line,
|
|
57
|
+
type: line.startsWith("internal") ? "internal" : void 0
|
|
58
|
+
};
|
|
59
|
+
parseMapped(trace, `${node[2]}:${node[3]}:${node[4]}`);
|
|
60
|
+
return trace;
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
};
|
|
64
|
+
const parseChromium = (line) => {
|
|
65
|
+
const parts = CHROMIUM_REGEX.exec(line);
|
|
66
|
+
if (parts) {
|
|
67
|
+
debugLog(`parse chrome error stack line: "${line}"`, `found: ${JSON.stringify(parts)}`);
|
|
68
|
+
const isNative = parts[2]?.startsWith("native");
|
|
69
|
+
const isEval = parts[2]?.startsWith("eval") || parts[1]?.startsWith("eval");
|
|
70
|
+
let evalOrigin;
|
|
71
|
+
let windowsParts;
|
|
72
|
+
if (isEval) {
|
|
73
|
+
const subMatch = CHROMIUM_EVAL_REGEX.exec(line);
|
|
74
|
+
if (subMatch) {
|
|
75
|
+
const split = /^(\S+):(\d+):(\d+)$|^(\S+):(\d+)$/.exec(subMatch[1]);
|
|
76
|
+
if (split) {
|
|
77
|
+
parts[2] = split[4] ?? split[1];
|
|
78
|
+
parts[3] = split[5] ?? split[2];
|
|
79
|
+
parts[4] = split[3];
|
|
80
|
+
} else if (subMatch[2]) {
|
|
81
|
+
parts[2] = subMatch[1];
|
|
82
|
+
}
|
|
83
|
+
if (subMatch[2]) {
|
|
84
|
+
evalOrigin = {
|
|
85
|
+
column: subMatch[4] ? +subMatch[4] : void 0,
|
|
86
|
+
file: subMatch[2],
|
|
87
|
+
line: subMatch[3] ? +subMatch[3] : void 0,
|
|
88
|
+
methodName: "eval",
|
|
89
|
+
raw: line,
|
|
90
|
+
type: "eval"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
const windowsSubMatch = WINDOWS_EVAL_REGEX.exec(line);
|
|
95
|
+
if (windowsSubMatch) {
|
|
96
|
+
windowsParts = {
|
|
97
|
+
column: windowsSubMatch[5] ? +windowsSubMatch[5] : void 0,
|
|
98
|
+
file: windowsSubMatch[3],
|
|
99
|
+
line: windowsSubMatch[4] ? +windowsSubMatch[4] : void 0
|
|
100
|
+
};
|
|
101
|
+
evalOrigin = {
|
|
102
|
+
column: windowsSubMatch[8] ? +windowsSubMatch[8] : void 0,
|
|
103
|
+
file: windowsSubMatch[2],
|
|
104
|
+
line: windowsSubMatch[7] ? +windowsSubMatch[7] : void 0,
|
|
105
|
+
methodName: "eval",
|
|
106
|
+
raw: windowsSubMatch[0],
|
|
107
|
+
type: "eval"
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const [methodName, file] = extractSafariExtensionDetails(
|
|
113
|
+
// Normalize IE's 'Anonymous function'
|
|
114
|
+
parts[1] ? parts[1].replace(/^Anonymous function$/, "<anonymous>") : UNKNOWN_FUNCTION,
|
|
115
|
+
parts[2]
|
|
116
|
+
);
|
|
117
|
+
const trace = {
|
|
118
|
+
column: parts[4] ? +parts[4] : void 0,
|
|
119
|
+
evalOrigin,
|
|
120
|
+
file,
|
|
121
|
+
line: parts[3] ? +parts[3] : void 0,
|
|
122
|
+
methodName,
|
|
123
|
+
raw: line,
|
|
124
|
+
// eslint-disable-next-line sonarjs/no-nested-conditional
|
|
125
|
+
type: isEval ? "eval" : isNative ? "native" : void 0
|
|
126
|
+
};
|
|
127
|
+
if (windowsParts) {
|
|
128
|
+
trace.column = windowsParts.column;
|
|
129
|
+
trace.file = windowsParts.file;
|
|
130
|
+
trace.line = windowsParts.line;
|
|
131
|
+
} else {
|
|
132
|
+
parseMapped(trace, `${file}:${parts[3]}:${parts[4]}`);
|
|
133
|
+
}
|
|
134
|
+
return trace;
|
|
135
|
+
}
|
|
136
|
+
return void 0;
|
|
137
|
+
};
|
|
138
|
+
const parseGecko = (line, topFrameMeta) => {
|
|
139
|
+
const parts = GECKO_REGEX.exec(line);
|
|
140
|
+
if (parts) {
|
|
141
|
+
debugLog(`parse gecko error stack line: "${line}"`, `found: ${JSON.stringify(parts)}`);
|
|
142
|
+
const isEval = parts[3]?.includes(" > eval");
|
|
143
|
+
const subMatch = isEval && parts[3] && GECKO_EVAL_REGEX.exec(parts[3]);
|
|
144
|
+
let evalOrigin;
|
|
145
|
+
if (isEval && subMatch) {
|
|
146
|
+
parts[3] = subMatch[1];
|
|
147
|
+
evalOrigin = {
|
|
148
|
+
column: parts[5] ? +parts[5] : void 0,
|
|
149
|
+
file: parts[3],
|
|
150
|
+
line: parts[4] ? +parts[4] : void 0,
|
|
151
|
+
methodName: "eval",
|
|
152
|
+
raw: line,
|
|
153
|
+
type: "eval"
|
|
154
|
+
};
|
|
155
|
+
parts[4] = subMatch[2];
|
|
156
|
+
}
|
|
157
|
+
const [methodName, file] = extractSafariExtensionDetails(
|
|
158
|
+
// Normalize IE's 'Anonymous function'
|
|
159
|
+
parts[1] ? parts[1].replace(/^Anonymous function$/, "<anonymous>") : UNKNOWN_FUNCTION,
|
|
160
|
+
parts[3]
|
|
161
|
+
);
|
|
162
|
+
let column;
|
|
163
|
+
if ((topFrameMeta?.type === "safari" || !isEval && topFrameMeta?.type === "firefox") && topFrameMeta.column) {
|
|
164
|
+
column = topFrameMeta.column;
|
|
165
|
+
} else if (!isEval && parts[5]) {
|
|
166
|
+
column = +parts[5];
|
|
167
|
+
}
|
|
168
|
+
let lineNumber;
|
|
169
|
+
if ((topFrameMeta?.type === "safari" || !isEval && topFrameMeta?.type === "firefox") && topFrameMeta.line) {
|
|
170
|
+
lineNumber = topFrameMeta.line;
|
|
171
|
+
} else if (parts[4]) {
|
|
172
|
+
lineNumber = +parts[4];
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
column,
|
|
176
|
+
evalOrigin,
|
|
177
|
+
file,
|
|
178
|
+
line: lineNumber,
|
|
179
|
+
methodName,
|
|
180
|
+
raw: line,
|
|
181
|
+
// eslint-disable-next-line sonarjs/no-nested-conditional
|
|
182
|
+
type: isEval ? "eval" : file.includes("[native code]") ? "native" : void 0
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return void 0;
|
|
186
|
+
};
|
|
187
|
+
const parseFirefox = (line, topFrameMeta) => {
|
|
188
|
+
const parts = FIREFOX_REGEX.exec(line);
|
|
189
|
+
const isEval = parts ? parts[2].includes(" > eval") : false;
|
|
190
|
+
if (!isEval && parts) {
|
|
191
|
+
debugLog(`parse firefox error stack line: "${line}"`, `found: ${JSON.stringify(parts)}`);
|
|
192
|
+
return {
|
|
193
|
+
column: parts[4] ? +parts[4] : topFrameMeta?.column ?? void 0,
|
|
194
|
+
file: parts[2],
|
|
195
|
+
line: parts[3] ? +parts[3] : topFrameMeta?.line ?? void 0,
|
|
196
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
197
|
+
raw: line,
|
|
198
|
+
type: void 0
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return void 0;
|
|
202
|
+
};
|
|
203
|
+
const parseReactAndroidNative = (line) => {
|
|
204
|
+
const parts = REACT_ANDROID_NATIVE_REGEX.exec(line);
|
|
205
|
+
if (parts) {
|
|
206
|
+
debugLog(`parse react android native error stack line: "${line}"`, `found: ${JSON.stringify(parts)}`);
|
|
207
|
+
return {
|
|
208
|
+
column: parts[3] ? +parts[3] : void 0,
|
|
209
|
+
file: parts[1],
|
|
210
|
+
line: parts[2] ? +parts[2] : void 0,
|
|
211
|
+
methodName: UNKNOWN_FUNCTION,
|
|
212
|
+
raw: line,
|
|
213
|
+
type: void 0
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return void 0;
|
|
217
|
+
};
|
|
218
|
+
const parseStacktrace = (error, { filter, frameLimit = 50 } = {}) => {
|
|
219
|
+
let lines = (error.stacktrace ?? error.stack ?? "").split("\n").map((line) => {
|
|
220
|
+
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, "$1") : line;
|
|
221
|
+
return cleanedLine.replace(/^\s+|\s+$/g, "");
|
|
222
|
+
}).filter((line) => !/\S*(?:Error: |AggregateError:)/.test(line) && line !== "eval code");
|
|
223
|
+
if (filter) {
|
|
224
|
+
lines = lines.filter((element) => filter(element));
|
|
225
|
+
}
|
|
226
|
+
lines = lines.slice(0, frameLimit);
|
|
227
|
+
return lines.reduce((stack, line, currentIndex) => {
|
|
228
|
+
if (!line) {
|
|
229
|
+
return stack;
|
|
230
|
+
}
|
|
231
|
+
if (line.length > 1024) {
|
|
232
|
+
return stack;
|
|
233
|
+
}
|
|
234
|
+
let parseResult;
|
|
235
|
+
if (/^\s*in\s.*/.test(line)) {
|
|
236
|
+
parseResult = parseNode(line);
|
|
237
|
+
} else if (/^.*?\s*at\s.*/.test(line)) {
|
|
238
|
+
parseResult = parseChromium(line);
|
|
239
|
+
} else if (/^.*?\s*@.*|\[native code\]/.test(line)) {
|
|
240
|
+
let topFrameMeta;
|
|
241
|
+
if (currentIndex === 0) {
|
|
242
|
+
if (error.columnNumber || error.lineNumber) {
|
|
243
|
+
topFrameMeta = {
|
|
244
|
+
// @ts-expect-error columnNumber and columnNumber property only exists on Firefox
|
|
245
|
+
column: error.columnNumber,
|
|
246
|
+
// @ts-expect-error columnNumber and lineNumber property only exists on Firefox
|
|
247
|
+
line: error.lineNumber,
|
|
248
|
+
type: "firefox"
|
|
249
|
+
};
|
|
250
|
+
} else if (error.line || error.column) {
|
|
251
|
+
topFrameMeta = {
|
|
252
|
+
// @ts-expect-error column property only exists on safari
|
|
253
|
+
column: error.column,
|
|
254
|
+
// @ts-expect-error line property only exists on safari
|
|
255
|
+
line: error.line,
|
|
256
|
+
type: "safari"
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
parseResult = parseFirefox(line, topFrameMeta) || parseGecko(line, topFrameMeta);
|
|
261
|
+
} else {
|
|
262
|
+
parseResult = parseReactAndroidNative(line);
|
|
263
|
+
}
|
|
264
|
+
if (parseResult) {
|
|
265
|
+
stack.push(parseResult);
|
|
266
|
+
} else {
|
|
267
|
+
debugLog(`parse error stack line: "${line}"`, "not parser found");
|
|
268
|
+
}
|
|
269
|
+
return stack;
|
|
270
|
+
}, []);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
export { parseStacktrace as default };
|