vitest 4.1.0-beta.1 → 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.
- package/LICENSE.md +36 -0
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -2
- package/dist/chunks/acorn.B2iPLyUM.js +5958 -0
- package/dist/chunks/{base.CBRNZa3k.js → base.DiopZV8F.js} +48 -14
- package/dist/chunks/{benchmark.B3N2zMcH.js → benchmark.BoqSLF53.js} +1 -1
- package/dist/chunks/{browser.d.8hOapKZr.d.ts → browser.d.BE4kbYok.d.ts} +2 -1
- package/dist/chunks/{cac.B1v3xxoC.js → cac.C4jjt2RX.js} +797 -13
- package/dist/chunks/{cli-api.B4CqEpI6.js → cli-api.ChbI1JU9.js} +322 -124
- package/dist/chunks/{config.d.idH22YSr.d.ts → config.d.Cr1Ep39N.d.ts} +6 -1
- package/dist/chunks/{console.uGgdMhyZ.js → console.CNlG1KsP.js} +2 -2
- package/dist/chunks/{constants.D_Q9UYh-.js → constants.B63TT-Bl.js} +1 -1
- package/dist/chunks/coverage.tyqbzn4W.js +1001 -0
- package/dist/chunks/{creator.C7WwjkuR.js → creator.yyCHuw5R.js} +1 -1
- package/dist/chunks/{global.d.B15mdLcR.d.ts → global.d.JeWMqlOm.d.ts} +1 -1
- package/dist/chunks/{globals.DjuGMoMc.js → globals.C6Ecf1TO.js} +6 -6
- package/dist/chunks/{index.Dm4xqZ0s.js → index.B-iBE_Gx.js} +20 -4
- package/dist/chunks/{coverage.BMlOMIWl.js → index.BCY_7LL2.js} +5 -969
- package/dist/chunks/{index.BiOAd_ki.js → index.CAN630q3.js} +7 -7
- package/dist/chunks/{index.DyBZXrH3.js → index.CFulQRmC.js} +1 -1
- package/dist/chunks/{index.BEFi2-_3.js → index.CouFDptX.js} +2 -2
- package/dist/chunks/{init-forks.CHeQ9Moq.js → init-forks.BnCXPazU.js} +1 -1
- package/dist/chunks/{init-threads.uZiNAuPk.js → init-threads.Cyh2PqXi.js} +1 -1
- package/dist/chunks/{init.DVtKdFty.js → init.B95Mm0Iz.js} +47 -9
- package/dist/chunks/native.mV0-490A.js +148 -0
- package/dist/chunks/nativeModuleMocker.D_q5sFv6.js +206 -0
- package/dist/chunks/nativeModuleRunner.BIakptoF.js +36 -0
- package/dist/chunks/{node.Ce0vMQM7.js → node.CrSEwhm4.js} +1 -1
- package/dist/chunks/{plugin.d.D8KU2PY_.d.ts → plugin.d.C9o5bttz.d.ts} +1 -1
- package/dist/chunks/{reporters.d.Db3MiIWX.d.ts → reporters.d.7faYdkxy.d.ts} +120 -51
- package/dist/chunks/{rpc.HLmECnw_.js → rpc.DcRWTy5G.js} +1 -1
- package/dist/chunks/{rpc.d.RH3apGEf.d.ts → rpc.d.CM7x9-sm.d.ts} +1 -0
- package/dist/chunks/{setup-common.BcqLPsn5.js → setup-common.cvFp-ao9.js} +2 -2
- package/dist/chunks/{startModuleRunner.C5CcWyXW.js → startVitestModuleRunner.BK-u7y4N.js} +163 -372
- package/dist/chunks/{test.prxIahgM.js → test.G82XYNFk.js} +9 -4
- package/dist/chunks/{utils.DvEY5TfP.js → utils.DT4VyRyl.js} +5 -1
- package/dist/chunks/{vm.CrifS09m.js → vm.BdLtzhnj.js} +13 -6
- package/dist/chunks/{worker.d.Bji1eq5g.d.ts → worker.d.CPzI2ZzJ.d.ts} +2 -2
- package/dist/cli.js +4 -3
- package/dist/config.d.ts +8 -8
- package/dist/config.js +1 -1
- package/dist/coverage.d.ts +7 -5
- package/dist/coverage.js +5 -4
- package/dist/index.d.ts +18 -23
- package/dist/index.js +5 -5
- package/dist/module-evaluator.d.ts +10 -1
- package/dist/node.d.ts +9 -9
- package/dist/node.js +18 -16
- package/dist/nodejs-worker-loader.js +41 -0
- package/dist/reporters.d.ts +5 -5
- package/dist/reporters.js +2 -2
- package/dist/runners.d.ts +2 -1
- package/dist/runners.js +4 -4
- package/dist/runtime.js +4 -5
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.d.ts +6 -6
- package/dist/worker.js +25 -18
- package/dist/workers/forks.js +21 -14
- package/dist/workers/runVmTests.js +7 -7
- package/dist/workers/threads.js +21 -14
- package/dist/workers/vmForks.js +14 -10
- package/dist/workers/vmThreads.js +14 -10
- package/package.json +17 -14
- package/suppress-warnings.cjs +1 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { chai } from '@vitest/expect';
|
|
2
|
-
import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.
|
|
3
|
-
import { r as rpc } from './rpc.
|
|
4
|
-
import { g as getWorkerState } from './utils.
|
|
5
|
-
import { T as TestRunner, N as NodeBenchmarkRunner } from './test.
|
|
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,
|
|
11
|
+
async function resolveSnapshotEnvironment(config, moduleRunner) {
|
|
12
12
|
if (!config.snapshotEnvironment) {
|
|
13
|
-
const { VitestNodeSnapshotEnvironment } = await import('./node.
|
|
13
|
+
const { VitestNodeSnapshotEnvironment } = await import('./node.CrSEwhm4.js');
|
|
14
14
|
return new VitestNodeSnapshotEnvironment();
|
|
15
15
|
}
|
|
16
|
-
const mod = await
|
|
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
|
}
|
|
@@ -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.
|
|
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 { 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.
|
|
2
|
-
import { b as bench } from './benchmark.
|
|
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';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isMainThread, parentPort } from 'node:worker_threads';
|
|
2
|
-
import { i as init } from './init.
|
|
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 './
|
|
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.
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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,8 +60,15 @@ 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
|
}
|
|
@@ -80,6 +88,36 @@ function emitModuleRunner(moduleRunner) {
|
|
|
80
88
|
moduleRunnerListeners.forEach((l) => l(moduleRunner));
|
|
81
89
|
}
|
|
82
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
|
+
|
|
83
121
|
const resolvingModules = /* @__PURE__ */ new Set();
|
|
84
122
|
async function execute(method, ctx, worker, traces) {
|
|
85
123
|
const prepareStart = performance.now();
|
|
@@ -331,4 +369,4 @@ function getFilesWithLocations(files) {
|
|
|
331
369
|
});
|
|
332
370
|
}
|
|
333
371
|
|
|
334
|
-
export { emitModuleRunner as e, 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.
|
|
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, a as TestProjectConfiguration } from './reporters.d.
|
|
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.
|