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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
2
2
|
import vm, { isContext, runInContext } from 'node:vm';
|
|
3
3
|
import { dirname, basename, extname, normalize, resolve } from 'pathe';
|
|
4
|
+
import { l as loadEnvironment } from './init.DMDG-idf.js';
|
|
4
5
|
import { distDir } from '../path.js';
|
|
5
|
-
import { createCustomConsole } from './console.
|
|
6
|
+
import { createCustomConsole } from './console.Cf-YriPC.js';
|
|
6
7
|
import fs from 'node:fs';
|
|
7
8
|
import { createRequire, Module, isBuiltin } from 'node:module';
|
|
8
9
|
import { toArray, isBareImport } from '@vitest/utils/helpers';
|
|
@@ -10,8 +11,8 @@ import { findNearestPackageData } from '@vitest/utils/resolver';
|
|
|
10
11
|
import { dirname as dirname$1 } from 'node:path';
|
|
11
12
|
import { CSS_LANGS_RE, KNOWN_ASSET_RE } from '@vitest/utils/constants';
|
|
12
13
|
import { getDefaultRequestStubs } from '../module-evaluator.js';
|
|
13
|
-
import { s as startVitestModuleRunner, c as createNodeImportMeta, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.
|
|
14
|
-
import { p as provideWorkerState } from './utils.
|
|
14
|
+
import { s as startVitestModuleRunner, c as createNodeImportMeta, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.BOmUtLIO.js';
|
|
15
|
+
import { p as provideWorkerState } from './utils.DvEY5TfP.js';
|
|
15
16
|
|
|
16
17
|
function interopCommonJsModule(interopDefault, mod) {
|
|
17
18
|
if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) return {
|
|
@@ -20,8 +21,11 @@ function interopCommonJsModule(interopDefault, mod) {
|
|
|
20
21
|
defaultExport: mod
|
|
21
22
|
};
|
|
22
23
|
if (interopDefault !== false && "__esModule" in mod && !isPrimitive(mod.default)) {
|
|
23
|
-
const defaultKets = Object.keys(mod.default)
|
|
24
|
-
|
|
24
|
+
const defaultKets = Object.keys(mod.default);
|
|
25
|
+
const moduleKeys = Object.keys(mod);
|
|
26
|
+
const allKeys = new Set([...defaultKets, ...moduleKeys]);
|
|
27
|
+
allKeys.delete("default");
|
|
28
|
+
return {
|
|
25
29
|
keys: Array.from(allKeys),
|
|
26
30
|
moduleExports: new Proxy(mod, { get(mod, prop) {
|
|
27
31
|
return mod[prop] ?? mod.default?.[prop];
|
|
@@ -41,7 +45,8 @@ function isPrimitive(obj) {
|
|
|
41
45
|
const SyntheticModule = vm.SyntheticModule;
|
|
42
46
|
const SourceTextModule = vm.SourceTextModule;
|
|
43
47
|
|
|
44
|
-
const _require = createRequire(import.meta.url)
|
|
48
|
+
const _require = createRequire(import.meta.url);
|
|
49
|
+
const requiresCache = /* @__PURE__ */ new WeakMap();
|
|
45
50
|
class CommonjsExecutor {
|
|
46
51
|
context;
|
|
47
52
|
requireCache = /* @__PURE__ */ new Map();
|
|
@@ -53,8 +58,12 @@ class CommonjsExecutor {
|
|
|
53
58
|
Module;
|
|
54
59
|
interopDefault;
|
|
55
60
|
constructor(options) {
|
|
56
|
-
this.context = options.context
|
|
57
|
-
|
|
61
|
+
this.context = options.context;
|
|
62
|
+
this.fs = options.fileMap;
|
|
63
|
+
this.interopDefault = options.interopDefault;
|
|
64
|
+
const primitives = vm.runInContext("({ Object, Array, Error })", this.context);
|
|
65
|
+
// eslint-disable-next-line ts/no-this-alias
|
|
66
|
+
const executor = this;
|
|
58
67
|
this.Module = class Module$1 {
|
|
59
68
|
exports;
|
|
60
69
|
isPreloading = false;
|
|
@@ -66,13 +75,20 @@ class CommonjsExecutor {
|
|
|
66
75
|
path;
|
|
67
76
|
paths = [];
|
|
68
77
|
constructor(id = "", parent) {
|
|
69
|
-
this.exports = primitives.Object.create(Object.prototype)
|
|
78
|
+
this.exports = primitives.Object.create(Object.prototype);
|
|
79
|
+
// in our case the path should always be resolved already
|
|
80
|
+
this.path = dirname(id);
|
|
81
|
+
this.id = id;
|
|
82
|
+
this.filename = id;
|
|
83
|
+
this.loaded = false;
|
|
84
|
+
this.parent = parent;
|
|
70
85
|
}
|
|
71
86
|
get require() {
|
|
72
87
|
const require = requiresCache.get(this);
|
|
73
88
|
if (require) return require;
|
|
74
89
|
const _require = Module$1.createRequire(this.id);
|
|
75
|
-
|
|
90
|
+
requiresCache.set(this, _require);
|
|
91
|
+
return _require;
|
|
76
92
|
}
|
|
77
93
|
static getSourceMapsSupport = () => ({
|
|
78
94
|
enabled: false,
|
|
@@ -89,16 +105,19 @@ class CommonjsExecutor {
|
|
|
89
105
|
throw new Error(`[vitest] "registerHooks" is not available when running in Vitest.`);
|
|
90
106
|
};
|
|
91
107
|
_compile(code, filename) {
|
|
92
|
-
const cjsModule = Module$1.wrap(code)
|
|
108
|
+
const cjsModule = Module$1.wrap(code);
|
|
109
|
+
const script = new vm.Script(cjsModule, {
|
|
93
110
|
filename,
|
|
94
111
|
importModuleDynamically: options.importModuleDynamically
|
|
95
112
|
});
|
|
96
113
|
// @ts-expect-error mark script with current identifier
|
|
97
114
|
script.identifier = filename;
|
|
98
|
-
const fn = script.runInContext(executor.context)
|
|
115
|
+
const fn = script.runInContext(executor.context);
|
|
116
|
+
const __dirname = dirname(filename);
|
|
99
117
|
executor.requireCache.set(filename, this);
|
|
100
118
|
try {
|
|
101
|
-
|
|
119
|
+
fn(this.exports, this.require, this, filename, __dirname);
|
|
120
|
+
return this.exports;
|
|
102
121
|
} finally {
|
|
103
122
|
this.loaded = true;
|
|
104
123
|
}
|
|
@@ -143,7 +162,9 @@ class CommonjsExecutor {
|
|
|
143
162
|
static stripTypeScriptTypes = Module.stripTypeScriptTypes;
|
|
144
163
|
static findPackageJSON = Module.findPackageJSON;
|
|
145
164
|
static Module = Module$1;
|
|
146
|
-
}
|
|
165
|
+
};
|
|
166
|
+
this.extensions[".js"] = this.requireJs;
|
|
167
|
+
this.extensions[".json"] = this.requireJson;
|
|
147
168
|
}
|
|
148
169
|
requireJs = (m, filename) => {
|
|
149
170
|
const content = this.fs.readFile(filename);
|
|
@@ -154,17 +175,22 @@ class CommonjsExecutor {
|
|
|
154
175
|
m.exports = JSON.parse(code);
|
|
155
176
|
};
|
|
156
177
|
createRequire = (filename) => {
|
|
157
|
-
const _require = createRequire(filename)
|
|
178
|
+
const _require = createRequire(filename);
|
|
179
|
+
const require = ((id) => {
|
|
158
180
|
const resolved = _require.resolve(id);
|
|
159
181
|
if (extname(resolved) === ".node" || isBuiltin(resolved)) return this.requireCoreModule(resolved);
|
|
160
182
|
const module = new this.Module(resolved);
|
|
161
183
|
return this.loadCommonJSModule(module, resolved);
|
|
162
184
|
});
|
|
163
|
-
|
|
185
|
+
require.resolve = _require.resolve;
|
|
186
|
+
Object.defineProperty(require, "extensions", {
|
|
164
187
|
get: () => this.extensions,
|
|
165
188
|
set: () => {},
|
|
166
189
|
configurable: true
|
|
167
|
-
})
|
|
190
|
+
});
|
|
191
|
+
require.main = void 0;
|
|
192
|
+
require.cache = this.publicRequireCache;
|
|
193
|
+
return require;
|
|
168
194
|
};
|
|
169
195
|
createProxyCache() {
|
|
170
196
|
return new Proxy(Object.create(null), {
|
|
@@ -187,39 +213,51 @@ class CommonjsExecutor {
|
|
|
187
213
|
const cached = this.requireCache.get(filename);
|
|
188
214
|
if (cached) return cached.exports;
|
|
189
215
|
const extension = this.findLongestRegisteredExtension(filename);
|
|
190
|
-
|
|
216
|
+
(this.extensions[extension] || this.extensions[".js"])(module, filename);
|
|
217
|
+
return module.exports;
|
|
191
218
|
}
|
|
192
219
|
findLongestRegisteredExtension(filename) {
|
|
193
220
|
const name = basename(filename);
|
|
194
|
-
let currentExtension
|
|
221
|
+
let currentExtension;
|
|
222
|
+
let index;
|
|
223
|
+
let startIndex = 0;
|
|
195
224
|
// eslint-disable-next-line no-cond-assign
|
|
196
225
|
while ((index = name.indexOf(".", startIndex)) !== -1) {
|
|
197
|
-
|
|
198
|
-
if (
|
|
226
|
+
startIndex = index + 1;
|
|
227
|
+
if (index === 0) continue;
|
|
228
|
+
currentExtension = name.slice(index);
|
|
229
|
+
if (this.extensions[currentExtension]) return currentExtension;
|
|
199
230
|
}
|
|
200
231
|
return ".js";
|
|
201
232
|
}
|
|
202
233
|
getCoreSyntheticModule(identifier) {
|
|
203
234
|
if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
|
|
204
|
-
const exports = this.require(identifier)
|
|
235
|
+
const exports = this.require(identifier);
|
|
236
|
+
const keys = Object.keys(exports);
|
|
237
|
+
const module = new SyntheticModule([...keys, "default"], () => {
|
|
205
238
|
for (const key of keys) module.setExport(key, exports[key]);
|
|
206
239
|
module.setExport("default", exports);
|
|
207
240
|
}, {
|
|
208
241
|
context: this.context,
|
|
209
242
|
identifier
|
|
210
243
|
});
|
|
211
|
-
|
|
244
|
+
this.moduleCache.set(identifier, module);
|
|
245
|
+
return module;
|
|
212
246
|
}
|
|
213
247
|
getCjsSyntheticModule(path, identifier) {
|
|
214
248
|
if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
|
|
215
|
-
const exports = this.require(path)
|
|
249
|
+
const exports = this.require(path);
|
|
250
|
+
// TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
|
|
251
|
+
const { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports);
|
|
252
|
+
const module = new SyntheticModule([...keys, "default"], function() {
|
|
216
253
|
for (const key of keys) this.setExport(key, moduleExports[key]);
|
|
217
254
|
this.setExport("default", defaultExport);
|
|
218
255
|
}, {
|
|
219
256
|
context: this.context,
|
|
220
257
|
identifier
|
|
221
258
|
});
|
|
222
|
-
|
|
259
|
+
this.moduleCache.set(identifier, module);
|
|
260
|
+
return module;
|
|
223
261
|
}
|
|
224
262
|
// TODO: use this in strict mode, when available in #2854
|
|
225
263
|
// private _getNamedCjsExports(path: string): Set<string> {
|
|
@@ -268,10 +306,13 @@ class CommonjsExecutor {
|
|
|
268
306
|
const moduleExports = _require(identifier);
|
|
269
307
|
if (identifier === "node:module" || identifier === "module") {
|
|
270
308
|
const module = new this.Module("/module.js");
|
|
271
|
-
|
|
309
|
+
module.exports = this.Module;
|
|
310
|
+
this.builtinCache[normalized] = module;
|
|
311
|
+
return module.exports;
|
|
272
312
|
}
|
|
313
|
+
this.builtinCache[normalized] = _require.cache[normalized];
|
|
273
314
|
// TODO: should we wrap module to rethrow context errors?
|
|
274
|
-
return
|
|
315
|
+
return moduleExports;
|
|
275
316
|
}
|
|
276
317
|
}
|
|
277
318
|
|
|
@@ -282,18 +323,21 @@ class EsmExecutor {
|
|
|
282
323
|
context;
|
|
283
324
|
#httpIp = IPnumber("127.0.0.0");
|
|
284
325
|
constructor(executor, options) {
|
|
285
|
-
this.executor = executor
|
|
326
|
+
this.executor = executor;
|
|
327
|
+
this.context = options.context;
|
|
286
328
|
}
|
|
287
329
|
async evaluateModule(m) {
|
|
288
330
|
if (m.status === "unlinked") this.esmLinkMap.set(m, m.link((identifier, referencer) => this.executor.resolveModule(identifier, referencer.identifier)));
|
|
289
|
-
|
|
331
|
+
await this.esmLinkMap.get(m);
|
|
332
|
+
if (m.status === "linked") await m.evaluate();
|
|
290
333
|
return m;
|
|
291
334
|
}
|
|
292
335
|
async createEsModule(fileURL, getCode) {
|
|
293
336
|
const cached = this.moduleCache.get(fileURL);
|
|
294
337
|
if (cached) return cached;
|
|
295
338
|
const promise = this.loadEsModule(fileURL, getCode);
|
|
296
|
-
|
|
339
|
+
this.moduleCache.set(fileURL, promise);
|
|
340
|
+
return promise;
|
|
297
341
|
}
|
|
298
342
|
async loadEsModule(fileURL, getCode) {
|
|
299
343
|
const code = await getCode();
|
|
@@ -303,29 +347,34 @@ class EsmExecutor {
|
|
|
303
347
|
const result = JSON.parse(code);
|
|
304
348
|
this.setExport("default", result);
|
|
305
349
|
});
|
|
306
|
-
|
|
350
|
+
this.moduleCache.set(fileURL, m);
|
|
351
|
+
return m;
|
|
307
352
|
}
|
|
308
353
|
const m = new SourceTextModule(code, {
|
|
309
354
|
identifier: fileURL,
|
|
310
355
|
context: this.context,
|
|
311
356
|
importModuleDynamically: this.executor.importModuleDynamically,
|
|
312
357
|
initializeImportMeta: (meta, mod) => {
|
|
313
|
-
|
|
358
|
+
meta.url = mod.identifier;
|
|
359
|
+
if (mod.identifier.startsWith("file:")) {
|
|
314
360
|
const filename = fileURLToPath(mod.identifier);
|
|
315
|
-
meta.filename = filename
|
|
361
|
+
meta.filename = filename;
|
|
362
|
+
meta.dirname = dirname$1(filename);
|
|
316
363
|
}
|
|
317
364
|
meta.resolve = (specifier, importer) => {
|
|
318
365
|
return this.executor.resolve(specifier, importer != null ? importer.toString() : mod.identifier);
|
|
319
366
|
};
|
|
320
367
|
}
|
|
321
368
|
});
|
|
322
|
-
|
|
369
|
+
this.moduleCache.set(fileURL, m);
|
|
370
|
+
return m;
|
|
323
371
|
}
|
|
324
372
|
async createWebAssemblyModule(fileUrl, getCode) {
|
|
325
373
|
const cached = this.moduleCache.get(fileUrl);
|
|
326
374
|
if (cached) return cached;
|
|
327
375
|
const m = this.loadWebAssemblyModule(getCode(), fileUrl);
|
|
328
|
-
|
|
376
|
+
this.moduleCache.set(fileUrl, m);
|
|
377
|
+
return m;
|
|
329
378
|
}
|
|
330
379
|
async createNetworkModule(fileUrl) {
|
|
331
380
|
// https://nodejs.org/api/esm.html#https-and-http-imports
|
|
@@ -341,14 +390,18 @@ class EsmExecutor {
|
|
|
341
390
|
async loadWebAssemblyModule(source, identifier) {
|
|
342
391
|
const cached = this.moduleCache.get(identifier);
|
|
343
392
|
if (cached) return cached;
|
|
344
|
-
const wasmModule = await WebAssembly.compile(source)
|
|
393
|
+
const wasmModule = await WebAssembly.compile(source);
|
|
394
|
+
const exports = WebAssembly.Module.exports(wasmModule);
|
|
395
|
+
const imports = WebAssembly.Module.imports(wasmModule);
|
|
396
|
+
const moduleLookup = {};
|
|
345
397
|
for (const { module } of imports) if (moduleLookup[module] === void 0) moduleLookup[module] = await this.executor.resolveModule(module, identifier);
|
|
346
398
|
const evaluateModule = (module) => this.evaluateModule(module);
|
|
347
399
|
return new SyntheticModule(exports.map(({ name }) => name), async function() {
|
|
348
400
|
const importsObject = {};
|
|
349
401
|
for (const { module, name } of imports) {
|
|
350
402
|
if (!importsObject[module]) importsObject[module] = {};
|
|
351
|
-
await evaluateModule(moduleLookup[module])
|
|
403
|
+
await evaluateModule(moduleLookup[module]);
|
|
404
|
+
importsObject[module][name] = moduleLookup[module].namespace[name];
|
|
352
405
|
}
|
|
353
406
|
const wasmInstance = new WebAssembly.Instance(wasmModule, importsObject);
|
|
354
407
|
for (const { name } of exports) this.setExport(name, wasmInstance.exports[name]);
|
|
@@ -368,12 +421,14 @@ class EsmExecutor {
|
|
|
368
421
|
if (cached) return cached;
|
|
369
422
|
const match = identifier.match(dataURIRegex);
|
|
370
423
|
if (!match || !match.groups) throw new Error("Invalid data URI");
|
|
371
|
-
const mime = match.groups.mime
|
|
424
|
+
const mime = match.groups.mime;
|
|
425
|
+
const encoding = match.groups.encoding;
|
|
372
426
|
if (mime === "application/wasm") {
|
|
373
427
|
if (!encoding) throw new Error("Missing data URI encoding");
|
|
374
428
|
if (encoding !== "base64") throw new Error(`Invalid data URI encoding: ${encoding}`);
|
|
375
429
|
const module = this.loadWebAssemblyModule(Buffer.from(match.groups.code, "base64"), identifier);
|
|
376
|
-
|
|
430
|
+
this.moduleCache.set(identifier, module);
|
|
431
|
+
return module;
|
|
377
432
|
}
|
|
378
433
|
let code = match.groups.code;
|
|
379
434
|
if (!encoding || encoding === "charset=utf-8") code = decodeURIComponent(code);
|
|
@@ -387,7 +442,8 @@ class EsmExecutor {
|
|
|
387
442
|
context: this.context,
|
|
388
443
|
identifier
|
|
389
444
|
});
|
|
390
|
-
|
|
445
|
+
this.moduleCache.set(identifier, module);
|
|
446
|
+
return module;
|
|
391
447
|
}
|
|
392
448
|
return this.createEsModule(identifier, () => code);
|
|
393
449
|
}
|
|
@@ -401,11 +457,13 @@ function IPmask(maskSize) {
|
|
|
401
457
|
return -1 << 32 - maskSize;
|
|
402
458
|
}
|
|
403
459
|
|
|
404
|
-
const CLIENT_ID = "/@vite/client"
|
|
460
|
+
const CLIENT_ID = "/@vite/client";
|
|
461
|
+
const CLIENT_FILE = pathToFileURL(CLIENT_ID).href;
|
|
405
462
|
class ViteExecutor {
|
|
406
463
|
esm;
|
|
407
464
|
constructor(options) {
|
|
408
|
-
this.options = options
|
|
465
|
+
this.options = options;
|
|
466
|
+
this.esm = options.esmExecutor;
|
|
409
467
|
}
|
|
410
468
|
resolve = (identifier) => {
|
|
411
469
|
if (identifier === CLIENT_ID) return identifier;
|
|
@@ -414,7 +472,10 @@ class ViteExecutor {
|
|
|
414
472
|
return this.options.context.__vitest_worker__;
|
|
415
473
|
}
|
|
416
474
|
async createViteModule(fileUrl) {
|
|
417
|
-
|
|
475
|
+
if (fileUrl === CLIENT_FILE || fileUrl === CLIENT_ID) return this.createViteClientModule();
|
|
476
|
+
const cached = this.esm.resolveCachedModule(fileUrl);
|
|
477
|
+
if (cached) return cached;
|
|
478
|
+
return this.esm.createEsModule(fileUrl, async () => {
|
|
418
479
|
try {
|
|
419
480
|
const result = await this.options.transform(fileUrl);
|
|
420
481
|
if (result.code) return result.code;
|
|
@@ -422,16 +483,20 @@ class ViteExecutor {
|
|
|
422
483
|
// rethrow vite error if it cannot load the module because it's not resolved
|
|
423
484
|
if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url")) {
|
|
424
485
|
const error = new Error(`Cannot find module '${fileUrl}'`, { cause });
|
|
425
|
-
|
|
486
|
+
error.code = "ERR_MODULE_NOT_FOUND";
|
|
487
|
+
throw error;
|
|
426
488
|
}
|
|
427
489
|
}
|
|
428
490
|
throw new Error(`[vitest] Failed to transform ${fileUrl}. Does the file exist?`);
|
|
429
491
|
});
|
|
430
492
|
}
|
|
431
493
|
createViteClientModule() {
|
|
432
|
-
const identifier = CLIENT_ID
|
|
494
|
+
const identifier = CLIENT_ID;
|
|
495
|
+
const cached = this.esm.resolveCachedModule(identifier);
|
|
433
496
|
if (cached) return cached;
|
|
434
|
-
const stub = this.options.viteClientModule
|
|
497
|
+
const stub = this.options.viteClientModule;
|
|
498
|
+
const moduleKeys = Object.keys(stub);
|
|
499
|
+
const module = new SyntheticModule(moduleKeys, function() {
|
|
435
500
|
moduleKeys.forEach((key) => {
|
|
436
501
|
this.setExport(key, stub[key]);
|
|
437
502
|
});
|
|
@@ -439,16 +504,23 @@ class ViteExecutor {
|
|
|
439
504
|
context: this.options.context,
|
|
440
505
|
identifier
|
|
441
506
|
});
|
|
442
|
-
|
|
507
|
+
this.esm.cacheModule(identifier, module);
|
|
508
|
+
return module;
|
|
443
509
|
}
|
|
444
510
|
canResolve = (fileUrl) => {
|
|
445
511
|
if (fileUrl === CLIENT_FILE) return true;
|
|
446
|
-
const config = this.workerState.config.deps?.web || {}
|
|
447
|
-
|
|
512
|
+
const config = this.workerState.config.deps?.web || {};
|
|
513
|
+
const [modulePath] = fileUrl.split("?");
|
|
514
|
+
if (config.transformCss && CSS_LANGS_RE.test(modulePath)) return true;
|
|
515
|
+
if (config.transformAssets && KNOWN_ASSET_RE.test(modulePath)) return true;
|
|
516
|
+
if (toArray(config.transformGlobPattern).some((pattern) => pattern.test(modulePath))) return true;
|
|
517
|
+
return false;
|
|
448
518
|
};
|
|
449
519
|
}
|
|
450
520
|
|
|
451
|
-
const { existsSync } = fs
|
|
521
|
+
const { existsSync } = fs;
|
|
522
|
+
// always defined when we use vm pool
|
|
523
|
+
const nativeResolve = import.meta.resolve;
|
|
452
524
|
// TODO: improve Node.js strict mode support in #2854
|
|
453
525
|
class ExternalModulesExecutor {
|
|
454
526
|
cjs;
|
|
@@ -459,21 +531,28 @@ class ExternalModulesExecutor {
|
|
|
459
531
|
resolvers = [];
|
|
460
532
|
#networkSupported = null;
|
|
461
533
|
constructor(options) {
|
|
462
|
-
this.options = options
|
|
534
|
+
this.options = options;
|
|
535
|
+
this.context = options.context;
|
|
536
|
+
this.fs = options.fileMap;
|
|
537
|
+
this.esm = new EsmExecutor(this, { context: this.context });
|
|
538
|
+
this.cjs = new CommonjsExecutor({
|
|
463
539
|
context: this.context,
|
|
464
540
|
importModuleDynamically: this.importModuleDynamically,
|
|
465
541
|
fileMap: options.fileMap,
|
|
466
542
|
interopDefault: options.interopDefault
|
|
467
|
-
})
|
|
543
|
+
});
|
|
544
|
+
this.vite = new ViteExecutor({
|
|
468
545
|
esmExecutor: this.esm,
|
|
469
546
|
context: this.context,
|
|
470
547
|
transform: options.transform,
|
|
471
548
|
viteClientModule: options.viteClientModule
|
|
472
|
-
})
|
|
549
|
+
});
|
|
550
|
+
this.resolvers = [this.vite.resolve];
|
|
473
551
|
}
|
|
474
552
|
async import(identifier) {
|
|
475
553
|
const module = await this.createModule(identifier);
|
|
476
|
-
|
|
554
|
+
await this.esm.evaluateModule(module);
|
|
555
|
+
return module.namespace;
|
|
477
556
|
}
|
|
478
557
|
require(identifier) {
|
|
479
558
|
return this.cjs.require(identifier);
|
|
@@ -516,7 +595,9 @@ class ExternalModulesExecutor {
|
|
|
516
595
|
url: identifier,
|
|
517
596
|
path: identifier
|
|
518
597
|
};
|
|
519
|
-
const isFileUrl = identifier.startsWith("file://")
|
|
598
|
+
const isFileUrl = identifier.startsWith("file://");
|
|
599
|
+
const pathUrl = isFileUrl ? fileURLToPath(identifier.split("?")[0]) : identifier;
|
|
600
|
+
const fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString();
|
|
520
601
|
let type;
|
|
521
602
|
if (this.vite.canResolve(fileUrl)) type = "vite";
|
|
522
603
|
else if (extension === ".mjs") type = "module";
|
|
@@ -538,7 +619,8 @@ class ExternalModulesExecutor {
|
|
|
538
619
|
// https://github.com/nodejs/node/pull/49038
|
|
539
620
|
if ((type === "module" || type === "commonjs" || type === "wasm") && !existsSync(path)) {
|
|
540
621
|
const error = /* @__PURE__ */ new Error(`Cannot find ${isBareImport(path) ? "package" : "module"} '${path}'`);
|
|
541
|
-
|
|
622
|
+
error.code = "ERR_MODULE_NOT_FOUND";
|
|
623
|
+
throw error;
|
|
542
624
|
}
|
|
543
625
|
switch (type) {
|
|
544
626
|
case "data": return this.esm.createDataModule(identifier);
|
|
@@ -567,48 +649,70 @@ class FileMap {
|
|
|
567
649
|
const cached = this.fsCache.get(path);
|
|
568
650
|
if (cached != null) return cached;
|
|
569
651
|
const source = await promises.readFile(path, "utf-8");
|
|
570
|
-
|
|
652
|
+
this.fsCache.set(path, source);
|
|
653
|
+
return source;
|
|
571
654
|
}
|
|
572
655
|
readFile(path) {
|
|
573
656
|
const cached = this.fsCache.get(path);
|
|
574
657
|
if (cached != null) return cached;
|
|
575
658
|
const source = readFileSync(path, "utf-8");
|
|
576
|
-
|
|
659
|
+
this.fsCache.set(path, source);
|
|
660
|
+
return source;
|
|
577
661
|
}
|
|
578
662
|
readBuffer(path) {
|
|
579
663
|
const cached = this.fsBufferCache.get(path);
|
|
580
664
|
if (cached != null) return cached;
|
|
581
665
|
const buffer = readFileSync(path);
|
|
582
|
-
|
|
666
|
+
this.fsBufferCache.set(path, buffer);
|
|
667
|
+
return buffer;
|
|
583
668
|
}
|
|
584
669
|
}
|
|
585
670
|
|
|
586
|
-
const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href
|
|
671
|
+
const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href;
|
|
672
|
+
const fileMap = new FileMap();
|
|
673
|
+
const packageCache = /* @__PURE__ */ new Map();
|
|
587
674
|
async function runVmTests(method, state) {
|
|
588
|
-
const {
|
|
675
|
+
const { ctx, rpc } = state;
|
|
676
|
+
const beforeEnvironmentTime = performance.now();
|
|
677
|
+
const { environment } = await loadEnvironment(ctx.environment.name, ctx.config.root, rpc);
|
|
678
|
+
state.environment = environment;
|
|
589
679
|
if (!environment.setupVM) {
|
|
590
|
-
const envName = ctx.environment.name
|
|
680
|
+
const envName = ctx.environment.name;
|
|
681
|
+
const packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
|
|
591
682
|
throw new TypeError(`Environment "${ctx.environment.name}" is not a valid environment. Path "${packageId}" doesn't support vm environment because it doesn't provide "setupVM" method.`);
|
|
592
683
|
}
|
|
593
684
|
const vm = await environment.setupVM(ctx.environment.options || ctx.config.environmentOptions || {});
|
|
594
|
-
|
|
685
|
+
state.durations.environment = performance.now() - beforeEnvironmentTime;
|
|
686
|
+
process.env.VITEST_VM_POOL = "1";
|
|
687
|
+
if (!vm.getVmContext) throw new TypeError(`Environment ${environment.name} doesn't provide "getVmContext" method. It should return a context created by "vm.createContext" method.`);
|
|
595
688
|
const context = vm.getVmContext();
|
|
596
689
|
if (!isContext(context)) throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
|
|
597
|
-
provideWorkerState(context, state)
|
|
598
|
-
|
|
690
|
+
provideWorkerState(context, state);
|
|
691
|
+
// this is unfortunately needed for our own dependencies
|
|
692
|
+
// we need to find a way to not rely on this by default
|
|
693
|
+
// because browser doesn't provide these globals
|
|
694
|
+
context.process = process;
|
|
695
|
+
context.global = context;
|
|
696
|
+
context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state);
|
|
697
|
+
// TODO: don't hardcode setImmediate in fake timers defaults
|
|
698
|
+
context.setImmediate = setImmediate;
|
|
699
|
+
context.clearImmediate = clearImmediate;
|
|
700
|
+
const stubs = getDefaultRequestStubs(context);
|
|
701
|
+
const externalModulesExecutor = new ExternalModulesExecutor({
|
|
599
702
|
context,
|
|
600
703
|
fileMap,
|
|
601
704
|
packageCache,
|
|
602
705
|
transform: rpc.transform,
|
|
603
706
|
viteClientModule: stubs["/@vite/client"]
|
|
604
|
-
})
|
|
707
|
+
});
|
|
708
|
+
const moduleRunner = startVitestModuleRunner({
|
|
605
709
|
context,
|
|
606
710
|
evaluatedModules: state.evaluatedModules,
|
|
607
711
|
state,
|
|
608
712
|
externalModulesExecutor,
|
|
609
713
|
createImportMeta: createNodeImportMeta
|
|
610
714
|
});
|
|
611
|
-
|
|
715
|
+
Object.defineProperty(context, VITEST_VM_CONTEXT_SYMBOL, {
|
|
612
716
|
value: {
|
|
613
717
|
context,
|
|
614
718
|
externalModulesExecutor
|
|
@@ -616,20 +720,23 @@ async function runVmTests(method, state) {
|
|
|
616
720
|
configurable: true,
|
|
617
721
|
enumerable: false,
|
|
618
722
|
writable: false
|
|
619
|
-
})
|
|
723
|
+
});
|
|
724
|
+
context.__vitest_mocker__ = moduleRunner.mocker;
|
|
725
|
+
if (ctx.config.serializedDefines) try {
|
|
620
726
|
runInContext(ctx.config.serializedDefines, context, { filename: "virtual:load-defines.js" });
|
|
621
727
|
} catch (error) {
|
|
622
728
|
throw new Error(`Failed to load custom "defines": ${error.message}`);
|
|
623
729
|
}
|
|
624
730
|
await moduleRunner.mocker.initializeSpyModule();
|
|
625
|
-
const { run } = await moduleRunner.import(entryFile)
|
|
731
|
+
const { run } = await moduleRunner.import(entryFile);
|
|
732
|
+
const fileSpecs = ctx.files.map((f) => typeof f === "string" ? {
|
|
626
733
|
filepath: f,
|
|
627
734
|
testLocations: void 0
|
|
628
735
|
} : f);
|
|
629
736
|
try {
|
|
630
737
|
await run(method, fileSpecs, ctx.config, moduleRunner);
|
|
631
738
|
} finally {
|
|
632
|
-
await vm.teardown?.()
|
|
739
|
+
await vm.teardown?.();
|
|
633
740
|
}
|
|
634
741
|
}
|
|
635
742
|
|