vitest 4.0.7 → 4.0.9

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.
Files changed (65) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/browser.d.ts +2 -2
  3. package/dist/browser.js +2 -2
  4. package/dist/chunks/{base.D3GxgUMI.js → base.CiIV2DDC.js} +71 -36
  5. package/dist/chunks/{benchmark.DHKMYAts.js → benchmark.B3N2zMcH.js} +9 -4
  6. package/dist/chunks/{browser.d.-LKfRopd.d.ts → browser.d.DnU_kh8a.d.ts} +1 -1
  7. package/dist/chunks/{cac.G9DAn-c7.js → cac.B_NTJoIH.js} +115 -42
  8. package/dist/chunks/{cli-api.Csks4as1.js → cli-api.D48wY175.js} +1863 -845
  9. package/dist/chunks/console.Cf-YriPC.js +146 -0
  10. package/dist/chunks/{coverage.C2LA1DSL.js → coverage.BUlIqJrL.js} +284 -114
  11. package/dist/chunks/{creator.cqqifzG7.js → creator.BzqvXeRE.js} +75 -31
  12. package/dist/chunks/{date.-jtEtIeV.js → date.Bq6ZW5rf.js} +17 -6
  13. package/dist/chunks/{git.BFNcloKD.js → git.Bm2pzPAa.js} +3 -3
  14. package/dist/chunks/{global.d.DxtanrNO.d.ts → global.d.BQDgW9Pr.d.ts} +1 -1
  15. package/dist/chunks/{globals.BGT_RUsD.js → globals.DBrtKPdh.js} +5 -5
  16. package/dist/chunks/index.0kCJoeWi.js +220 -0
  17. package/dist/chunks/{index.CWIFvlX5.js → index.BfmpdV5p.js} +165 -54
  18. package/dist/chunks/{index.RwjEGCQ0.js → index.CGezRSGU.js} +2 -2
  19. package/dist/chunks/{index.DEPqWSIZ.js → index.CPA8jGhR.js} +33 -16
  20. package/dist/chunks/{index.CVpyv-Zg.js → index.kotH7DY7.js} +832 -373
  21. package/dist/chunks/{index.jMQYiEWE.js → index.op2Re5rn.js} +22 -12
  22. package/dist/chunks/{index.Dc3xnDvT.js → index.z7NPOg2E.js} +4 -4
  23. package/dist/chunks/{init-forks.IU-xQ2_X.js → init-forks.aqTzCSR2.js} +14 -4
  24. package/dist/chunks/{init-threads.C_NWvZkU.js → init-threads.C7T0-YMD.js} +1 -1
  25. package/dist/chunks/{init.fmH9J833.js → init.BQhNfT0h.js} +53 -30
  26. package/dist/chunks/{inspector.DLZxSeU3.js → inspector.CvyFGlXm.js} +25 -10
  27. package/dist/chunks/{moduleRunner.d.DEkTotCv.d.ts → moduleRunner.d.BxT-OjLR.d.ts} +1 -1
  28. package/dist/chunks/{node.BwAWWjHZ.js → node.Ce0vMQM7.js} +1 -1
  29. package/dist/chunks/{plugin.d.Cpes8Bt6.d.ts → plugin.d.DevON6kQ.d.ts} +1 -1
  30. package/dist/chunks/{reporters.d.CSNcMDxF.d.ts → reporters.d.BQ0wpUaj.d.ts} +6 -5
  31. package/dist/chunks/{rpc.D38ahn14.js → rpc.BytlcPfC.js} +20 -7
  32. package/dist/chunks/{setup-common.DR1sucx6.js → setup-common.Dw1XgX0v.js} +20 -8
  33. package/dist/chunks/{startModuleRunner.Cn7hCL7D.js → startModuleRunner.DLjmA_wU.js} +209 -86
  34. package/dist/chunks/{test.B6aJd6T3.js → test.w5HLbjmU.js} +48 -22
  35. package/dist/chunks/{utils.CG9h5ccR.js → utils.DvEY5TfP.js} +14 -5
  36. package/dist/chunks/{vi.BZvkKVkM.js → vi.CyIUVSoU.js} +267 -117
  37. package/dist/chunks/{vm.BL7_zzOr.js → vm.DXN8eCh2.js} +181 -75
  38. package/dist/chunks/{worker.d.D25zYZ7N.d.ts → worker.d.ZGohxCEd.d.ts} +74 -7
  39. package/dist/cli.js +2 -2
  40. package/dist/config.d.ts +5 -5
  41. package/dist/coverage.d.ts +3 -3
  42. package/dist/coverage.js +1 -1
  43. package/dist/environments.js +1 -1
  44. package/dist/index.d.ts +5 -5
  45. package/dist/index.js +5 -5
  46. package/dist/module-evaluator.d.ts +2 -2
  47. package/dist/module-evaluator.js +88 -38
  48. package/dist/module-runner.js +2 -2
  49. package/dist/node.d.ts +7 -7
  50. package/dist/node.js +17 -13
  51. package/dist/reporters.d.ts +3 -3
  52. package/dist/reporters.js +2 -2
  53. package/dist/runners.js +7 -7
  54. package/dist/snapshot.js +2 -2
  55. package/dist/suite.js +2 -2
  56. package/dist/worker.d.ts +1 -1
  57. package/dist/worker.js +15 -15
  58. package/dist/workers/forks.js +16 -16
  59. package/dist/workers/runVmTests.js +41 -22
  60. package/dist/workers/threads.js +16 -16
  61. package/dist/workers/vmForks.js +11 -11
  62. package/dist/workers/vmThreads.js +11 -11
  63. package/package.json +20 -20
  64. package/dist/chunks/console.CTJL2nuH.js +0 -115
  65. package/dist/chunks/index.Bgo3tNWt.js +0 -176
@@ -34,22 +34,39 @@ class VitestTransport {
34
34
 
35
35
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
36
36
  function normalizeWindowsPath(input = "") {
37
- return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
37
+ if (!input) return input;
38
+ return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
38
39
  }
39
- const _UNC_REGEX = /^[/\\]{2}/, _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, _DRIVE_LETTER_RE = /^[A-Za-z]:$/, _EXTNAME_RE = /.(\.[^./]+|\.)$/, normalize = function(path) {
40
+ const _UNC_REGEX = /^[/\\]{2}/;
41
+ const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
42
+ const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
43
+ const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
44
+ const normalize = function(path) {
40
45
  if (path.length === 0) return ".";
41
46
  path = normalizeWindowsPath(path);
42
- const isUNCPath = path.match(_UNC_REGEX), isPathAbsolute = isAbsolute(path), trailingSeparator = path[path.length - 1] === "/";
43
- if (path = normalizeString(path, !isPathAbsolute), path.length === 0) return isPathAbsolute ? "/" : trailingSeparator ? "./" : ".";
47
+ const isUNCPath = path.match(_UNC_REGEX);
48
+ const isPathAbsolute = isAbsolute(path);
49
+ const trailingSeparator = path[path.length - 1] === "/";
50
+ path = normalizeString(path, !isPathAbsolute);
51
+ if (path.length === 0) {
52
+ if (isPathAbsolute) return "/";
53
+ return trailingSeparator ? "./" : ".";
54
+ }
44
55
  if (trailingSeparator) path += "/";
45
56
  if (_DRIVE_LETTER_RE.test(path)) path += "/";
46
- return isUNCPath ? isPathAbsolute ? `//${path}` : `//./${path}` : isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
47
- }, join = function(...segments) {
57
+ if (isUNCPath) {
58
+ if (!isPathAbsolute) return `//./${path}`;
59
+ return `//${path}`;
60
+ }
61
+ return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
62
+ };
63
+ const join = function(...segments) {
48
64
  let path = "";
49
65
  for (const seg of segments) {
50
66
  if (!seg) continue;
51
67
  if (path.length > 0) {
52
- const pathTrailing = path[path.length - 1] === "/", segLeading = seg[0] === "/";
68
+ const pathTrailing = path[path.length - 1] === "/";
69
+ const segLeading = seg[0] === "/";
53
70
  if (pathTrailing && segLeading) path += seg.slice(1);
54
71
  else path += pathTrailing || segLeading ? seg : `/${seg}`;
55
72
  } else path += seg;
@@ -57,19 +74,29 @@ const _UNC_REGEX = /^[/\\]{2}/, _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\
57
74
  return normalize(path);
58
75
  };
59
76
  function cwd$1() {
60
- return typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd().replace(/\\/g, "/") : "/";
77
+ if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
78
+ return "/";
61
79
  }
62
80
  const resolve = function(...arguments_) {
63
81
  arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
64
- let resolvedPath = "", resolvedAbsolute = false;
82
+ let resolvedPath = "";
83
+ let resolvedAbsolute = false;
65
84
  for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
66
85
  const path = index >= 0 ? arguments_[index] : cwd$1();
67
- !path || path.length === 0 || (resolvedPath = `${path}/${resolvedPath}`, resolvedAbsolute = isAbsolute(path));
86
+ if (!path || path.length === 0) continue;
87
+ resolvedPath = `${path}/${resolvedPath}`;
88
+ resolvedAbsolute = isAbsolute(path);
68
89
  }
69
- return resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute), resolvedAbsolute && !isAbsolute(resolvedPath) ? `/${resolvedPath}` : resolvedPath.length > 0 ? resolvedPath : ".";
90
+ resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
91
+ if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
92
+ return resolvedPath.length > 0 ? resolvedPath : ".";
70
93
  };
71
94
  function normalizeString(path, allowAboveRoot) {
72
- let res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, char = null;
95
+ let res = "";
96
+ let lastSegmentLength = 0;
97
+ let lastSlash = -1;
98
+ let dots = 0;
99
+ let char = null;
73
100
  for (let index = 0; index <= path.length; ++index) {
74
101
  if (index < path.length) char = path[index];
75
102
  else if (char === "/") break;
@@ -80,22 +107,35 @@ function normalizeString(path, allowAboveRoot) {
80
107
  if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
81
108
  if (res.length > 2) {
82
109
  const lastSlashIndex = res.lastIndexOf("/");
83
- if (lastSlashIndex === -1) res = "", lastSegmentLength = 0;
84
- else res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
85
- lastSlash = index, dots = 0;
110
+ if (lastSlashIndex === -1) {
111
+ res = "";
112
+ lastSegmentLength = 0;
113
+ } else {
114
+ res = res.slice(0, lastSlashIndex);
115
+ lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
116
+ }
117
+ lastSlash = index;
118
+ dots = 0;
86
119
  continue;
87
120
  } else if (res.length > 0) {
88
- res = "", lastSegmentLength = 0, lastSlash = index, dots = 0;
121
+ res = "";
122
+ lastSegmentLength = 0;
123
+ lastSlash = index;
124
+ dots = 0;
89
125
  continue;
90
126
  }
91
127
  }
92
- if (allowAboveRoot) res += res.length > 0 ? "/.." : "..", lastSegmentLength = 2;
128
+ if (allowAboveRoot) {
129
+ res += res.length > 0 ? "/.." : "..";
130
+ lastSegmentLength = 2;
131
+ }
93
132
  } else {
94
133
  if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`;
95
134
  else res = path.slice(lastSlash + 1, index);
96
135
  lastSegmentLength = index - lastSlash - 1;
97
136
  }
98
- lastSlash = index, dots = 0;
137
+ lastSlash = index;
138
+ dots = 0;
99
139
  } else if (char === "." && dots !== -1) ++dots;
100
140
  else dots = -1;
101
141
  }
@@ -103,15 +143,18 @@ function normalizeString(path, allowAboveRoot) {
103
143
  }
104
144
  const isAbsolute = function(p) {
105
145
  return _IS_ABSOLUTE_RE.test(p);
106
- }, extname = function(p) {
146
+ };
147
+ const extname = function(p) {
107
148
  if (p === "..") return "";
108
149
  const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
109
150
  return match && match[1] || "";
110
- }, dirname = function(p) {
151
+ };
152
+ const dirname = function(p) {
111
153
  const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
112
154
  if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
113
155
  return segments.join("/") || (isAbsolute(p) ? "/" : ".");
114
- }, basename = function(p, extension) {
156
+ };
157
+ const basename = function(p, extension) {
115
158
  const segments = normalizeWindowsPath(p).split("/");
116
159
  let lastSegment = "";
117
160
  for (let i = segments.length - 1; i >= 0; i--) {
@@ -130,7 +173,7 @@ function findMockRedirect(root, mockPath, external) {
130
173
  // it's a node_module alias
131
174
  // all mocks should be inside <root>/__mocks__
132
175
  if (external || isNodeBuiltin(mockPath) || !existsSync(mockPath)) {
133
- const mockDirname = dirname(path), mockFolder = join(root, "__mocks__", mockDirname);
176
+ const mockFolder = join(root, "__mocks__", dirname(path));
134
177
  if (!existsSync(mockFolder)) return null;
135
178
  const baseOriginal = basename(path);
136
179
  function findFile(mockFolder, baseOriginal) {
@@ -139,7 +182,7 @@ function findMockRedirect(root, mockPath, external) {
139
182
  const path = resolve(mockFolder, file);
140
183
  // if the same name, return the file
141
184
  if (statSync(path).isFile()) return path;
142
- {
185
+ else {
143
186
  // find folder/index.{js,ts}
144
187
  const indexFile = findFile(path, "index");
145
188
  if (indexFile) return indexFile;
@@ -149,7 +192,7 @@ function findMockRedirect(root, mockPath, external) {
149
192
  }
150
193
  return findFile(mockFolder, baseOriginal);
151
194
  }
152
- const dir = dirname(path), baseId = basename(path), fullPath = resolve(dir, "__mocks__", baseId);
195
+ const fullPath = resolve(dirname(path), "__mocks__", basename(path));
153
196
  return existsSync(fullPath) ? fullPath : null;
154
197
  }
155
198
  const builtins = new Set([
@@ -167,14 +210,20 @@ const builtins = new Set([
167
210
  "timers/promises",
168
211
  "util/types",
169
212
  "wasi"
170
- ]), prefixedBuiltins$1 = new Set([
213
+ ]);
214
+ // https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
215
+ const prefixedBuiltins$1 = new Set([
171
216
  "node:sea",
172
217
  "node:sqlite",
173
218
  "node:test",
174
219
  "node:test/reporters"
175
- ]), NODE_BUILTIN_NAMESPACE = "node:";
220
+ ]);
221
+ const NODE_BUILTIN_NAMESPACE = "node:";
176
222
  function isNodeBuiltin(id) {
177
- return nodeModule.isBuiltin ? nodeModule.isBuiltin(id) : prefixedBuiltins$1.has(id) ? true : builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
223
+ // Added in v18.6.0
224
+ if (nodeModule.isBuiltin) return nodeModule.isBuiltin(id);
225
+ if (prefixedBuiltins$1.has(id)) return true;
226
+ return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
178
227
  }
179
228
 
180
229
  const spyModulePath = resolve$1(distDir, "spy.js");
@@ -186,7 +235,8 @@ class VitestMocker {
186
235
  registries = /* @__PURE__ */ new Map();
187
236
  mockContext = { callstack: null };
188
237
  constructor(moduleRunner, options) {
189
- this.moduleRunner = moduleRunner, this.options = options;
238
+ this.moduleRunner = moduleRunner;
239
+ this.options = options;
190
240
  const context = this.options.context;
191
241
  if (context) this.primitives = vm.runInContext("({ Object, Error, Function, RegExp, Symbol, Array, Map })", context);
192
242
  else this.primitives = {
@@ -227,7 +277,8 @@ class VitestMocker {
227
277
  return this.options.moduleDirectories || [];
228
278
  }
229
279
  async initializeSpyModule() {
230
- this.spyModule ||= await this.moduleRunner.import(spyModulePath);
280
+ if (this.spyModule) return;
281
+ this.spyModule = await this.moduleRunner.import(spyModulePath);
231
282
  }
232
283
  getMockerRegistry() {
233
284
  const suite = this.getSuiteFilepath();
@@ -238,8 +289,12 @@ class VitestMocker {
238
289
  this.registries.clear();
239
290
  }
240
291
  invalidateModuleById(id) {
241
- const mockId = this.getMockPath(id), node = this.evaluatedModules.getModuleById(mockId);
242
- if (node) this.evaluatedModules.invalidateModule(node), node.mockedExports = void 0;
292
+ const mockId = this.getMockPath(id);
293
+ const node = this.evaluatedModules.getModuleById(mockId);
294
+ if (node) {
295
+ this.evaluatedModules.invalidateModule(node);
296
+ node.mockedExports = void 0;
297
+ }
243
298
  }
244
299
  isModuleDirectory(path) {
245
300
  return this.moduleDirectories.some((dir) => path.includes(dir));
@@ -248,8 +303,10 @@ class VitestMocker {
248
303
  return this.options.getCurrentTestFilepath() || "global";
249
304
  }
250
305
  createError(message, codeFrame) {
251
- const Error = this.primitives.Error, error = new Error(message);
252
- return Object.assign(error, { codeFrame }), error;
306
+ const Error = this.primitives.Error;
307
+ const error = new Error(message);
308
+ Object.assign(error, { codeFrame });
309
+ return error;
253
310
  }
254
311
  async resolveId(rawId, importer) {
255
312
  const result = await this.options.resolveId(rawId, importer);
@@ -271,26 +328,31 @@ class VitestMocker {
271
328
  };
272
329
  }
273
330
  async resolveMocks() {
274
- VitestMocker.pendingIds.length && (await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
331
+ if (!VitestMocker.pendingIds.length) return;
332
+ await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
275
333
  const { id, url, external } = await this.resolveId(mock.id, mock.importer);
276
334
  if (mock.action === "unmock") this.unmockPath(id);
277
335
  if (mock.action === "mock") this.mockPath(mock.id, id, url, external, mock.type, mock.factory);
278
- })), VitestMocker.pendingIds = []);
336
+ }));
337
+ VitestMocker.pendingIds = [];
279
338
  }
280
339
  ensureModule(id, url) {
281
340
  const node = this.evaluatedModules.ensureModule(id, url);
282
- return node.meta = {
341
+ // TODO
342
+ node.meta = {
283
343
  id,
284
344
  url,
285
345
  code: "",
286
346
  file: null,
287
347
  invalidate: false
288
- }, node;
348
+ };
349
+ return node;
289
350
  }
290
351
  async callFunctionMock(id, url, mock) {
291
352
  const node = this.ensureModule(id, url);
292
353
  if (node.exports) return node.exports;
293
- const exports = await mock.resolve(), moduleExports = new Proxy(exports, { get: (target, prop) => {
354
+ const exports$1 = await mock.resolve();
355
+ const moduleExports = new Proxy(exports$1, { get: (target, prop) => {
294
356
  const val = target[prop];
295
357
  // 'then' can exist on non-Promise objects, need nested instanceof check for logic to work
296
358
  if (prop === "then") {
@@ -309,7 +371,8 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
309
371
  }
310
372
  return val;
311
373
  } });
312
- return node.exports = moduleExports, moduleExports;
374
+ node.exports = moduleExports;
375
+ return moduleExports;
313
376
  }
314
377
  // public method to avoid circular dependency
315
378
  getMockContext() {
@@ -335,7 +398,8 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
335
398
  }, object, mockExports);
336
399
  }
337
400
  unmockPath(id) {
338
- this.getMockerRegistry().deleteById(id), this.invalidateModuleById(id);
401
+ this.getMockerRegistry().deleteById(id);
402
+ this.invalidateModuleById(id);
339
403
  }
340
404
  mockPath(originalId, id, url, external, mockType, factory) {
341
405
  const registry = this.getMockerRegistry();
@@ -350,7 +414,8 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
350
414
  this.invalidateModuleById(id);
351
415
  }
352
416
  async importActual(rawId, importer, callstack) {
353
- const { url } = await this.resolveId(rawId, importer), node = await this.moduleRunner.fetchModule(url, importer);
417
+ const { url } = await this.resolveId(rawId, importer);
418
+ const node = await this.moduleRunner.fetchModule(url, importer);
354
419
  return await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
355
420
  }
356
421
  async importMock(rawId, importer) {
@@ -362,7 +427,9 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
362
427
  else mock = new AutomockedModule(rawId, id, rawId);
363
428
  }
364
429
  if (mock.type === "automock" || mock.type === "autospy") {
365
- const node = await this.moduleRunner.fetchModule(url, importer), mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true), Object = this.primitives.Object;
430
+ const node = await this.moduleRunner.fetchModule(url, importer);
431
+ const mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true);
432
+ const Object = this.primitives.Object;
366
433
  return this.mockObject(mod, Object.create(Object.prototype), mock.type);
367
434
  }
368
435
  if (mock.type === "manual") return this.callFunctionMock(id, url, mock);
@@ -374,19 +441,30 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
374
441
  if (mock.type === "automock" || mock.type === "autospy") {
375
442
  const cache = this.evaluatedModules.getModuleById(mockId);
376
443
  if (cache && cache.mockedExports) return cache.mockedExports;
377
- const Object = this.primitives.Object, exports = Object.create(null);
378
- Object.defineProperty(exports, Symbol.toStringTag, {
444
+ const Object = this.primitives.Object;
445
+ // we have to define a separate object that will copy all properties into itself
446
+ // and can't just use the same `exports` define automatically by Vite before the evaluator
447
+ const exports$1 = Object.create(null);
448
+ Object.defineProperty(exports$1, Symbol.toStringTag, {
379
449
  value: "Module",
380
450
  configurable: true,
381
451
  writable: true
382
452
  });
383
453
  const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url));
384
- node.meta = evaluatedNode.meta, node.file = evaluatedNode.file, node.mockedExports = exports;
454
+ node.meta = evaluatedNode.meta;
455
+ node.file = evaluatedNode.file;
456
+ node.mockedExports = exports$1;
385
457
  const mod = await this.moduleRunner.cachedRequest(url, node, callstack, void 0, true);
386
- return this.mockObject(mod, exports, mock.type), exports;
458
+ this.mockObject(mod, exports$1, mock.type);
459
+ return exports$1;
387
460
  }
388
461
  if (mock.type === "manual" && !callstack.includes(mockId) && !callstack.includes(url)) try {
389
- return callstack.push(mockId), this.mockContext.callstack = callstack, await this.callFunctionMock(mockId, this.getMockPath(url), mock);
462
+ callstack.push(mockId);
463
+ // this will not work if user does Promise.all(import(), import())
464
+ // we can also use AsyncLocalStorage to store callstack, but this won't work in the browser
465
+ // maybe we should improve mock API in the future?
466
+ this.mockContext.callstack = callstack;
467
+ return await this.callFunctionMock(mockId, this.getMockPath(url), mock);
390
468
  } finally {
391
469
  this.mockContext.callstack = null;
392
470
  const indexMock = callstack.indexOf(mockId);
@@ -396,7 +474,8 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
396
474
  }
397
475
  async mockedRequest(url, evaluatedNode, callstack) {
398
476
  const mock = this.getDependencyMock(evaluatedNode.id);
399
- if (mock) return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
477
+ if (!mock) return;
478
+ return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
400
479
  }
401
480
  queueMock(id, importer, factoryOrOptions) {
402
481
  const mockType = getMockType(factoryOrOptions);
@@ -417,7 +496,9 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
417
496
  }
418
497
  }
419
498
  function getMockType(factoryOrOptions) {
420
- return factoryOrOptions ? typeof factoryOrOptions === "function" ? "manual" : factoryOrOptions.spy ? "autospy" : "automock" : "automock";
499
+ if (!factoryOrOptions) return "automock";
500
+ if (typeof factoryOrOptions === "function") return "manual";
501
+ return factoryOrOptions.spy ? "autospy" : "automock";
421
502
  }
422
503
  // unique id that is not available as "$bare_import" like "test"
423
504
  // https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
@@ -426,7 +507,8 @@ const prefixedBuiltins = new Set([
426
507
  "node:sqlite",
427
508
  "node:test",
428
509
  "node:test/reporters"
429
- ]), isWindows$1 = process.platform === "win32";
510
+ ]);
511
+ const isWindows$1 = process.platform === "win32";
430
512
  // transform file url to id
431
513
  // virtual:custom -> virtual:custom
432
514
  // \0custom -> \0custom
@@ -436,8 +518,9 @@ const prefixedBuiltins = new Set([
436
518
  // C:\root\id.js -> /id.js
437
519
  // TODO: expose this in vite/module-runner
438
520
  function normalizeModuleId(file) {
521
+ if (prefixedBuiltins.has(file)) return file;
439
522
  // if it's not in the root, keep it as a path, not a URL
440
- return prefixedBuiltins.has(file) ? file : slash(file).replace(/^\/@fs\//, isWindows$1 ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/").replace(/^file:\//, "/");
523
+ return slash(file).replace(/^\/@fs\//, isWindows$1 ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/").replace(/^file:\//, "/");
441
524
  }
442
525
  const windowsSlashRE = /\\/g;
443
526
  function slash(p) {
@@ -446,12 +529,15 @@ function slash(p) {
446
529
  const multipleSlashRe = /^\/+/;
447
530
  // module-runner incorrectly replaces file:///path with `///path`
448
531
  function fixLeadingSlashes(id) {
449
- return id.startsWith("//") ? id.replace(multipleSlashRe, "/") : id;
532
+ if (id.startsWith("//")) return id.replace(multipleSlashRe, "/");
533
+ return id;
450
534
  }
451
535
 
452
536
  const createNodeImportMeta = (modulePath) => {
453
537
  if (!viteModuleRunner.createDefaultImportMeta) throw new Error(`createNodeImportMeta is not supported in this version of Vite.`);
454
- const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath), href = defaultMeta.url, importMetaResolver = createImportMetaResolver();
538
+ const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath);
539
+ const href = defaultMeta.url;
540
+ const importMetaResolver = createImportMetaResolver();
455
541
  return {
456
542
  ...defaultMeta,
457
543
  main: false,
@@ -461,21 +547,27 @@ const createNodeImportMeta = (modulePath) => {
461
547
  };
462
548
  };
463
549
  function createImportMetaResolver() {
464
- if (import.meta.resolve) return (specifier, importer) => import.meta.resolve(specifier, importer);
550
+ if (!import.meta.resolve) return;
551
+ return (specifier, importer) => import.meta.resolve(specifier, importer);
465
552
  }
466
553
  // @ts-expect-error overriding private method
467
554
  class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
468
555
  mocker;
469
556
  moduleExecutionInfo;
470
557
  constructor(vitestOptions) {
471
- const options = vitestOptions, transport = new VitestTransport(options.transport), evaluatedModules = options.evaluatedModules;
472
- if (super({
558
+ const options = vitestOptions;
559
+ const transport = new VitestTransport(options.transport);
560
+ const evaluatedModules = options.evaluatedModules;
561
+ super({
473
562
  transport,
474
563
  hmr: false,
475
564
  evaluatedModules,
476
565
  sourcemapInterceptor: "prepareStackTrace",
477
566
  createImportMeta: vitestOptions.createImportMeta
478
- }, options.evaluator), this.vitestOptions = vitestOptions, this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo, this.mocker = options.mocker || new VitestMocker(this, {
567
+ }, options.evaluator);
568
+ this.vitestOptions = vitestOptions;
569
+ this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo;
570
+ this.mocker = options.mocker || new VitestMocker(this, {
479
571
  spyModule: options.spyModule,
480
572
  context: options.vm?.context,
481
573
  resolveId: options.transport.resolveId,
@@ -488,7 +580,8 @@ class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
488
580
  getCurrentTestFilepath() {
489
581
  return options.getWorkerState().filepath;
490
582
  }
491
- }), options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
583
+ });
584
+ if (options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
492
585
  else Object.defineProperty(globalThis, "__vitest_mocker__", {
493
586
  configurable: true,
494
587
  writable: true,
@@ -502,8 +595,8 @@ class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
502
595
  * We should keep the Vite behavour when there is a `strict` flag.
503
596
  * @internal
504
597
  */
505
- processImport(exports) {
506
- return exports;
598
+ processImport(exports$1) {
599
+ return exports$1;
507
600
  }
508
601
  async import(rawId) {
509
602
  const resolved = await this.vitestOptions.transport.resolveId(rawId);
@@ -528,7 +621,8 @@ class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
528
621
  const node = await this.fetchModule(mocked);
529
622
  return this._cachedRequest(mocked, node, callstack, metadata);
530
623
  }
531
- return mocked != null && typeof mocked === "object" ? mocked : this._cachedRequest(url, mod, callstack, metadata);
624
+ if (mocked != null && typeof mocked === "object") return mocked;
625
+ return this._cachedRequest(url, mod, callstack, metadata);
532
626
  }
533
627
  /** @internal */
534
628
  _invalidateSubTreeById(ids, invalidated = /* @__PURE__ */ new Set()) {
@@ -544,7 +638,10 @@ class VitestModuleRunner extends viteModuleRunner.ModuleRunner {
544
638
  }
545
639
  }
546
640
 
547
- const bareVitestRegexp = /^@?vitest(?:\/|$)/, normalizedDistDir = normalize$1(distDir), relativeIds = {}, externalizeMap = /* @__PURE__ */ new Map();
641
+ const bareVitestRegexp = /^@?vitest(?:\/|$)/;
642
+ const normalizedDistDir = normalize$1(distDir);
643
+ const relativeIds = {};
644
+ const externalizeMap = /* @__PURE__ */ new Map();
548
645
  // all Vitest imports always need to be externalized
549
646
  function getCachedVitestImport(id, state) {
550
647
  if (id.startsWith("/@fs/") || id.startsWith("\\@fs\\")) id = id.slice(process.platform === "win32" ? 5 : 4);
@@ -554,31 +651,42 @@ function getCachedVitestImport(id, state) {
554
651
  };
555
652
  // always externalize Vitest because we import from there before running tests
556
653
  // so we already have it cached by Node.js
557
- const root = state().config.root, relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
654
+ const root = state().config.root;
655
+ const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
558
656
  if (id.includes(distDir) || id.includes(normalizedDistDir)) {
559
657
  const externalize = id.startsWith("file://") ? id : pathToFileURL(id).toString();
560
- return externalizeMap.set(id, externalize), {
658
+ externalizeMap.set(id, externalize);
659
+ return {
561
660
  externalize,
562
661
  type: "module"
563
662
  };
564
663
  }
565
664
  if (relativeRoot && relativeRoot !== "/" && id.startsWith(relativeRoot)) {
566
- const path = join$1(root, id), externalize = pathToFileURL(path).toString();
567
- return externalizeMap.set(id, externalize), {
665
+ const externalize = pathToFileURL(join$1(root, id)).toString();
666
+ externalizeMap.set(id, externalize);
667
+ return {
568
668
  externalize,
569
669
  type: "module"
570
670
  };
571
671
  }
572
- return bareVitestRegexp.test(id) ? (externalizeMap.set(id, id), {
573
- externalize: id,
574
- type: "module"
575
- }) : null;
672
+ if (bareVitestRegexp.test(id)) {
673
+ externalizeMap.set(id, id);
674
+ return {
675
+ externalize: id,
676
+ type: "module"
677
+ };
678
+ }
679
+ return null;
576
680
  }
577
681
 
578
682
  // Store globals in case tests overwrite them
579
- const processListeners = process.listeners.bind(process), processOn = process.on.bind(process), processOff = process.off.bind(process), dispose = [];
683
+ const processListeners = process.listeners.bind(process);
684
+ const processOn = process.on.bind(process);
685
+ const processOff = process.off.bind(process);
686
+ const dispose = [];
580
687
  function listenForErrors(state) {
581
- dispose.forEach((fn) => fn()), dispose.length = 0;
688
+ dispose.forEach((fn) => fn());
689
+ dispose.length = 0;
582
690
  function catchError(err, type, event) {
583
691
  const worker = state();
584
692
  // if there is another listener, assume that it's handled by user code
@@ -586,31 +694,43 @@ function listenForErrors(state) {
586
694
  if (processListeners(event).length > 1) return;
587
695
  const error = serializeValue(err);
588
696
  if (typeof error === "object" && error != null) {
589
- if (error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0, worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
697
+ error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
698
+ if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
590
699
  }
591
700
  state().rpc.onUnhandledError(error, type);
592
701
  }
593
- const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException"), unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
594
- processOn("uncaughtException", uncaughtException), processOn("unhandledRejection", unhandledRejection), dispose.push(() => {
595
- processOff("uncaughtException", uncaughtException), processOff("unhandledRejection", unhandledRejection);
702
+ const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
703
+ const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
704
+ processOn("uncaughtException", uncaughtException);
705
+ processOn("unhandledRejection", unhandledRejection);
706
+ dispose.push(() => {
707
+ processOff("uncaughtException", uncaughtException);
708
+ processOff("unhandledRejection", unhandledRejection);
596
709
  });
597
710
  }
598
711
 
599
- const { readFileSync } = fs, browserExternalId = "__vite-browser-external", browserExternalLength = 24;
712
+ const { readFileSync } = fs;
713
+ const browserExternalId = "__vite-browser-external";
714
+ const browserExternalLength = 24;
600
715
  const VITEST_VM_CONTEXT_SYMBOL = "__vitest_vm_context__";
601
- const cwd = process.cwd(), isWindows = process.platform === "win32";
716
+ const cwd = process.cwd();
717
+ const isWindows = process.platform === "win32";
602
718
  function startVitestModuleRunner(options) {
603
- const state = () => globalThis.__vitest_worker__ || options.state, rpc = () => state().rpc;
719
+ const state = () => globalThis.__vitest_worker__ || options.state;
720
+ const rpc = () => state().rpc;
604
721
  process.exit = (code = process.exitCode || 0) => {
605
722
  throw new Error(`process.exit unexpectedly called with "${code}"`);
606
- }, listenForErrors(state);
723
+ };
724
+ listenForErrors(state);
607
725
  const environment = () => {
608
726
  const environment = state().environment;
609
727
  return environment.viteEnvironment || environment.name;
610
- }, vm = options.context && options.externalModulesExecutor ? {
728
+ };
729
+ const vm = options.context && options.externalModulesExecutor ? {
611
730
  context: options.context,
612
731
  externalModulesExecutor: options.externalModulesExecutor
613
- } : void 0, evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
732
+ } : void 0;
733
+ const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
614
734
  get moduleExecutionInfo() {
615
735
  return state().moduleExecutionInfo;
616
736
  },
@@ -618,7 +738,8 @@ function startVitestModuleRunner(options) {
618
738
  return state().config.deps.interopDefault;
619
739
  },
620
740
  getCurrentTestFilepath: () => state().filepath
621
- }), moduleRunner = new VitestModuleRunner({
741
+ });
742
+ const moduleRunner = new VitestModuleRunner({
622
743
  spyModule: options.spyModule,
623
744
  evaluatedModules: options.evaluatedModules,
624
745
  evaluator,
@@ -654,15 +775,17 @@ function startVitestModuleRunner(options) {
654
775
  type: "builtin"
655
776
  };
656
777
  const result = await rpc().fetch(id, importer, environment(), options);
657
- return "cached" in result ? {
778
+ if ("cached" in result) return {
658
779
  code: readFileSync(result.tmp, "utf-8"),
659
780
  ...result
660
- } : result;
781
+ };
782
+ return result;
661
783
  } catch (cause) {
662
784
  // rethrow vite error if it cannot load the module because it's not resolved
663
785
  if (typeof cause === "object" && cause != null && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url") || typeof cause?.message === "string" && cause.message.startsWith("Cannot find module '")) {
664
786
  const error = new Error(`Cannot find ${isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from '${importer}'` : ""}`, { cause });
665
- throw error.code = "ERR_MODULE_NOT_FOUND", error;
787
+ error.code = "ERR_MODULE_NOT_FOUND";
788
+ throw error;
666
789
  }
667
790
  throw cause;
668
791
  } finally {