@vitest/utils 4.0.0-beta.1 → 4.0.0-beta.11
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/LICENSE +1 -1
- package/dist/chunk-_commonjsHelpers.js +1 -154
- package/dist/chunk-pathe.M-eThtNZ.js +156 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.js +49 -0
- package/dist/diff.d.ts +2 -13
- package/dist/diff.js +6 -4
- package/dist/display.d.ts +28 -0
- package/dist/display.js +727 -0
- package/dist/error.d.ts +2 -4
- package/dist/error.js +5 -125
- package/dist/helpers.d.ts +22 -5
- package/dist/helpers.js +60 -16
- package/dist/highlight.d.ts +9 -0
- package/dist/highlight.js +538 -0
- package/dist/index.d.ts +4 -61
- package/dist/index.js +0 -632
- package/dist/offset.d.ts +5 -0
- package/dist/offset.js +32 -0
- package/dist/resolver.d.ts +7 -0
- package/dist/resolver.js +71 -0
- package/dist/serialize.d.ts +3 -0
- package/dist/serialize.js +118 -0
- package/dist/source-map.d.ts +33 -117
- package/dist/source-map.js +245 -763
- package/dist/timers.d.ts +18 -0
- package/dist/timers.js +32 -0
- package/dist/types.d.ts +1 -1
- package/package.json +32 -11
package/dist/source-map.js
CHANGED
|
@@ -1,788 +1,216 @@
|
|
|
1
1
|
import { isPrimitive, notNullish } from './helpers.js';
|
|
2
|
+
import { r as resolve } from './chunk-pathe.M-eThtNZ.js';
|
|
3
|
+
import './constants.js';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// src/vlq.ts
|
|
6
|
+
var comma = ",".charCodeAt(0);
|
|
7
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
8
|
+
var intToChar = new Uint8Array(64);
|
|
9
|
+
var charToInt = new Uint8Array(128);
|
|
7
10
|
for (let i = 0; i < chars.length; i++) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
const c = chars.charCodeAt(i);
|
|
12
|
+
intToChar[i] = c;
|
|
13
|
+
charToInt[c] = i;
|
|
11
14
|
}
|
|
12
15
|
function decodeInteger(reader, relative) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
let value = 0;
|
|
17
|
+
let shift = 0;
|
|
18
|
+
let integer = 0;
|
|
19
|
+
do {
|
|
20
|
+
const c = reader.next();
|
|
21
|
+
integer = charToInt[c];
|
|
22
|
+
value |= (integer & 31) << shift;
|
|
23
|
+
shift += 5;
|
|
24
|
+
} while (integer & 32);
|
|
25
|
+
const shouldNegate = value & 1;
|
|
26
|
+
value >>>= 1;
|
|
27
|
+
if (shouldNegate) {
|
|
28
|
+
value = -2147483648 | -value;
|
|
29
|
+
}
|
|
30
|
+
return relative + value;
|
|
28
31
|
}
|
|
29
32
|
function hasMoreVlq(reader, max) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return reader.peek() !== comma;
|
|
33
|
-
}
|
|
34
|
-
class StringReader {
|
|
35
|
-
constructor(buffer) {
|
|
36
|
-
this.pos = 0;
|
|
37
|
-
this.buffer = buffer;
|
|
38
|
-
}
|
|
39
|
-
next() {
|
|
40
|
-
return this.buffer.charCodeAt(this.pos++);
|
|
41
|
-
}
|
|
42
|
-
peek() {
|
|
43
|
-
return this.buffer.charCodeAt(this.pos);
|
|
44
|
-
}
|
|
45
|
-
indexOf(char) {
|
|
46
|
-
const { buffer, pos } = this;
|
|
47
|
-
const idx = buffer.indexOf(char, pos);
|
|
48
|
-
return idx === -1 ? buffer.length : idx;
|
|
49
|
-
}
|
|
33
|
+
if (reader.pos >= max) return false;
|
|
34
|
+
return reader.peek() !== comma;
|
|
50
35
|
}
|
|
36
|
+
var StringReader = class {
|
|
37
|
+
constructor(buffer) {
|
|
38
|
+
this.pos = 0;
|
|
39
|
+
this.buffer = buffer;
|
|
40
|
+
}
|
|
41
|
+
next() {
|
|
42
|
+
return this.buffer.charCodeAt(this.pos++);
|
|
43
|
+
}
|
|
44
|
+
peek() {
|
|
45
|
+
return this.buffer.charCodeAt(this.pos);
|
|
46
|
+
}
|
|
47
|
+
indexOf(char) {
|
|
48
|
+
const { buffer, pos } = this;
|
|
49
|
+
const idx = buffer.indexOf(char, pos);
|
|
50
|
+
return idx === -1 ? buffer.length : idx;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
51
53
|
|
|
54
|
+
// src/sourcemap-codec.ts
|
|
52
55
|
function decode(mappings) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
else {
|
|
82
|
-
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
seg = [genColumn];
|
|
87
|
-
}
|
|
88
|
-
line.push(seg);
|
|
89
|
-
reader.pos++;
|
|
90
|
-
}
|
|
91
|
-
if (!sorted)
|
|
92
|
-
sort(line);
|
|
93
|
-
decoded.push(line);
|
|
94
|
-
reader.pos = semi + 1;
|
|
95
|
-
} while (reader.pos <= length);
|
|
96
|
-
return decoded;
|
|
97
|
-
}
|
|
98
|
-
function sort(line) {
|
|
99
|
-
line.sort(sortComparator$1);
|
|
100
|
-
}
|
|
101
|
-
function sortComparator$1(a, b) {
|
|
102
|
-
return a[0] - b[0];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Matches the scheme of a URL, eg "http://"
|
|
106
|
-
const schemeRegex = /^[\w+.-]+:\/\//;
|
|
107
|
-
/**
|
|
108
|
-
* Matches the parts of a URL:
|
|
109
|
-
* 1. Scheme, including ":", guaranteed.
|
|
110
|
-
* 2. User/password, including "@", optional.
|
|
111
|
-
* 3. Host, guaranteed.
|
|
112
|
-
* 4. Port, including ":", optional.
|
|
113
|
-
* 5. Path, including "/", optional.
|
|
114
|
-
* 6. Query, including "?", optional.
|
|
115
|
-
* 7. Hash, including "#", optional.
|
|
116
|
-
*/
|
|
117
|
-
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
|
|
118
|
-
/**
|
|
119
|
-
* File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
|
|
120
|
-
* with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
|
|
121
|
-
*
|
|
122
|
-
* 1. Host, optional.
|
|
123
|
-
* 2. Path, which may include "/", guaranteed.
|
|
124
|
-
* 3. Query, including "?", optional.
|
|
125
|
-
* 4. Hash, including "#", optional.
|
|
126
|
-
*/
|
|
127
|
-
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
|
|
128
|
-
var UrlType;
|
|
129
|
-
(function (UrlType) {
|
|
130
|
-
UrlType[UrlType["Empty"] = 1] = "Empty";
|
|
131
|
-
UrlType[UrlType["Hash"] = 2] = "Hash";
|
|
132
|
-
UrlType[UrlType["Query"] = 3] = "Query";
|
|
133
|
-
UrlType[UrlType["RelativePath"] = 4] = "RelativePath";
|
|
134
|
-
UrlType[UrlType["AbsolutePath"] = 5] = "AbsolutePath";
|
|
135
|
-
UrlType[UrlType["SchemeRelative"] = 6] = "SchemeRelative";
|
|
136
|
-
UrlType[UrlType["Absolute"] = 7] = "Absolute";
|
|
137
|
-
})(UrlType || (UrlType = {}));
|
|
138
|
-
function isAbsoluteUrl(input) {
|
|
139
|
-
return schemeRegex.test(input);
|
|
140
|
-
}
|
|
141
|
-
function isSchemeRelativeUrl(input) {
|
|
142
|
-
return input.startsWith('//');
|
|
143
|
-
}
|
|
144
|
-
function isAbsolutePath(input) {
|
|
145
|
-
return input.startsWith('/');
|
|
146
|
-
}
|
|
147
|
-
function isFileUrl(input) {
|
|
148
|
-
return input.startsWith('file:');
|
|
149
|
-
}
|
|
150
|
-
function isRelative(input) {
|
|
151
|
-
return /^[.?#]/.test(input);
|
|
152
|
-
}
|
|
153
|
-
function parseAbsoluteUrl(input) {
|
|
154
|
-
const match = urlRegex.exec(input);
|
|
155
|
-
return makeUrl(match[1], match[2] || '', match[3], match[4] || '', match[5] || '/', match[6] || '', match[7] || '');
|
|
156
|
-
}
|
|
157
|
-
function parseFileUrl(input) {
|
|
158
|
-
const match = fileRegex.exec(input);
|
|
159
|
-
const path = match[2];
|
|
160
|
-
return makeUrl('file:', '', match[1] || '', '', isAbsolutePath(path) ? path : '/' + path, match[3] || '', match[4] || '');
|
|
161
|
-
}
|
|
162
|
-
function makeUrl(scheme, user, host, port, path, query, hash) {
|
|
163
|
-
return {
|
|
164
|
-
scheme,
|
|
165
|
-
user,
|
|
166
|
-
host,
|
|
167
|
-
port,
|
|
168
|
-
path,
|
|
169
|
-
query,
|
|
170
|
-
hash,
|
|
171
|
-
type: UrlType.Absolute,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function parseUrl(input) {
|
|
175
|
-
if (isSchemeRelativeUrl(input)) {
|
|
176
|
-
const url = parseAbsoluteUrl('http:' + input);
|
|
177
|
-
url.scheme = '';
|
|
178
|
-
url.type = UrlType.SchemeRelative;
|
|
179
|
-
return url;
|
|
180
|
-
}
|
|
181
|
-
if (isAbsolutePath(input)) {
|
|
182
|
-
const url = parseAbsoluteUrl('http://foo.com' + input);
|
|
183
|
-
url.scheme = '';
|
|
184
|
-
url.host = '';
|
|
185
|
-
url.type = UrlType.AbsolutePath;
|
|
186
|
-
return url;
|
|
187
|
-
}
|
|
188
|
-
if (isFileUrl(input))
|
|
189
|
-
return parseFileUrl(input);
|
|
190
|
-
if (isAbsoluteUrl(input))
|
|
191
|
-
return parseAbsoluteUrl(input);
|
|
192
|
-
const url = parseAbsoluteUrl('http://foo.com/' + input);
|
|
193
|
-
url.scheme = '';
|
|
194
|
-
url.host = '';
|
|
195
|
-
url.type = input
|
|
196
|
-
? input.startsWith('?')
|
|
197
|
-
? UrlType.Query
|
|
198
|
-
: input.startsWith('#')
|
|
199
|
-
? UrlType.Hash
|
|
200
|
-
: UrlType.RelativePath
|
|
201
|
-
: UrlType.Empty;
|
|
202
|
-
return url;
|
|
203
|
-
}
|
|
204
|
-
function stripPathFilename(path) {
|
|
205
|
-
// If a path ends with a parent directory "..", then it's a relative path with excess parent
|
|
206
|
-
// paths. It's not a file, so we can't strip it.
|
|
207
|
-
if (path.endsWith('/..'))
|
|
208
|
-
return path;
|
|
209
|
-
const index = path.lastIndexOf('/');
|
|
210
|
-
return path.slice(0, index + 1);
|
|
211
|
-
}
|
|
212
|
-
function mergePaths(url, base) {
|
|
213
|
-
normalizePath(base, base.type);
|
|
214
|
-
// If the path is just a "/", then it was an empty path to begin with (remember, we're a relative
|
|
215
|
-
// path).
|
|
216
|
-
if (url.path === '/') {
|
|
217
|
-
url.path = base.path;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
// Resolution happens relative to the base path's directory, not the file.
|
|
221
|
-
url.path = stripPathFilename(base.path) + url.path;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* The path can have empty directories "//", unneeded parents "foo/..", or current directory
|
|
226
|
-
* "foo/.". We need to normalize to a standard representation.
|
|
227
|
-
*/
|
|
228
|
-
function normalizePath(url, type) {
|
|
229
|
-
const rel = type <= UrlType.RelativePath;
|
|
230
|
-
const pieces = url.path.split('/');
|
|
231
|
-
// We need to preserve the first piece always, so that we output a leading slash. The item at
|
|
232
|
-
// pieces[0] is an empty string.
|
|
233
|
-
let pointer = 1;
|
|
234
|
-
// Positive is the number of real directories we've output, used for popping a parent directory.
|
|
235
|
-
// Eg, "foo/bar/.." will have a positive 2, and we can decrement to be left with just "foo".
|
|
236
|
-
let positive = 0;
|
|
237
|
-
// We need to keep a trailing slash if we encounter an empty directory (eg, splitting "foo/" will
|
|
238
|
-
// generate `["foo", ""]` pieces). And, if we pop a parent directory. But once we encounter a
|
|
239
|
-
// real directory, we won't need to append, unless the other conditions happen again.
|
|
240
|
-
let addTrailingSlash = false;
|
|
241
|
-
for (let i = 1; i < pieces.length; i++) {
|
|
242
|
-
const piece = pieces[i];
|
|
243
|
-
// An empty directory, could be a trailing slash, or just a double "//" in the path.
|
|
244
|
-
if (!piece) {
|
|
245
|
-
addTrailingSlash = true;
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
// If we encounter a real directory, then we don't need to append anymore.
|
|
249
|
-
addTrailingSlash = false;
|
|
250
|
-
// A current directory, which we can always drop.
|
|
251
|
-
if (piece === '.')
|
|
252
|
-
continue;
|
|
253
|
-
// A parent directory, we need to see if there are any real directories we can pop. Else, we
|
|
254
|
-
// have an excess of parents, and we'll need to keep the "..".
|
|
255
|
-
if (piece === '..') {
|
|
256
|
-
if (positive) {
|
|
257
|
-
addTrailingSlash = true;
|
|
258
|
-
positive--;
|
|
259
|
-
pointer--;
|
|
260
|
-
}
|
|
261
|
-
else if (rel) {
|
|
262
|
-
// If we're in a relativePath, then we need to keep the excess parents. Else, in an absolute
|
|
263
|
-
// URL, protocol relative URL, or an absolute path, we don't need to keep excess.
|
|
264
|
-
pieces[pointer++] = piece;
|
|
265
|
-
}
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
// We've encountered a real directory. Move it to the next insertion pointer, which accounts for
|
|
269
|
-
// any popped or dropped directories.
|
|
270
|
-
pieces[pointer++] = piece;
|
|
271
|
-
positive++;
|
|
272
|
-
}
|
|
273
|
-
let path = '';
|
|
274
|
-
for (let i = 1; i < pointer; i++) {
|
|
275
|
-
path += '/' + pieces[i];
|
|
276
|
-
}
|
|
277
|
-
if (!path || (addTrailingSlash && !path.endsWith('/..'))) {
|
|
278
|
-
path += '/';
|
|
279
|
-
}
|
|
280
|
-
url.path = path;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Attempts to resolve `input` URL/path relative to `base`.
|
|
284
|
-
*/
|
|
285
|
-
function resolve$2(input, base) {
|
|
286
|
-
if (!input && !base)
|
|
287
|
-
return '';
|
|
288
|
-
const url = parseUrl(input);
|
|
289
|
-
let inputType = url.type;
|
|
290
|
-
if (base && inputType !== UrlType.Absolute) {
|
|
291
|
-
const baseUrl = parseUrl(base);
|
|
292
|
-
const baseType = baseUrl.type;
|
|
293
|
-
switch (inputType) {
|
|
294
|
-
case UrlType.Empty:
|
|
295
|
-
url.hash = baseUrl.hash;
|
|
296
|
-
// fall through
|
|
297
|
-
case UrlType.Hash:
|
|
298
|
-
url.query = baseUrl.query;
|
|
299
|
-
// fall through
|
|
300
|
-
case UrlType.Query:
|
|
301
|
-
case UrlType.RelativePath:
|
|
302
|
-
mergePaths(url, baseUrl);
|
|
303
|
-
// fall through
|
|
304
|
-
case UrlType.AbsolutePath:
|
|
305
|
-
// The host, user, and port are joined, you can't copy one without the others.
|
|
306
|
-
url.user = baseUrl.user;
|
|
307
|
-
url.host = baseUrl.host;
|
|
308
|
-
url.port = baseUrl.port;
|
|
309
|
-
// fall through
|
|
310
|
-
case UrlType.SchemeRelative:
|
|
311
|
-
// The input doesn't have a schema at least, so we need to copy at least that over.
|
|
312
|
-
url.scheme = baseUrl.scheme;
|
|
313
|
-
}
|
|
314
|
-
if (baseType > inputType)
|
|
315
|
-
inputType = baseType;
|
|
316
|
-
}
|
|
317
|
-
normalizePath(url, inputType);
|
|
318
|
-
const queryHash = url.query + url.hash;
|
|
319
|
-
switch (inputType) {
|
|
320
|
-
// This is impossible, because of the empty checks at the start of the function.
|
|
321
|
-
// case UrlType.Empty:
|
|
322
|
-
case UrlType.Hash:
|
|
323
|
-
case UrlType.Query:
|
|
324
|
-
return queryHash;
|
|
325
|
-
case UrlType.RelativePath: {
|
|
326
|
-
// The first char is always a "/", and we need it to be relative.
|
|
327
|
-
const path = url.path.slice(1);
|
|
328
|
-
if (!path)
|
|
329
|
-
return queryHash || '.';
|
|
330
|
-
if (isRelative(base || input) && !isRelative(path)) {
|
|
331
|
-
// If base started with a leading ".", or there is no base and input started with a ".",
|
|
332
|
-
// then we need to ensure that the relative path starts with a ".". We don't know if
|
|
333
|
-
// relative starts with a "..", though, so check before prepending.
|
|
334
|
-
return './' + path + queryHash;
|
|
335
|
-
}
|
|
336
|
-
return path + queryHash;
|
|
56
|
+
const { length } = mappings;
|
|
57
|
+
const reader = new StringReader(mappings);
|
|
58
|
+
const decoded = [];
|
|
59
|
+
let genColumn = 0;
|
|
60
|
+
let sourcesIndex = 0;
|
|
61
|
+
let sourceLine = 0;
|
|
62
|
+
let sourceColumn = 0;
|
|
63
|
+
let namesIndex = 0;
|
|
64
|
+
do {
|
|
65
|
+
const semi = reader.indexOf(";");
|
|
66
|
+
const line = [];
|
|
67
|
+
let sorted = true;
|
|
68
|
+
let lastCol = 0;
|
|
69
|
+
genColumn = 0;
|
|
70
|
+
while (reader.pos < semi) {
|
|
71
|
+
let seg;
|
|
72
|
+
genColumn = decodeInteger(reader, genColumn);
|
|
73
|
+
if (genColumn < lastCol) sorted = false;
|
|
74
|
+
lastCol = genColumn;
|
|
75
|
+
if (hasMoreVlq(reader, semi)) {
|
|
76
|
+
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
|
77
|
+
sourceLine = decodeInteger(reader, sourceLine);
|
|
78
|
+
sourceColumn = decodeInteger(reader, sourceColumn);
|
|
79
|
+
if (hasMoreVlq(reader, semi)) {
|
|
80
|
+
namesIndex = decodeInteger(reader, namesIndex);
|
|
81
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
|
|
82
|
+
} else {
|
|
83
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
|
337
84
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
85
|
+
} else {
|
|
86
|
+
seg = [genColumn];
|
|
87
|
+
}
|
|
88
|
+
line.push(seg);
|
|
89
|
+
reader.pos++;
|
|
342
90
|
}
|
|
91
|
+
if (!sorted) sort(line);
|
|
92
|
+
decoded.push(line);
|
|
93
|
+
reader.pos = semi + 1;
|
|
94
|
+
} while (reader.pos <= length);
|
|
95
|
+
return decoded;
|
|
343
96
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// The base is always treated as a directory, if it's not empty.
|
|
347
|
-
// https://github.com/mozilla/source-map/blob/8cb3ee57/lib/util.js#L327
|
|
348
|
-
// https://github.com/chromium/chromium/blob/da4adbb3/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js#L400-L401
|
|
349
|
-
if (base && !base.endsWith('/'))
|
|
350
|
-
base += '/';
|
|
351
|
-
return resolve$2(input, base);
|
|
97
|
+
function sort(line) {
|
|
98
|
+
line.sort(sortComparator);
|
|
352
99
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
* Removes everything after the last "/", but leaves the slash.
|
|
356
|
-
*/
|
|
357
|
-
function stripFilename(path) {
|
|
358
|
-
if (!path)
|
|
359
|
-
return '';
|
|
360
|
-
const index = path.lastIndexOf('/');
|
|
361
|
-
return path.slice(0, index + 1);
|
|
100
|
+
function sortComparator(a, b) {
|
|
101
|
+
return a[0] - b[0];
|
|
362
102
|
}
|
|
363
103
|
|
|
364
|
-
|
|
365
|
-
const SOURCES_INDEX = 1;
|
|
366
|
-
const SOURCE_LINE = 2;
|
|
367
|
-
const SOURCE_COLUMN = 3;
|
|
368
|
-
const NAMES_INDEX = 4;
|
|
369
|
-
const REV_GENERATED_LINE = 1;
|
|
370
|
-
const REV_GENERATED_COLUMN = 2;
|
|
104
|
+
// src/trace-mapping.ts
|
|
371
105
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (!owned)
|
|
379
|
-
mappings = mappings.slice();
|
|
380
|
-
for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) {
|
|
381
|
-
mappings[i] = sortSegments(mappings[i], owned);
|
|
382
|
-
}
|
|
383
|
-
return mappings;
|
|
384
|
-
}
|
|
385
|
-
function nextUnsortedSegmentLine(mappings, start) {
|
|
386
|
-
for (let i = start; i < mappings.length; i++) {
|
|
387
|
-
if (!isSorted(mappings[i]))
|
|
388
|
-
return i;
|
|
389
|
-
}
|
|
390
|
-
return mappings.length;
|
|
391
|
-
}
|
|
392
|
-
function isSorted(line) {
|
|
393
|
-
for (let j = 1; j < line.length; j++) {
|
|
394
|
-
if (line[j][COLUMN] < line[j - 1][COLUMN]) {
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
return true;
|
|
399
|
-
}
|
|
400
|
-
function sortSegments(line, owned) {
|
|
401
|
-
if (!owned)
|
|
402
|
-
line = line.slice();
|
|
403
|
-
return line.sort(sortComparator);
|
|
404
|
-
}
|
|
405
|
-
function sortComparator(a, b) {
|
|
406
|
-
return a[COLUMN] - b[COLUMN];
|
|
407
|
-
}
|
|
106
|
+
// src/sourcemap-segment.ts
|
|
107
|
+
var COLUMN = 0;
|
|
108
|
+
var SOURCES_INDEX = 1;
|
|
109
|
+
var SOURCE_LINE = 2;
|
|
110
|
+
var SOURCE_COLUMN = 3;
|
|
111
|
+
var NAMES_INDEX = 4;
|
|
408
112
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
* A binary search implementation that returns the index if a match is found.
|
|
412
|
-
* If no match is found, then the left-index (the index associated with the item that comes just
|
|
413
|
-
* before the desired index) is returned. To maintain proper sort order, a splice would happen at
|
|
414
|
-
* the next index:
|
|
415
|
-
*
|
|
416
|
-
* ```js
|
|
417
|
-
* const array = [1, 3];
|
|
418
|
-
* const needle = 2;
|
|
419
|
-
* const index = binarySearch(array, needle, (item, needle) => item - needle);
|
|
420
|
-
*
|
|
421
|
-
* assert.equal(index, 0);
|
|
422
|
-
* array.splice(index + 1, 0, needle);
|
|
423
|
-
* assert.deepEqual(array, [1, 2, 3]);
|
|
424
|
-
* ```
|
|
425
|
-
*/
|
|
113
|
+
// src/binary-search.ts
|
|
114
|
+
var found = false;
|
|
426
115
|
function binarySearch(haystack, needle, low, high) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
if (cmp < 0) {
|
|
435
|
-
low = mid + 1;
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
high = mid - 1;
|
|
439
|
-
}
|
|
116
|
+
while (low <= high) {
|
|
117
|
+
const mid = low + (high - low >> 1);
|
|
118
|
+
const cmp = haystack[mid][COLUMN] - needle;
|
|
119
|
+
if (cmp === 0) {
|
|
120
|
+
found = true;
|
|
121
|
+
return mid;
|
|
440
122
|
}
|
|
441
|
-
|
|
442
|
-
|
|
123
|
+
if (cmp < 0) {
|
|
124
|
+
low = mid + 1;
|
|
125
|
+
} else {
|
|
126
|
+
high = mid - 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
found = false;
|
|
130
|
+
return low - 1;
|
|
443
131
|
}
|
|
444
132
|
function upperBound(haystack, needle, index) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return index;
|
|
133
|
+
for (let i = index + 1; i < haystack.length; index = i++) {
|
|
134
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
135
|
+
}
|
|
136
|
+
return index;
|
|
450
137
|
}
|
|
451
138
|
function lowerBound(haystack, needle, index) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return index;
|
|
457
|
-
}
|
|
458
|
-
function memoizedState() {
|
|
459
|
-
return {
|
|
460
|
-
lastKey: -1,
|
|
461
|
-
lastNeedle: -1,
|
|
462
|
-
lastIndex: -1,
|
|
463
|
-
};
|
|
139
|
+
for (let i = index - 1; i >= 0; index = i--) {
|
|
140
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
141
|
+
}
|
|
142
|
+
return index;
|
|
464
143
|
}
|
|
465
|
-
/**
|
|
466
|
-
* This overly complicated beast is just to record the last tested line/column and the resulting
|
|
467
|
-
* index, allowing us to skip a few tests if mappings are monotonically increasing.
|
|
468
|
-
*/
|
|
469
144
|
function memoizedBinarySearch(haystack, needle, state, key) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
if (needle >= lastNeedle) {
|
|
479
|
-
// lastIndex may be -1 if the previous needle was not found.
|
|
480
|
-
low = lastIndex === -1 ? 0 : lastIndex;
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
high = lastIndex;
|
|
484
|
-
}
|
|
145
|
+
const { lastKey, lastNeedle, lastIndex } = state;
|
|
146
|
+
let low = 0;
|
|
147
|
+
let high = haystack.length - 1;
|
|
148
|
+
if (key === lastKey) {
|
|
149
|
+
if (needle === lastNeedle) {
|
|
150
|
+
found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
|
|
151
|
+
return lastIndex;
|
|
485
152
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
// Rebuilds the original source files, with mappings that are ordered by source line/column instead
|
|
492
|
-
// of generated line/column.
|
|
493
|
-
function buildBySources(decoded, memos) {
|
|
494
|
-
const sources = memos.map(buildNullArray);
|
|
495
|
-
for (let i = 0; i < decoded.length; i++) {
|
|
496
|
-
const line = decoded[i];
|
|
497
|
-
for (let j = 0; j < line.length; j++) {
|
|
498
|
-
const seg = line[j];
|
|
499
|
-
if (seg.length === 1)
|
|
500
|
-
continue;
|
|
501
|
-
const sourceIndex = seg[SOURCES_INDEX];
|
|
502
|
-
const sourceLine = seg[SOURCE_LINE];
|
|
503
|
-
const sourceColumn = seg[SOURCE_COLUMN];
|
|
504
|
-
const originalSource = sources[sourceIndex];
|
|
505
|
-
const originalLine = (originalSource[sourceLine] || (originalSource[sourceLine] = []));
|
|
506
|
-
const memo = memos[sourceIndex];
|
|
507
|
-
// The binary search either found a match, or it found the left-index just before where the
|
|
508
|
-
// segment should go. Either way, we want to insert after that. And there may be multiple
|
|
509
|
-
// generated segments associated with an original location, so there may need to move several
|
|
510
|
-
// indexes before we find where we need to insert.
|
|
511
|
-
let index = upperBound(originalLine, sourceColumn, memoizedBinarySearch(originalLine, sourceColumn, memo, sourceLine));
|
|
512
|
-
memo.lastIndex = ++index;
|
|
513
|
-
insert(originalLine, index, [sourceColumn, i, seg[COLUMN]]);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
return sources;
|
|
517
|
-
}
|
|
518
|
-
function insert(array, index, value) {
|
|
519
|
-
for (let i = array.length; i > index; i--) {
|
|
520
|
-
array[i] = array[i - 1];
|
|
153
|
+
if (needle >= lastNeedle) {
|
|
154
|
+
low = lastIndex === -1 ? 0 : lastIndex;
|
|
155
|
+
} else {
|
|
156
|
+
high = lastIndex;
|
|
521
157
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
// Numeric properties on objects are magically sorted in ascending order by the engine regardless of
|
|
527
|
-
// the insertion order. So, by setting any numeric keys, even out of order, we'll get ascending
|
|
528
|
-
// order when iterating with for-in.
|
|
529
|
-
function buildNullArray() {
|
|
530
|
-
return { __proto__: null };
|
|
158
|
+
}
|
|
159
|
+
state.lastKey = key;
|
|
160
|
+
state.lastNeedle = needle;
|
|
161
|
+
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
531
162
|
}
|
|
532
163
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
constructor(map, mapUrl) {
|
|
539
|
-
const isString = typeof map === 'string';
|
|
540
|
-
if (!isString && map._decodedMemo)
|
|
541
|
-
return map;
|
|
542
|
-
const parsed = (isString ? JSON.parse(map) : map);
|
|
543
|
-
const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
|
|
544
|
-
this.version = version;
|
|
545
|
-
this.file = file;
|
|
546
|
-
this.names = names || [];
|
|
547
|
-
this.sourceRoot = sourceRoot;
|
|
548
|
-
this.sources = sources;
|
|
549
|
-
this.sourcesContent = sourcesContent;
|
|
550
|
-
this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || undefined;
|
|
551
|
-
const from = resolve$1(sourceRoot || '', stripFilename(mapUrl));
|
|
552
|
-
this.resolvedSources = sources.map((s) => resolve$1(s || '', from));
|
|
553
|
-
const { mappings } = parsed;
|
|
554
|
-
if (typeof mappings === 'string') {
|
|
555
|
-
this._encoded = mappings;
|
|
556
|
-
this._decoded = undefined;
|
|
557
|
-
}
|
|
558
|
-
else {
|
|
559
|
-
this._encoded = undefined;
|
|
560
|
-
this._decoded = maybeSort(mappings, isString);
|
|
561
|
-
}
|
|
562
|
-
this._decodedMemo = memoizedState();
|
|
563
|
-
this._bySources = undefined;
|
|
564
|
-
this._bySourceMemos = undefined;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* Typescript doesn't allow friend access to private fields, so this just casts the map into a type
|
|
569
|
-
* with public access modifiers.
|
|
570
|
-
*/
|
|
164
|
+
// src/trace-mapping.ts
|
|
165
|
+
var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
|
|
166
|
+
var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
|
|
167
|
+
var LEAST_UPPER_BOUND = -1;
|
|
168
|
+
var GREATEST_LOWER_BOUND = 1;
|
|
571
169
|
function cast(map) {
|
|
572
|
-
|
|
170
|
+
return map;
|
|
573
171
|
}
|
|
574
|
-
/**
|
|
575
|
-
* Returns the decoded (array of lines of segments) form of the SourceMap's mappings field.
|
|
576
|
-
*/
|
|
577
172
|
function decodedMappings(map) {
|
|
578
|
-
|
|
579
|
-
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
|
|
580
175
|
}
|
|
581
|
-
/**
|
|
582
|
-
* A higher-level API to find the source/line/column associated with a generated line/column
|
|
583
|
-
* (think, from a stack trace). Line is 1-based, but column is 0-based, due to legacy behavior in
|
|
584
|
-
* `source-map` library.
|
|
585
|
-
*/
|
|
586
176
|
function originalPositionFor(map, needle) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
function generatedPositionFor(map, needle) {
|
|
612
|
-
const { source, line, column, bias } = needle;
|
|
613
|
-
return generatedPosition(map, source, line, column, bias || GREATEST_LOWER_BOUND, false);
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Iterates each mapping in generated position order.
|
|
617
|
-
*/
|
|
618
|
-
function eachMapping(map, cb) {
|
|
619
|
-
const decoded = decodedMappings(map);
|
|
620
|
-
const { names, resolvedSources } = map;
|
|
621
|
-
for (let i = 0; i < decoded.length; i++) {
|
|
622
|
-
const line = decoded[i];
|
|
623
|
-
for (let j = 0; j < line.length; j++) {
|
|
624
|
-
const seg = line[j];
|
|
625
|
-
const generatedLine = i + 1;
|
|
626
|
-
const generatedColumn = seg[0];
|
|
627
|
-
let source = null;
|
|
628
|
-
let originalLine = null;
|
|
629
|
-
let originalColumn = null;
|
|
630
|
-
let name = null;
|
|
631
|
-
if (seg.length !== 1) {
|
|
632
|
-
source = resolvedSources[seg[1]];
|
|
633
|
-
originalLine = seg[2] + 1;
|
|
634
|
-
originalColumn = seg[3];
|
|
635
|
-
}
|
|
636
|
-
if (seg.length === 5)
|
|
637
|
-
name = names[seg[4]];
|
|
638
|
-
cb({
|
|
639
|
-
generatedLine,
|
|
640
|
-
generatedColumn,
|
|
641
|
-
source,
|
|
642
|
-
originalLine,
|
|
643
|
-
originalColumn,
|
|
644
|
-
name,
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
}
|
|
177
|
+
let { line, column, bias } = needle;
|
|
178
|
+
line--;
|
|
179
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
180
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
181
|
+
const decoded = decodedMappings(map);
|
|
182
|
+
if (line >= decoded.length) return OMapping(null, null, null, null);
|
|
183
|
+
const segments = decoded[line];
|
|
184
|
+
const index = traceSegmentInternal(
|
|
185
|
+
segments,
|
|
186
|
+
cast(map)._decodedMemo,
|
|
187
|
+
line,
|
|
188
|
+
column,
|
|
189
|
+
bias || GREATEST_LOWER_BOUND
|
|
190
|
+
);
|
|
191
|
+
if (index === -1) return OMapping(null, null, null, null);
|
|
192
|
+
const segment = segments[index];
|
|
193
|
+
if (segment.length === 1) return OMapping(null, null, null, null);
|
|
194
|
+
const { names, resolvedSources } = map;
|
|
195
|
+
return OMapping(
|
|
196
|
+
resolvedSources[segment[SOURCES_INDEX]],
|
|
197
|
+
segment[SOURCE_LINE] + 1,
|
|
198
|
+
segment[SOURCE_COLUMN],
|
|
199
|
+
segment.length === 5 ? names[segment[NAMES_INDEX]] : null
|
|
200
|
+
);
|
|
648
201
|
}
|
|
649
202
|
function OMapping(source, line, column, name) {
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
function GMapping(line, column) {
|
|
653
|
-
return { line, column };
|
|
203
|
+
return { source, line, column, name };
|
|
654
204
|
}
|
|
655
205
|
function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
if (index === -1 || index === segments.length)
|
|
663
|
-
return -1;
|
|
664
|
-
return index;
|
|
665
|
-
}
|
|
666
|
-
function generatedPosition(map, source, line, column, bias, all) {
|
|
667
|
-
var _a;
|
|
668
|
-
line--;
|
|
669
|
-
if (line < 0)
|
|
670
|
-
throw new Error(LINE_GTR_ZERO);
|
|
671
|
-
if (column < 0)
|
|
672
|
-
throw new Error(COL_GTR_EQ_ZERO);
|
|
673
|
-
const { sources, resolvedSources } = map;
|
|
674
|
-
let sourceIndex = sources.indexOf(source);
|
|
675
|
-
if (sourceIndex === -1)
|
|
676
|
-
sourceIndex = resolvedSources.indexOf(source);
|
|
677
|
-
if (sourceIndex === -1)
|
|
678
|
-
return all ? [] : GMapping(null, null);
|
|
679
|
-
const generated = ((_a = cast(map))._bySources || (_a._bySources = buildBySources(decodedMappings(map), (cast(map)._bySourceMemos = sources.map(memoizedState)))));
|
|
680
|
-
const segments = generated[sourceIndex][line];
|
|
681
|
-
if (segments == null)
|
|
682
|
-
return all ? [] : GMapping(null, null);
|
|
683
|
-
const memo = cast(map)._bySourceMemos[sourceIndex];
|
|
684
|
-
const index = traceSegmentInternal(segments, memo, line, column, bias);
|
|
685
|
-
if (index === -1)
|
|
686
|
-
return GMapping(null, null);
|
|
687
|
-
const segment = segments[index];
|
|
688
|
-
return GMapping(segment[REV_GENERATED_LINE] + 1, segment[REV_GENERATED_COLUMN]);
|
|
206
|
+
let index = memoizedBinarySearch(segments, column, memo, line);
|
|
207
|
+
if (found) {
|
|
208
|
+
index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
|
|
209
|
+
} else if (bias === LEAST_UPPER_BOUND) index++;
|
|
210
|
+
if (index === -1 || index === segments.length) return -1;
|
|
211
|
+
return index;
|
|
689
212
|
}
|
|
690
213
|
|
|
691
|
-
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
692
|
-
function normalizeWindowsPath(input = "") {
|
|
693
|
-
if (!input) {
|
|
694
|
-
return input;
|
|
695
|
-
}
|
|
696
|
-
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
697
|
-
}
|
|
698
|
-
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
699
|
-
function cwd() {
|
|
700
|
-
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
701
|
-
return process.cwd().replace(/\\/g, "/");
|
|
702
|
-
}
|
|
703
|
-
return "/";
|
|
704
|
-
}
|
|
705
|
-
const resolve = function(...arguments_) {
|
|
706
|
-
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
707
|
-
let resolvedPath = "";
|
|
708
|
-
let resolvedAbsolute = false;
|
|
709
|
-
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
710
|
-
const path = index >= 0 ? arguments_[index] : cwd();
|
|
711
|
-
if (!path || path.length === 0) {
|
|
712
|
-
continue;
|
|
713
|
-
}
|
|
714
|
-
resolvedPath = `${path}/${resolvedPath}`;
|
|
715
|
-
resolvedAbsolute = isAbsolute(path);
|
|
716
|
-
}
|
|
717
|
-
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
718
|
-
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
|
719
|
-
return `/${resolvedPath}`;
|
|
720
|
-
}
|
|
721
|
-
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
722
|
-
};
|
|
723
|
-
function normalizeString(path, allowAboveRoot) {
|
|
724
|
-
let res = "";
|
|
725
|
-
let lastSegmentLength = 0;
|
|
726
|
-
let lastSlash = -1;
|
|
727
|
-
let dots = 0;
|
|
728
|
-
let char = null;
|
|
729
|
-
for (let index = 0; index <= path.length; ++index) {
|
|
730
|
-
if (index < path.length) {
|
|
731
|
-
char = path[index];
|
|
732
|
-
} else if (char === "/") {
|
|
733
|
-
break;
|
|
734
|
-
} else {
|
|
735
|
-
char = "/";
|
|
736
|
-
}
|
|
737
|
-
if (char === "/") {
|
|
738
|
-
if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {
|
|
739
|
-
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
|
740
|
-
if (res.length > 2) {
|
|
741
|
-
const lastSlashIndex = res.lastIndexOf("/");
|
|
742
|
-
if (lastSlashIndex === -1) {
|
|
743
|
-
res = "";
|
|
744
|
-
lastSegmentLength = 0;
|
|
745
|
-
} else {
|
|
746
|
-
res = res.slice(0, lastSlashIndex);
|
|
747
|
-
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
748
|
-
}
|
|
749
|
-
lastSlash = index;
|
|
750
|
-
dots = 0;
|
|
751
|
-
continue;
|
|
752
|
-
} else if (res.length > 0) {
|
|
753
|
-
res = "";
|
|
754
|
-
lastSegmentLength = 0;
|
|
755
|
-
lastSlash = index;
|
|
756
|
-
dots = 0;
|
|
757
|
-
continue;
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
if (allowAboveRoot) {
|
|
761
|
-
res += res.length > 0 ? "/.." : "..";
|
|
762
|
-
lastSegmentLength = 2;
|
|
763
|
-
}
|
|
764
|
-
} else {
|
|
765
|
-
if (res.length > 0) {
|
|
766
|
-
res += `/${path.slice(lastSlash + 1, index)}`;
|
|
767
|
-
} else {
|
|
768
|
-
res = path.slice(lastSlash + 1, index);
|
|
769
|
-
}
|
|
770
|
-
lastSegmentLength = index - lastSlash - 1;
|
|
771
|
-
}
|
|
772
|
-
lastSlash = index;
|
|
773
|
-
dots = 0;
|
|
774
|
-
} else if (char === "." && dots !== -1) {
|
|
775
|
-
++dots;
|
|
776
|
-
} else {
|
|
777
|
-
dots = -1;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
return res;
|
|
781
|
-
}
|
|
782
|
-
const isAbsolute = function(p) {
|
|
783
|
-
return _IS_ABSOLUTE_RE.test(p);
|
|
784
|
-
};
|
|
785
|
-
|
|
786
214
|
const CHROME_IE_STACK_REGEXP = /^\s*at .*(?:\S:\d+|\(native\))/m;
|
|
787
215
|
const SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\[native code\])?$/;
|
|
788
216
|
const stackIgnorePatterns = [
|
|
@@ -796,6 +224,8 @@ const stackIgnorePatterns = [
|
|
|
796
224
|
"/node_modules/chai/",
|
|
797
225
|
"/node_modules/tinypool/",
|
|
798
226
|
"/node_modules/tinyspy/",
|
|
227
|
+
"/vite/dist/node/module-runner",
|
|
228
|
+
"/rolldown-vite/dist/node/module-runner",
|
|
799
229
|
"/deps/chunk-",
|
|
800
230
|
"/deps/@vitest",
|
|
801
231
|
"/deps/loupe",
|
|
@@ -843,14 +273,35 @@ function parseSingleFFOrSafariStack(raw) {
|
|
|
843
273
|
if (line.includes(" > eval")) {
|
|
844
274
|
line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
|
|
845
275
|
}
|
|
846
|
-
|
|
276
|
+
// Early return for lines that don't look like Firefox/Safari stack traces
|
|
277
|
+
// Firefox/Safari stack traces must contain '@' and should have location info after it
|
|
278
|
+
if (!line.includes("@")) {
|
|
847
279
|
return null;
|
|
848
280
|
}
|
|
849
|
-
//
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
281
|
+
// Find the correct @ that separates function name from location
|
|
282
|
+
// For cases like '@https://@fs/path' or 'functionName@https://@fs/path'
|
|
283
|
+
// we need to find the first @ that precedes a valid location (containing :)
|
|
284
|
+
let atIndex = -1;
|
|
285
|
+
let locationPart = "";
|
|
286
|
+
let functionName;
|
|
287
|
+
// Try each @ from left to right to find the one that gives us a valid location
|
|
288
|
+
for (let i = 0; i < line.length; i++) {
|
|
289
|
+
if (line[i] === "@") {
|
|
290
|
+
const candidateLocation = line.slice(i + 1);
|
|
291
|
+
// Minimum length 3 for valid location: 1 for filename + 1 for colon + 1 for line number (e.g., "a:1")
|
|
292
|
+
if (candidateLocation.includes(":") && candidateLocation.length >= 3) {
|
|
293
|
+
atIndex = i;
|
|
294
|
+
locationPart = candidateLocation;
|
|
295
|
+
functionName = i > 0 ? line.slice(0, i) : undefined;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Validate we found a valid location with minimum length (filename:line format)
|
|
301
|
+
if (atIndex === -1 || !locationPart.includes(":") || locationPart.length < 3) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
const [url, lineNumber, columnNumber] = extractLocation(locationPart);
|
|
854
305
|
if (!url || !lineNumber || !columnNumber) {
|
|
855
306
|
return null;
|
|
856
307
|
}
|
|
@@ -901,7 +352,7 @@ function parseSingleV8Stack(raw) {
|
|
|
901
352
|
// normalize Windows path (\ -> /)
|
|
902
353
|
file = file.startsWith("node:") || file.startsWith("internal:") ? file : resolve(file);
|
|
903
354
|
if (method) {
|
|
904
|
-
method = method.replace(/__vite_ssr_import_\d+__\./g, "");
|
|
355
|
+
method = method.replace(/__vite_ssr_import_\d+__\./g, "").replace(/(Object\.)?__vite_ssr_export_default__\s?/g, "");
|
|
905
356
|
}
|
|
906
357
|
return {
|
|
907
358
|
method,
|
|
@@ -931,17 +382,15 @@ function parseStacktrace(stack, options = {}) {
|
|
|
931
382
|
if (!map || typeof map !== "object" || !map.version) {
|
|
932
383
|
return shouldFilter(ignoreStackEntries, stack.file) ? null : stack;
|
|
933
384
|
}
|
|
934
|
-
const traceMap = new
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
file = file.slice(1);
|
|
944
|
-
}
|
|
385
|
+
const traceMap = new DecodedMap(map, stack.file);
|
|
386
|
+
const position = getOriginalPosition(traceMap, stack);
|
|
387
|
+
if (!position) {
|
|
388
|
+
return stack;
|
|
389
|
+
}
|
|
390
|
+
const { line, column, source, name } = position;
|
|
391
|
+
let file = source || stack.file;
|
|
392
|
+
if (file.match(/\/\w:\//)) {
|
|
393
|
+
file = file.slice(1);
|
|
945
394
|
}
|
|
946
395
|
if (shouldFilter(ignoreStackEntries, file)) {
|
|
947
396
|
return null;
|
|
@@ -992,5 +441,38 @@ function parseErrorStacktrace(e, options = {}) {
|
|
|
992
441
|
e.stacks = stackFrames;
|
|
993
442
|
return stackFrames;
|
|
994
443
|
}
|
|
444
|
+
class DecodedMap {
|
|
445
|
+
_encoded;
|
|
446
|
+
_decoded;
|
|
447
|
+
_decodedMemo;
|
|
448
|
+
url;
|
|
449
|
+
version;
|
|
450
|
+
names = [];
|
|
451
|
+
resolvedSources;
|
|
452
|
+
constructor(map, from) {
|
|
453
|
+
this.map = map;
|
|
454
|
+
const { mappings, names, sources } = map;
|
|
455
|
+
this.version = map.version;
|
|
456
|
+
this.names = names || [];
|
|
457
|
+
this._encoded = mappings || "";
|
|
458
|
+
this._decodedMemo = memoizedState();
|
|
459
|
+
this.url = from;
|
|
460
|
+
this.resolvedSources = (sources || []).map((s) => resolve(s || "", from));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function memoizedState() {
|
|
464
|
+
return {
|
|
465
|
+
lastKey: -1,
|
|
466
|
+
lastNeedle: -1,
|
|
467
|
+
lastIndex: -1
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function getOriginalPosition(map, needle) {
|
|
471
|
+
const result = originalPositionFor(map, needle);
|
|
472
|
+
if (result.column == null) {
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
return result;
|
|
476
|
+
}
|
|
995
477
|
|
|
996
|
-
export {
|
|
478
|
+
export { DecodedMap, createStackString, stackIgnorePatterns as defaultStackIgnorePatterns, getOriginalPosition, parseErrorStacktrace, parseSingleFFOrSafariStack, parseSingleStack, parseSingleV8Stack, parseStacktrace };
|