vitest 4.0.6 → 4.0.7

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 (43) hide show
  1. package/dist/browser.d.ts +2 -2
  2. package/dist/chunks/{base.BAf_bYeI.js → base.D3GxgUMI.js} +43 -50
  3. package/dist/chunks/{browser.d.ScGeWTou.d.ts → browser.d.-LKfRopd.d.ts} +1 -1
  4. package/dist/chunks/{cac.BBqWH4nd.js → cac.G9DAn-c7.js} +8 -7
  5. package/dist/chunks/{cli-api.UL3SwFUb.js → cli-api.Csks4as1.js} +29 -24
  6. package/dist/chunks/{coverage.DuCn_Tmx.js → coverage.C2LA1DSL.js} +9 -1
  7. package/dist/chunks/{global.d.DdOkMiVb.d.ts → global.d.DxtanrNO.d.ts} +1 -1
  8. package/dist/chunks/{index.BL8Hg4Uk.js → index.CVpyv-Zg.js} +7 -9
  9. package/dist/chunks/{index.DV0mQLEO.js → index.CWIFvlX5.js} +50 -24
  10. package/dist/chunks/{resolveSnapshotEnvironment.BZzLjzkh.js → index.DEPqWSIZ.js} +12 -12
  11. package/dist/chunks/{index.CpdwpN7L.js → index.jMQYiEWE.js} +1 -1
  12. package/dist/chunks/{init-forks.CSGFj9zN.js → init-forks.IU-xQ2_X.js} +3 -2
  13. package/dist/chunks/{init-threads.CIJLeFO8.js → init-threads.C_NWvZkU.js} +3 -2
  14. package/dist/chunks/{init.DUeOfNO9.js → init.fmH9J833.js} +85 -38
  15. package/dist/chunks/{moduleRunner.d.TP-w6tIQ.d.ts → moduleRunner.d.DEkTotCv.d.ts} +1 -1
  16. package/dist/chunks/{plugin.d.lctzD3Wk.d.ts → plugin.d.Cpes8Bt6.d.ts} +1 -1
  17. package/dist/chunks/{reporters.d.PEs0tXod.d.ts → reporters.d.CSNcMDxF.d.ts} +15 -6
  18. package/dist/chunks/{rpc.Dv1Jt3i2.js → rpc.D38ahn14.js} +8 -11
  19. package/dist/chunks/{startModuleRunner.Di-EZqh0.js → startModuleRunner.Cn7hCL7D.js} +26 -26
  20. package/dist/chunks/{test.CnspO-X4.js → test.B6aJd6T3.js} +1 -1
  21. package/dist/chunks/{vm.Co_lR2NL.js → vm.BL7_zzOr.js} +6 -5
  22. package/dist/chunks/{worker.d.B4Hthdvt.d.ts → worker.d.D25zYZ7N.d.ts} +22 -4
  23. package/dist/cli.js +2 -2
  24. package/dist/config.d.ts +5 -5
  25. package/dist/coverage.d.ts +3 -3
  26. package/dist/coverage.js +1 -1
  27. package/dist/environments.js +2 -1
  28. package/dist/index.d.ts +5 -5
  29. package/dist/module-evaluator.d.ts +2 -2
  30. package/dist/module-runner.js +1 -1
  31. package/dist/node.d.ts +7 -7
  32. package/dist/node.js +7 -7
  33. package/dist/reporters.d.ts +3 -3
  34. package/dist/reporters.js +2 -2
  35. package/dist/runners.js +2 -2
  36. package/dist/worker.d.ts +2 -1
  37. package/dist/worker.js +21 -21
  38. package/dist/workers/forks.js +27 -24
  39. package/dist/workers/runVmTests.js +4 -4
  40. package/dist/workers/threads.js +27 -24
  41. package/dist/workers/vmForks.js +10 -10
  42. package/dist/workers/vmThreads.js +10 -10
  43. package/package.json +12 -12
@@ -1,13 +1,23 @@
1
1
  import { chai } from '@vitest/expect';
2
2
  import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.DR1sucx6.js';
3
- import { r as rpc } from './rpc.Dv1Jt3i2.js';
3
+ import { r as rpc } from './rpc.D38ahn14.js';
4
4
  import { g as getWorkerState } from './utils.CG9h5ccR.js';
5
- import { V as VitestTestRunner, N as NodeBenchmarkRunner } from './test.CnspO-X4.js';
5
+ import { V as VitestTestRunner, N as NodeBenchmarkRunner } from './test.B6aJd6T3.js';
6
6
 
7
7
  function setupChaiConfig(config) {
8
8
  Object.assign(chai.config, config);
9
9
  }
10
10
 
11
+ async function resolveSnapshotEnvironment(config, executor) {
12
+ if (!config.snapshotEnvironment) {
13
+ const { VitestNodeSnapshotEnvironment } = await import('./node.BwAWWjHZ.js');
14
+ return new VitestNodeSnapshotEnvironment();
15
+ }
16
+ const mod = await executor.import(config.snapshotEnvironment);
17
+ if (typeof mod.default !== "object" || !mod.default) throw new Error("Snapshot environment module must have a default export object with a shape of `SnapshotEnvironment`");
18
+ return mod.default;
19
+ }
20
+
11
21
  async function getTestRunnerConstructor(config, moduleRunner) {
12
22
  if (!config.runner) return config.mode === "test" ? VitestTestRunner : NodeBenchmarkRunner;
13
23
  const mod = await moduleRunner.import(config.runner);
@@ -67,14 +77,4 @@ async function resolveTestRunner(config, moduleRunner) {
67
77
  }, testRunner;
68
78
  }
69
79
 
70
- async function resolveSnapshotEnvironment(config, executor) {
71
- if (!config.snapshotEnvironment) {
72
- const { VitestNodeSnapshotEnvironment } = await import('./node.BwAWWjHZ.js');
73
- return new VitestNodeSnapshotEnvironment();
74
- }
75
- const mod = await executor.import(config.snapshotEnvironment);
76
- if (typeof mod.default !== "object" || !mod.default) throw new Error("Snapshot environment module must have a default export object with a shape of `SnapshotEnvironment`");
77
- return mod.default;
78
- }
79
-
80
80
  export { resolveSnapshotEnvironment as a, resolveTestRunner as r, setupChaiConfig as s };
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import { getTasks, getFullName, getTests } from '@vitest/runner/utils';
3
3
  import * as pathe from 'pathe';
4
4
  import c from 'tinyrainbow';
5
- import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName, s as separator } from './index.BL8Hg4Uk.js';
5
+ import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName, s as separator } from './index.CVpyv-Zg.js';
6
6
  import { stripVTControlCharacters } from 'node:util';
7
7
  import { notNullish } from '@vitest/utils/helpers';
8
8
 
@@ -1,5 +1,5 @@
1
1
  import v8 from 'node:v8';
2
- import { i as init } from './init.DUeOfNO9.js';
2
+ import { i as init } from './init.fmH9J833.js';
3
3
 
4
4
  if (!process.send) throw new Error("Expected worker to be run in node:child_process");
5
5
  // Store globals in case tests overwrite them
@@ -16,7 +16,8 @@ function workerInit(options) {
16
16
  serialize: v8.serialize,
17
17
  deserialize: (v) => v8.deserialize(Buffer.from(v)),
18
18
  runTests: (state) => executeTests("run", state),
19
- collectTests: (state) => executeTests("collect", state)
19
+ collectTests: (state) => executeTests("collect", state),
20
+ setup: options.setup
20
21
  });
21
22
  async function executeTests(method, state) {
22
23
  state.ctx.config = unwrapSerializableConfig(state.ctx.config);
@@ -1,5 +1,5 @@
1
1
  import { isMainThread, parentPort } from 'node:worker_threads';
2
- import { i as init } from './init.DUeOfNO9.js';
2
+ import { i as init } from './init.fmH9J833.js';
3
3
 
4
4
  if (isMainThread || !parentPort) throw new Error("Expected worker to be run in node:worker_threads");
5
5
  function workerInit(options) {
@@ -10,7 +10,8 @@ function workerInit(options) {
10
10
  off: (callback) => parentPort.off("message", callback),
11
11
  teardown: () => parentPort.removeAllListeners("message"),
12
12
  runTests: async (state) => runTests("run", state),
13
- collectTests: async (state) => runTests("collect", state)
13
+ collectTests: async (state) => runTests("collect", state),
14
+ setup: options.setup
14
15
  });
15
16
  }
16
17
 
@@ -1,15 +1,15 @@
1
- import { serializeError } from '@vitest/utils/error';
2
- import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
3
1
  import { readFileSync } from 'node:fs';
4
2
  import { isBuiltin } from 'node:module';
5
3
  import { pathToFileURL } from 'node:url';
6
4
  import { resolve } from 'pathe';
7
5
  import { ModuleRunner } from 'vite/module-runner';
8
- import { b as VitestTransport } from './startModuleRunner.Di-EZqh0.js';
9
- import { e as environments } from './index.DV0mQLEO.js';
6
+ import { b as VitestTransport } from './startModuleRunner.Cn7hCL7D.js';
7
+ import { e as environments } from './index.CWIFvlX5.js';
8
+ import { serializeError } from '@vitest/utils/error';
9
+ import { o as onCancel, a as rpcDone, c as createRuntimeRpc } from './rpc.D38ahn14.js';
10
+ import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
10
11
  import { s as setupInspect } from './inspector.DLZxSeU3.js';
11
12
  import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
12
- import { c as createRuntimeRpc, a as rpcDone } from './rpc.Dv1Jt3i2.js';
13
13
 
14
14
  function isBuiltinEnvironment(env) {
15
15
  return env in environments;
@@ -44,10 +44,9 @@ async function createEnvironmentLoader(root, rpc) {
44
44
  }
45
45
  return _loaders.get(root);
46
46
  }
47
- async function loadEnvironment(ctx, rpc) {
48
- const name = ctx.environment.name;
47
+ async function loadEnvironment(name, root, rpc) {
49
48
  if (isBuiltinEnvironment(name)) return { environment: environments[name] };
50
- const root = ctx.config.root, loader = await createEnvironmentLoader(root, rpc), packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__"))?.id ?? resolve(root, name), pkg = await loader.import(packageId);
49
+ const loader = await createEnvironmentLoader(root, rpc), packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__"))?.id ?? resolve(root, name), pkg = await loader.import(packageId);
51
50
  if (!pkg || !pkg.default || typeof pkg.default !== "object") throw new TypeError(`Environment "${name}" is not a valid environment. Path "${packageId}" should export default object with a "setup" or/and "setupVM" method.`);
52
51
  const environment = pkg.default;
53
52
  if (environment.transformMode != null && environment.transformMode !== "web" && environment.transformMode !== "ssr") throw new TypeError(`Environment "${name}" is not a valid environment. Path "${packageId}" should export default object with a "transformMode" method equal to "ssr" or "web", received "${environment.transformMode}".`);
@@ -62,10 +61,7 @@ async function loadEnvironment(ctx, rpc) {
62
61
 
63
62
  const resolvingModules = /* @__PURE__ */ new Set(), globalListeners = /* @__PURE__ */ new Set();
64
63
  async function execute(method, ctx, worker) {
65
- const prepareStart = performance.now(), cleanups = [setupInspect(ctx)];
66
- let environmentLoader;
67
- // RPC is used to communicate between worker (be it a thread worker or child process or a custom implementation) and the main thread
68
- const { rpc, onCancel } = createRuntimeRpc(worker);
64
+ const prepareStart = performance.now(), cleanups = [setupInspect(ctx)], rpc = ctx.rpc;
69
65
  try {
70
66
  // do not close the RPC channel so that we can get the error messages sent to the main thread
71
67
  cleanups.push(async () => {
@@ -73,21 +69,19 @@ async function execute(method, ctx, worker) {
73
69
  reject(/* @__PURE__ */ new Error(`[vitest-worker]: Closing rpc while "${method}" was pending`));
74
70
  }));
75
71
  });
76
- const beforeEnvironmentTime = performance.now(), { environment, loader } = await loadEnvironment(ctx, rpc);
77
- environmentLoader = loader;
78
72
  const state = {
79
73
  ctx,
80
74
  evaluatedModules: new VitestEvaluatedModules(),
81
75
  resolvingModules,
82
76
  moduleExecutionInfo: /* @__PURE__ */ new Map(),
83
77
  config: ctx.config,
84
- onCancel,
85
- environment,
78
+ environment: null,
86
79
  durations: {
87
- environment: beforeEnvironmentTime,
80
+ environment: 0,
88
81
  prepare: prepareStart
89
82
  },
90
83
  rpc,
84
+ onCancel,
91
85
  onCleanup: (listener) => globalListeners.add(listener),
92
86
  providedContext: ctx.providedContext,
93
87
  onFilterStackTrace(stack) {
@@ -98,7 +92,7 @@ async function execute(method, ctx, worker) {
98
92
  if (!worker[methodName] || typeof worker[methodName] !== "function") throw new TypeError(`Test worker should expose "runTests" method. Received "${typeof worker.runTests}".`);
99
93
  await worker[methodName](state);
100
94
  } finally {
101
- await rpcDone().catch(() => {}), await Promise.all(cleanups.map((fn) => fn())).catch(() => {}), await environmentLoader?.close();
95
+ await rpcDone().catch(() => {}), await Promise.all(cleanups.map((fn) => fn())).catch(() => {});
102
96
  }
103
97
  }
104
98
  function run(ctx, worker) {
@@ -110,6 +104,7 @@ function collect(ctx, worker) {
110
104
  async function teardown() {
111
105
  await Promise.all([...globalListeners].map((l) => l()));
112
106
  }
107
+ const env = process.env;
113
108
  function createImportMetaEnvProxy() {
114
109
  // packages/vitest/src/node/plugins/index.ts:146
115
110
  const booleanKeys = [
@@ -117,7 +112,7 @@ function createImportMetaEnvProxy() {
117
112
  "PROD",
118
113
  "SSR"
119
114
  ];
120
- return new Proxy(process.env, {
115
+ return new Proxy(env, {
121
116
  get(_, key) {
122
117
  if (typeof key === "string") return booleanKeys.includes(key) ? !!process.env[key] : process.env[key];
123
118
  },
@@ -135,19 +130,37 @@ let reportMemory = false;
135
130
  /** @experimental */
136
131
  function init(worker) {
137
132
  worker.on(onMessage);
138
- let runPromise, isRunning = false;
133
+ let runPromise, isRunning = false, workerTeardown, setupContext;
139
134
  function send(response) {
140
135
  worker.post(worker.serialize ? worker.serialize(response) : response);
141
136
  }
142
137
  async function onMessage(rawMessage) {
143
138
  const message = worker.deserialize ? worker.deserialize(rawMessage) : rawMessage;
144
139
  if (message?.__vitest_worker_request__ === true) switch (message.type) {
145
- case "start":
146
- reportMemory = message.options.reportMemory, send({
147
- type: "started",
148
- __vitest_worker_response__
149
- });
140
+ case "start": {
141
+ reportMemory = message.options.reportMemory;
142
+ const { environment, config, pool } = message.context;
143
+ try {
144
+ const rpc = createRuntimeRpc(worker);
145
+ setupContext = {
146
+ environment,
147
+ config,
148
+ pool,
149
+ rpc,
150
+ projectName: config.name || ""
151
+ }, workerTeardown = await worker.setup?.(setupContext), send({
152
+ type: "started",
153
+ __vitest_worker_response__
154
+ });
155
+ } catch (error) {
156
+ send({
157
+ type: "started",
158
+ __vitest_worker_response__,
159
+ error: serializeError(error)
160
+ });
161
+ }
150
162
  break;
163
+ }
151
164
  case "run":
152
165
  // Prevent concurrent execution if worker is already running
153
166
  if (isRunning) {
@@ -158,9 +171,22 @@ function init(worker) {
158
171
  });
159
172
  return;
160
173
  }
161
- isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
162
174
  try {
163
- runPromise = run(message.context, worker).catch((error) => serializeError(error));
175
+ process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
176
+ } catch (error) {
177
+ return send({
178
+ type: "testfileFinished",
179
+ __vitest_worker_response__,
180
+ error: serializeError(error),
181
+ usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
182
+ });
183
+ }
184
+ isRunning = true;
185
+ try {
186
+ runPromise = run({
187
+ ...setupContext,
188
+ ...message.context
189
+ }, worker).catch((error) => serializeError(error));
164
190
  const error = await runPromise;
165
191
  send({
166
192
  type: "testfileFinished",
@@ -182,9 +208,22 @@ function init(worker) {
182
208
  });
183
209
  return;
184
210
  }
185
- isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
186
211
  try {
187
- runPromise = collect(message.context, worker).catch((error) => serializeError(error));
212
+ process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
213
+ } catch (error) {
214
+ return send({
215
+ type: "testfileFinished",
216
+ __vitest_worker_response__,
217
+ error: serializeError(error),
218
+ usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
219
+ });
220
+ }
221
+ isRunning = true;
222
+ try {
223
+ runPromise = collect({
224
+ ...setupContext,
225
+ ...message.context
226
+ }, worker).catch((error) => serializeError(error));
188
227
  const error = await runPromise;
189
228
  send({
190
229
  type: "testfileFinished",
@@ -196,18 +235,26 @@ function init(worker) {
196
235
  runPromise = void 0, isRunning = false;
197
236
  }
198
237
  break;
199
- case "stop": {
238
+ case "stop":
200
239
  await runPromise;
201
- const error = await teardown().catch((error) => serializeError(error));
202
- send({
203
- type: "stopped",
204
- error,
205
- __vitest_worker_response__
206
- }), worker.teardown?.();
240
+ try {
241
+ const error = await teardown().catch((error) => serializeError(error));
242
+ await workerTeardown?.(), send({
243
+ type: "stopped",
244
+ error,
245
+ __vitest_worker_response__
246
+ });
247
+ } catch (error) {
248
+ send({
249
+ type: "stopped",
250
+ error: serializeError(error),
251
+ __vitest_worker_response__
252
+ });
253
+ }
254
+ worker.teardown?.();
207
255
  break;
208
- }
209
256
  }
210
257
  }
211
258
  }
212
259
 
213
- export { init as i };
260
+ export { init as i, loadEnvironment as l };
@@ -2,7 +2,7 @@ import * as _vitest_spy from '@vitest/spy';
2
2
  import vm from 'node:vm';
3
3
  import * as viteModuleRunner from 'vite/module-runner';
4
4
  import { ModuleEvaluator, ModuleRunnerImportMeta, ModuleRunnerContext, EvaluatedModuleNode, FetchFunction, EvaluatedModules } from 'vite/module-runner';
5
- import { R as RuntimeRPC, d as ResolveFunctionResult, W as WorkerGlobalState } from './worker.d.B4Hthdvt.js';
5
+ import { R as RuntimeRPC, e as ResolveFunctionResult, W as WorkerGlobalState } from './worker.d.D25zYZ7N.js';
6
6
  import { MockedModule, MockedModuleType } from '@vitest/mocker';
7
7
  import { P as PendingSuiteMock, b as MockFactory, a as MockOptions } from './mocker.d.BE_2ls6u.js';
8
8
 
@@ -1,4 +1,4 @@
1
- import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.PEs0tXod.js';
1
+ import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.CSNcMDxF.js';
2
2
 
3
3
  interface VitestPluginContext {
4
4
  vitest: Vitest;
@@ -1,13 +1,13 @@
1
1
  import { TaskMeta, Suite, File, TestAnnotation, ImportDuration, Test, Task, TaskResultPack, FileSpecification, CancelReason, SequenceSetupFiles, SequenceHooks } from '@vitest/runner';
2
2
  import { TestError, SerializedError, Arrayable, ParsedStack, Awaitable } from '@vitest/utils';
3
- import { A as AfterSuiteRunMeta, U as UserConsoleLog, P as ProvidedContext, C as ContextRPC, L as LabelColor } from './worker.d.B4Hthdvt.js';
3
+ import { A as AfterSuiteRunMeta, U as UserConsoleLog, P as ProvidedContext, d as ContextTestEnvironment, f as WorkerTestEnvironment, g as WorkerExecuteContext, L as LabelColor } from './worker.d.D25zYZ7N.js';
4
4
  import { Writable } from 'node:stream';
5
5
  import { TransformResult as TransformResult$1, ViteDevServer, Plugin, UserConfig as UserConfig$1, DepOptimizationConfig, ServerOptions, ConfigEnv, AliasOptions } from 'vite';
6
6
  import { MockedModule } from '@vitest/mocker';
7
7
  import { StackTraceParserOptions } from '@vitest/utils/source-map';
8
8
  import { BrowserCommands } from 'vitest/browser';
9
9
  import { B as BrowserTraceViewMode, S as SerializedConfig, F as FakeTimerInstallOpts } from './config.d.BTfZNUu9.js';
10
- import { S as SerializedTestSpecification, B as BrowserTesterOptions } from './browser.d.ScGeWTou.js';
10
+ import { S as SerializedTestSpecification, B as BrowserTesterOptions } from './browser.d.-LKfRopd.js';
11
11
  import { PrettyFormatOptions } from '@vitest/pretty-format';
12
12
  import { SnapshotSummary, SnapshotStateOptions } from '@vitest/snapshot';
13
13
  import { SerializedDiffOptions } from '@vitest/utils/diff';
@@ -1445,6 +1445,7 @@ interface BrowserConfigOptions {
1445
1445
  * Isolate test environment after each test
1446
1446
  *
1447
1447
  * @default true
1448
+ * @deprecated use top-level `isolate` instead
1448
1449
  */
1449
1450
  isolate?: boolean;
1450
1451
  /**
@@ -1452,6 +1453,7 @@ interface BrowserConfigOptions {
1452
1453
  * This option only has effect in headless mode (enabled in CI by default)
1453
1454
  *
1454
1455
  * @default // Same as "test.fileParallelism"
1456
+ * @deprecated use top-level `fileParallelism` instead
1455
1457
  */
1456
1458
  fileParallelism?: boolean;
1457
1459
  /**
@@ -1866,7 +1868,7 @@ interface PoolOptions {
1866
1868
  project: TestProject;
1867
1869
  method: "run" | "collect";
1868
1870
  cacheFs?: boolean;
1869
- environment: string;
1871
+ environment: ContextTestEnvironment;
1870
1872
  execArgv: string[];
1871
1873
  env: Partial<NodeJS.ProcessEnv>;
1872
1874
  }
@@ -1901,7 +1903,8 @@ interface PoolTask {
1901
1903
  * so modifying it once will modify it for every task.
1902
1904
  */
1903
1905
  execArgv: string[];
1904
- context: ContextRPC;
1906
+ context: WorkerExecuteContext;
1907
+ environment: ContextTestEnvironment;
1905
1908
  memoryLimit: number | null;
1906
1909
  }
1907
1910
  type WorkerRequest = {
@@ -1911,15 +1914,20 @@ type WorkerRequest = {
1911
1914
  options: {
1912
1915
  reportMemory: boolean;
1913
1916
  };
1917
+ context: {
1918
+ environment: WorkerTestEnvironment;
1919
+ config: SerializedConfig;
1920
+ pool: string;
1921
+ };
1914
1922
  } | {
1915
1923
  type: "stop";
1916
1924
  } | {
1917
1925
  type: "run";
1918
- context: ContextRPC;
1926
+ context: WorkerExecuteContext;
1919
1927
  poolId: number;
1920
1928
  } | {
1921
1929
  type: "collect";
1922
- context: ContextRPC;
1930
+ context: WorkerExecuteContext;
1923
1931
  poolId: number;
1924
1932
  } | {
1925
1933
  type: "cancel";
@@ -1928,6 +1936,7 @@ type WorkerResponse = {
1928
1936
  __vitest_worker_response__: true;
1929
1937
  } & ({
1930
1938
  type: "started";
1939
+ error?: unknown;
1931
1940
  } | {
1932
1941
  type: "stopped";
1933
1942
  error?: unknown;
@@ -22,13 +22,14 @@ async function rpcDone() {
22
22
  const awaitable = Array.from(promises);
23
23
  return Promise.all(awaitable);
24
24
  }
25
- let previousRpc;
25
+ const onCancelCallbacks = [];
26
+ function onCancel(callback) {
27
+ onCancelCallbacks.push(callback);
28
+ }
26
29
  function createRuntimeRpc(options) {
27
- if (previousRpc) previousRpc.$close(), previousRpc = void 0;
28
- let setCancel = (_reason) => {};
29
- const onCancel = new Promise((resolve) => {
30
- setCancel = resolve;
31
- }), rpc = createSafeRpc(createBirpc({ onCancel: setCancel }, {
30
+ return createSafeRpc(createBirpc({ async onCancel(reason) {
31
+ await Promise.all(onCancelCallbacks.map((fn) => fn(reason)));
32
+ } }, {
32
33
  eventNames: [
33
34
  "onUserConsoleLog",
34
35
  "onCollected",
@@ -37,10 +38,6 @@ function createRuntimeRpc(options) {
37
38
  timeout: -1,
38
39
  ...options
39
40
  }));
40
- return previousRpc = rpc, {
41
- rpc,
42
- onCancel
43
- };
44
41
  }
45
42
  function createSafeRpc(rpc) {
46
43
  return new Proxy(rpc, { get(target, p, handler) {
@@ -63,4 +60,4 @@ function rpc() {
63
60
  return rpc;
64
61
  }
65
62
 
66
- export { rpcDone as a, createRuntimeRpc as c, rpc as r };
63
+ export { rpcDone as a, createRuntimeRpc as c, onCancel as o, rpc as r };
@@ -11,6 +11,27 @@ import vm from 'node:vm';
11
11
  import { MockerRegistry, mockObject, RedirectedModule, AutomockedModule } from '@vitest/mocker';
12
12
  import * as viteModuleRunner from 'vite/module-runner';
13
13
 
14
+ class VitestTransport {
15
+ constructor(options) {
16
+ this.options = options;
17
+ }
18
+ async invoke(event) {
19
+ if (event.type !== "custom") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support Vite HMR events.`) };
20
+ if (event.event !== "vite:invoke") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support ${event.event} event.`) };
21
+ const { name, data } = event.data;
22
+ if (name === "getBuiltins")
23
+ // we return an empty array here to avoid client-side builtin check,
24
+ // as we need builtins to go through `fetchModule`
25
+ return { result: [] };
26
+ if (name !== "fetchModule") return { error: /* @__PURE__ */ new Error(`Unknown method: ${name}. Expected "fetchModule".`) };
27
+ try {
28
+ return { result: await this.options.fetchModule(...data) };
29
+ } catch (error) {
30
+ return { error };
31
+ }
32
+ }
33
+ }
34
+
14
35
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
15
36
  function normalizeWindowsPath(input = "") {
16
37
  return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
@@ -428,27 +449,6 @@ function fixLeadingSlashes(id) {
428
449
  return id.startsWith("//") ? id.replace(multipleSlashRe, "/") : id;
429
450
  }
430
451
 
431
- class VitestTransport {
432
- constructor(options) {
433
- this.options = options;
434
- }
435
- async invoke(event) {
436
- if (event.type !== "custom") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support Vite HMR events.`) };
437
- if (event.event !== "vite:invoke") return { error: /* @__PURE__ */ new Error(`Vitest Module Runner doesn't support ${event.event} event.`) };
438
- const { name, data } = event.data;
439
- if (name === "getBuiltins")
440
- // we return an empty array here to avoid client-side builtin check,
441
- // as we need builtins to go through `fetchModule`
442
- return { result: [] };
443
- if (name !== "fetchModule") return { error: /* @__PURE__ */ new Error(`Unknown method: ${name}. Expected "fetchModule".`) };
444
- try {
445
- return { result: await this.options.fetchModule(...data) };
446
- } catch (error) {
447
- return { error };
448
- }
449
- }
450
- }
451
-
452
452
  const createNodeImportMeta = (modulePath) => {
453
453
  if (!viteModuleRunner.createDefaultImportMeta) throw new Error(`createNodeImportMeta is not supported in this version of Vite.`);
454
454
  const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath), href = defaultMeta.url, importMetaResolver = createImportMetaResolver();
@@ -575,24 +575,24 @@ function getCachedVitestImport(id, state) {
575
575
  }) : null;
576
576
  }
577
577
 
578
- const dispose = [];
578
+ // 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 = [];
579
580
  function listenForErrors(state) {
580
581
  dispose.forEach((fn) => fn()), dispose.length = 0;
581
582
  function catchError(err, type, event) {
582
583
  const worker = state();
583
584
  // if there is another listener, assume that it's handled by user code
584
585
  // one is Vitest's own listener
585
- if (process.listeners(event).length > 1) return;
586
+ if (processListeners(event).length > 1) return;
586
587
  const error = serializeValue(err);
587
588
  if (typeof error === "object" && error != null) {
588
589
  if (error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0, worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
589
- error.VITEST_AFTER_ENV_TEARDOWN = worker.environmentTeardownRun;
590
590
  }
591
591
  state().rpc.onUnhandledError(error, type);
592
592
  }
593
593
  const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException"), unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
594
- process.on("uncaughtException", uncaughtException), process.on("unhandledRejection", unhandledRejection), dispose.push(() => {
595
- process.off("uncaughtException", uncaughtException), process.off("unhandledRejection", unhandledRejection);
594
+ processOn("uncaughtException", uncaughtException), processOn("unhandledRejection", unhandledRejection), dispose.push(() => {
595
+ processOff("uncaughtException", uncaughtException), processOff("unhandledRejection", unhandledRejection);
596
596
  });
597
597
  }
598
598
 
@@ -8,7 +8,7 @@ import { getTests, getNames, getTestName } from '@vitest/runner/utils';
8
8
  import { processError } from '@vitest/utils/error';
9
9
  import { normalize } from 'pathe';
10
10
  import { a as getSnapshotClient, i as inject, c as createExpect, v as vi } from './vi.BZvkKVkM.js';
11
- import { r as rpc } from './rpc.Dv1Jt3i2.js';
11
+ import { r as rpc } from './rpc.D38ahn14.js';
12
12
 
13
13
  function createBenchmarkResult(name) {
14
14
  return {
@@ -1,6 +1,7 @@
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.fmH9J833.js';
4
5
  import { distDir } from '../path.js';
5
6
  import { createCustomConsole } from './console.CTJL2nuH.js';
6
7
  import fs from 'node:fs';
@@ -10,7 +11,7 @@ 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 { s as startVitestModuleRunner, c as createNodeImportMeta, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.Cn7hCL7D.js';
14
15
  import { p as provideWorkerState } from './utils.CG9h5ccR.js';
15
16
 
16
17
  function interopCommonJsModule(interopDefault, mod) {
@@ -585,13 +586,13 @@ class FileMap {
585
586
 
586
587
  const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href, fileMap = new FileMap(), packageCache = /* @__PURE__ */ new Map();
587
588
  async function runVmTests(method, state) {
588
- const { environment, ctx, rpc } = state;
589
- if (!environment.setupVM) {
589
+ const { ctx, rpc } = state, beforeEnvironmentTime = performance.now(), { environment } = await loadEnvironment(ctx.environment.name, ctx.config.root, rpc);
590
+ if (state.environment = environment, !environment.setupVM) {
590
591
  const envName = ctx.environment.name, packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
591
592
  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
593
  }
593
594
  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.`);
595
+ if (state.durations.environment = performance.now() - beforeEnvironmentTime, 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.`);
595
596
  const context = vm.getVmContext();
596
597
  if (!isContext(context)) throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
597
598
  provideWorkerState(context, state), context.process = process, context.global = context, context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state), context.setImmediate = setImmediate, context.clearImmediate = clearImmediate;
@@ -629,7 +630,7 @@ async function runVmTests(method, state) {
629
630
  try {
630
631
  await run(method, fileSpecs, ctx.config, moduleRunner);
631
632
  } finally {
632
- await vm.teardown?.(), state.environmentTeardownRun = true;
633
+ await vm.teardown?.();
633
634
  }
634
635
  }
635
636
 
@@ -167,18 +167,37 @@ interface ContextTestEnvironment {
167
167
  name: string;
168
168
  options: Record<string, any> | null;
169
169
  }
170
+ interface WorkerTestEnvironment {
171
+ name: string;
172
+ options: Record<string, any> | null;
173
+ }
170
174
  type TestExecutionMethod = "run" | "collect";
175
+ interface WorkerExecuteContext {
176
+ files: FileSpecification[];
177
+ providedContext: Record<string, any>;
178
+ invalidates?: string[];
179
+ /** Exposed to test runner as `VITEST_WORKER_ID`. Value is unique per each isolated worker. */
180
+ workerId: number;
181
+ }
171
182
  interface ContextRPC {
172
183
  pool: string;
173
184
  config: SerializedConfig;
174
185
  projectName: string;
186
+ environment: WorkerTestEnvironment;
187
+ rpc: WorkerRPC;
175
188
  files: FileSpecification[];
176
- environment: ContextTestEnvironment;
177
189
  providedContext: Record<string, any>;
178
190
  invalidates?: string[];
179
191
  /** Exposed to test runner as `VITEST_WORKER_ID`. Value is unique per each isolated worker. */
180
192
  workerId: number;
181
193
  }
194
+ interface WorkerSetupContext {
195
+ environment: WorkerTestEnvironment;
196
+ pool: string;
197
+ config: SerializedConfig;
198
+ projectName: string;
199
+ rpc: WorkerRPC;
200
+ }
182
201
  interface WorkerGlobalState {
183
202
  ctx: ContextRPC;
184
203
  config: SerializedConfig;
@@ -194,11 +213,10 @@ interface WorkerGlobalState {
194
213
  SSR: boolean;
195
214
  };
196
215
  environment: Environment;
197
- environmentTeardownRun?: boolean;
198
- onCancel: Promise<CancelReason>;
199
216
  evaluatedModules: EvaluatedModules;
200
217
  resolvingModules: Set<string>;
201
218
  moduleExecutionInfo: Map<string, any>;
219
+ onCancel: (listener: (reason: CancelReason) => unknown) => void;
202
220
  onCleanup: (listener: () => unknown) => void;
203
221
  providedContext: Record<string, any>;
204
222
  durations: {
@@ -208,4 +226,4 @@ interface WorkerGlobalState {
208
226
  onFilterStackTrace?: (trace: string) => string;
209
227
  }
210
228
 
211
- export type { AfterSuiteRunMeta as A, BirpcOptions as B, ContextRPC as C, LabelColor as L, ModuleGraphData as M, ProvidedContext as P, RuntimeRPC as R, TestExecutionMethod as T, UserConsoleLog as U, WorkerGlobalState as W, BirpcReturn as a, RunnerRPC as b, ContextTestEnvironment as c, ResolveFunctionResult as d };
229
+ export type { AfterSuiteRunMeta as A, BirpcOptions as B, ContextRPC as C, LabelColor as L, ModuleGraphData as M, ProvidedContext as P, RuntimeRPC as R, TestExecutionMethod as T, UserConsoleLog as U, WorkerGlobalState as W, WorkerSetupContext as a, BirpcReturn as b, RunnerRPC as c, ContextTestEnvironment as d, ResolveFunctionResult as e, WorkerTestEnvironment as f, WorkerExecuteContext as g };
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
- import { c as createCLI } from './chunks/cac.BBqWH4nd.js';
1
+ import { c as createCLI } from './chunks/cac.G9DAn-c7.js';
2
2
  import '@vitest/utils/helpers';
3
3
  import 'events';
4
4
  import 'pathe';
5
5
  import 'tinyrainbow';
6
6
  import './chunks/constants.D_Q9UYh-.js';
7
- import './chunks/index.BL8Hg4Uk.js';
7
+ import './chunks/index.CVpyv-Zg.js';
8
8
  import 'node:fs';
9
9
  import 'node:fs/promises';
10
10
  import 'node:perf_hooks';