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