vitest 4.0.6 → 4.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +2 -2
- package/dist/chunks/base.BgTO2qAg.js +156 -0
- package/dist/chunks/{benchmark.DHKMYAts.js → benchmark.B3N2zMcH.js} +9 -4
- package/dist/chunks/{browser.d.ScGeWTou.d.ts → browser.d.DTTM2PTh.d.ts} +1 -1
- package/dist/chunks/{cac.BBqWH4nd.js → cac.CfkWq8Qy.js} +117 -43
- package/dist/chunks/{cli-api.UL3SwFUb.js → cli-api.BQ-bjcRi.js} +1870 -847
- package/dist/chunks/console.Cf-YriPC.js +146 -0
- package/dist/chunks/{coverage.DuCn_Tmx.js → coverage.NVjCOln1.js} +281 -103
- package/dist/chunks/{creator.cqqifzG7.js → creator.fzVyoMf3.js} +74 -30
- package/dist/chunks/{date.-jtEtIeV.js → date.Bq6ZW5rf.js} +17 -6
- package/dist/chunks/{git.BFNcloKD.js → git.Bm2pzPAa.js} +3 -3
- package/dist/chunks/{global.d.DdOkMiVb.d.ts → global.d.DVdCfKp5.d.ts} +1 -1
- package/dist/chunks/{globals.BGT_RUsD.js → globals.DOh96BiR.js} +5 -5
- package/dist/chunks/{resolveSnapshotEnvironment.BZzLjzkh.js → index.BY4-tcno.js} +42 -25
- package/dist/chunks/{index.Bgo3tNWt.js → index.DAL392Ss.js} +40 -15
- package/dist/chunks/{index.RwjEGCQ0.js → index.DIFZf73e.js} +2 -2
- package/dist/chunks/{index.DV0mQLEO.js → index.DfKyPFVi.js} +195 -64
- package/dist/chunks/{index.BL8Hg4Uk.js → index.kotH7DY7.js} +837 -380
- package/dist/chunks/{index.CpdwpN7L.js → index.op2Re5rn.js} +22 -12
- package/dist/chunks/{init-forks.CSGFj9zN.js → init-forks.2hx7cf78.js} +16 -5
- package/dist/chunks/{init-threads.CIJLeFO8.js → init-threads.Cm4OCIWA.js} +3 -2
- package/dist/chunks/{init.DUeOfNO9.js → init.DMDG-idf.js} +124 -54
- package/dist/chunks/{inspector.DLZxSeU3.js → inspector.CvyFGlXm.js} +25 -10
- package/dist/chunks/{moduleRunner.d.TP-w6tIQ.d.ts → moduleRunner.d.CzOZ_4wC.d.ts} +1 -1
- package/dist/chunks/{node.BwAWWjHZ.js → node.Ce0vMQM7.js} +1 -1
- package/dist/chunks/{plugin.d.lctzD3Wk.d.ts → plugin.d.D4RrtywJ.d.ts} +1 -1
- package/dist/chunks/{reporters.d.PEs0tXod.d.ts → reporters.d.Da1D1VbQ.d.ts} +19 -9
- package/dist/chunks/rpc.BUV7uWKJ.js +76 -0
- package/dist/chunks/{setup-common.DR1sucx6.js → setup-common.LGjNSzXp.js} +20 -8
- package/dist/chunks/{startModuleRunner.Di-EZqh0.js → startModuleRunner.BOmUtLIO.js} +228 -105
- package/dist/chunks/{test.CnspO-X4.js → test.ClrAtjMv.js} +48 -22
- package/dist/chunks/{utils.CG9h5ccR.js → utils.DvEY5TfP.js} +14 -5
- package/dist/chunks/{vi.BZvkKVkM.js → vi.Bgcdy3bQ.js} +261 -111
- package/dist/chunks/{vm.Co_lR2NL.js → vm.BIkCDs68.js} +177 -70
- package/dist/chunks/{worker.d.B4Hthdvt.d.ts → worker.d.DadbA89M.d.ts} +52 -6
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +5 -5
- package/dist/coverage.d.ts +3 -3
- package/dist/coverage.js +1 -1
- package/dist/environments.js +2 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/module-evaluator.d.ts +2 -2
- package/dist/module-evaluator.js +85 -35
- package/dist/module-runner.js +2 -2
- package/dist/node.d.ts +7 -7
- package/dist/node.js +16 -12
- package/dist/reporters.d.ts +3 -3
- package/dist/reporters.js +2 -2
- package/dist/runners.js +7 -7
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.d.ts +2 -1
- package/dist/worker.js +27 -27
- package/dist/workers/forks.js +34 -31
- package/dist/workers/runVmTests.js +41 -22
- package/dist/workers/threads.js +34 -31
- package/dist/workers/vmForks.js +14 -14
- package/dist/workers/vmThreads.js +14 -14
- package/package.json +20 -20
- package/dist/chunks/base.BAf_bYeI.js +0 -128
- package/dist/chunks/console.CTJL2nuH.js +0 -115
- package/dist/chunks/rpc.Dv1Jt3i2.js +0 -66
|
@@ -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.kotH7DY7.js';
|
|
6
6
|
import { stripVTControlCharacters } from 'node:util';
|
|
7
7
|
import { notNullish } from '@vitest/utils/helpers';
|
|
8
8
|
|
|
@@ -98,16 +98,19 @@ function renderBenchmark(result, widths) {
|
|
|
98
98
|
].join(" ");
|
|
99
99
|
}
|
|
100
100
|
function renderTable(options) {
|
|
101
|
-
const output = []
|
|
101
|
+
const output = [];
|
|
102
|
+
const benchMap = {};
|
|
102
103
|
for (const task of options.tasks) if (task.meta.benchmark && task.result?.benchmark) benchMap[task.id] = {
|
|
103
104
|
current: task.result.benchmark,
|
|
104
105
|
baseline: options.compare?.[task.id]
|
|
105
106
|
};
|
|
106
|
-
const benchCount = Object.entries(benchMap).length
|
|
107
|
+
const benchCount = Object.entries(benchMap).length;
|
|
108
|
+
const columnWidths = computeColumnWidths(Object.values(benchMap).flatMap((v) => [v.current, v.baseline]).filter(notNullish));
|
|
107
109
|
let idx = 0;
|
|
108
110
|
const padding = " ".repeat(1 );
|
|
109
111
|
for (const task of options.tasks) {
|
|
110
|
-
const duration = task.result?.duration
|
|
112
|
+
const duration = task.result?.duration;
|
|
113
|
+
const bench = benchMap[task.id];
|
|
111
114
|
let prefix = "";
|
|
112
115
|
if (idx === 0 && task.meta?.benchmark) prefix += `${renderTableHead(columnWidths)}\n${padding}`;
|
|
113
116
|
prefix += ` ${getStateSymbol(task)} `;
|
|
@@ -123,7 +126,8 @@ function renderTable(options) {
|
|
|
123
126
|
let body = renderBenchmark(bench.current, columnWidths);
|
|
124
127
|
if (options.compare && bench.baseline) {
|
|
125
128
|
if (bench.current.hz) {
|
|
126
|
-
const diff = bench.current.hz / bench.baseline.hz
|
|
129
|
+
const diff = bench.current.hz / bench.baseline.hz;
|
|
130
|
+
const diffFixed = diff.toFixed(2);
|
|
127
131
|
if (diffFixed === "1.0.0") body += c.gray(` [${diffFixed}x]`);
|
|
128
132
|
if (diff > 1) body += c.blue(` [${diffFixed}x] ⇑`);
|
|
129
133
|
else body += c.red(` [${diffFixed}x] ⇓`);
|
|
@@ -140,7 +144,8 @@ function renderTable(options) {
|
|
|
140
144
|
if (task.result?.state !== "pass" && outputMap.get(task) != null) {
|
|
141
145
|
let data = outputMap.get(task);
|
|
142
146
|
if (typeof data === "string") {
|
|
143
|
-
|
|
147
|
+
data = stripVTControlCharacters(data.trim().split("\n").filter(Boolean).pop());
|
|
148
|
+
if (data === "") data = void 0;
|
|
144
149
|
}
|
|
145
150
|
if (data != null) {
|
|
146
151
|
const out = ` ${" ".repeat(options.level)}${F_RIGHT} ${data}`;
|
|
@@ -155,7 +160,8 @@ function renderTable(options) {
|
|
|
155
160
|
class BenchmarkReporter extends DefaultReporter {
|
|
156
161
|
compare;
|
|
157
162
|
async onInit(ctx) {
|
|
158
|
-
|
|
163
|
+
super.onInit(ctx);
|
|
164
|
+
if (this.ctx.config.benchmark?.compare) {
|
|
159
165
|
const compareFile = pathe.resolve(this.ctx.config.root, this.ctx.config.benchmark?.compare);
|
|
160
166
|
try {
|
|
161
167
|
this.compare = flattenFormattedBenchmarkReport(JSON.parse(await fs.promises.readFile(compareFile, "utf-8")));
|
|
@@ -173,7 +179,8 @@ class BenchmarkReporter extends DefaultReporter {
|
|
|
173
179
|
}
|
|
174
180
|
}
|
|
175
181
|
onTestSuiteResult(testSuite) {
|
|
176
|
-
super.onTestSuiteResult(testSuite)
|
|
182
|
+
super.onTestSuiteResult(testSuite);
|
|
183
|
+
this.printSuiteTable(testSuite);
|
|
177
184
|
}
|
|
178
185
|
printTestModule(testModule) {
|
|
179
186
|
this.printSuiteTable(testModule);
|
|
@@ -181,11 +188,13 @@ class BenchmarkReporter extends DefaultReporter {
|
|
|
181
188
|
printSuiteTable(testTask) {
|
|
182
189
|
const state = testTask.state();
|
|
183
190
|
if (state === "pending" || state === "queued") return;
|
|
184
|
-
const benches = testTask.task.tasks.filter((t) => t.meta.benchmark)
|
|
191
|
+
const benches = testTask.task.tasks.filter((t) => t.meta.benchmark);
|
|
192
|
+
const duration = testTask.task.result?.duration || 0;
|
|
185
193
|
if (benches.length > 0 && benches.every((t) => t.result?.state !== "run" && t.result?.state !== "queued")) {
|
|
186
194
|
let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, separator)}`;
|
|
187
195
|
if (duration != null && duration > this.ctx.config.slowTestThreshold) title += c.yellow(` ${Math.round(duration)}${c.dim("ms")}`);
|
|
188
|
-
this.log(title)
|
|
196
|
+
this.log(title);
|
|
197
|
+
this.log(renderTable({
|
|
189
198
|
tasks: benches,
|
|
190
199
|
level: 1,
|
|
191
200
|
columns: this.ctx.logger.getColumns(),
|
|
@@ -203,8 +212,9 @@ class BenchmarkReporter extends DefaultReporter {
|
|
|
203
212
|
outputFile = pathe.resolve(this.ctx.config.root, outputFile);
|
|
204
213
|
const outputDirectory = pathe.dirname(outputFile);
|
|
205
214
|
if (!fs.existsSync(outputDirectory)) await fs.promises.mkdir(outputDirectory, { recursive: true });
|
|
206
|
-
const
|
|
207
|
-
await fs.promises.writeFile(outputFile, JSON.stringify(output, null, 2))
|
|
215
|
+
const output = createBenchmarkJsonReport(testModules.map((t) => t.task.file));
|
|
216
|
+
await fs.promises.writeFile(outputFile, JSON.stringify(output, null, 2));
|
|
217
|
+
this.log(`Benchmark report written to ${outputFile}`);
|
|
208
218
|
}
|
|
209
219
|
}
|
|
210
220
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import v8 from 'node:v8';
|
|
2
|
-
import { i as init } from './init.
|
|
2
|
+
import { i as init } from './init.DMDG-idf.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
|
|
6
|
-
const processExit = process.exit.bind(process)
|
|
6
|
+
const processExit = process.exit.bind(process);
|
|
7
|
+
const processSend = process.send.bind(process);
|
|
8
|
+
const processOn = process.on.bind(process);
|
|
9
|
+
const processOff = process.off.bind(process);
|
|
10
|
+
const processRemoveAllListeners = process.removeAllListeners.bind(process);
|
|
7
11
|
// Work-around for nodejs/node#55094
|
|
8
12
|
if (process.execArgv.some((execArg) => execArg.startsWith("--prof") || execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"))) processOn("SIGTERM", () => processExit());
|
|
9
13
|
function workerInit(options) {
|
|
@@ -16,7 +20,8 @@ function workerInit(options) {
|
|
|
16
20
|
serialize: v8.serialize,
|
|
17
21
|
deserialize: (v) => v8.deserialize(Buffer.from(v)),
|
|
18
22
|
runTests: (state) => executeTests("run", state),
|
|
19
|
-
collectTests: (state) => executeTests("collect", state)
|
|
23
|
+
collectTests: (state) => executeTests("collect", state),
|
|
24
|
+
setup: options.setup
|
|
20
25
|
});
|
|
21
26
|
async function executeTests(method, state) {
|
|
22
27
|
state.ctx.config = unwrapSerializableConfig(state.ctx.config);
|
|
@@ -36,7 +41,8 @@ function unwrapSerializableConfig(config) {
|
|
|
36
41
|
if (testNamePattern.startsWith("$$vitest:")) config.testNamePattern = parseRegexp(testNamePattern.slice(9));
|
|
37
42
|
}
|
|
38
43
|
if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
|
|
39
|
-
const { keys, original } = config.defines
|
|
44
|
+
const { keys, original } = config.defines;
|
|
45
|
+
const defines = {};
|
|
40
46
|
// Apply all keys from the original. Entries which had undefined value are missing from original now
|
|
41
47
|
for (const key of keys) defines[key] = original[key];
|
|
42
48
|
config.defines = defines;
|
|
@@ -47,8 +53,13 @@ function parseRegexp(input) {
|
|
|
47
53
|
// Parse input
|
|
48
54
|
// eslint-disable-next-line regexp/no-misleading-capturing-group
|
|
49
55
|
const m = input.match(/(\/?)(.+)\1([a-z]*)/i);
|
|
56
|
+
// match nothing
|
|
57
|
+
if (!m) return /$^/;
|
|
58
|
+
// Invalid flags
|
|
59
|
+
// eslint-disable-next-line regexp/optimal-quantifier-concatenation
|
|
60
|
+
if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) return new RegExp(input);
|
|
50
61
|
// Create the regular expression
|
|
51
|
-
return
|
|
62
|
+
return new RegExp(m[2], m[3]);
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
export { workerInit as w };
|
|
@@ -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.DMDG-idf.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,20 +1,21 @@
|
|
|
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.
|
|
9
|
-
import { e as environments } from './index.
|
|
10
|
-
import {
|
|
6
|
+
import { b as VitestTransport } from './startModuleRunner.BOmUtLIO.js';
|
|
7
|
+
import { e as environments } from './index.DfKyPFVi.js';
|
|
8
|
+
import { serializeError } from '@vitest/utils/error';
|
|
9
|
+
import { o as onCancel, a as rpcDone, c as createRuntimeRpc } from './rpc.BUV7uWKJ.js';
|
|
10
|
+
import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
|
|
11
|
+
import { s as setupInspect } from './inspector.CvyFGlXm.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;
|
|
16
16
|
}
|
|
17
|
-
const isWindows = process.platform === "win32"
|
|
17
|
+
const isWindows = process.platform === "win32";
|
|
18
|
+
const _loaders = /* @__PURE__ */ new Map();
|
|
18
19
|
async function createEnvironmentLoader(root, rpc) {
|
|
19
20
|
const cachedLoader = _loaders.get(root);
|
|
20
21
|
if (!cachedLoader || cachedLoader.isClosed()) {
|
|
@@ -40,32 +41,37 @@ async function createEnvironmentLoader(root, rpc) {
|
|
|
40
41
|
}
|
|
41
42
|
})
|
|
42
43
|
});
|
|
43
|
-
_loaders.set(root, moduleRunner)
|
|
44
|
+
_loaders.set(root, moduleRunner);
|
|
45
|
+
await moduleRunner.import("/@vite/env");
|
|
44
46
|
}
|
|
45
47
|
return _loaders.get(root);
|
|
46
48
|
}
|
|
47
|
-
async function loadEnvironment(
|
|
48
|
-
const name = ctx.environment.name;
|
|
49
|
+
async function loadEnvironment(name, root, rpc) {
|
|
49
50
|
if (isBuiltinEnvironment(name)) return { environment: environments[name] };
|
|
50
|
-
const
|
|
51
|
+
const loader = await createEnvironmentLoader(root, rpc);
|
|
52
|
+
const packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__"))?.id ?? resolve(root, name);
|
|
53
|
+
const pkg = await loader.import(packageId);
|
|
51
54
|
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
55
|
const environment = pkg.default;
|
|
53
56
|
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}".`);
|
|
54
|
-
if (environment.transformMode)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
if (environment.transformMode) {
|
|
58
|
+
console.warn(`The Vitest environment ${environment.name} defines the "transformMode". This options was deprecated in Vitest 4 and will be removed in the next major version. Please, use "viteEnvironment" instead.`);
|
|
59
|
+
// keep for backwards compat
|
|
60
|
+
environment.viteEnvironment ??= environment.transformMode === "ssr" ? "ssr" : "client";
|
|
61
|
+
}
|
|
57
62
|
return {
|
|
58
63
|
environment,
|
|
59
64
|
loader
|
|
60
65
|
};
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
const resolvingModules = /* @__PURE__ */ new Set()
|
|
68
|
+
const resolvingModules = /* @__PURE__ */ new Set();
|
|
69
|
+
const globalListeners = /* @__PURE__ */ new Set();
|
|
64
70
|
async function execute(method, ctx, worker) {
|
|
65
|
-
const prepareStart = performance.now()
|
|
66
|
-
|
|
71
|
+
const prepareStart = performance.now();
|
|
72
|
+
const cleanups = [setupInspect(ctx)];
|
|
67
73
|
// 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
|
|
74
|
+
const rpc = ctx.rpc;
|
|
69
75
|
try {
|
|
70
76
|
// do not close the RPC channel so that we can get the error messages sent to the main thread
|
|
71
77
|
cleanups.push(async () => {
|
|
@@ -73,32 +79,32 @@ async function execute(method, ctx, worker) {
|
|
|
73
79
|
reject(/* @__PURE__ */ new Error(`[vitest-worker]: Closing rpc while "${method}" was pending`));
|
|
74
80
|
}));
|
|
75
81
|
});
|
|
76
|
-
const beforeEnvironmentTime = performance.now(), { environment, loader } = await loadEnvironment(ctx, rpc);
|
|
77
|
-
environmentLoader = loader;
|
|
78
82
|
const state = {
|
|
79
83
|
ctx,
|
|
80
84
|
evaluatedModules: new VitestEvaluatedModules(),
|
|
81
85
|
resolvingModules,
|
|
82
86
|
moduleExecutionInfo: /* @__PURE__ */ new Map(),
|
|
83
87
|
config: ctx.config,
|
|
84
|
-
|
|
85
|
-
environment,
|
|
88
|
+
environment: null,
|
|
86
89
|
durations: {
|
|
87
|
-
environment:
|
|
90
|
+
environment: 0,
|
|
88
91
|
prepare: prepareStart
|
|
89
92
|
},
|
|
90
93
|
rpc,
|
|
94
|
+
onCancel,
|
|
91
95
|
onCleanup: (listener) => globalListeners.add(listener),
|
|
92
96
|
providedContext: ctx.providedContext,
|
|
93
97
|
onFilterStackTrace(stack) {
|
|
94
98
|
return createStackString(parseStacktrace(stack));
|
|
95
99
|
},
|
|
96
100
|
metaEnv: createImportMetaEnvProxy()
|
|
97
|
-
}
|
|
101
|
+
};
|
|
102
|
+
const methodName = method === "collect" ? "collectTests" : "runTests";
|
|
98
103
|
if (!worker[methodName] || typeof worker[methodName] !== "function") throw new TypeError(`Test worker should expose "runTests" method. Received "${typeof worker.runTests}".`);
|
|
99
104
|
await worker[methodName](state);
|
|
100
105
|
} finally {
|
|
101
|
-
await rpcDone().catch(() => {})
|
|
106
|
+
await rpcDone().catch(() => {});
|
|
107
|
+
await Promise.all(cleanups.map((fn) => fn())).catch(() => {});
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
function run(ctx, worker) {
|
|
@@ -110,6 +116,7 @@ function collect(ctx, worker) {
|
|
|
110
116
|
async function teardown() {
|
|
111
117
|
await Promise.all([...globalListeners].map((l) => l()));
|
|
112
118
|
}
|
|
119
|
+
const env = process.env;
|
|
113
120
|
function createImportMetaEnvProxy() {
|
|
114
121
|
// packages/vitest/src/node/plugins/index.ts:146
|
|
115
122
|
const booleanKeys = [
|
|
@@ -117,9 +124,11 @@ function createImportMetaEnvProxy() {
|
|
|
117
124
|
"PROD",
|
|
118
125
|
"SSR"
|
|
119
126
|
];
|
|
120
|
-
return new Proxy(
|
|
127
|
+
return new Proxy(env, {
|
|
121
128
|
get(_, key) {
|
|
122
|
-
if (typeof key
|
|
129
|
+
if (typeof key !== "string") return;
|
|
130
|
+
if (booleanKeys.includes(key)) return !!process.env[key];
|
|
131
|
+
return process.env[key];
|
|
123
132
|
},
|
|
124
133
|
set(_, key, value) {
|
|
125
134
|
if (typeof key !== "string") return true;
|
|
@@ -130,24 +139,48 @@ function createImportMetaEnvProxy() {
|
|
|
130
139
|
});
|
|
131
140
|
}
|
|
132
141
|
|
|
133
|
-
const __vitest_worker_response__ = true
|
|
142
|
+
const __vitest_worker_response__ = true;
|
|
143
|
+
const memoryUsage = process.memoryUsage.bind(process);
|
|
134
144
|
let reportMemory = false;
|
|
135
145
|
/** @experimental */
|
|
136
146
|
function init(worker) {
|
|
137
147
|
worker.on(onMessage);
|
|
138
|
-
let runPromise
|
|
148
|
+
let runPromise;
|
|
149
|
+
let isRunning = false;
|
|
150
|
+
let workerTeardown;
|
|
151
|
+
let setupContext;
|
|
139
152
|
function send(response) {
|
|
140
153
|
worker.post(worker.serialize ? worker.serialize(response) : response);
|
|
141
154
|
}
|
|
142
155
|
async function onMessage(rawMessage) {
|
|
143
156
|
const message = worker.deserialize ? worker.deserialize(rawMessage) : rawMessage;
|
|
144
|
-
if (message?.__vitest_worker_request__
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
157
|
+
if (message?.__vitest_worker_request__ !== true) return;
|
|
158
|
+
switch (message.type) {
|
|
159
|
+
case "start": {
|
|
160
|
+
reportMemory = message.options.reportMemory;
|
|
161
|
+
const { environment, config, pool } = message.context;
|
|
162
|
+
try {
|
|
163
|
+
setupContext = {
|
|
164
|
+
environment,
|
|
165
|
+
config,
|
|
166
|
+
pool,
|
|
167
|
+
rpc: createRuntimeRpc(worker),
|
|
168
|
+
projectName: config.name || ""
|
|
169
|
+
};
|
|
170
|
+
workerTeardown = await worker.setup?.(setupContext);
|
|
171
|
+
send({
|
|
172
|
+
type: "started",
|
|
173
|
+
__vitest_worker_response__
|
|
174
|
+
});
|
|
175
|
+
} catch (error) {
|
|
176
|
+
send({
|
|
177
|
+
type: "started",
|
|
178
|
+
__vitest_worker_response__,
|
|
179
|
+
error: serializeError(error)
|
|
180
|
+
});
|
|
181
|
+
}
|
|
150
182
|
break;
|
|
183
|
+
}
|
|
151
184
|
case "run":
|
|
152
185
|
// Prevent concurrent execution if worker is already running
|
|
153
186
|
if (isRunning) {
|
|
@@ -158,18 +191,32 @@ function init(worker) {
|
|
|
158
191
|
});
|
|
159
192
|
return;
|
|
160
193
|
}
|
|
161
|
-
isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
162
194
|
try {
|
|
163
|
-
|
|
164
|
-
|
|
195
|
+
process.env.VITEST_POOL_ID = String(message.poolId);
|
|
196
|
+
process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
return send({
|
|
199
|
+
type: "testfileFinished",
|
|
200
|
+
__vitest_worker_response__,
|
|
201
|
+
error: serializeError(error),
|
|
202
|
+
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
isRunning = true;
|
|
206
|
+
try {
|
|
207
|
+
runPromise = run({
|
|
208
|
+
...setupContext,
|
|
209
|
+
...message.context
|
|
210
|
+
}, worker).catch((error) => serializeError(error));
|
|
165
211
|
send({
|
|
166
212
|
type: "testfileFinished",
|
|
167
213
|
__vitest_worker_response__,
|
|
168
|
-
error,
|
|
214
|
+
error: await runPromise,
|
|
169
215
|
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
170
216
|
});
|
|
171
217
|
} finally {
|
|
172
|
-
runPromise = void 0
|
|
218
|
+
runPromise = void 0;
|
|
219
|
+
isRunning = false;
|
|
173
220
|
}
|
|
174
221
|
break;
|
|
175
222
|
case "collect":
|
|
@@ -182,32 +229,55 @@ function init(worker) {
|
|
|
182
229
|
});
|
|
183
230
|
return;
|
|
184
231
|
}
|
|
185
|
-
isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
186
232
|
try {
|
|
187
|
-
|
|
188
|
-
|
|
233
|
+
process.env.VITEST_POOL_ID = String(message.poolId);
|
|
234
|
+
process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
return send({
|
|
237
|
+
type: "testfileFinished",
|
|
238
|
+
__vitest_worker_response__,
|
|
239
|
+
error: serializeError(error),
|
|
240
|
+
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
isRunning = true;
|
|
244
|
+
try {
|
|
245
|
+
runPromise = collect({
|
|
246
|
+
...setupContext,
|
|
247
|
+
...message.context
|
|
248
|
+
}, worker).catch((error) => serializeError(error));
|
|
189
249
|
send({
|
|
190
250
|
type: "testfileFinished",
|
|
191
251
|
__vitest_worker_response__,
|
|
192
|
-
error,
|
|
252
|
+
error: await runPromise,
|
|
193
253
|
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
194
254
|
});
|
|
195
255
|
} finally {
|
|
196
|
-
runPromise = void 0
|
|
256
|
+
runPromise = void 0;
|
|
257
|
+
isRunning = false;
|
|
197
258
|
}
|
|
198
259
|
break;
|
|
199
|
-
case "stop":
|
|
260
|
+
case "stop":
|
|
200
261
|
await runPromise;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
262
|
+
try {
|
|
263
|
+
const error = await teardown().catch((error) => serializeError(error));
|
|
264
|
+
await workerTeardown?.();
|
|
265
|
+
send({
|
|
266
|
+
type: "stopped",
|
|
267
|
+
error,
|
|
268
|
+
__vitest_worker_response__
|
|
269
|
+
});
|
|
270
|
+
} catch (error) {
|
|
271
|
+
send({
|
|
272
|
+
type: "stopped",
|
|
273
|
+
error: serializeError(error),
|
|
274
|
+
__vitest_worker_response__
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
worker.teardown?.();
|
|
207
278
|
break;
|
|
208
|
-
}
|
|
209
279
|
}
|
|
210
280
|
}
|
|
211
281
|
}
|
|
212
282
|
|
|
213
|
-
export { init as i };
|
|
283
|
+
export { init as i, loadEnvironment as l };
|
|
@@ -2,33 +2,48 @@ import { createRequire } from 'node:module';
|
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
3
|
|
|
4
4
|
const __require = createRequire(import.meta.url);
|
|
5
|
-
let inspector
|
|
5
|
+
let inspector;
|
|
6
|
+
let session;
|
|
6
7
|
/**
|
|
7
8
|
* Enables debugging inside `worker_threads` and `child_process`.
|
|
8
9
|
* Should be called as early as possible when worker/process has been set up.
|
|
9
10
|
*/
|
|
10
11
|
function setupInspect(ctx) {
|
|
11
|
-
const config = ctx.config
|
|
12
|
+
const config = ctx.config;
|
|
13
|
+
const isEnabled = config.inspector.enabled;
|
|
12
14
|
if (isEnabled) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
inspector = __require("node:inspector");
|
|
16
|
+
if (!(inspector.url() !== void 0)) {
|
|
17
|
+
inspector.open(config.inspector.port, config.inspector.host, config.inspector.waitForDebugger);
|
|
18
|
+
if (config.inspectBrk) {
|
|
15
19
|
const firstTestFile = typeof ctx.files[0] === "string" ? ctx.files[0] : ctx.files[0].filepath;
|
|
16
20
|
// Stop at first test file
|
|
17
|
-
if (firstTestFile)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
if (firstTestFile) {
|
|
22
|
+
session = new inspector.Session();
|
|
23
|
+
session.connect();
|
|
24
|
+
session.post("Debugger.enable");
|
|
25
|
+
session.post("Debugger.setBreakpointByUrl", {
|
|
26
|
+
lineNumber: 0,
|
|
27
|
+
url: pathToFileURL(firstTestFile)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
21
30
|
}
|
|
22
31
|
}
|
|
23
32
|
}
|
|
24
33
|
const keepOpen = shouldKeepOpen(config);
|
|
25
34
|
return function cleanup() {
|
|
26
|
-
if (isEnabled && !keepOpen && inspector)
|
|
35
|
+
if (isEnabled && !keepOpen && inspector) {
|
|
36
|
+
inspector.close();
|
|
37
|
+
session?.disconnect();
|
|
38
|
+
}
|
|
27
39
|
};
|
|
28
40
|
}
|
|
29
41
|
function closeInspector(config) {
|
|
30
42
|
const keepOpen = shouldKeepOpen(config);
|
|
31
|
-
if (inspector && !keepOpen)
|
|
43
|
+
if (inspector && !keepOpen) {
|
|
44
|
+
inspector.close();
|
|
45
|
+
session?.disconnect();
|
|
46
|
+
}
|
|
32
47
|
}
|
|
33
48
|
function shouldKeepOpen(config) {
|
|
34
49
|
// In watch mode the inspector can persist re-runs if isolation is disabled and a single worker is used
|
|
@@ -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,
|
|
5
|
+
import { R as RuntimeRPC, e as ResolveFunctionResult, W as WorkerGlobalState } from './worker.d.DadbA89M.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,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.DvEY5TfP.js';
|
|
3
3
|
import '@vitest/utils/timers';
|
|
4
4
|
|
|
5
5
|
class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {
|
|
@@ -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,
|
|
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.DadbA89M.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.
|
|
10
|
+
import { S as SerializedTestSpecification, B as BrowserTesterOptions } from './browser.d.DTTM2PTh.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
|
/**
|
|
@@ -1533,7 +1535,7 @@ interface BrowserConfigOptions {
|
|
|
1533
1535
|
/**
|
|
1534
1536
|
* Commands that will be executed on the server
|
|
1535
1537
|
* via the browser `import("vitest/browser").commands` API.
|
|
1536
|
-
* @see {@link https://vitest.dev/
|
|
1538
|
+
* @see {@link https://vitest.dev/api/browser/commands}
|
|
1537
1539
|
*/
|
|
1538
1540
|
commands?: Record<string, BrowserCommand<any>>;
|
|
1539
1541
|
/**
|
|
@@ -1694,7 +1696,7 @@ type ToMatchScreenshotResolvePath = (data: {
|
|
|
1694
1696
|
platform: NodeJS.Platform;
|
|
1695
1697
|
/**
|
|
1696
1698
|
* The value provided to
|
|
1697
|
-
* {@linkcode https://vitest.dev/
|
|
1699
|
+
* {@linkcode https://vitest.dev/config/browser/screenshotdirectory|browser.screenshotDirectory},
|
|
1698
1700
|
* if none is provided, its default value.
|
|
1699
1701
|
*/
|
|
1700
1702
|
screenshotDirectory: string;
|
|
@@ -1866,7 +1868,7 @@ interface PoolOptions {
|
|
|
1866
1868
|
project: TestProject;
|
|
1867
1869
|
method: "run" | "collect";
|
|
1868
1870
|
cacheFs?: boolean;
|
|
1869
|
-
environment:
|
|
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:
|
|
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:
|
|
1926
|
+
context: WorkerExecuteContext;
|
|
1919
1927
|
poolId: number;
|
|
1920
1928
|
} | {
|
|
1921
1929
|
type: "collect";
|
|
1922
|
-
context:
|
|
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;
|
|
@@ -2443,9 +2452,10 @@ interface InlineConfig {
|
|
|
2443
2452
|
*/
|
|
2444
2453
|
benchmark?: BenchmarkUserOptions;
|
|
2445
2454
|
/**
|
|
2446
|
-
*
|
|
2455
|
+
* A list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that match your test files.
|
|
2447
2456
|
*
|
|
2448
2457
|
* @default ['**\/*.{test,spec}.?(c|m)[jt]s?(x)']
|
|
2458
|
+
* @see {@link https://vitest.dev/config/include}
|
|
2449
2459
|
*/
|
|
2450
2460
|
include?: string[];
|
|
2451
2461
|
/**
|