vitest 4.0.17 → 4.1.0-beta.2

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 (74) hide show
  1. package/LICENSE.md +36 -0
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +2 -2
  4. package/dist/chunks/acorn.B2iPLyUM.js +5958 -0
  5. package/dist/chunks/{base.XJJQZiKB.js → base.DiopZV8F.js} +49 -14
  6. package/dist/chunks/{benchmark.B3N2zMcH.js → benchmark.BoqSLF53.js} +1 -1
  7. package/dist/chunks/{browser.d.ChKACdzH.d.ts → browser.d.BE4kbYok.d.ts} +4 -1
  8. package/dist/chunks/{cac.jRCLJDDc.js → cac.C4jjt2RX.js} +816 -14
  9. package/dist/chunks/{cli-api.Cx2DW4Bc.js → cli-api.ChbI1JU9.js} +412 -166
  10. package/dist/chunks/{config.d.Cy95HiCx.d.ts → config.d.Cr1Ep39N.d.ts} +13 -11
  11. package/dist/chunks/{console.Cf-YriPC.js → console.CNlG1KsP.js} +3 -2
  12. package/dist/chunks/{constants.D_Q9UYh-.js → constants.B63TT-Bl.js} +1 -1
  13. package/dist/chunks/coverage.tyqbzn4W.js +1001 -0
  14. package/dist/chunks/{creator.DAmOKTvJ.js → creator.yyCHuw5R.js} +33 -2
  15. package/dist/chunks/{global.d.B15mdLcR.d.ts → global.d.JeWMqlOm.d.ts} +1 -1
  16. package/dist/chunks/{globals.DOayXfHP.js → globals.C6Ecf1TO.js} +11 -10
  17. package/dist/chunks/{index.M8mOzt4Y.js → index.B-iBE_Gx.js} +21 -5
  18. package/dist/chunks/{coverage.AVPTjMgw.js → index.BCY_7LL2.js} +5 -959
  19. package/dist/chunks/{index.6Qv1eEA6.js → index.CAN630q3.js} +20 -8
  20. package/dist/chunks/{index.C5r1PdPD.js → index.CFulQRmC.js} +1 -1
  21. package/dist/chunks/{index.Z5E_ObnR.js → index.CouFDptX.js} +4 -2
  22. package/dist/chunks/{init-forks.BC6ZwHQN.js → init-forks.BnCXPazU.js} +1 -1
  23. package/dist/chunks/{init-threads.CxSxLC0N.js → init-threads.Cyh2PqXi.js} +1 -1
  24. package/dist/chunks/{init.C9kljSTm.js → init.B95Mm0Iz.js} +65 -12
  25. package/dist/chunks/native.mV0-490A.js +148 -0
  26. package/dist/chunks/nativeModuleMocker.D_q5sFv6.js +206 -0
  27. package/dist/chunks/nativeModuleRunner.BIakptoF.js +36 -0
  28. package/dist/chunks/{node.Ce0vMQM7.js → node.CrSEwhm4.js} +1 -1
  29. package/dist/chunks/{plugin.d.CtqpEehP.d.ts → plugin.d.C9o5bttz.d.ts} +1 -1
  30. package/dist/chunks/{reporters.d.CWXNI2jG.d.ts → reporters.d.7faYdkxy.d.ts} +146 -49
  31. package/dist/chunks/rpc.DcRWTy5G.js +148 -0
  32. package/dist/chunks/{rpc.d.RH3apGEf.d.ts → rpc.d.CM7x9-sm.d.ts} +1 -0
  33. package/dist/chunks/{setup-common.Cm-kSBVi.js → setup-common.cvFp-ao9.js} +2 -2
  34. package/dist/chunks/{startModuleRunner.DEj0jb3e.js → startVitestModuleRunner.BK-u7y4N.js} +182 -391
  35. package/dist/chunks/{vi.2VT5v0um.js → test.G82XYNFk.js} +505 -119
  36. package/dist/chunks/{utils.DvEY5TfP.js → utils.DT4VyRyl.js} +5 -1
  37. package/dist/chunks/{vm.CMjifoPa.js → vm.BdLtzhnj.js} +15 -11
  38. package/dist/chunks/{worker.d.Dyxm8DEL.d.ts → worker.d.CPzI2ZzJ.d.ts} +2 -2
  39. package/dist/cli.js +4 -3
  40. package/dist/config.d.ts +11 -11
  41. package/dist/config.js +1 -1
  42. package/dist/coverage.d.ts +10 -8
  43. package/dist/coverage.js +7 -4
  44. package/dist/environments.js +2 -0
  45. package/dist/index.d.ts +30 -23
  46. package/dist/index.js +9 -8
  47. package/dist/module-evaluator.d.ts +10 -1
  48. package/dist/module-evaluator.js +1 -5
  49. package/dist/node.d.ts +13 -12
  50. package/dist/node.js +27 -25
  51. package/dist/nodejs-worker-loader.js +41 -0
  52. package/dist/reporters.d.ts +8 -8
  53. package/dist/reporters.js +4 -2
  54. package/dist/runners.d.ts +24 -4
  55. package/dist/runners.js +6 -6
  56. package/dist/runtime.d.ts +6 -0
  57. package/dist/runtime.js +35 -0
  58. package/dist/snapshot.js +4 -2
  59. package/dist/suite.js +4 -2
  60. package/dist/worker.d.ts +8 -7
  61. package/dist/worker.js +25 -20
  62. package/dist/workers/forks.js +21 -16
  63. package/dist/workers/runVmTests.js +11 -13
  64. package/dist/workers/threads.js +21 -16
  65. package/dist/workers/vmForks.js +14 -11
  66. package/dist/workers/vmThreads.js +14 -11
  67. package/package.json +28 -29
  68. package/suppress-warnings.cjs +1 -0
  69. package/dist/chunks/date.Bq6ZW5rf.js +0 -73
  70. package/dist/chunks/rpc.BoxB0q7B.js +0 -76
  71. package/dist/chunks/test.B8ej_ZHS.js +0 -254
  72. package/dist/mocker.d.ts +0 -1
  73. package/dist/mocker.js +0 -1
  74. package/dist/module-runner.js +0 -17
@@ -1,25 +1,25 @@
1
1
  import { chai } from '@vitest/expect';
2
- import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.Cm-kSBVi.js';
3
- import { r as rpc } from './rpc.BoxB0q7B.js';
4
- import { g as getWorkerState } from './utils.DvEY5TfP.js';
5
- import { V as VitestTestRunner, N as NodeBenchmarkRunner } from './test.B8ej_ZHS.js';
2
+ import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.cvFp-ao9.js';
3
+ import { r as rpc } from './rpc.DcRWTy5G.js';
4
+ import { g as getWorkerState } from './utils.DT4VyRyl.js';
5
+ import { T as TestRunner, N as NodeBenchmarkRunner } from './test.G82XYNFk.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) {
11
+ async function resolveSnapshotEnvironment(config, moduleRunner) {
12
12
  if (!config.snapshotEnvironment) {
13
- const { VitestNodeSnapshotEnvironment } = await import('./node.Ce0vMQM7.js');
13
+ const { VitestNodeSnapshotEnvironment } = await import('./node.CrSEwhm4.js');
14
14
  return new VitestNodeSnapshotEnvironment();
15
15
  }
16
- const mod = await executor.import(config.snapshotEnvironment);
16
+ const mod = await moduleRunner.import(config.snapshotEnvironment);
17
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
18
  return mod.default;
19
19
  }
20
20
 
21
21
  async function getTestRunnerConstructor(config, moduleRunner) {
22
- if (!config.runner) return config.mode === "test" ? VitestTestRunner : NodeBenchmarkRunner;
22
+ if (!config.runner) return config.mode === "test" ? TestRunner : NodeBenchmarkRunner;
23
23
  const mod = await moduleRunner.import(config.runner);
24
24
  if (!mod.default && typeof mod.default !== "function") throw new Error(`Runner must export a default function, but got ${typeof mod.default} imported from ${config.runner}`);
25
25
  return mod.default;
@@ -78,6 +78,18 @@ async function resolveTestRunner(config, moduleRunner, traces) {
78
78
  state.durations.prepare = 0;
79
79
  state.durations.environment = 0;
80
80
  });
81
+ // Strip function conditions from retry config before sending via RPC
82
+ // Functions cannot be cloned by structured clone algorithm
83
+ const sanitizeRetryConditions = (task) => {
84
+ if (task.retry && typeof task.retry === "object" && typeof task.retry.condition === "function")
85
+ // Remove function condition - it can't be serialized
86
+ task.retry = {
87
+ ...task.retry,
88
+ condition: void 0
89
+ };
90
+ if (task.tasks) task.tasks.forEach(sanitizeRetryConditions);
91
+ };
92
+ files.forEach(sanitizeRetryConditions);
81
93
  rpc().onCollected(files);
82
94
  await originalOnCollected?.call(testRunner, files);
83
95
  };
@@ -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.M8mOzt4Y.js';
5
+ import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName, s as separator } from './index.B-iBE_Gx.js';
6
6
  import { stripVTControlCharacters } from 'node:util';
7
7
  import { notNullish } from '@vitest/utils/helpers';
8
8
 
@@ -1,5 +1,5 @@
1
- import { b as assert, c as createExpect, g as globalExpect, i as inject, s as should, v as vi, d as vitest } from './vi.2VT5v0um.js';
2
- import { b as bench } from './benchmark.B3N2zMcH.js';
1
+ import { N as NodeBenchmarkRunner, T as TestRunner, a as assert, c as createExpect, g as globalExpect, i as inject, s as should, v as vi, b as vitest } from './test.G82XYNFk.js';
2
+ import { b as bench } from './benchmark.BoqSLF53.js';
3
3
  import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
4
4
  import { expectTypeOf } from 'expect-type';
5
5
  import { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, recordArtifact, suite, test } from '@vitest/runner';
@@ -9,7 +9,9 @@ const assertType = function assertType() {};
9
9
 
10
10
  var index = /*#__PURE__*/Object.freeze({
11
11
  __proto__: null,
12
+ BenchmarkRunner: NodeBenchmarkRunner,
12
13
  EvaluatedModules: VitestEvaluatedModules,
14
+ TestRunner: TestRunner,
13
15
  afterAll: afterAll,
14
16
  afterEach: afterEach,
15
17
  assert: assert,
@@ -1,4 +1,4 @@
1
- import { i as init } from './init.C9kljSTm.js';
1
+ import { i as init } from './init.B95Mm0Iz.js';
2
2
 
3
3
  if (!process.send) throw new Error("Expected worker to be run in node:child_process");
4
4
  // Store globals in case tests overwrite them
@@ -1,5 +1,5 @@
1
1
  import { isMainThread, parentPort } from 'node:worker_threads';
2
- import { i as init } from './init.C9kljSTm.js';
2
+ import { i as init } from './init.B95Mm0Iz.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) {
@@ -3,11 +3,12 @@ import { isBuiltin } from 'node:module';
3
3
  import { pathToFileURL } from 'node:url';
4
4
  import { resolve } from 'pathe';
5
5
  import { ModuleRunner } from 'vite/module-runner';
6
- import { b as VitestTransport } from './startModuleRunner.DEj0jb3e.js';
6
+ import { b as VitestTransport } from './startVitestModuleRunner.BK-u7y4N.js';
7
7
  import { e as environments } from './index.CyBMJtT7.js';
8
+ import { serializeValue } from '@vitest/utils/serialize';
8
9
  import { serializeError } from '@vitest/utils/error';
9
10
  import { T as Traces } from './traces.CCmnQaNT.js';
10
- import { o as onCancel, a as rpcDone, c as createRuntimeRpc } from './rpc.BoxB0q7B.js';
11
+ import { o as onCancel, a as rpcDone, c as createRuntimeRpc } from './rpc.DcRWTy5G.js';
11
12
  import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
12
13
  import { s as setupInspect } from './inspector.CvyFGlXm.js';
13
14
  import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
@@ -46,11 +47,11 @@ function createEnvironmentLoader(root, rpc) {
46
47
  }
47
48
  return _loaders.get(root);
48
49
  }
49
- async function loadEnvironment(name, root, rpc, traces) {
50
- if (isBuiltinEnvironment(name)) return { environment: environments[name] };
51
- const loader = createEnvironmentLoader(root, rpc);
52
- const packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await traces.$("vitest.runtime.environment.resolve", () => rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__")))?.id ?? resolve(root, name);
53
- const pkg = await traces.$("vitest.runtime.environment.import", () => loader.import(packageId));
50
+ async function loadNativeEnvironment(name, root, traces) {
51
+ const packageId = name[0] === "." || name[0] === "/" ? pathToFileURL(resolve(root, name)).toString() : import.meta.resolve(`vitest-environment-${name}`, pathToFileURL(root).toString());
52
+ return resolveEnvironmentFromModule(name, packageId, await traces.$("vitest.runtime.environment.import", () => import(packageId)));
53
+ }
54
+ function resolveEnvironmentFromModule(name, packageId, pkg) {
54
55
  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.`);
55
56
  const environment = pkg.default;
56
57
  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}".`);
@@ -59,14 +60,65 @@ async function loadEnvironment(name, root, rpc, traces) {
59
60
  // keep for backwards compat
60
61
  environment.viteEnvironment ??= environment.transformMode === "ssr" ? "ssr" : "client";
61
62
  }
63
+ return environment;
64
+ }
65
+ async function loadEnvironment(name, root, rpc, traces, viteModuleRunner) {
66
+ if (isBuiltinEnvironment(name)) return { environment: environments[name] };
67
+ if (!viteModuleRunner) return { environment: await loadNativeEnvironment(name, root, traces) };
68
+ const loader = createEnvironmentLoader(root, rpc);
69
+ const packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await traces.$("vitest.runtime.environment.resolve", () => rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__")))?.id ?? resolve(root, name);
62
70
  return {
63
- environment,
71
+ environment: resolveEnvironmentFromModule(name, packageId, await traces.$("vitest.runtime.environment.import", () => loader.import(packageId))),
64
72
  loader
65
73
  };
66
74
  }
67
75
 
76
+ const cleanupListeners = /* @__PURE__ */ new Set();
77
+ const moduleRunnerListeners = /* @__PURE__ */ new Set();
78
+ function onCleanup(cb) {
79
+ cleanupListeners.add(cb);
80
+ }
81
+ async function cleanup() {
82
+ await Promise.all([...cleanupListeners].map((l) => l()));
83
+ }
84
+ function onModuleRunner(cb) {
85
+ moduleRunnerListeners.add(cb);
86
+ }
87
+ function emitModuleRunner(moduleRunner) {
88
+ moduleRunnerListeners.forEach((l) => l(moduleRunner));
89
+ }
90
+
91
+ // Store globals in case tests overwrite them
92
+ const processListeners = process.listeners.bind(process);
93
+ const processOn = process.on.bind(process);
94
+ const processOff = process.off.bind(process);
95
+ const dispose = [];
96
+ function listenForErrors(state) {
97
+ dispose.forEach((fn) => fn());
98
+ dispose.length = 0;
99
+ function catchError(err, type, event) {
100
+ const worker = state();
101
+ // if there is another listener, assume that it's handled by user code
102
+ // one is Vitest's own listener
103
+ if (processListeners(event).length > 1) return;
104
+ const error = serializeValue(err);
105
+ if (typeof error === "object" && error != null) {
106
+ error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
107
+ if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
108
+ }
109
+ state().rpc.onUnhandledError(error, type);
110
+ }
111
+ const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
112
+ const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
113
+ processOn("uncaughtException", uncaughtException);
114
+ processOn("unhandledRejection", unhandledRejection);
115
+ dispose.push(() => {
116
+ processOff("uncaughtException", uncaughtException);
117
+ processOff("unhandledRejection", unhandledRejection);
118
+ });
119
+ }
120
+
68
121
  const resolvingModules = /* @__PURE__ */ new Set();
69
- const globalListeners = /* @__PURE__ */ new Set();
70
122
  async function execute(method, ctx, worker, traces) {
71
123
  const prepareStart = performance.now();
72
124
  const cleanups = [setupInspect(ctx)];
@@ -92,7 +144,7 @@ async function execute(method, ctx, worker, traces) {
92
144
  },
93
145
  rpc,
94
146
  onCancel,
95
- onCleanup: (listener) => globalListeners.add(listener),
147
+ onCleanup: onCleanup,
96
148
  providedContext: ctx.providedContext,
97
149
  onFilterStackTrace(stack) {
98
150
  return createStackString(parseStacktrace(stack));
@@ -114,7 +166,7 @@ function collect(ctx, worker, traces) {
114
166
  return execute("collect", ctx, worker, traces);
115
167
  }
116
168
  async function teardown() {
117
- await Promise.all([...globalListeners].map((l) => l()));
169
+ await cleanup();
118
170
  }
119
171
  const env = process.env;
120
172
  function createImportMetaEnvProxy() {
@@ -146,6 +198,7 @@ let traces;
146
198
  /** @experimental */
147
199
  function init(worker) {
148
200
  worker.on(onMessage);
201
+ if (worker.onModuleRunner) onModuleRunner(worker.onModuleRunner);
149
202
  let runPromise;
150
203
  let isRunning = false;
151
204
  let workerTeardown;
@@ -316,4 +369,4 @@ function getFilesWithLocations(files) {
316
369
  });
317
370
  }
318
371
 
319
- export { init as i, loadEnvironment as l };
372
+ export { listenForErrors as a, emitModuleRunner as e, init as i, loadEnvironment as l };
@@ -0,0 +1,148 @@
1
+ import module$1, { isBuiltin } from 'node:module';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { MessageChannel } from 'node:worker_threads';
4
+ import { initSyntaxLexers, hoistMocks } from '@vitest/mocker/transforms';
5
+ import { cleanUrl } from '@vitest/utils/helpers';
6
+ import { p as parse } from './acorn.B2iPLyUM.js';
7
+ import MagicString from 'magic-string';
8
+ import { resolve } from 'pathe';
9
+ import c from 'tinyrainbow';
10
+ import { distDir } from '../path.js';
11
+ import { t as toBuiltin } from './modules.BJuCwlRJ.js';
12
+ import 'node:path';
13
+
14
+ const NOW_LENGTH = Date.now().toString().length;
15
+ const REGEXP_VITEST = /* @__PURE__ */ new RegExp(`%3Fvitest=\\d{${NOW_LENGTH}}`);
16
+ const REGEXP_MOCK_ACTUAL = /\?mock=actual/;
17
+ async function setupNodeLoaderHooks(worker) {
18
+ if (module$1.setSourceMapsSupport) module$1.setSourceMapsSupport(true);
19
+ else if (process.setSourceMapsEnabled) process.setSourceMapsEnabled(true);
20
+ if (worker.config.experimental.nodeLoader !== false) await initSyntaxLexers();
21
+ if (typeof module$1.registerHooks === "function") module$1.registerHooks({
22
+ resolve(specifier, context, nextResolve) {
23
+ if (specifier.includes("mock=actual")) {
24
+ // url is already resolved by `importActual`
25
+ const moduleId = specifier.replace(REGEXP_MOCK_ACTUAL, "");
26
+ const builtin = isBuiltin(moduleId);
27
+ return {
28
+ url: builtin ? toBuiltin(moduleId) : moduleId,
29
+ format: builtin ? "builtin" : void 0,
30
+ shortCircuit: true
31
+ };
32
+ }
33
+ const isVitest = specifier.includes("%3Fvitest=");
34
+ const result = nextResolve(isVitest ? specifier.replace(REGEXP_VITEST, "") : specifier, context);
35
+ // avoid tracking /node_modules/ module graph for performance reasons
36
+ if (context.parentURL && result.url && !result.url.includes("/node_modules/")) worker.rpc.ensureModuleGraphEntry(result.url, context.parentURL).catch(() => {
37
+ // ignore errors
38
+ });
39
+ // this is require for in-source tests to be invalidated if
40
+ // one of the files already imported it in --maxWorkers=1 --no-isolate
41
+ if (isVitest) result.url = `${result.url}?vitest=${Date.now()}`;
42
+ if (worker.config.experimental.nodeLoader === false || !context.parentURL || result.url.includes(distDir) || context.parentURL?.toString().includes(distDir)) return result;
43
+ const mockedResult = getNativeMocker()?.resolveMockedModule(result.url, context.parentURL);
44
+ if (mockedResult != null) return mockedResult;
45
+ return result;
46
+ },
47
+ load: worker.config.experimental.nodeLoader === false ? void 0 : createLoadHook()
48
+ });
49
+ else if (module$1.register) {
50
+ if (worker.config.experimental.nodeLoader !== false) console.warn(`${c.bgYellow(" WARNING ")} "module.registerHooks" is not supported in Node.js ${process.version}. This means that some features like module mocking or in-source testing are not supported. Upgrade your Node.js version to at least 22.15 or disable "experimental.nodeLoader" flag manually.\n`);
51
+ const { port1, port2 } = new MessageChannel();
52
+ port1.unref();
53
+ port2.unref();
54
+ port1.on("message", (data) => {
55
+ if (!data || typeof data !== "object") return;
56
+ switch (data.event) {
57
+ case "register-module-graph-entry": {
58
+ const { url, parentURL } = data;
59
+ worker.rpc.ensureModuleGraphEntry(url, parentURL);
60
+ return;
61
+ }
62
+ default: console.error("Unknown message event:", data.event);
63
+ }
64
+ });
65
+ /** Registers {@link file://./../nodejsWorkerLoader.ts} */
66
+ module$1.register("#nodejs-worker-loader", {
67
+ parentURL: import.meta.url,
68
+ data: { port: port2 },
69
+ transferList: [port2]
70
+ });
71
+ } else if (!process.versions.deno && !process.versions.bun) console.warn("\"module.registerHooks\" and \"module.register\" are not supported. Some Vitest features may not work. Please, use Node.js 18.19.0 or higher.");
72
+ }
73
+ function replaceInSourceMarker(url, source, ms) {
74
+ const re = /import\.meta\.vitest/g;
75
+ let match;
76
+ let overridden = false;
77
+ // eslint-disable-next-line no-cond-assign
78
+ while (match = re.exec(source)) {
79
+ const { index, "0": code } = match;
80
+ overridden = true;
81
+ // should it support process.vitest for CJS modules?
82
+ ms().overwrite(index, index + code.length, "IMPORT_META_TEST()");
83
+ }
84
+ if (overridden) {
85
+ const filename = resolve(fileURLToPath(url));
86
+ // appending instead of prepending because functions are hoisted and we don't change the offset
87
+ ms().append(`;\nfunction IMPORT_META_TEST() { return typeof __vitest_worker__ !== 'undefined' && __vitest_worker__.filepath === "${filename.replace(/"/g, "\\\"")}" ? __vitest_index__ : undefined; }`);
88
+ }
89
+ }
90
+ const ignoreFormats = new Set([
91
+ "addon",
92
+ "builtin",
93
+ "wasm"
94
+ ]);
95
+ function createLoadHook(_worker) {
96
+ return (url, context, nextLoad) => {
97
+ const result = url.includes("mock=") && isBuiltin(cleanUrl(url)) ? { format: "commonjs" } : nextLoad(url, context);
98
+ if (result.format && ignoreFormats.has(result.format) || url.includes(distDir)) return result;
99
+ const mocker = getNativeMocker();
100
+ mocker?.checkCircularManualMock(url);
101
+ if (url.includes("mock=automock") || url.includes("mock=autospy")) {
102
+ const automockedResult = mocker?.loadAutomock(url, result);
103
+ if (automockedResult != null) return automockedResult;
104
+ return result;
105
+ }
106
+ if (url.includes("mock=manual")) {
107
+ const mockedResult = mocker?.loadManualMock(url, result);
108
+ if (mockedResult != null) return mockedResult;
109
+ return result;
110
+ }
111
+ // ignore non-vitest modules for performance reasons,
112
+ // vi.hoisted and vi.mock won't work outside of test files or setup files
113
+ if (!result.source || !url.includes("vitest=")) return result;
114
+ const filename = url.startsWith("file://") ? fileURLToPath(url) : url;
115
+ const source = result.source.toString();
116
+ const transformedCode = result.format?.includes("typescript") ? module$1.stripTypeScriptTypes(source) : source;
117
+ let _ms;
118
+ const ms = () => _ms || (_ms = new MagicString(source));
119
+ if (source.includes("import.meta.vitest")) replaceInSourceMarker(url, source, ms);
120
+ hoistMocks(transformedCode, filename, (code) => parse(code, {
121
+ ecmaVersion: "latest",
122
+ sourceType: result.format === "module" || result.format === "module-typescript" || result.format === "typescript" ? "module" : "script"
123
+ }), {
124
+ magicString: ms,
125
+ globalThisAccessor: "\"__vitest_mocker__\""
126
+ });
127
+ let code;
128
+ if (_ms) code = `${_ms.toString()}\n//# sourceMappingURL=${genSourceMapUrl(_ms.generateMap({
129
+ hires: "boundary",
130
+ source: filename
131
+ }))}`;
132
+ else code = source;
133
+ return {
134
+ format: result.format,
135
+ shortCircuit: true,
136
+ source: code
137
+ };
138
+ };
139
+ }
140
+ function genSourceMapUrl(map) {
141
+ if (typeof map !== "string") map = JSON.stringify(map);
142
+ return `data:application/json;base64,${Buffer.from(map).toString("base64")}`;
143
+ }
144
+ function getNativeMocker() {
145
+ return typeof __vitest_mocker__ !== "undefined" ? __vitest_mocker__ : void 0;
146
+ }
147
+
148
+ export { setupNodeLoaderHooks };
@@ -0,0 +1,206 @@
1
+ import module$1, { isBuiltin } from 'node:module';
2
+ import { fileURLToPath, pathToFileURL } from 'node:url';
3
+ import { automockModule, createManualModuleSource, collectModuleExports } from '@vitest/mocker/transforms';
4
+ import { cleanUrl, createDefer } from '@vitest/utils/helpers';
5
+ import { p as parse } from './acorn.B2iPLyUM.js';
6
+ import { isAbsolute } from 'pathe';
7
+ import { t as toBuiltin } from './modules.BJuCwlRJ.js';
8
+ import { B as BareModuleMocker, n as normalizeModuleId } from './startVitestModuleRunner.BK-u7y4N.js';
9
+ import 'node:fs';
10
+ import './utils.DT4VyRyl.js';
11
+ import '@vitest/utils/timers';
12
+ import '../path.js';
13
+ import 'node:path';
14
+ import '../module-evaluator.js';
15
+ import 'node:vm';
16
+ import 'vite/module-runner';
17
+ import './traces.CCmnQaNT.js';
18
+ import '@vitest/mocker';
19
+ import '@vitest/mocker/redirect';
20
+
21
+ class NativeModuleMocker extends BareModuleMocker {
22
+ wrapDynamicImport(moduleFactory) {
23
+ if (typeof moduleFactory === "function") return new Promise((resolve, reject) => {
24
+ this.resolveMocks().finally(() => {
25
+ moduleFactory().then(resolve, reject);
26
+ });
27
+ });
28
+ return moduleFactory;
29
+ }
30
+ resolveMockedModule(url, parentURL) {
31
+ // don't mock modules inside of packages because there is
32
+ // a high chance that it uses `require` which is not mockable
33
+ // because we use top-level await in "manual" mocks.
34
+ // for the sake of consistency we don't support mocking anything at all
35
+ if (parentURL.includes("/node_modules/")) return;
36
+ const moduleId = normalizeModuleId(url.startsWith("file://") ? fileURLToPath(url) : url);
37
+ const mockedModule = this.getDependencyMock(moduleId);
38
+ if (!mockedModule) return;
39
+ if (mockedModule.type === "redirect") return {
40
+ url: pathToFileURL(mockedModule.redirect).toString(),
41
+ shortCircuit: true
42
+ };
43
+ if (mockedModule.type === "automock" || mockedModule.type === "autospy") return {
44
+ url: injectQuery(url, parentURL, `mock=${mockedModule.type}`),
45
+ shortCircuit: true
46
+ };
47
+ if (mockedModule.type === "manual") return {
48
+ url: injectQuery(url, parentURL, "mock=manual"),
49
+ shortCircuit: true
50
+ };
51
+ }
52
+ loadAutomock(url, result) {
53
+ const moduleId = cleanUrl(normalizeModuleId(url.startsWith("file://") ? fileURLToPath(url) : url));
54
+ let source;
55
+ if (isBuiltin(moduleId)) {
56
+ const builtinModule = getBuiltinModule(moduleId);
57
+ const exports$1 = Object.keys(builtinModule);
58
+ source = `
59
+ import * as builtinModule from '${toBuiltin(moduleId)}?mock=actual'
60
+
61
+ ${exports$1.map((key, index) => {
62
+ return `
63
+ const __${index} = builtinModule["${key}"]
64
+ export { __${index} as "${key}" }
65
+ `;
66
+ }).join("")}`;
67
+ } else source = result.source?.toString();
68
+ if (source == null) return;
69
+ const mockType = url.includes("mock=automock") ? "automock" : "autospy";
70
+ const transformedCode = transformCode(source, result.format || "module", moduleId);
71
+ try {
72
+ const ms = automockModule(transformedCode, mockType, (code) => parse(code, {
73
+ sourceType: "module",
74
+ ecmaVersion: "latest"
75
+ }), { id: moduleId });
76
+ return {
77
+ format: "module",
78
+ source: `${ms.toString()}\n//# sourceMappingURL=${genSourceMapUrl(ms.generateMap({
79
+ hires: "boundary",
80
+ source: moduleId
81
+ }))}`,
82
+ shortCircuit: true
83
+ };
84
+ } catch (cause) {
85
+ throw new Error(`Cannot automock '${url}' because it failed to parse.`, { cause });
86
+ }
87
+ }
88
+ loadManualMock(url, result) {
89
+ const moduleId = cleanUrl(normalizeModuleId(url.startsWith("file://") ? fileURLToPath(url) : url));
90
+ // should not be possible
91
+ if (this.getDependencyMock(moduleId)?.type !== "manual") {
92
+ console.warn(`Vitest detected unregistered manual mock ${moduleId}. This is a bug in Vitest. Please, open a new issue with reproduction.`);
93
+ return;
94
+ }
95
+ if (isBuiltin(moduleId)) {
96
+ const builtinModule = getBuiltinModule(toBuiltin(moduleId));
97
+ return {
98
+ format: "module",
99
+ source: createManualModuleSource(moduleId, Object.keys(builtinModule)),
100
+ shortCircuit: true
101
+ };
102
+ }
103
+ if (!result.source) return;
104
+ const transformedCode = transformCode(result.source.toString(), result.format || "module", moduleId);
105
+ if (transformedCode == null) return;
106
+ const format = result.format?.startsWith("module") ? "module" : "commonjs";
107
+ try {
108
+ return {
109
+ format: "module",
110
+ source: createManualModuleSource(moduleId, collectModuleExports(moduleId, transformedCode, format)),
111
+ shortCircuit: true
112
+ };
113
+ } catch (cause) {
114
+ throw new Error(`Failed to mock '${url}'. See the cause for more information.`, { cause });
115
+ }
116
+ }
117
+ processedModules = /* @__PURE__ */ new Map();
118
+ checkCircularManualMock(url) {
119
+ const id = cleanUrl(normalizeModuleId(url.startsWith("file://") ? fileURLToPath(url) : url));
120
+ this.processedModules.set(id, (this.processedModules.get(id) ?? 0) + 1);
121
+ // the module is mocked and requested a second time, let's resolve
122
+ // the factory function that will redefine the exports later
123
+ if (this.originalModulePromises.has(id)) {
124
+ const factoryPromise = this.factoryPromises.get(id);
125
+ this.originalModulePromises.get(id)?.resolve({ __factoryPromise: factoryPromise });
126
+ }
127
+ }
128
+ originalModulePromises = /* @__PURE__ */ new Map();
129
+ factoryPromises = /* @__PURE__ */ new Map();
130
+ // potential performance improvement:
131
+ // store by URL, not ids, no need to call url.*to* methods and normalizeModuleId
132
+ getFactoryModule(id) {
133
+ const mock = this.getMockerRegistry().getById(id);
134
+ if (!mock || mock.type !== "manual") throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`);
135
+ const mockResult = mock.resolve();
136
+ if (mockResult instanceof Promise) {
137
+ // to avoid circular dependency, we resolve this function as {__factoryPromise} in `checkCircularManualMock`
138
+ // when it's requested the second time. then the exports are exposed as `undefined`,
139
+ // but later redefined when the promise is actually resolved
140
+ const promise = createDefer();
141
+ promise.finally(() => {
142
+ this.originalModulePromises.delete(id);
143
+ });
144
+ mockResult.then(promise.resolve, promise.reject).finally(() => {
145
+ this.factoryPromises.delete(id);
146
+ });
147
+ this.factoryPromises.set(id, mockResult);
148
+ this.originalModulePromises.set(id, promise);
149
+ // Node.js on windows processes all the files first, and then runs them
150
+ // unlike Node.js logic on Mac and Unix where it also runs the code while evaluating
151
+ // So on Linux/Mac this `if` won't be hit because `checkCircularManualMock` will resolve it
152
+ // And on Windows, the `checkCircularManualMock` will never have `originalModulePromises`
153
+ // because `getFactoryModule` is not called until the evaluation phase
154
+ // But if we track how many times the module was transformed,
155
+ // we can deduce when to return `__factoryPromise` to support circular modules
156
+ if ((this.processedModules.get(id) ?? 0) > 1) {
157
+ this.processedModules.set(id, (this.processedModules.get(id) ?? 1) - 1);
158
+ promise.resolve({ __factoryPromise: mockResult });
159
+ }
160
+ return promise;
161
+ }
162
+ return mockResult;
163
+ }
164
+ importActual(rawId, importer) {
165
+ const resolvedId = import.meta.resolve(rawId, pathToFileURL(importer).toString());
166
+ const url = new URL(resolvedId);
167
+ url.searchParams.set("mock", "actual");
168
+ return import(url.toString());
169
+ }
170
+ importMock(rawId, importer) {
171
+ const resolvedId = import.meta.resolve(rawId, pathToFileURL(importer).toString());
172
+ // file is already mocked
173
+ if (resolvedId.includes("mock=")) return import(resolvedId);
174
+ const filename = fileURLToPath(resolvedId);
175
+ const external = !isAbsolute(filename) || this.isModuleDirectory(resolvedId) ? normalizeModuleId(rawId) : null;
176
+ // file is not mocked, automock or redirect it
177
+ const redirect = this.findMockRedirect(filename, external);
178
+ if (redirect) return import(pathToFileURL(redirect).toString());
179
+ const url = new URL(resolvedId);
180
+ url.searchParams.set("mock", "automock");
181
+ return import(url.toString());
182
+ }
183
+ }
184
+ const replacePercentageRE = /%/g;
185
+ function injectQuery(url, importer, queryToInject) {
186
+ const { search, hash } = new URL(url.replace(replacePercentageRE, "%25"), importer);
187
+ return `${cleanUrl(url)}?${queryToInject}${search ? `&${search.slice(1)}` : ""}${hash ?? ""}`;
188
+ }
189
+ let __require;
190
+ function getBuiltinModule(moduleId) {
191
+ __require ??= module$1.createRequire(import.meta.url);
192
+ return __require(`${moduleId}?mock=actual`);
193
+ }
194
+ function genSourceMapUrl(map) {
195
+ if (typeof map !== "string") map = JSON.stringify(map);
196
+ return `data:application/json;base64,${Buffer.from(map).toString("base64")}`;
197
+ }
198
+ function transformCode(code, format, filename) {
199
+ if (format.includes("typescript")) {
200
+ if (!module$1.stripTypeScriptTypes) throw new Error(`Cannot parse '${filename}' because "module.stripTypeScriptTypes" is not supported. Module mocking requires Node.js 22.15 or higher. This is NOT a bug of Vitest.`);
201
+ return module$1.stripTypeScriptTypes(code);
202
+ }
203
+ return code;
204
+ }
205
+
206
+ export { NativeModuleMocker };
@@ -0,0 +1,36 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ import { r as resolveModule } from './index.BCY_7LL2.js';
3
+ import { resolve } from 'pathe';
4
+ import { ModuleRunner } from 'vite/module-runner';
5
+
6
+ class NativeModuleRunner extends ModuleRunner {
7
+ /**
8
+ * @internal
9
+ */
10
+ mocker;
11
+ constructor(root, mocker) {
12
+ super({
13
+ hmr: false,
14
+ sourcemapInterceptor: false,
15
+ transport: { invoke() {
16
+ throw new Error("Unexpected `invoke`");
17
+ } }
18
+ });
19
+ this.root = root;
20
+ this.mocker = mocker;
21
+ if (mocker) Object.defineProperty(globalThis, "__vitest_mocker__", {
22
+ configurable: true,
23
+ writable: true,
24
+ value: mocker
25
+ });
26
+ }
27
+ async import(moduleId) {
28
+ const path = resolveModule(moduleId, { paths: [this.root] }) ?? resolve(this.root, moduleId);
29
+ // resolveModule doesn't keep the query params, so we need to add them back
30
+ let queryParams = "";
31
+ if (moduleId.includes("?") && !path.includes("?")) queryParams = moduleId.slice(moduleId.indexOf("?"));
32
+ return import(pathToFileURL(path + queryParams).toString());
33
+ }
34
+ }
35
+
36
+ export { NativeModuleRunner as N };
@@ -1,5 +1,5 @@
1
1
  import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
2
- import { g as getWorkerState } from './utils.DvEY5TfP.js';
2
+ import { g as getWorkerState } from './utils.DT4VyRyl.js';
3
3
  import '@vitest/utils/timers';
4
4
 
5
5
  class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {
@@ -1,5 +1,5 @@
1
1
  import { DevEnvironment } from 'vite';
2
- import { V as Vitest, T as TestProject, b as TestProjectConfiguration } from './reporters.d.CWXNI2jG.js';
2
+ import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.7faYdkxy.js';
3
3
 
4
4
  /**
5
5
  * Generate a unique cache identifier.