vitest 4.0.0-beta.9 → 4.0.1
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 +86 -102
- package/browser/context.d.ts +7 -0
- package/browser/context.js +20 -0
- package/dist/browser.d.ts +24 -7
- package/dist/browser.js +15 -5
- package/dist/chunks/{base.CA5N8Af0.js → base.BYPMk0VN.js} +36 -36
- package/dist/chunks/{benchmark.CJUa-Hsa.js → benchmark.DHKMYAts.js} +2 -2
- package/dist/chunks/{browser.d.DtfyY9yS.d.ts → browser.d.B9iJzZyn.d.ts} +3 -3
- package/dist/chunks/{cac.Dt7e1TIu.js → cac.DrF4Gm0S.js} +47 -73
- package/dist/chunks/{cli-api.eAzsLIxz.js → cli-api.W2Q-JQoO.js} +1524 -296
- package/dist/chunks/{config.d.DacWrqWe.d.ts → config.d.u2CUDWwS.d.ts} +5 -19
- package/dist/chunks/{console.7h5kHUIf.js → console.CTJL2nuH.js} +4 -6
- package/dist/chunks/{coverage.CDRAMTt7.js → coverage.FU3w4IrQ.js} +125 -1108
- package/dist/chunks/{creator.KEg6n5IC.js → creator.DucAaYBz.js} +10 -37
- package/dist/chunks/{defaults.CXFFjsi8.js → defaults.BOqNVLsY.js} +0 -1
- package/dist/chunks/environment.d.CrsxCzP1.d.ts +29 -0
- package/dist/chunks/evaluatedModules.Dg1zASAC.js +17 -0
- package/dist/chunks/{global.d.K6uBQHzY.d.ts → global.d.BgJSTpgQ.d.ts} +2 -17
- package/dist/chunks/{globals.CJrTTbxC.js → globals.BGT_RUsD.js} +11 -7
- package/dist/chunks/{index.BjKEiSn0.js → index.BdSLhLDZ.js} +3 -3
- package/dist/chunks/{index.DfviD7lX.js → index.CbWINfS7.js} +49 -21
- package/dist/chunks/{index.BIP7prJq.js → index.CcRZ6fUh.js} +1493 -114
- package/dist/chunks/{index.X0nbfr6-.js → index.Dc3xnDvT.js} +48 -289
- package/dist/chunks/{index.C832ioot.js → index.RwjEGCQ0.js} +4 -4
- package/dist/chunks/init-forks.WglB-sfY.js +54 -0
- package/dist/chunks/init-threads.Czek6eA5.js +17 -0
- package/dist/chunks/init.94FWN9pW.js +213 -0
- package/dist/chunks/{inspector.CvQD-Nie.js → inspector.DLZxSeU3.js} +2 -6
- package/dist/chunks/{moduleRunner.d.DxTLreRD.d.ts → moduleRunner.d.YtNsMIoJ.d.ts} +9 -14
- package/dist/chunks/{node.CyipiPvJ.js → node.BwAWWjHZ.js} +3 -4
- package/dist/chunks/{plugin.d.CIk0YiKb.d.ts → plugin.d.DQU1R5px.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DmP-iHLr.d.ts → reporters.d.BMKt7f6I.d.ts} +1064 -1021
- package/dist/chunks/{resolveSnapshotEnvironment.Bvv2zr69.js → resolveSnapshotEnvironment.DJJKMKxb.js} +7 -8
- package/dist/chunks/{rpc.BKr6mtxz.js → rpc.cD77ENhU.js} +13 -14
- package/dist/chunks/{setup-common.B7I37Tji.js → setup-common.DR1sucx6.js} +6 -6
- package/dist/chunks/{startModuleRunner.BDRvKSdz.js → startModuleRunner.iF1E9Bt4.js} +126 -110
- package/dist/chunks/{test.BAlBebnP.js → test.C3RPt8JR.js} +7 -7
- package/dist/chunks/{utils.D2R2NiOH.js → utils.CG9h5ccR.js} +2 -5
- package/dist/chunks/{vi.BB37KeLx.js → vi.BZvkKVkM.js} +61 -164
- package/dist/chunks/{vm.CjLTDaST.js → vm.CuMWYx_F.js} +20 -29
- package/dist/chunks/{worker.d.B2r4Ln6p.d.ts → worker.d.BFk-vvBU.d.ts} +42 -6
- package/dist/cli.js +12 -11
- package/dist/config.cjs +0 -1
- package/dist/config.d.ts +11 -13
- package/dist/config.js +1 -1
- package/dist/coverage.d.ts +7 -6
- package/dist/coverage.js +3 -14
- package/dist/environments.d.ts +3 -6
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +20 -25
- package/dist/index.js +11 -7
- package/dist/module-evaluator.d.ts +5 -4
- package/dist/module-evaluator.js +11 -13
- package/dist/module-runner.js +5 -5
- package/dist/node.d.ts +82 -25
- package/dist/node.js +23 -20
- package/dist/reporters.d.ts +10 -9
- package/dist/reporters.js +12 -11
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +9 -7
- package/dist/snapshot.js +3 -3
- package/dist/suite.js +4 -3
- package/dist/worker.d.ts +26 -0
- package/dist/worker.js +45 -165
- package/dist/workers/forks.js +26 -43
- package/dist/workers/runVmTests.js +16 -12
- package/dist/workers/threads.js +26 -31
- package/dist/workers/vmForks.js +26 -39
- package/dist/workers/vmThreads.js +26 -29
- package/package.json +48 -32
- package/worker.d.ts +1 -0
- package/browser.d.ts +0 -1
- package/dist/chunks/environment.d.2fYMoz3o.d.ts +0 -66
- package/dist/chunks/moduleTransport.I-bgQy0S.js +0 -19
- package/dist/chunks/resolver.Bx6lE0iq.js +0 -119
- package/dist/chunks/typechecker.DB-fIMaH.js +0 -805
- package/dist/chunks/utils.C2YI6McM.js +0 -52
- package/dist/chunks/worker.d.DJ6qxO2w.d.ts +0 -8
- package/dist/workers.d.ts +0 -38
- package/dist/workers.js +0 -49
- package/execute.d.ts +0 -1
- package/utils.d.ts +0 -1
- package/workers.d.ts +0 -1
|
@@ -1,301 +1,60 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { resolve, isAbsolute, dirname, join } from 'node:path';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import 'node:module';
|
|
4
|
+
import 'node:url';
|
|
5
5
|
import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
|
|
6
6
|
import require$$0 from 'readline';
|
|
7
7
|
import require$$0$1 from 'events';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
get: function () { return e[k]; }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
return Object.freeze(n);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/*
|
|
25
|
-
How it works:
|
|
26
|
-
`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
|
|
9
|
+
/**
|
|
10
|
+
* Resolve an absolute path from {@link root}, but only
|
|
11
|
+
* if {@link input} isn't already absolute.
|
|
12
|
+
*
|
|
13
|
+
* @param input The path to resolve.
|
|
14
|
+
* @param root The base path; default = process.cwd()
|
|
15
|
+
* @returns The resolved absolute path.
|
|
27
16
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
value;
|
|
31
|
-
next;
|
|
32
|
-
|
|
33
|
-
constructor(value) {
|
|
34
|
-
this.value = value;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
class Queue {
|
|
39
|
-
#head;
|
|
40
|
-
#tail;
|
|
41
|
-
#size;
|
|
42
|
-
|
|
43
|
-
constructor() {
|
|
44
|
-
this.clear();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
enqueue(value) {
|
|
48
|
-
const node = new Node(value);
|
|
49
|
-
|
|
50
|
-
if (this.#head) {
|
|
51
|
-
this.#tail.next = node;
|
|
52
|
-
this.#tail = node;
|
|
53
|
-
} else {
|
|
54
|
-
this.#head = node;
|
|
55
|
-
this.#tail = node;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.#size++;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
dequeue() {
|
|
62
|
-
const current = this.#head;
|
|
63
|
-
if (!current) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
this.#head = this.#head.next;
|
|
68
|
-
this.#size--;
|
|
69
|
-
return current.value;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
clear() {
|
|
73
|
-
this.#head = undefined;
|
|
74
|
-
this.#tail = undefined;
|
|
75
|
-
this.#size = 0;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get size() {
|
|
79
|
-
return this.#size;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
* [Symbol.iterator]() {
|
|
83
|
-
let current = this.#head;
|
|
84
|
-
|
|
85
|
-
while (current) {
|
|
86
|
-
yield current.value;
|
|
87
|
-
current = current.next;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function pLimit(concurrency) {
|
|
93
|
-
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
|
|
94
|
-
throw new TypeError('Expected `concurrency` to be a number from 1 and up');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const queue = new Queue();
|
|
98
|
-
let activeCount = 0;
|
|
99
|
-
|
|
100
|
-
const next = () => {
|
|
101
|
-
activeCount--;
|
|
102
|
-
|
|
103
|
-
if (queue.size > 0) {
|
|
104
|
-
queue.dequeue()();
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const run = async (fn, resolve, args) => {
|
|
109
|
-
activeCount++;
|
|
110
|
-
|
|
111
|
-
const result = (async () => fn(...args))();
|
|
112
|
-
|
|
113
|
-
resolve(result);
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
await result;
|
|
117
|
-
} catch {}
|
|
118
|
-
|
|
119
|
-
next();
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const enqueue = (fn, resolve, args) => {
|
|
123
|
-
queue.enqueue(run.bind(undefined, fn, resolve, args));
|
|
124
|
-
|
|
125
|
-
(async () => {
|
|
126
|
-
// This function needs to wait until the next microtask before comparing
|
|
127
|
-
// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously
|
|
128
|
-
// when the run function is dequeued and called. The comparison in the if-statement
|
|
129
|
-
// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.
|
|
130
|
-
await Promise.resolve();
|
|
131
|
-
|
|
132
|
-
if (activeCount < concurrency && queue.size > 0) {
|
|
133
|
-
queue.dequeue()();
|
|
134
|
-
}
|
|
135
|
-
})();
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const generator = (fn, ...args) => new Promise(resolve => {
|
|
139
|
-
enqueue(fn, resolve, args);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
Object.defineProperties(generator, {
|
|
143
|
-
activeCount: {
|
|
144
|
-
get: () => activeCount,
|
|
145
|
-
},
|
|
146
|
-
pendingCount: {
|
|
147
|
-
get: () => queue.size,
|
|
148
|
-
},
|
|
149
|
-
clearQueue: {
|
|
150
|
-
value: () => {
|
|
151
|
-
queue.clear();
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
return generator;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
class EndError extends Error {
|
|
160
|
-
constructor(value) {
|
|
161
|
-
super();
|
|
162
|
-
this.value = value;
|
|
163
|
-
}
|
|
17
|
+
function absolute(input, root) {
|
|
18
|
+
return isAbsolute(input) ? input : resolve(root || ".", input);
|
|
164
19
|
}
|
|
165
20
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
tester,
|
|
182
|
-
{
|
|
183
|
-
concurrency = Number.POSITIVE_INFINITY,
|
|
184
|
-
preserveOrder = true,
|
|
185
|
-
} = {},
|
|
186
|
-
) {
|
|
187
|
-
const limit = pLimit(concurrency);
|
|
188
|
-
|
|
189
|
-
// Start all the promises concurrently with optional limit.
|
|
190
|
-
const items = [...iterable].map(element => [element, limit(testElement, element, tester)]);
|
|
191
|
-
|
|
192
|
-
// Check the promises either serially or concurrently.
|
|
193
|
-
const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY);
|
|
194
|
-
|
|
195
|
-
try {
|
|
196
|
-
await Promise.all(items.map(element => checkLimit(finder, element)));
|
|
197
|
-
} catch (error) {
|
|
198
|
-
if (error instanceof EndError) {
|
|
199
|
-
return error.value;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
throw error;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const typeMappings = {
|
|
207
|
-
directory: 'isDirectory',
|
|
208
|
-
file: 'isFile',
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
function checkType(type) {
|
|
212
|
-
if (Object.hasOwnProperty.call(typeMappings, type)) {
|
|
213
|
-
return;
|
|
21
|
+
/**
|
|
22
|
+
* Get all parent directories of {@link base}.
|
|
23
|
+
* Stops after {@link Options['last']} is processed.
|
|
24
|
+
*
|
|
25
|
+
* @returns An array of absolute paths of all parent directories.
|
|
26
|
+
*/
|
|
27
|
+
function up(base, options) {
|
|
28
|
+
let { last, cwd } = options || {};
|
|
29
|
+
let tmp = absolute(base, cwd);
|
|
30
|
+
let root = absolute(last || "/", cwd);
|
|
31
|
+
let prev, arr = [];
|
|
32
|
+
while (prev !== root) {
|
|
33
|
+
arr.push(tmp);
|
|
34
|
+
tmp = dirname(prev = tmp);
|
|
35
|
+
if (tmp === prev) break;
|
|
214
36
|
}
|
|
215
|
-
|
|
216
|
-
throw new Error(`Invalid type specified: ${type}`);
|
|
37
|
+
return arr;
|
|
217
38
|
}
|
|
218
39
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const statFunction = allowSymlinks ? promises.stat : promises.lstat;
|
|
237
|
-
|
|
238
|
-
return pLocate(paths, async path_ => {
|
|
239
|
-
try {
|
|
240
|
-
const stat = await statFunction(path.resolve(cwd, path_));
|
|
241
|
-
return matchType(type, stat);
|
|
242
|
-
} catch {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
}, {concurrency, preserveOrder});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
|
|
249
|
-
|
|
250
|
-
const findUpStop = Symbol('findUpStop');
|
|
251
|
-
|
|
252
|
-
async function findUpMultiple(name, options = {}) {
|
|
253
|
-
let directory = path.resolve(toPath(options.cwd) || '');
|
|
254
|
-
const {root} = path.parse(directory);
|
|
255
|
-
const stopAt = path.resolve(directory, options.stopAt || root);
|
|
256
|
-
const limit = options.limit || Number.POSITIVE_INFINITY;
|
|
257
|
-
const paths = [name].flat();
|
|
258
|
-
|
|
259
|
-
const runMatcher = async locateOptions => {
|
|
260
|
-
if (typeof name !== 'function') {
|
|
261
|
-
return locatePath(paths, locateOptions);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const foundPath = await name(locateOptions.cwd);
|
|
265
|
-
if (typeof foundPath === 'string') {
|
|
266
|
-
return locatePath([foundPath], locateOptions);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return foundPath;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const matches = [];
|
|
273
|
-
// eslint-disable-next-line no-constant-condition
|
|
274
|
-
while (true) {
|
|
275
|
-
// eslint-disable-next-line no-await-in-loop
|
|
276
|
-
const foundPath = await runMatcher({...options, cwd: directory});
|
|
277
|
-
|
|
278
|
-
if (foundPath === findUpStop) {
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (foundPath) {
|
|
283
|
-
matches.push(path.resolve(directory, foundPath));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (directory === stopAt || matches.length >= limit) {
|
|
287
|
-
break;
|
|
40
|
+
/**
|
|
41
|
+
* Get the first path that matches any of the names provided.
|
|
42
|
+
*
|
|
43
|
+
* > [NOTE]
|
|
44
|
+
* > The order of {@link names} is respected.
|
|
45
|
+
*
|
|
46
|
+
* @param names The item names to find.
|
|
47
|
+
* @returns The absolute path of the first item found, if any.
|
|
48
|
+
*/
|
|
49
|
+
function any(names, options) {
|
|
50
|
+
let dir, start = options && options.cwd || "";
|
|
51
|
+
let j = 0, len = names.length, tmp;
|
|
52
|
+
for (dir of up(start, options)) {
|
|
53
|
+
for (j = 0; j < len; j++) {
|
|
54
|
+
tmp = join(dir, names[j]);
|
|
55
|
+
if (existsSync(tmp)) return tmp;
|
|
288
56
|
}
|
|
289
|
-
|
|
290
|
-
directory = path.dirname(directory);
|
|
291
57
|
}
|
|
292
|
-
|
|
293
|
-
return matches;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
async function findUp(name, options = {}) {
|
|
297
|
-
const matches = await findUpMultiple(name, {...options, limit: 1});
|
|
298
|
-
return matches[0];
|
|
299
58
|
}
|
|
300
59
|
|
|
301
60
|
var prompts$2 = {};
|
|
@@ -6576,9 +6335,9 @@ function requirePrompts () {
|
|
|
6576
6335
|
var promptsExports = requirePrompts();
|
|
6577
6336
|
var prompt = /*@__PURE__*/getDefaultExportFromCjs(promptsExports);
|
|
6578
6337
|
|
|
6579
|
-
var index = /*#__PURE__*/
|
|
6338
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
6580
6339
|
__proto__: null,
|
|
6581
6340
|
default: prompt
|
|
6582
|
-
}
|
|
6341
|
+
});
|
|
6583
6342
|
|
|
6584
|
-
export {
|
|
6343
|
+
export { any as a, index as i, prompt as p };
|
|
@@ -1,15 +1,15 @@
|
|
|
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.
|
|
2
|
-
import { b as bench } from './benchmark.
|
|
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.BZvkKVkM.js';
|
|
2
|
+
import { b as bench } from './benchmark.DHKMYAts.js';
|
|
3
|
+
import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
|
|
3
4
|
import { expectTypeOf } from 'expect-type';
|
|
4
5
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, suite, test } from '@vitest/runner';
|
|
5
|
-
import { EvaluatedModules } from 'vite/module-runner';
|
|
6
6
|
import { chai } from '@vitest/expect';
|
|
7
7
|
|
|
8
8
|
const assertType = function assertType() {};
|
|
9
9
|
|
|
10
10
|
var index = /*#__PURE__*/Object.freeze({
|
|
11
11
|
__proto__: null,
|
|
12
|
-
EvaluatedModules:
|
|
12
|
+
EvaluatedModules: VitestEvaluatedModules,
|
|
13
13
|
afterAll: afterAll,
|
|
14
14
|
afterEach: afterEach,
|
|
15
15
|
assert: assert,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import v8 from 'node:v8';
|
|
2
|
+
import { i as init } from './init.94FWN9pW.js';
|
|
3
|
+
|
|
4
|
+
if (!process.send) throw new Error("Expected worker to be run in node:child_process");
|
|
5
|
+
// Store globals in case tests overwrite them
|
|
6
|
+
const processExit = process.exit.bind(process), processSend = process.send.bind(process), processOn = process.on.bind(process), processOff = process.off.bind(process), processRemoveAllListeners = process.removeAllListeners.bind(process);
|
|
7
|
+
// Work-around for nodejs/node#55094
|
|
8
|
+
if (process.execArgv.some((execArg) => execArg.startsWith("--prof") || execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"))) processOn("SIGTERM", () => processExit());
|
|
9
|
+
function workerInit(options) {
|
|
10
|
+
const { runTests } = options;
|
|
11
|
+
init({
|
|
12
|
+
post: (v) => processSend(v),
|
|
13
|
+
on: (cb) => processOn("message", cb),
|
|
14
|
+
off: (cb) => processOff("message", cb),
|
|
15
|
+
teardown: () => processRemoveAllListeners("message"),
|
|
16
|
+
serialize: v8.serialize,
|
|
17
|
+
deserialize: (v) => v8.deserialize(Buffer.from(v)),
|
|
18
|
+
runTests: (state) => executeTests("run", state),
|
|
19
|
+
collectTests: (state) => executeTests("collect", state)
|
|
20
|
+
});
|
|
21
|
+
async function executeTests(method, state) {
|
|
22
|
+
state.ctx.config = unwrapSerializableConfig(state.ctx.config);
|
|
23
|
+
try {
|
|
24
|
+
await runTests(method, state);
|
|
25
|
+
} finally {
|
|
26
|
+
process.exit = processExit;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reverts the wrapping done by `wrapSerializableConfig` in {@link file://./../../node/pool/runtimes/forks.ts}
|
|
32
|
+
*/
|
|
33
|
+
function unwrapSerializableConfig(config) {
|
|
34
|
+
if (config.testNamePattern && typeof config.testNamePattern === "string") {
|
|
35
|
+
const testNamePattern = config.testNamePattern;
|
|
36
|
+
if (testNamePattern.startsWith("$$vitest:")) config.testNamePattern = parseRegexp(testNamePattern.slice(9));
|
|
37
|
+
}
|
|
38
|
+
if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
|
|
39
|
+
const { keys, original } = config.defines, defines = {};
|
|
40
|
+
// Apply all keys from the original. Entries which had undefined value are missing from original now
|
|
41
|
+
for (const key of keys) defines[key] = original[key];
|
|
42
|
+
config.defines = defines;
|
|
43
|
+
}
|
|
44
|
+
return config;
|
|
45
|
+
}
|
|
46
|
+
function parseRegexp(input) {
|
|
47
|
+
// Parse input
|
|
48
|
+
// eslint-disable-next-line regexp/no-misleading-capturing-group
|
|
49
|
+
const m = input.match(/(\/?)(.+)\1([a-z]*)/i);
|
|
50
|
+
// Create the regular expression
|
|
51
|
+
return m ? m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3]) ? new RegExp(input) : new RegExp(m[2], m[3]) : /$^/;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { workerInit as w };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isMainThread, parentPort } from 'node:worker_threads';
|
|
2
|
+
import { i as init } from './init.94FWN9pW.js';
|
|
3
|
+
|
|
4
|
+
if (isMainThread || !parentPort) throw new Error("Expected worker to be run in node:worker_threads");
|
|
5
|
+
function workerInit(options) {
|
|
6
|
+
const { runTests } = options;
|
|
7
|
+
init({
|
|
8
|
+
post: (response) => parentPort.postMessage(response),
|
|
9
|
+
on: (callback) => parentPort.on("message", callback),
|
|
10
|
+
off: (callback) => parentPort.off("message", callback),
|
|
11
|
+
teardown: () => parentPort.removeAllListeners("message"),
|
|
12
|
+
runTests: async (state) => runTests("run", state),
|
|
13
|
+
collectTests: async (state) => runTests("collect", state)
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { workerInit as w };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { serializeError } from '@vitest/utils/error';
|
|
2
|
+
import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { isBuiltin } from 'node:module';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
import { resolve } from 'pathe';
|
|
7
|
+
import { ModuleRunner } from 'vite/module-runner';
|
|
8
|
+
import { b as VitestTransport } from './startModuleRunner.iF1E9Bt4.js';
|
|
9
|
+
import { e as environments } from './index.CbWINfS7.js';
|
|
10
|
+
import { s as setupInspect } from './inspector.DLZxSeU3.js';
|
|
11
|
+
import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
|
|
12
|
+
import { c as createRuntimeRpc, a as rpcDone } from './rpc.cD77ENhU.js';
|
|
13
|
+
|
|
14
|
+
function isBuiltinEnvironment(env) {
|
|
15
|
+
return env in environments;
|
|
16
|
+
}
|
|
17
|
+
const isWindows = process.platform === "win32", _loaders = /* @__PURE__ */ new Map();
|
|
18
|
+
async function createEnvironmentLoader(root, rpc) {
|
|
19
|
+
const cachedLoader = _loaders.get(root);
|
|
20
|
+
if (!cachedLoader || cachedLoader.isClosed()) {
|
|
21
|
+
_loaders.delete(root);
|
|
22
|
+
const moduleRunner = new ModuleRunner({
|
|
23
|
+
hmr: false,
|
|
24
|
+
sourcemapInterceptor: "prepareStackTrace",
|
|
25
|
+
transport: new VitestTransport({
|
|
26
|
+
async fetchModule(id, importer, options) {
|
|
27
|
+
const result = await rpc.fetch(id, importer, "__vitest__", options);
|
|
28
|
+
if ("cached" in result) return {
|
|
29
|
+
code: readFileSync(result.tmp, "utf-8"),
|
|
30
|
+
...result
|
|
31
|
+
};
|
|
32
|
+
if (isWindows && "externalize" in result)
|
|
33
|
+
// TODO: vitest returns paths for external modules, but Vite returns file://
|
|
34
|
+
// https://github.com/vitejs/vite/pull/20449
|
|
35
|
+
result.externalize = isBuiltin(id) || /^(?:node:|data:|http:|https:|file:)/.test(id) ? result.externalize : pathToFileURL(result.externalize).toString();
|
|
36
|
+
return result;
|
|
37
|
+
},
|
|
38
|
+
async resolveId(id, importer) {
|
|
39
|
+
return rpc.resolve(id, importer, "__vitest__");
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
_loaders.set(root, moduleRunner), await moduleRunner.import("/@vite/env");
|
|
44
|
+
}
|
|
45
|
+
return _loaders.get(root);
|
|
46
|
+
}
|
|
47
|
+
async function loadEnvironment(ctx, rpc) {
|
|
48
|
+
const name = ctx.environment.name;
|
|
49
|
+
if (isBuiltinEnvironment(name)) return { environment: environments[name] };
|
|
50
|
+
const root = ctx.config.root, loader = await createEnvironmentLoader(root, rpc), packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__"))?.id ?? resolve(root, name), pkg = await loader.import(packageId);
|
|
51
|
+
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
|
+
const environment = pkg.default;
|
|
53
|
+
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
|
+
// keep for backwards compat
|
|
56
|
+
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.`), environment.viteEnvironment ??= environment.transformMode === "ssr" ? "ssr" : "client";
|
|
57
|
+
return {
|
|
58
|
+
environment,
|
|
59
|
+
loader
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const resolvingModules = /* @__PURE__ */ new Set(), globalListeners = /* @__PURE__ */ new Set();
|
|
64
|
+
async function execute(method, ctx, worker) {
|
|
65
|
+
const prepareStart = performance.now(), cleanups = [setupInspect(ctx)];
|
|
66
|
+
let environmentLoader;
|
|
67
|
+
// RPC is used to communicate between worker (be it a thread worker or child process or a custom implementation) and the main thread
|
|
68
|
+
const { rpc, onCancel } = createRuntimeRpc(worker);
|
|
69
|
+
try {
|
|
70
|
+
// do not close the RPC channel so that we can get the error messages sent to the main thread
|
|
71
|
+
cleanups.push(async () => {
|
|
72
|
+
await Promise.all(rpc.$rejectPendingCalls(({ method, reject }) => {
|
|
73
|
+
reject(/* @__PURE__ */ new Error(`[vitest-worker]: Closing rpc while "${method}" was pending`));
|
|
74
|
+
}));
|
|
75
|
+
});
|
|
76
|
+
const beforeEnvironmentTime = performance.now(), { environment, loader } = await loadEnvironment(ctx, rpc);
|
|
77
|
+
environmentLoader = loader;
|
|
78
|
+
const state = {
|
|
79
|
+
ctx,
|
|
80
|
+
evaluatedModules: new VitestEvaluatedModules(),
|
|
81
|
+
resolvingModules,
|
|
82
|
+
moduleExecutionInfo: /* @__PURE__ */ new Map(),
|
|
83
|
+
config: ctx.config,
|
|
84
|
+
onCancel,
|
|
85
|
+
environment,
|
|
86
|
+
durations: {
|
|
87
|
+
environment: beforeEnvironmentTime,
|
|
88
|
+
prepare: prepareStart
|
|
89
|
+
},
|
|
90
|
+
rpc,
|
|
91
|
+
onCleanup: (listener) => globalListeners.add(listener),
|
|
92
|
+
providedContext: ctx.providedContext,
|
|
93
|
+
onFilterStackTrace(stack) {
|
|
94
|
+
return createStackString(parseStacktrace(stack));
|
|
95
|
+
},
|
|
96
|
+
metaEnv: createImportMetaEnvProxy()
|
|
97
|
+
}, methodName = method === "collect" ? "collectTests" : "runTests";
|
|
98
|
+
if (!worker[methodName] || typeof worker[methodName] !== "function") throw new TypeError(`Test worker should expose "runTests" method. Received "${typeof worker.runTests}".`);
|
|
99
|
+
await worker[methodName](state);
|
|
100
|
+
} finally {
|
|
101
|
+
await rpcDone().catch(() => {}), await Promise.all(cleanups.map((fn) => fn())).catch(() => {}), await environmentLoader?.close();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function run(ctx, worker) {
|
|
105
|
+
return execute("run", ctx, worker);
|
|
106
|
+
}
|
|
107
|
+
function collect(ctx, worker) {
|
|
108
|
+
return execute("collect", ctx, worker);
|
|
109
|
+
}
|
|
110
|
+
async function teardown() {
|
|
111
|
+
await Promise.all([...globalListeners].map((l) => l()));
|
|
112
|
+
}
|
|
113
|
+
function createImportMetaEnvProxy() {
|
|
114
|
+
// packages/vitest/src/node/plugins/index.ts:146
|
|
115
|
+
const booleanKeys = [
|
|
116
|
+
"DEV",
|
|
117
|
+
"PROD",
|
|
118
|
+
"SSR"
|
|
119
|
+
];
|
|
120
|
+
return new Proxy(process.env, {
|
|
121
|
+
get(_, key) {
|
|
122
|
+
if (typeof key === "string") return booleanKeys.includes(key) ? !!process.env[key] : process.env[key];
|
|
123
|
+
},
|
|
124
|
+
set(_, key, value) {
|
|
125
|
+
if (typeof key !== "string") return true;
|
|
126
|
+
if (booleanKeys.includes(key)) process.env[key] = value ? "1" : "";
|
|
127
|
+
else process.env[key] = value;
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const __vitest_worker_response__ = true, memoryUsage = process.memoryUsage.bind(process);
|
|
134
|
+
let reportMemory = false;
|
|
135
|
+
/** @experimental */
|
|
136
|
+
function init(worker) {
|
|
137
|
+
worker.on(onMessage);
|
|
138
|
+
let runPromise, isRunning = false;
|
|
139
|
+
function send(response) {
|
|
140
|
+
worker.post(worker.serialize ? worker.serialize(response) : response);
|
|
141
|
+
}
|
|
142
|
+
async function onMessage(rawMessage) {
|
|
143
|
+
const message = worker.deserialize ? worker.deserialize(rawMessage) : rawMessage;
|
|
144
|
+
if (message?.__vitest_worker_request__ === true) switch (message.type) {
|
|
145
|
+
case "start":
|
|
146
|
+
reportMemory = message.options.reportMemory, send({
|
|
147
|
+
type: "started",
|
|
148
|
+
__vitest_worker_response__
|
|
149
|
+
});
|
|
150
|
+
break;
|
|
151
|
+
case "run":
|
|
152
|
+
// Prevent concurrent execution if worker is already running
|
|
153
|
+
if (isRunning) {
|
|
154
|
+
send({
|
|
155
|
+
type: "testfileFinished",
|
|
156
|
+
__vitest_worker_response__,
|
|
157
|
+
error: serializeError(/* @__PURE__ */ new Error("[vitest-worker]: Worker is already running tests"))
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
162
|
+
try {
|
|
163
|
+
runPromise = run(message.context, worker).catch((error) => serializeError(error));
|
|
164
|
+
const error = await runPromise;
|
|
165
|
+
send({
|
|
166
|
+
type: "testfileFinished",
|
|
167
|
+
__vitest_worker_response__,
|
|
168
|
+
error,
|
|
169
|
+
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
170
|
+
});
|
|
171
|
+
} finally {
|
|
172
|
+
runPromise = void 0, isRunning = false;
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
case "collect":
|
|
176
|
+
// Prevent concurrent execution if worker is already running
|
|
177
|
+
if (isRunning) {
|
|
178
|
+
send({
|
|
179
|
+
type: "testfileFinished",
|
|
180
|
+
__vitest_worker_response__,
|
|
181
|
+
error: serializeError(/* @__PURE__ */ new Error("[vitest-worker]: Worker is already running tests"))
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
isRunning = true, process.env.VITEST_POOL_ID = String(message.poolId), process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
|
186
|
+
try {
|
|
187
|
+
runPromise = collect(message.context, worker).catch((error) => serializeError(error));
|
|
188
|
+
const error = await runPromise;
|
|
189
|
+
send({
|
|
190
|
+
type: "testfileFinished",
|
|
191
|
+
__vitest_worker_response__,
|
|
192
|
+
error,
|
|
193
|
+
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
|
194
|
+
});
|
|
195
|
+
} finally {
|
|
196
|
+
runPromise = void 0, isRunning = false;
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
case "stop": {
|
|
200
|
+
await runPromise;
|
|
201
|
+
const error = await teardown().catch((error) => serializeError(error));
|
|
202
|
+
send({
|
|
203
|
+
type: "stopped",
|
|
204
|
+
error,
|
|
205
|
+
__vitest_worker_response__
|
|
206
|
+
}), worker.teardown?.();
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { init as i };
|
|
@@ -10,10 +10,7 @@ let inspector, session;
|
|
|
10
10
|
function setupInspect(ctx) {
|
|
11
11
|
const config = ctx.config, isEnabled = config.inspector.enabled;
|
|
12
12
|
if (isEnabled) {
|
|
13
|
-
inspector = __require("node:inspector")
|
|
14
|
-
// Inspector may be open already if "isolate: false" is used
|
|
15
|
-
const isOpen = inspector.url() !== void 0;
|
|
16
|
-
if (!isOpen) {
|
|
13
|
+
if (inspector = __require("node:inspector"), !(inspector.url() !== void 0)) {
|
|
17
14
|
if (inspector.open(config.inspector.port, config.inspector.host, config.inspector.waitForDebugger), config.inspectBrk) {
|
|
18
15
|
const firstTestFile = typeof ctx.files[0] === "string" ? ctx.files[0] : ctx.files[0].filepath;
|
|
19
16
|
// Stop at first test file
|
|
@@ -35,8 +32,7 @@ function closeInspector(config) {
|
|
|
35
32
|
}
|
|
36
33
|
function shouldKeepOpen(config) {
|
|
37
34
|
// In watch mode the inspector can persist re-runs if isolation is disabled and a single worker is used
|
|
38
|
-
|
|
39
|
-
return config.watch && (isIsolatedSingleFork || isIsolatedSingleThread);
|
|
35
|
+
return config.watch && config.isolate === false && config.maxWorkers === 1;
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
export { closeInspector as c, setupInspect as s };
|