@idlebox/common 1.5.13 → 1.5.14
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/lib/autoindex.d.ts +3 -3
- package/lib/autoindex.d.ts.map +1 -1
- package/lib/autoindex.js +4 -2
- package/lib/autoindex.js.map +1 -1
- package/lib/error/pretty.nodejs.d.ts +0 -29
- package/lib/error/pretty.nodejs.d.ts.map +1 -1
- package/lib/error/pretty.nodejs.js +157 -237
- package/lib/error/pretty.nodejs.js.map +1 -1
- package/lib/error/stack-parser.v8.d.ts +31 -0
- package/lib/error/stack-parser.v8.d.ts.map +1 -0
- package/lib/error/stack-parser.v8.js +106 -0
- package/lib/error/stack-parser.v8.js.map +1 -0
- package/package.json +7 -7
- package/src/autoindex.ts +5 -3
- package/src/error/pretty.nodejs.ts +214 -337
- package/src/error/stack-parser.v8.ts +157 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { isAbsolute } from '../path/isAbsolute.js';
|
|
2
|
+
|
|
3
|
+
const padding = /^(?<padding> {4})at /.source;
|
|
4
|
+
const func_call = /(?<func_name>(?:(?:async|new) )?[^/\\\s]+) (?:\[as (?<func_alias>[^\]]+)] )?/.source;
|
|
5
|
+
// xxxx.yyyyy [as eval]
|
|
6
|
+
const line_column = /(?::(?<line>\d+))?(?::(?<column>\d+))?/.source;
|
|
7
|
+
const locationEsm = /(?<schema>node:|file:\/\/|https?:\/\/)?(?<path2>[^:]+)/.source;
|
|
8
|
+
// node:internal/modules/cjs/loader.js:883:14
|
|
9
|
+
const locationCjs = /(?<path1>(?:\/|[a-zA-Z]:)[^:]+)/.source;
|
|
10
|
+
// /data/to/file.js
|
|
11
|
+
const location = `(?:${locationCjs}|${locationEsm})${line_column}`;
|
|
12
|
+
|
|
13
|
+
const regNormal = new RegExp(`${padding}${func_call}\\(${location}\\)$`);
|
|
14
|
+
type TypeMatchNormal = 'padding' | TypeMatchNoFile | TypeMatchFileOnly;
|
|
15
|
+
|
|
16
|
+
const regNoFile = new RegExp(`${padding}${func_call}$`);
|
|
17
|
+
type TypeMatchNoFile = 'padding' | 'func_name' | 'func_alias';
|
|
18
|
+
|
|
19
|
+
const regFileOnly = new RegExp(`${padding}${location}$`);
|
|
20
|
+
type TypeMatchFileOnly = 'padding' | 'schema' | 'path1' | 'path2' | 'line' | 'column';
|
|
21
|
+
|
|
22
|
+
const regEvalItem = new RegExp(`\\(eval at ${func_call}`, 'g');
|
|
23
|
+
const eval_source = /, (?<eval_func>[\S]+):(?<eval_line>\d+):(?<eval_column>\d+)/.source;
|
|
24
|
+
const regEval = new RegExp(`${padding}${func_call}.*?\\(${location}\\)+${eval_source}`);
|
|
25
|
+
type TypeMatchEval = 'padding' | TypeMatchNoFile | TypeMatchFileOnly | 'eval_func' | 'eval_line' | 'eval_column';
|
|
26
|
+
|
|
27
|
+
const regInvalid = new RegExp(`${padding}(?<content>.+) \\(${location}\\)$`);
|
|
28
|
+
type TypeMatchInvalid = TypeMatchFileOnly | 'content';
|
|
29
|
+
|
|
30
|
+
export function parseStackString(stack: string) {
|
|
31
|
+
return stack.split('\n').map(parseStackLine);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface IFunction {
|
|
35
|
+
name: string;
|
|
36
|
+
alias?: string;
|
|
37
|
+
}
|
|
38
|
+
interface IFileLocation {
|
|
39
|
+
path: string;
|
|
40
|
+
schema: string; // '' | 'node:' | 'file:' | 'http:' | 'https:';
|
|
41
|
+
line: number;
|
|
42
|
+
column: number;
|
|
43
|
+
isAbsolute: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface IEvalDef {
|
|
46
|
+
eval_func: string;
|
|
47
|
+
eval_line: number;
|
|
48
|
+
eval_column: number;
|
|
49
|
+
funcs: string[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface IStructreStackLine {
|
|
53
|
+
invalid?: boolean;
|
|
54
|
+
special?: boolean;
|
|
55
|
+
toString(): string;
|
|
56
|
+
padding?: string;
|
|
57
|
+
func?: IFunction;
|
|
58
|
+
location?: IFileLocation;
|
|
59
|
+
eval?: IEvalDef;
|
|
60
|
+
_matches?: RegExp;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function matchLine<T extends string>(line: string, reg: RegExp): null | Record<T, string> {
|
|
64
|
+
const m = reg.exec(line);
|
|
65
|
+
if (!m) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return m.groups as any;
|
|
69
|
+
}
|
|
70
|
+
const endingSlashes = /\/+$/;
|
|
71
|
+
function addLoc(ret: IStructreStackLine, m: Record<TypeMatchFileOnly, string>) {
|
|
72
|
+
const path = m.path1 || m.path2;
|
|
73
|
+
ret.location = {
|
|
74
|
+
schema: m.schema?.replace(endingSlashes, '') ?? '',
|
|
75
|
+
path: path,
|
|
76
|
+
line: Number.parseInt(m.line, 10),
|
|
77
|
+
column: Number.parseInt(m.column, 10),
|
|
78
|
+
isAbsolute: isAbsolute(path),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function addFunc(ret: IStructreStackLine, m: Record<TypeMatchNoFile, string>) {
|
|
83
|
+
ret.func = {
|
|
84
|
+
name: m.func_name,
|
|
85
|
+
alias: m.func_alias,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function parseStackLine(line: string): IStructreStackLine {
|
|
90
|
+
const __raw = line;
|
|
91
|
+
const ret: IStructreStackLine = {
|
|
92
|
+
invalid: false,
|
|
93
|
+
toString() {
|
|
94
|
+
return __raw;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
Object.assign(ret, { __raw });
|
|
98
|
+
|
|
99
|
+
const mNormal = matchLine<TypeMatchNormal>(line, regNormal);
|
|
100
|
+
if (mNormal) {
|
|
101
|
+
ret._matches = regNormal;
|
|
102
|
+
ret.padding = mNormal.padding;
|
|
103
|
+
addFunc(ret, mNormal);
|
|
104
|
+
addLoc(ret, mNormal);
|
|
105
|
+
return ret;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const mFile = matchLine<TypeMatchFileOnly>(line, regFileOnly);
|
|
109
|
+
if (mFile) {
|
|
110
|
+
ret._matches = regFileOnly;
|
|
111
|
+
ret.padding = mFile.padding;
|
|
112
|
+
addLoc(ret, mFile);
|
|
113
|
+
return ret;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const mNoFile = matchLine<TypeMatchNoFile>(line, regNoFile);
|
|
117
|
+
if (mNoFile) {
|
|
118
|
+
ret._matches = regNoFile;
|
|
119
|
+
ret.padding = mNoFile.padding;
|
|
120
|
+
addFunc(ret, mNoFile);
|
|
121
|
+
return ret;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const mEval = matchLine<TypeMatchEval>(line.replaceAll(regEvalItem, ''), regEval);
|
|
125
|
+
if (mEval) {
|
|
126
|
+
ret._matches = regEval;
|
|
127
|
+
ret.padding = mEval.padding;
|
|
128
|
+
addFunc(ret, mEval);
|
|
129
|
+
addLoc(ret, mEval);
|
|
130
|
+
|
|
131
|
+
ret.eval = {
|
|
132
|
+
eval_column: Number.parseInt(mEval.eval_column, 10),
|
|
133
|
+
eval_func: mEval.eval_func,
|
|
134
|
+
eval_line: Number.parseInt(mEval.eval_line, 10),
|
|
135
|
+
funcs: [],
|
|
136
|
+
};
|
|
137
|
+
for (const item of line.matchAll(regEvalItem)) {
|
|
138
|
+
// biome-ignore lint/style/noNonNullAssertion: 有匹配必然有 groups
|
|
139
|
+
ret.eval.funcs.push(item.groups!['func_name']);
|
|
140
|
+
}
|
|
141
|
+
ret.eval.funcs.push(mEval.eval_func);
|
|
142
|
+
|
|
143
|
+
return ret;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const mInv = matchLine<TypeMatchInvalid>(line, regInvalid);
|
|
147
|
+
if (mInv) {
|
|
148
|
+
const path = mInv.path1 || mInv.path2;
|
|
149
|
+
if (path.endsWith(mInv.content)) {
|
|
150
|
+
addLoc(ret, mInv);
|
|
151
|
+
return ret;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
ret.invalid = true;
|
|
156
|
+
return ret;
|
|
157
|
+
}
|