vitest 4.0.6 → 4.0.8

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.BgTO2qAg.js +156 -0
  5. package/dist/chunks/{benchmark.DHKMYAts.js → benchmark.B3N2zMcH.js} +9 -4
  6. package/dist/chunks/{browser.d.ScGeWTou.d.ts → browser.d.DTTM2PTh.d.ts} +1 -1
  7. package/dist/chunks/{cac.BBqWH4nd.js → cac.CfkWq8Qy.js} +117 -43
  8. package/dist/chunks/{cli-api.UL3SwFUb.js → cli-api.BQ-bjcRi.js} +1870 -847
  9. package/dist/chunks/console.Cf-YriPC.js +146 -0
  10. package/dist/chunks/{coverage.DuCn_Tmx.js → coverage.NVjCOln1.js} +281 -103
  11. package/dist/chunks/{creator.cqqifzG7.js → creator.fzVyoMf3.js} +74 -30
  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.DdOkMiVb.d.ts → global.d.DVdCfKp5.d.ts} +1 -1
  15. package/dist/chunks/{globals.BGT_RUsD.js → globals.DOh96BiR.js} +5 -5
  16. package/dist/chunks/{resolveSnapshotEnvironment.BZzLjzkh.js → index.BY4-tcno.js} +42 -25
  17. package/dist/chunks/{index.Bgo3tNWt.js → index.DAL392Ss.js} +40 -15
  18. package/dist/chunks/{index.RwjEGCQ0.js → index.DIFZf73e.js} +2 -2
  19. package/dist/chunks/{index.DV0mQLEO.js → index.DfKyPFVi.js} +195 -64
  20. package/dist/chunks/{index.BL8Hg4Uk.js → index.kotH7DY7.js} +837 -380
  21. package/dist/chunks/{index.CpdwpN7L.js → index.op2Re5rn.js} +22 -12
  22. package/dist/chunks/{init-forks.CSGFj9zN.js → init-forks.2hx7cf78.js} +16 -5
  23. package/dist/chunks/{init-threads.CIJLeFO8.js → init-threads.Cm4OCIWA.js} +3 -2
  24. package/dist/chunks/{init.DUeOfNO9.js → init.DMDG-idf.js} +124 -54
  25. package/dist/chunks/{inspector.DLZxSeU3.js → inspector.CvyFGlXm.js} +25 -10
  26. package/dist/chunks/{moduleRunner.d.TP-w6tIQ.d.ts → moduleRunner.d.CzOZ_4wC.d.ts} +1 -1
  27. package/dist/chunks/{node.BwAWWjHZ.js → node.Ce0vMQM7.js} +1 -1
  28. package/dist/chunks/{plugin.d.lctzD3Wk.d.ts → plugin.d.D4RrtywJ.d.ts} +1 -1
  29. package/dist/chunks/{reporters.d.PEs0tXod.d.ts → reporters.d.Da1D1VbQ.d.ts} +19 -9
  30. package/dist/chunks/rpc.BUV7uWKJ.js +76 -0
  31. package/dist/chunks/{setup-common.DR1sucx6.js → setup-common.LGjNSzXp.js} +20 -8
  32. package/dist/chunks/{startModuleRunner.Di-EZqh0.js → startModuleRunner.BOmUtLIO.js} +228 -105
  33. package/dist/chunks/{test.CnspO-X4.js → test.ClrAtjMv.js} +48 -22
  34. package/dist/chunks/{utils.CG9h5ccR.js → utils.DvEY5TfP.js} +14 -5
  35. package/dist/chunks/{vi.BZvkKVkM.js → vi.Bgcdy3bQ.js} +261 -111
  36. package/dist/chunks/{vm.Co_lR2NL.js → vm.BIkCDs68.js} +177 -70
  37. package/dist/chunks/{worker.d.B4Hthdvt.d.ts → worker.d.DadbA89M.d.ts} +52 -6
  38. package/dist/cli.js +2 -2
  39. package/dist/config.d.ts +5 -5
  40. package/dist/coverage.d.ts +3 -3
  41. package/dist/coverage.js +1 -1
  42. package/dist/environments.js +2 -1
  43. package/dist/index.d.ts +5 -5
  44. package/dist/index.js +5 -5
  45. package/dist/module-evaluator.d.ts +2 -2
  46. package/dist/module-evaluator.js +85 -35
  47. package/dist/module-runner.js +2 -2
  48. package/dist/node.d.ts +7 -7
  49. package/dist/node.js +16 -12
  50. package/dist/reporters.d.ts +3 -3
  51. package/dist/reporters.js +2 -2
  52. package/dist/runners.js +7 -7
  53. package/dist/snapshot.js +2 -2
  54. package/dist/suite.js +2 -2
  55. package/dist/worker.d.ts +2 -1
  56. package/dist/worker.js +27 -27
  57. package/dist/workers/forks.js +34 -31
  58. package/dist/workers/runVmTests.js +41 -22
  59. package/dist/workers/threads.js +34 -31
  60. package/dist/workers/vmForks.js +14 -14
  61. package/dist/workers/vmThreads.js +14 -14
  62. package/package.json +20 -20
  63. package/dist/chunks/base.BAf_bYeI.js +0 -128
  64. package/dist/chunks/console.CTJL2nuH.js +0 -115
  65. package/dist/chunks/rpc.Dv1Jt3i2.js +0 -66
@@ -1,8 +1,9 @@
1
1
  import { fileURLToPath, pathToFileURL } from 'node:url';
2
2
  import vm, { isContext, runInContext } from 'node:vm';
3
3
  import { dirname, basename, extname, normalize, resolve } from 'pathe';
4
+ import { l as loadEnvironment } from './init.DMDG-idf.js';
4
5
  import { distDir } from '../path.js';
5
- import { createCustomConsole } from './console.CTJL2nuH.js';
6
+ import { createCustomConsole } from './console.Cf-YriPC.js';
6
7
  import fs from 'node:fs';
7
8
  import { createRequire, Module, isBuiltin } from 'node:module';
8
9
  import { toArray, isBareImport } from '@vitest/utils/helpers';
@@ -10,8 +11,8 @@ import { findNearestPackageData } from '@vitest/utils/resolver';
10
11
  import { dirname as dirname$1 } from 'node:path';
11
12
  import { CSS_LANGS_RE, KNOWN_ASSET_RE } from '@vitest/utils/constants';
12
13
  import { getDefaultRequestStubs } from '../module-evaluator.js';
13
- import { s as startVitestModuleRunner, c as createNodeImportMeta, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.Di-EZqh0.js';
14
- import { p as provideWorkerState } from './utils.CG9h5ccR.js';
14
+ import { s as startVitestModuleRunner, c as createNodeImportMeta, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.BOmUtLIO.js';
15
+ import { p as provideWorkerState } from './utils.DvEY5TfP.js';
15
16
 
16
17
  function interopCommonJsModule(interopDefault, mod) {
17
18
  if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) return {
@@ -20,8 +21,11 @@ function interopCommonJsModule(interopDefault, mod) {
20
21
  defaultExport: mod
21
22
  };
22
23
  if (interopDefault !== false && "__esModule" in mod && !isPrimitive(mod.default)) {
23
- const defaultKets = Object.keys(mod.default), moduleKeys = Object.keys(mod), allKeys = new Set([...defaultKets, ...moduleKeys]);
24
- return allKeys.delete("default"), {
24
+ const defaultKets = Object.keys(mod.default);
25
+ const moduleKeys = Object.keys(mod);
26
+ const allKeys = new Set([...defaultKets, ...moduleKeys]);
27
+ allKeys.delete("default");
28
+ return {
25
29
  keys: Array.from(allKeys),
26
30
  moduleExports: new Proxy(mod, { get(mod, prop) {
27
31
  return mod[prop] ?? mod.default?.[prop];
@@ -41,7 +45,8 @@ function isPrimitive(obj) {
41
45
  const SyntheticModule = vm.SyntheticModule;
42
46
  const SourceTextModule = vm.SourceTextModule;
43
47
 
44
- const _require = createRequire(import.meta.url), requiresCache = /* @__PURE__ */ new WeakMap();
48
+ const _require = createRequire(import.meta.url);
49
+ const requiresCache = /* @__PURE__ */ new WeakMap();
45
50
  class CommonjsExecutor {
46
51
  context;
47
52
  requireCache = /* @__PURE__ */ new Map();
@@ -53,8 +58,12 @@ class CommonjsExecutor {
53
58
  Module;
54
59
  interopDefault;
55
60
  constructor(options) {
56
- this.context = options.context, this.fs = options.fileMap, this.interopDefault = options.interopDefault;
57
- const primitives = vm.runInContext("({ Object, Array, Error })", this.context), executor = this;
61
+ this.context = options.context;
62
+ this.fs = options.fileMap;
63
+ this.interopDefault = options.interopDefault;
64
+ const primitives = vm.runInContext("({ Object, Array, Error })", this.context);
65
+ // eslint-disable-next-line ts/no-this-alias
66
+ const executor = this;
58
67
  this.Module = class Module$1 {
59
68
  exports;
60
69
  isPreloading = false;
@@ -66,13 +75,20 @@ class CommonjsExecutor {
66
75
  path;
67
76
  paths = [];
68
77
  constructor(id = "", parent) {
69
- this.exports = primitives.Object.create(Object.prototype), this.path = dirname(id), this.id = id, this.filename = id, this.loaded = false, this.parent = parent;
78
+ this.exports = primitives.Object.create(Object.prototype);
79
+ // in our case the path should always be resolved already
80
+ this.path = dirname(id);
81
+ this.id = id;
82
+ this.filename = id;
83
+ this.loaded = false;
84
+ this.parent = parent;
70
85
  }
71
86
  get require() {
72
87
  const require = requiresCache.get(this);
73
88
  if (require) return require;
74
89
  const _require = Module$1.createRequire(this.id);
75
- return requiresCache.set(this, _require), _require;
90
+ requiresCache.set(this, _require);
91
+ return _require;
76
92
  }
77
93
  static getSourceMapsSupport = () => ({
78
94
  enabled: false,
@@ -89,16 +105,19 @@ class CommonjsExecutor {
89
105
  throw new Error(`[vitest] "registerHooks" is not available when running in Vitest.`);
90
106
  };
91
107
  _compile(code, filename) {
92
- const cjsModule = Module$1.wrap(code), script = new vm.Script(cjsModule, {
108
+ const cjsModule = Module$1.wrap(code);
109
+ const script = new vm.Script(cjsModule, {
93
110
  filename,
94
111
  importModuleDynamically: options.importModuleDynamically
95
112
  });
96
113
  // @ts-expect-error mark script with current identifier
97
114
  script.identifier = filename;
98
- const fn = script.runInContext(executor.context), __dirname = dirname(filename);
115
+ const fn = script.runInContext(executor.context);
116
+ const __dirname = dirname(filename);
99
117
  executor.requireCache.set(filename, this);
100
118
  try {
101
- return fn(this.exports, this.require, this, filename, __dirname), this.exports;
119
+ fn(this.exports, this.require, this, filename, __dirname);
120
+ return this.exports;
102
121
  } finally {
103
122
  this.loaded = true;
104
123
  }
@@ -143,7 +162,9 @@ class CommonjsExecutor {
143
162
  static stripTypeScriptTypes = Module.stripTypeScriptTypes;
144
163
  static findPackageJSON = Module.findPackageJSON;
145
164
  static Module = Module$1;
146
- }, this.extensions[".js"] = this.requireJs, this.extensions[".json"] = this.requireJson;
165
+ };
166
+ this.extensions[".js"] = this.requireJs;
167
+ this.extensions[".json"] = this.requireJson;
147
168
  }
148
169
  requireJs = (m, filename) => {
149
170
  const content = this.fs.readFile(filename);
@@ -154,17 +175,22 @@ class CommonjsExecutor {
154
175
  m.exports = JSON.parse(code);
155
176
  };
156
177
  createRequire = (filename) => {
157
- const _require = createRequire(filename), require = ((id) => {
178
+ const _require = createRequire(filename);
179
+ const require = ((id) => {
158
180
  const resolved = _require.resolve(id);
159
181
  if (extname(resolved) === ".node" || isBuiltin(resolved)) return this.requireCoreModule(resolved);
160
182
  const module = new this.Module(resolved);
161
183
  return this.loadCommonJSModule(module, resolved);
162
184
  });
163
- return require.resolve = _require.resolve, Object.defineProperty(require, "extensions", {
185
+ require.resolve = _require.resolve;
186
+ Object.defineProperty(require, "extensions", {
164
187
  get: () => this.extensions,
165
188
  set: () => {},
166
189
  configurable: true
167
- }), require.main = void 0, require.cache = this.publicRequireCache, require;
190
+ });
191
+ require.main = void 0;
192
+ require.cache = this.publicRequireCache;
193
+ return require;
168
194
  };
169
195
  createProxyCache() {
170
196
  return new Proxy(Object.create(null), {
@@ -187,39 +213,51 @@ class CommonjsExecutor {
187
213
  const cached = this.requireCache.get(filename);
188
214
  if (cached) return cached.exports;
189
215
  const extension = this.findLongestRegisteredExtension(filename);
190
- return (this.extensions[extension] || this.extensions[".js"])(module, filename), module.exports;
216
+ (this.extensions[extension] || this.extensions[".js"])(module, filename);
217
+ return module.exports;
191
218
  }
192
219
  findLongestRegisteredExtension(filename) {
193
220
  const name = basename(filename);
194
- let currentExtension, index, startIndex = 0;
221
+ let currentExtension;
222
+ let index;
223
+ let startIndex = 0;
195
224
  // eslint-disable-next-line no-cond-assign
196
225
  while ((index = name.indexOf(".", startIndex)) !== -1) {
197
- if (startIndex = index + 1, index === 0) continue;
198
- if (currentExtension = name.slice(index), this.extensions[currentExtension]) return currentExtension;
226
+ startIndex = index + 1;
227
+ if (index === 0) continue;
228
+ currentExtension = name.slice(index);
229
+ if (this.extensions[currentExtension]) return currentExtension;
199
230
  }
200
231
  return ".js";
201
232
  }
202
233
  getCoreSyntheticModule(identifier) {
203
234
  if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
204
- const exports = this.require(identifier), keys = Object.keys(exports), module = new SyntheticModule([...keys, "default"], () => {
235
+ const exports = this.require(identifier);
236
+ const keys = Object.keys(exports);
237
+ const module = new SyntheticModule([...keys, "default"], () => {
205
238
  for (const key of keys) module.setExport(key, exports[key]);
206
239
  module.setExport("default", exports);
207
240
  }, {
208
241
  context: this.context,
209
242
  identifier
210
243
  });
211
- return this.moduleCache.set(identifier, module), module;
244
+ this.moduleCache.set(identifier, module);
245
+ return module;
212
246
  }
213
247
  getCjsSyntheticModule(path, identifier) {
214
248
  if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
215
- const exports = this.require(path), { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports), module = new SyntheticModule([...keys, "default"], function() {
249
+ const exports = this.require(path);
250
+ // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
251
+ const { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports);
252
+ const module = new SyntheticModule([...keys, "default"], function() {
216
253
  for (const key of keys) this.setExport(key, moduleExports[key]);
217
254
  this.setExport("default", defaultExport);
218
255
  }, {
219
256
  context: this.context,
220
257
  identifier
221
258
  });
222
- return this.moduleCache.set(identifier, module), module;
259
+ this.moduleCache.set(identifier, module);
260
+ return module;
223
261
  }
224
262
  // TODO: use this in strict mode, when available in #2854
225
263
  // private _getNamedCjsExports(path: string): Set<string> {
@@ -268,10 +306,13 @@ class CommonjsExecutor {
268
306
  const moduleExports = _require(identifier);
269
307
  if (identifier === "node:module" || identifier === "module") {
270
308
  const module = new this.Module("/module.js");
271
- return module.exports = this.Module, this.builtinCache[normalized] = module, module.exports;
309
+ module.exports = this.Module;
310
+ this.builtinCache[normalized] = module;
311
+ return module.exports;
272
312
  }
313
+ this.builtinCache[normalized] = _require.cache[normalized];
273
314
  // TODO: should we wrap module to rethrow context errors?
274
- return this.builtinCache[normalized] = _require.cache[normalized], moduleExports;
315
+ return moduleExports;
275
316
  }
276
317
  }
277
318
 
@@ -282,18 +323,21 @@ class EsmExecutor {
282
323
  context;
283
324
  #httpIp = IPnumber("127.0.0.0");
284
325
  constructor(executor, options) {
285
- this.executor = executor, this.context = options.context;
326
+ this.executor = executor;
327
+ this.context = options.context;
286
328
  }
287
329
  async evaluateModule(m) {
288
330
  if (m.status === "unlinked") this.esmLinkMap.set(m, m.link((identifier, referencer) => this.executor.resolveModule(identifier, referencer.identifier)));
289
- if (await this.esmLinkMap.get(m), m.status === "linked") await m.evaluate();
331
+ await this.esmLinkMap.get(m);
332
+ if (m.status === "linked") await m.evaluate();
290
333
  return m;
291
334
  }
292
335
  async createEsModule(fileURL, getCode) {
293
336
  const cached = this.moduleCache.get(fileURL);
294
337
  if (cached) return cached;
295
338
  const promise = this.loadEsModule(fileURL, getCode);
296
- return this.moduleCache.set(fileURL, promise), promise;
339
+ this.moduleCache.set(fileURL, promise);
340
+ return promise;
297
341
  }
298
342
  async loadEsModule(fileURL, getCode) {
299
343
  const code = await getCode();
@@ -303,29 +347,34 @@ class EsmExecutor {
303
347
  const result = JSON.parse(code);
304
348
  this.setExport("default", result);
305
349
  });
306
- return this.moduleCache.set(fileURL, m), m;
350
+ this.moduleCache.set(fileURL, m);
351
+ return m;
307
352
  }
308
353
  const m = new SourceTextModule(code, {
309
354
  identifier: fileURL,
310
355
  context: this.context,
311
356
  importModuleDynamically: this.executor.importModuleDynamically,
312
357
  initializeImportMeta: (meta, mod) => {
313
- if (meta.url = mod.identifier, mod.identifier.startsWith("file:")) {
358
+ meta.url = mod.identifier;
359
+ if (mod.identifier.startsWith("file:")) {
314
360
  const filename = fileURLToPath(mod.identifier);
315
- meta.filename = filename, meta.dirname = dirname$1(filename);
361
+ meta.filename = filename;
362
+ meta.dirname = dirname$1(filename);
316
363
  }
317
364
  meta.resolve = (specifier, importer) => {
318
365
  return this.executor.resolve(specifier, importer != null ? importer.toString() : mod.identifier);
319
366
  };
320
367
  }
321
368
  });
322
- return this.moduleCache.set(fileURL, m), m;
369
+ this.moduleCache.set(fileURL, m);
370
+ return m;
323
371
  }
324
372
  async createWebAssemblyModule(fileUrl, getCode) {
325
373
  const cached = this.moduleCache.get(fileUrl);
326
374
  if (cached) return cached;
327
375
  const m = this.loadWebAssemblyModule(getCode(), fileUrl);
328
- return this.moduleCache.set(fileUrl, m), m;
376
+ this.moduleCache.set(fileUrl, m);
377
+ return m;
329
378
  }
330
379
  async createNetworkModule(fileUrl) {
331
380
  // https://nodejs.org/api/esm.html#https-and-http-imports
@@ -341,14 +390,18 @@ class EsmExecutor {
341
390
  async loadWebAssemblyModule(source, identifier) {
342
391
  const cached = this.moduleCache.get(identifier);
343
392
  if (cached) return cached;
344
- const wasmModule = await WebAssembly.compile(source), exports = WebAssembly.Module.exports(wasmModule), imports = WebAssembly.Module.imports(wasmModule), moduleLookup = {};
393
+ const wasmModule = await WebAssembly.compile(source);
394
+ const exports = WebAssembly.Module.exports(wasmModule);
395
+ const imports = WebAssembly.Module.imports(wasmModule);
396
+ const moduleLookup = {};
345
397
  for (const { module } of imports) if (moduleLookup[module] === void 0) moduleLookup[module] = await this.executor.resolveModule(module, identifier);
346
398
  const evaluateModule = (module) => this.evaluateModule(module);
347
399
  return new SyntheticModule(exports.map(({ name }) => name), async function() {
348
400
  const importsObject = {};
349
401
  for (const { module, name } of imports) {
350
402
  if (!importsObject[module]) importsObject[module] = {};
351
- await evaluateModule(moduleLookup[module]), importsObject[module][name] = moduleLookup[module].namespace[name];
403
+ await evaluateModule(moduleLookup[module]);
404
+ importsObject[module][name] = moduleLookup[module].namespace[name];
352
405
  }
353
406
  const wasmInstance = new WebAssembly.Instance(wasmModule, importsObject);
354
407
  for (const { name } of exports) this.setExport(name, wasmInstance.exports[name]);
@@ -368,12 +421,14 @@ class EsmExecutor {
368
421
  if (cached) return cached;
369
422
  const match = identifier.match(dataURIRegex);
370
423
  if (!match || !match.groups) throw new Error("Invalid data URI");
371
- const mime = match.groups.mime, encoding = match.groups.encoding;
424
+ const mime = match.groups.mime;
425
+ const encoding = match.groups.encoding;
372
426
  if (mime === "application/wasm") {
373
427
  if (!encoding) throw new Error("Missing data URI encoding");
374
428
  if (encoding !== "base64") throw new Error(`Invalid data URI encoding: ${encoding}`);
375
429
  const module = this.loadWebAssemblyModule(Buffer.from(match.groups.code, "base64"), identifier);
376
- return this.moduleCache.set(identifier, module), module;
430
+ this.moduleCache.set(identifier, module);
431
+ return module;
377
432
  }
378
433
  let code = match.groups.code;
379
434
  if (!encoding || encoding === "charset=utf-8") code = decodeURIComponent(code);
@@ -387,7 +442,8 @@ class EsmExecutor {
387
442
  context: this.context,
388
443
  identifier
389
444
  });
390
- return this.moduleCache.set(identifier, module), module;
445
+ this.moduleCache.set(identifier, module);
446
+ return module;
391
447
  }
392
448
  return this.createEsModule(identifier, () => code);
393
449
  }
@@ -401,11 +457,13 @@ function IPmask(maskSize) {
401
457
  return -1 << 32 - maskSize;
402
458
  }
403
459
 
404
- const CLIENT_ID = "/@vite/client", CLIENT_FILE = pathToFileURL(CLIENT_ID).href;
460
+ const CLIENT_ID = "/@vite/client";
461
+ const CLIENT_FILE = pathToFileURL(CLIENT_ID).href;
405
462
  class ViteExecutor {
406
463
  esm;
407
464
  constructor(options) {
408
- this.options = options, this.esm = options.esmExecutor;
465
+ this.options = options;
466
+ this.esm = options.esmExecutor;
409
467
  }
410
468
  resolve = (identifier) => {
411
469
  if (identifier === CLIENT_ID) return identifier;
@@ -414,7 +472,10 @@ class ViteExecutor {
414
472
  return this.options.context.__vitest_worker__;
415
473
  }
416
474
  async createViteModule(fileUrl) {
417
- return fileUrl === CLIENT_FILE || fileUrl === CLIENT_ID ? this.createViteClientModule() : this.esm.resolveCachedModule(fileUrl) || this.esm.createEsModule(fileUrl, async () => {
475
+ if (fileUrl === CLIENT_FILE || fileUrl === CLIENT_ID) return this.createViteClientModule();
476
+ const cached = this.esm.resolveCachedModule(fileUrl);
477
+ if (cached) return cached;
478
+ return this.esm.createEsModule(fileUrl, async () => {
418
479
  try {
419
480
  const result = await this.options.transform(fileUrl);
420
481
  if (result.code) return result.code;
@@ -422,16 +483,20 @@ class ViteExecutor {
422
483
  // rethrow vite error if it cannot load the module because it's not resolved
423
484
  if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url")) {
424
485
  const error = new Error(`Cannot find module '${fileUrl}'`, { cause });
425
- throw error.code = "ERR_MODULE_NOT_FOUND", error;
486
+ error.code = "ERR_MODULE_NOT_FOUND";
487
+ throw error;
426
488
  }
427
489
  }
428
490
  throw new Error(`[vitest] Failed to transform ${fileUrl}. Does the file exist?`);
429
491
  });
430
492
  }
431
493
  createViteClientModule() {
432
- const identifier = CLIENT_ID, cached = this.esm.resolveCachedModule(identifier);
494
+ const identifier = CLIENT_ID;
495
+ const cached = this.esm.resolveCachedModule(identifier);
433
496
  if (cached) return cached;
434
- const stub = this.options.viteClientModule, moduleKeys = Object.keys(stub), module = new SyntheticModule(moduleKeys, function() {
497
+ const stub = this.options.viteClientModule;
498
+ const moduleKeys = Object.keys(stub);
499
+ const module = new SyntheticModule(moduleKeys, function() {
435
500
  moduleKeys.forEach((key) => {
436
501
  this.setExport(key, stub[key]);
437
502
  });
@@ -439,16 +504,23 @@ class ViteExecutor {
439
504
  context: this.options.context,
440
505
  identifier
441
506
  });
442
- return this.esm.cacheModule(identifier, module), module;
507
+ this.esm.cacheModule(identifier, module);
508
+ return module;
443
509
  }
444
510
  canResolve = (fileUrl) => {
445
511
  if (fileUrl === CLIENT_FILE) return true;
446
- const config = this.workerState.config.deps?.web || {}, [modulePath] = fileUrl.split("?");
447
- return !!(config.transformCss && CSS_LANGS_RE.test(modulePath) || config.transformAssets && KNOWN_ASSET_RE.test(modulePath) || toArray(config.transformGlobPattern).some((pattern) => pattern.test(modulePath)));
512
+ const config = this.workerState.config.deps?.web || {};
513
+ const [modulePath] = fileUrl.split("?");
514
+ if (config.transformCss && CSS_LANGS_RE.test(modulePath)) return true;
515
+ if (config.transformAssets && KNOWN_ASSET_RE.test(modulePath)) return true;
516
+ if (toArray(config.transformGlobPattern).some((pattern) => pattern.test(modulePath))) return true;
517
+ return false;
448
518
  };
449
519
  }
450
520
 
451
- const { existsSync } = fs, nativeResolve = import.meta.resolve;
521
+ const { existsSync } = fs;
522
+ // always defined when we use vm pool
523
+ const nativeResolve = import.meta.resolve;
452
524
  // TODO: improve Node.js strict mode support in #2854
453
525
  class ExternalModulesExecutor {
454
526
  cjs;
@@ -459,21 +531,28 @@ class ExternalModulesExecutor {
459
531
  resolvers = [];
460
532
  #networkSupported = null;
461
533
  constructor(options) {
462
- this.options = options, this.context = options.context, this.fs = options.fileMap, this.esm = new EsmExecutor(this, { context: this.context }), this.cjs = new CommonjsExecutor({
534
+ this.options = options;
535
+ this.context = options.context;
536
+ this.fs = options.fileMap;
537
+ this.esm = new EsmExecutor(this, { context: this.context });
538
+ this.cjs = new CommonjsExecutor({
463
539
  context: this.context,
464
540
  importModuleDynamically: this.importModuleDynamically,
465
541
  fileMap: options.fileMap,
466
542
  interopDefault: options.interopDefault
467
- }), this.vite = new ViteExecutor({
543
+ });
544
+ this.vite = new ViteExecutor({
468
545
  esmExecutor: this.esm,
469
546
  context: this.context,
470
547
  transform: options.transform,
471
548
  viteClientModule: options.viteClientModule
472
- }), this.resolvers = [this.vite.resolve];
549
+ });
550
+ this.resolvers = [this.vite.resolve];
473
551
  }
474
552
  async import(identifier) {
475
553
  const module = await this.createModule(identifier);
476
- return await this.esm.evaluateModule(module), module.namespace;
554
+ await this.esm.evaluateModule(module);
555
+ return module.namespace;
477
556
  }
478
557
  require(identifier) {
479
558
  return this.cjs.require(identifier);
@@ -516,7 +595,9 @@ class ExternalModulesExecutor {
516
595
  url: identifier,
517
596
  path: identifier
518
597
  };
519
- const isFileUrl = identifier.startsWith("file://"), pathUrl = isFileUrl ? fileURLToPath(identifier.split("?")[0]) : identifier, fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString();
598
+ const isFileUrl = identifier.startsWith("file://");
599
+ const pathUrl = isFileUrl ? fileURLToPath(identifier.split("?")[0]) : identifier;
600
+ const fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString();
520
601
  let type;
521
602
  if (this.vite.canResolve(fileUrl)) type = "vite";
522
603
  else if (extension === ".mjs") type = "module";
@@ -538,7 +619,8 @@ class ExternalModulesExecutor {
538
619
  // https://github.com/nodejs/node/pull/49038
539
620
  if ((type === "module" || type === "commonjs" || type === "wasm") && !existsSync(path)) {
540
621
  const error = /* @__PURE__ */ new Error(`Cannot find ${isBareImport(path) ? "package" : "module"} '${path}'`);
541
- throw error.code = "ERR_MODULE_NOT_FOUND", error;
622
+ error.code = "ERR_MODULE_NOT_FOUND";
623
+ throw error;
542
624
  }
543
625
  switch (type) {
544
626
  case "data": return this.esm.createDataModule(identifier);
@@ -567,48 +649,70 @@ class FileMap {
567
649
  const cached = this.fsCache.get(path);
568
650
  if (cached != null) return cached;
569
651
  const source = await promises.readFile(path, "utf-8");
570
- return this.fsCache.set(path, source), source;
652
+ this.fsCache.set(path, source);
653
+ return source;
571
654
  }
572
655
  readFile(path) {
573
656
  const cached = this.fsCache.get(path);
574
657
  if (cached != null) return cached;
575
658
  const source = readFileSync(path, "utf-8");
576
- return this.fsCache.set(path, source), source;
659
+ this.fsCache.set(path, source);
660
+ return source;
577
661
  }
578
662
  readBuffer(path) {
579
663
  const cached = this.fsBufferCache.get(path);
580
664
  if (cached != null) return cached;
581
665
  const buffer = readFileSync(path);
582
- return this.fsBufferCache.set(path, buffer), buffer;
666
+ this.fsBufferCache.set(path, buffer);
667
+ return buffer;
583
668
  }
584
669
  }
585
670
 
586
- const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href, fileMap = new FileMap(), packageCache = /* @__PURE__ */ new Map();
671
+ const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href;
672
+ const fileMap = new FileMap();
673
+ const packageCache = /* @__PURE__ */ new Map();
587
674
  async function runVmTests(method, state) {
588
- const { environment, ctx, rpc } = state;
675
+ const { ctx, rpc } = state;
676
+ const beforeEnvironmentTime = performance.now();
677
+ const { environment } = await loadEnvironment(ctx.environment.name, ctx.config.root, rpc);
678
+ state.environment = environment;
589
679
  if (!environment.setupVM) {
590
- const envName = ctx.environment.name, packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
680
+ const envName = ctx.environment.name;
681
+ const packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
591
682
  throw new TypeError(`Environment "${ctx.environment.name}" is not a valid environment. Path "${packageId}" doesn't support vm environment because it doesn't provide "setupVM" method.`);
592
683
  }
593
684
  const vm = await environment.setupVM(ctx.environment.options || ctx.config.environmentOptions || {});
594
- if (state.durations.environment = performance.now() - state.durations.environment, process.env.VITEST_VM_POOL = "1", !vm.getVmContext) throw new TypeError(`Environment ${environment.name} doesn't provide "getVmContext" method. It should return a context created by "vm.createContext" method.`);
685
+ state.durations.environment = performance.now() - beforeEnvironmentTime;
686
+ process.env.VITEST_VM_POOL = "1";
687
+ if (!vm.getVmContext) throw new TypeError(`Environment ${environment.name} doesn't provide "getVmContext" method. It should return a context created by "vm.createContext" method.`);
595
688
  const context = vm.getVmContext();
596
689
  if (!isContext(context)) throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
597
- provideWorkerState(context, state), context.process = process, context.global = context, context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state), context.setImmediate = setImmediate, context.clearImmediate = clearImmediate;
598
- const stubs = getDefaultRequestStubs(context), externalModulesExecutor = new ExternalModulesExecutor({
690
+ provideWorkerState(context, state);
691
+ // this is unfortunately needed for our own dependencies
692
+ // we need to find a way to not rely on this by default
693
+ // because browser doesn't provide these globals
694
+ context.process = process;
695
+ context.global = context;
696
+ context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state);
697
+ // TODO: don't hardcode setImmediate in fake timers defaults
698
+ context.setImmediate = setImmediate;
699
+ context.clearImmediate = clearImmediate;
700
+ const stubs = getDefaultRequestStubs(context);
701
+ const externalModulesExecutor = new ExternalModulesExecutor({
599
702
  context,
600
703
  fileMap,
601
704
  packageCache,
602
705
  transform: rpc.transform,
603
706
  viteClientModule: stubs["/@vite/client"]
604
- }), moduleRunner = startVitestModuleRunner({
707
+ });
708
+ const moduleRunner = startVitestModuleRunner({
605
709
  context,
606
710
  evaluatedModules: state.evaluatedModules,
607
711
  state,
608
712
  externalModulesExecutor,
609
713
  createImportMeta: createNodeImportMeta
610
714
  });
611
- if (Object.defineProperty(context, VITEST_VM_CONTEXT_SYMBOL, {
715
+ Object.defineProperty(context, VITEST_VM_CONTEXT_SYMBOL, {
612
716
  value: {
613
717
  context,
614
718
  externalModulesExecutor
@@ -616,20 +720,23 @@ async function runVmTests(method, state) {
616
720
  configurable: true,
617
721
  enumerable: false,
618
722
  writable: false
619
- }), context.__vitest_mocker__ = moduleRunner.mocker, ctx.config.serializedDefines) try {
723
+ });
724
+ context.__vitest_mocker__ = moduleRunner.mocker;
725
+ if (ctx.config.serializedDefines) try {
620
726
  runInContext(ctx.config.serializedDefines, context, { filename: "virtual:load-defines.js" });
621
727
  } catch (error) {
622
728
  throw new Error(`Failed to load custom "defines": ${error.message}`);
623
729
  }
624
730
  await moduleRunner.mocker.initializeSpyModule();
625
- const { run } = await moduleRunner.import(entryFile), fileSpecs = ctx.files.map((f) => typeof f === "string" ? {
731
+ const { run } = await moduleRunner.import(entryFile);
732
+ const fileSpecs = ctx.files.map((f) => typeof f === "string" ? {
626
733
  filepath: f,
627
734
  testLocations: void 0
628
735
  } : f);
629
736
  try {
630
737
  await run(method, fileSpecs, ctx.config, moduleRunner);
631
738
  } finally {
632
- await vm.teardown?.(), state.environmentTeardownRun = true;
739
+ await vm.teardown?.();
633
740
  }
634
741
  }
635
742