@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.
@@ -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
- const comma = ','.charCodeAt(0);
4
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
5
- const intToChar = new Uint8Array(64); // 64 possible chars.
6
- const charToInt = new Uint8Array(128); // z is 122 in ASCII
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
- const c = chars.charCodeAt(i);
9
- intToChar[i] = c;
10
- charToInt[c] = i;
11
+ const c = chars.charCodeAt(i);
12
+ intToChar[i] = c;
13
+ charToInt[c] = i;
11
14
  }
12
15
  function decodeInteger(reader, relative) {
13
- let value = 0;
14
- let shift = 0;
15
- let integer = 0;
16
- do {
17
- const c = reader.next();
18
- integer = charToInt[c];
19
- value |= (integer & 31) << shift;
20
- shift += 5;
21
- } while (integer & 32);
22
- const shouldNegate = value & 1;
23
- value >>>= 1;
24
- if (shouldNegate) {
25
- value = -2147483648 | -value;
26
- }
27
- return relative + value;
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
- if (reader.pos >= max)
31
- return false;
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
- const { length } = mappings;
54
- const reader = new StringReader(mappings);
55
- const decoded = [];
56
- let genColumn = 0;
57
- let sourcesIndex = 0;
58
- let sourceLine = 0;
59
- let sourceColumn = 0;
60
- let namesIndex = 0;
61
- do {
62
- const semi = reader.indexOf(';');
63
- const line = [];
64
- let sorted = true;
65
- let lastCol = 0;
66
- genColumn = 0;
67
- while (reader.pos < semi) {
68
- let seg;
69
- genColumn = decodeInteger(reader, genColumn);
70
- if (genColumn < lastCol)
71
- sorted = false;
72
- lastCol = genColumn;
73
- if (hasMoreVlq(reader, semi)) {
74
- sourcesIndex = decodeInteger(reader, sourcesIndex);
75
- sourceLine = decodeInteger(reader, sourceLine);
76
- sourceColumn = decodeInteger(reader, sourceColumn);
77
- if (hasMoreVlq(reader, semi)) {
78
- namesIndex = decodeInteger(reader, namesIndex);
79
- seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
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
- case UrlType.AbsolutePath:
339
- return url.path + queryHash;
340
- default:
341
- return url.scheme + '//' + url.user + url.host + url.port + url.path + queryHash;
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
- function resolve$1(input, base) {
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
- const COLUMN = 0;
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
- function maybeSort(mappings, owned) {
373
- const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
374
- if (unsortedIndex === mappings.length)
375
- return mappings;
376
- // If we own the array (meaning we parsed it from JSON), then we're free to directly mutate it. If
377
- // not, we do not want to modify the consumer's input array.
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
- let found = false;
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
- while (low <= high) {
428
- const mid = low + ((high - low) >> 1);
429
- const cmp = haystack[mid][COLUMN] - needle;
430
- if (cmp === 0) {
431
- found = true;
432
- return mid;
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
- found = false;
442
- return low - 1;
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
- for (let i = index + 1; i < haystack.length; index = i++) {
446
- if (haystack[i][COLUMN] !== needle)
447
- break;
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
- for (let i = index - 1; i >= 0; index = i--) {
453
- if (haystack[i][COLUMN] !== needle)
454
- break;
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
- const { lastKey, lastNeedle, lastIndex } = state;
471
- let low = 0;
472
- let high = haystack.length - 1;
473
- if (key === lastKey) {
474
- if (needle === lastNeedle) {
475
- found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
476
- return lastIndex;
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
- state.lastKey = key;
487
- state.lastNeedle = needle;
488
- return (state.lastIndex = binarySearch(haystack, needle, low, high));
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
- array[index] = value;
523
- }
524
- // Null arrays allow us to use ordered index keys without actually allocating contiguous memory like
525
- // a real array. We use a null-prototype object to avoid prototype pollution and deoptimizations.
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
- const LINE_GTR_ZERO = '`line` must be greater than 0 (lines start at line 1)';
534
- const COL_GTR_EQ_ZERO = '`column` must be greater than or equal to 0 (columns start at column 0)';
535
- const LEAST_UPPER_BOUND = -1;
536
- const GREATEST_LOWER_BOUND = 1;
537
- class TraceMap {
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
- return map;
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
- var _a;
579
- return ((_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded)));
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
- let { line, column, bias } = needle;
588
- line--;
589
- if (line < 0)
590
- throw new Error(LINE_GTR_ZERO);
591
- if (column < 0)
592
- throw new Error(COL_GTR_EQ_ZERO);
593
- const decoded = decodedMappings(map);
594
- // It's common for parent source maps to have pointers to lines that have no
595
- // mapping (like a "//# sourceMappingURL=") at the end of the child file.
596
- if (line >= decoded.length)
597
- return OMapping(null, null, null, null);
598
- const segments = decoded[line];
599
- const index = traceSegmentInternal(segments, cast(map)._decodedMemo, line, column, bias || GREATEST_LOWER_BOUND);
600
- if (index === -1)
601
- return OMapping(null, null, null, null);
602
- const segment = segments[index];
603
- if (segment.length === 1)
604
- return OMapping(null, null, null, null);
605
- const { names, resolvedSources } = map;
606
- return OMapping(resolvedSources[segment[SOURCES_INDEX]], segment[SOURCE_LINE] + 1, segment[SOURCE_COLUMN], segment.length === 5 ? names[segment[NAMES_INDEX]] : null);
607
- }
608
- /**
609
- * Finds the generated line/column position of the provided source/line/column source position.
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
- return { source, line, column, name };
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
- let index = memoizedBinarySearch(segments, column, memo, line);
657
- if (found) {
658
- index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
659
- }
660
- else if (bias === LEAST_UPPER_BOUND)
661
- index++;
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
- if (!line.includes("@") && !line.includes(":")) {
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
- // eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/optimal-quantifier-concatenation
850
- const functionNameRegex = /((.*".+"[^@]*)?[^@]*)(@)/;
851
- const matches = line.match(functionNameRegex);
852
- const functionName = matches && matches[1] ? matches[1] : undefined;
853
- const [url, lineNumber, columnNumber] = extractLocation(line.replace(functionNameRegex, ""));
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 TraceMap(map);
935
- const { line, column, source, name } = originalPositionFor(traceMap, stack);
936
- let file = stack.file;
937
- if (source) {
938
- const fileUrl = stack.file.startsWith("file://") ? stack.file : `file://${stack.file}`;
939
- const sourceRootUrl = map.sourceRoot ? new URL(map.sourceRoot, fileUrl) : fileUrl;
940
- file = new URL(source, sourceRootUrl).pathname;
941
- // if the file path is on windows, we need to remove the leading slash
942
- if (file.match(/\/\w:\//)) {
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 { TraceMap, createStackString, eachMapping, generatedPositionFor, originalPositionFor, parseErrorStacktrace, parseSingleFFOrSafariStack, parseSingleStack, parseSingleV8Stack, parseStacktrace };
478
+ export { DecodedMap, createStackString, stackIgnorePatterns as defaultStackIgnorePatterns, getOriginalPosition, parseErrorStacktrace, parseSingleFFOrSafariStack, parseSingleStack, parseSingleV8Stack, parseStacktrace };