vitest 4.0.0-beta.4 → 4.0.0-beta.6
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 +8 -9
- package/dist/browser.js +3 -2
- package/dist/chunks/base.BXI97p6t.js +39 -0
- package/dist/chunks/{benchmark.CYdenmiT.js → benchmark.UW6Ezvxy.js} +6 -8
- package/dist/chunks/{browser.d.BRP8scJf.d.ts → browser.d.Cawq_X_N.d.ts} +1 -1
- package/dist/chunks/{cac.CY0IAxC4.js → cac.WE-urWw5.js} +38 -115
- package/dist/chunks/{cli-api.B8xRY9Zt.js → cli-api.CZz3evYC.js} +931 -1439
- package/dist/chunks/{config.d.DZo8c7fw.d.ts → config.d.CKNVOKm0.d.ts} +3 -8
- package/dist/chunks/{console.DoJHFxmj.js → console.B0quX7yH.js} +32 -68
- package/dist/chunks/{constants.CXzqaLmq.js → constants.D_Q9UYh-.js} +1 -6
- package/dist/chunks/{coverage.C84l9G-M.js → coverage.BPRS6xgn.js} +395 -665
- package/dist/chunks/{coverage.DVF1vEu8.js → coverage.D_JHT54q.js} +2 -2
- package/dist/chunks/{coverage.d.CNYjU4GF.d.ts → coverage.d.BZtK59WP.d.ts} +7 -5
- package/dist/chunks/{creator.yfA2ExGt.js → creator.KEg6n5IC.js} +29 -75
- package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
- package/dist/chunks/{environment.d.Bhm9oc0v.d.ts → environment.d.2fYMoz3o.d.ts} +26 -4
- package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
- package/dist/chunks/{global.d.DAhT2emn.d.ts → global.d.K6uBQHzY.d.ts} +1 -1
- package/dist/chunks/{globals.Dgo-vS5G.js → globals.lgsmH00r.js} +7 -6
- package/dist/chunks/{index.D3SKT3tv.js → index.7w0eqmYM.js} +14 -24
- package/dist/chunks/{index.D1_MsKEt.js → index.AR8aAkCC.js} +4 -2
- package/dist/chunks/{index.CmSc2RE5.js → index.BG0gqZH-.js} +43 -106
- package/dist/chunks/{index.CtUvr1c8.js → index.CsFXYRkW.js} +27 -46
- package/dist/chunks/{index.Bz6b0Ib7.js → index.VNI-1z5c.js} +276 -604
- package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
- package/dist/chunks/moduleRunner.d.8kKUsuDg.d.ts +202 -0
- package/dist/chunks/moduleTransport.I-bgQy0S.js +19 -0
- package/dist/chunks/{node.fjCdwEIl.js → node.BOqcT2jW.js} +1 -1
- package/dist/chunks/{plugin.d.CLhMcYdD.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DWg40D2B.d.ts → reporters.d.CqR9-CDJ.d.ts} +52 -101
- package/dist/chunks/resolver.Bx6lE0iq.js +119 -0
- package/dist/chunks/{rpc.jnQO9F8a.js → rpc.RpPylpp0.js} +7 -21
- package/dist/chunks/runBaseTests.D6sfuWBM.js +99 -0
- package/dist/chunks/{setup-common.Ebx5x0eP.js → setup-common.hLGRxhC8.js} +15 -27
- package/dist/chunks/startModuleRunner.C8TW8zTN.js +655 -0
- package/dist/chunks/{typechecker.CMNPqJOo.js → typechecker.Cd1wvxUM.js} +97 -209
- package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
- package/dist/chunks/{utils.XdZDrNZV.js → utils.C7__0Iv5.js} +7 -17
- package/dist/chunks/{vi.CA0EPI9Y.js → vi.BfdOiD4j.js} +116 -269
- package/dist/chunks/{vm.BUnLJt_P.js → vm.BHBje7cC.js} +101 -225
- package/dist/chunks/{worker.d.zjyR34Pb.d.ts → worker.d.D9QWnzAe.d.ts} +16 -13
- package/dist/chunks/{worker.d.C-1AbnVe.d.ts → worker.d.Db-UVmXc.d.ts} +1 -1
- package/dist/cli.js +4 -4
- package/dist/config.cjs +3 -9
- package/dist/config.d.ts +10 -12
- package/dist/config.js +1 -1
- package/dist/coverage.d.ts +10 -11
- package/dist/coverage.js +5 -6
- package/dist/environments.d.ts +2 -2
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +10 -9
- package/dist/index.js +6 -5
- package/dist/module-evaluator.d.ts +12 -0
- package/dist/module-evaluator.js +276 -0
- package/dist/module-runner.js +15 -0
- package/dist/node.d.ts +12 -13
- package/dist/node.js +19 -24
- package/dist/reporters.d.ts +7 -8
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +3 -3
- package/dist/runners.js +35 -57
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +82 -45
- package/dist/workers/forks.js +11 -10
- package/dist/workers/runVmTests.js +27 -46
- package/dist/workers/threads.js +11 -10
- package/dist/workers/vmForks.js +11 -10
- package/dist/workers/vmThreads.js +11 -10
- package/dist/workers.d.ts +5 -4
- package/dist/workers.js +17 -16
- package/package.json +22 -17
- package/dist/chunks/base.BaCDDRPG.js +0 -38
- package/dist/chunks/execute.Dt-pCVcL.js +0 -708
- package/dist/chunks/runBaseTests.DBVVLMSb.js +0 -129
- package/dist/execute.d.ts +0 -148
- package/dist/execute.js +0 -13
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
2
2
|
import vm, { isContext } from 'node:vm';
|
|
3
|
-
import { dirname, basename, extname, normalize,
|
|
3
|
+
import { dirname, basename, extname, normalize, resolve } from 'pathe';
|
|
4
4
|
import { distDir } from '../path.js';
|
|
5
|
-
import { createCustomConsole } from './console.
|
|
6
|
-
import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.Dt-pCVcL.js';
|
|
5
|
+
import { createCustomConsole } from './console.B0quX7yH.js';
|
|
7
6
|
import fs from 'node:fs';
|
|
7
|
+
import { createRequire, Module, isBuiltin } from 'node:module';
|
|
8
|
+
import { CSS_LANGS_RE, KNOWN_ASSET_RE, toArray, isBareImport } from '@vitest/utils';
|
|
9
|
+
import { f as findNearestPackageData } from './resolver.Bx6lE0iq.js';
|
|
8
10
|
import { dirname as dirname$1 } from 'node:path';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { p as provideWorkerState } from './utils.XdZDrNZV.js';
|
|
11
|
+
import { getDefaultRequestStubs } from '../module-evaluator.js';
|
|
12
|
+
import { s as startVitestModuleRunner, a as VITEST_VM_CONTEXT_SYMBOL } from './startModuleRunner.C8TW8zTN.js';
|
|
13
|
+
import { p as provideWorkerState } from './utils.C7__0Iv5.js';
|
|
13
14
|
|
|
14
15
|
function interopCommonJsModule(interopDefault, mod) {
|
|
15
16
|
if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) return {
|
|
@@ -18,11 +19,8 @@ function interopCommonJsModule(interopDefault, mod) {
|
|
|
18
19
|
defaultExport: mod
|
|
19
20
|
};
|
|
20
21
|
if (interopDefault !== false && "__esModule" in mod && !isPrimitive(mod.default)) {
|
|
21
|
-
const defaultKets = Object.keys(mod.default);
|
|
22
|
-
|
|
23
|
-
const allKeys = new Set([...defaultKets, ...moduleKeys]);
|
|
24
|
-
allKeys.delete("default");
|
|
25
|
-
return {
|
|
22
|
+
const defaultKets = Object.keys(mod.default), moduleKeys = Object.keys(mod), allKeys = new Set([...defaultKets, ...moduleKeys]);
|
|
23
|
+
return allKeys.delete("default"), {
|
|
26
24
|
keys: Array.from(allKeys),
|
|
27
25
|
moduleExports: new Proxy(mod, { get(mod, prop) {
|
|
28
26
|
return mod[prop] ?? mod.default?.[prop];
|
|
@@ -36,11 +34,14 @@ function interopCommonJsModule(interopDefault, mod) {
|
|
|
36
34
|
defaultExport: mod
|
|
37
35
|
};
|
|
38
36
|
}
|
|
37
|
+
function isPrimitive(obj) {
|
|
38
|
+
const isObject = obj != null && (typeof obj === "object" || typeof obj === "function");
|
|
39
|
+
return !isObject;
|
|
40
|
+
}
|
|
39
41
|
const SyntheticModule = vm.SyntheticModule;
|
|
40
42
|
const SourceTextModule = vm.SourceTextModule;
|
|
41
43
|
|
|
42
|
-
const _require = createRequire(import.meta.url);
|
|
43
|
-
const requiresCache = /* @__PURE__ */ new WeakMap();
|
|
44
|
+
const _require = createRequire(import.meta.url), requiresCache = /* @__PURE__ */ new WeakMap();
|
|
44
45
|
class CommonjsExecutor {
|
|
45
46
|
context;
|
|
46
47
|
requireCache = /* @__PURE__ */ new Map();
|
|
@@ -52,12 +53,8 @@ class CommonjsExecutor {
|
|
|
52
53
|
Module;
|
|
53
54
|
interopDefault;
|
|
54
55
|
constructor(options) {
|
|
55
|
-
this.context = options.context;
|
|
56
|
-
this.
|
|
57
|
-
this.interopDefault = options.interopDefault;
|
|
58
|
-
const primitives = vm.runInContext("({ Object, Array, Error })", this.context);
|
|
59
|
-
// eslint-disable-next-line ts/no-this-alias
|
|
60
|
-
const executor = this;
|
|
56
|
+
this.context = options.context, this.fs = options.fileMap, this.interopDefault = options.interopDefault;
|
|
57
|
+
const primitives = vm.runInContext("({ Object, Array, Error })", this.context), executor = this;
|
|
61
58
|
this.Module = class Module$1 {
|
|
62
59
|
exports;
|
|
63
60
|
isPreloading = false;
|
|
@@ -69,20 +66,13 @@ class CommonjsExecutor {
|
|
|
69
66
|
path;
|
|
70
67
|
paths = [];
|
|
71
68
|
constructor(id = "", parent) {
|
|
72
|
-
this.exports = primitives.Object.create(Object.prototype);
|
|
73
|
-
// in our case the path should always be resolved already
|
|
74
|
-
this.path = dirname(id);
|
|
75
|
-
this.id = id;
|
|
76
|
-
this.filename = id;
|
|
77
|
-
this.loaded = false;
|
|
78
|
-
this.parent = parent;
|
|
69
|
+
this.exports = primitives.Object.create(Object.prototype), this.path = dirname(id), this.id = id, this.filename = id, this.loaded = false, this.parent = parent;
|
|
79
70
|
}
|
|
80
71
|
get require() {
|
|
81
72
|
const require = requiresCache.get(this);
|
|
82
73
|
if (require) return require;
|
|
83
74
|
const _require = Module$1.createRequire(this.id);
|
|
84
|
-
requiresCache.set(this, _require);
|
|
85
|
-
return _require;
|
|
75
|
+
return requiresCache.set(this, _require), _require;
|
|
86
76
|
}
|
|
87
77
|
static getSourceMapsSupport = () => ({
|
|
88
78
|
enabled: false,
|
|
@@ -99,19 +89,16 @@ class CommonjsExecutor {
|
|
|
99
89
|
throw new Error(`[vitest] "registerHooks" is not available when running in Vitest.`);
|
|
100
90
|
};
|
|
101
91
|
_compile(code, filename) {
|
|
102
|
-
const cjsModule = Module$1.wrap(code)
|
|
103
|
-
const script = new vm.Script(cjsModule, {
|
|
92
|
+
const cjsModule = Module$1.wrap(code), script = new vm.Script(cjsModule, {
|
|
104
93
|
filename,
|
|
105
94
|
importModuleDynamically: options.importModuleDynamically
|
|
106
95
|
});
|
|
107
96
|
// @ts-expect-error mark script with current identifier
|
|
108
97
|
script.identifier = filename;
|
|
109
|
-
const fn = script.runInContext(executor.context);
|
|
110
|
-
const __dirname = dirname(filename);
|
|
98
|
+
const fn = script.runInContext(executor.context), __dirname = dirname(filename);
|
|
111
99
|
executor.requireCache.set(filename, this);
|
|
112
100
|
try {
|
|
113
|
-
fn(this.exports, this.require, this, filename, __dirname);
|
|
114
|
-
return this.exports;
|
|
101
|
+
return fn(this.exports, this.require, this, filename, __dirname), this.exports;
|
|
115
102
|
} finally {
|
|
116
103
|
this.loaded = true;
|
|
117
104
|
}
|
|
@@ -157,9 +144,7 @@ class CommonjsExecutor {
|
|
|
157
144
|
static stripTypeScriptTypes = Module.stripTypeScriptTypes;
|
|
158
145
|
static findPackageJSON = Module.findPackageJSON;
|
|
159
146
|
static Module = Module$1;
|
|
160
|
-
};
|
|
161
|
-
this.extensions[".js"] = this.requireJs;
|
|
162
|
-
this.extensions[".json"] = this.requireJson;
|
|
147
|
+
}, this.extensions[".js"] = this.requireJs, this.extensions[".json"] = this.requireJson;
|
|
163
148
|
}
|
|
164
149
|
requireJs = (m, filename) => {
|
|
165
150
|
const content = this.fs.readFile(filename);
|
|
@@ -170,23 +155,17 @@ class CommonjsExecutor {
|
|
|
170
155
|
m.exports = JSON.parse(code);
|
|
171
156
|
};
|
|
172
157
|
createRequire = (filename) => {
|
|
173
|
-
const _require = createRequire(filename)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const ext = extname(resolved);
|
|
177
|
-
if (ext === ".node" || isNodeBuiltin(resolved)) return this.requireCoreModule(resolved);
|
|
158
|
+
const _require = createRequire(filename), require = ((id) => {
|
|
159
|
+
const resolved = _require.resolve(id), ext = extname(resolved);
|
|
160
|
+
if (ext === ".node" || isBuiltin(resolved)) return this.requireCoreModule(resolved);
|
|
178
161
|
const module = new this.Module(resolved);
|
|
179
162
|
return this.loadCommonJSModule(module, resolved);
|
|
180
|
-
};
|
|
181
|
-
require.resolve = _require.resolve
|
|
182
|
-
Object.defineProperty(require, "extensions", {
|
|
163
|
+
});
|
|
164
|
+
return require.resolve = _require.resolve, Object.defineProperty(require, "extensions", {
|
|
183
165
|
get: () => this.extensions,
|
|
184
166
|
set: () => {},
|
|
185
167
|
configurable: true
|
|
186
|
-
});
|
|
187
|
-
require.main = void 0;
|
|
188
|
-
require.cache = this.publicRequireCache;
|
|
189
|
-
return require;
|
|
168
|
+
}), require.main = void 0, require.cache = this.publicRequireCache, require;
|
|
190
169
|
};
|
|
191
170
|
createProxyCache() {
|
|
192
171
|
return new Proxy(Object.create(null), {
|
|
@@ -208,53 +187,40 @@ class CommonjsExecutor {
|
|
|
208
187
|
loadCommonJSModule(module, filename) {
|
|
209
188
|
const cached = this.requireCache.get(filename);
|
|
210
189
|
if (cached) return cached.exports;
|
|
211
|
-
const extension = this.findLongestRegisteredExtension(filename);
|
|
212
|
-
|
|
213
|
-
loader(module, filename);
|
|
214
|
-
return module.exports;
|
|
190
|
+
const extension = this.findLongestRegisteredExtension(filename), loader = this.extensions[extension] || this.extensions[".js"];
|
|
191
|
+
return loader(module, filename), module.exports;
|
|
215
192
|
}
|
|
216
193
|
findLongestRegisteredExtension(filename) {
|
|
217
194
|
const name = basename(filename);
|
|
218
|
-
let currentExtension;
|
|
219
|
-
let index;
|
|
220
|
-
let startIndex = 0;
|
|
195
|
+
let currentExtension, index, startIndex = 0;
|
|
221
196
|
// eslint-disable-next-line no-cond-assign
|
|
222
197
|
while ((index = name.indexOf(".", startIndex)) !== -1) {
|
|
223
|
-
startIndex = index + 1;
|
|
224
|
-
if (
|
|
225
|
-
currentExtension = name.slice(index);
|
|
226
|
-
if (this.extensions[currentExtension]) return currentExtension;
|
|
198
|
+
if (startIndex = index + 1, index === 0) continue;
|
|
199
|
+
if (currentExtension = name.slice(index), this.extensions[currentExtension]) return currentExtension;
|
|
227
200
|
}
|
|
228
201
|
return ".js";
|
|
229
202
|
}
|
|
230
203
|
getCoreSyntheticModule(identifier) {
|
|
231
204
|
if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
|
|
232
|
-
const exports = this.require(identifier)
|
|
233
|
-
const keys = Object.keys(exports);
|
|
234
|
-
const module = new SyntheticModule([...keys, "default"], () => {
|
|
205
|
+
const exports = this.require(identifier), keys = Object.keys(exports), module = new SyntheticModule([...keys, "default"], () => {
|
|
235
206
|
for (const key of keys) module.setExport(key, exports[key]);
|
|
236
207
|
module.setExport("default", exports);
|
|
237
208
|
}, {
|
|
238
209
|
context: this.context,
|
|
239
210
|
identifier
|
|
240
211
|
});
|
|
241
|
-
this.moduleCache.set(identifier, module);
|
|
242
|
-
return module;
|
|
212
|
+
return this.moduleCache.set(identifier, module), module;
|
|
243
213
|
}
|
|
244
214
|
getCjsSyntheticModule(path, identifier) {
|
|
245
215
|
if (this.moduleCache.has(identifier)) return this.moduleCache.get(identifier);
|
|
246
|
-
const exports = this.require(path)
|
|
247
|
-
// TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
|
|
248
|
-
const { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports);
|
|
249
|
-
const module = new SyntheticModule([...keys, "default"], function() {
|
|
216
|
+
const exports = this.require(path), { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports), module = new SyntheticModule([...keys, "default"], function() {
|
|
250
217
|
for (const key of keys) this.setExport(key, moduleExports[key]);
|
|
251
218
|
this.setExport("default", defaultExport);
|
|
252
219
|
}, {
|
|
253
220
|
context: this.context,
|
|
254
221
|
identifier
|
|
255
222
|
});
|
|
256
|
-
this.moduleCache.set(identifier, module);
|
|
257
|
-
return module;
|
|
223
|
+
return this.moduleCache.set(identifier, module), module;
|
|
258
224
|
}
|
|
259
225
|
// TODO: use this in strict mode, when available in #2854
|
|
260
226
|
// private _getNamedCjsExports(path: string): Set<string> {
|
|
@@ -294,7 +260,7 @@ class CommonjsExecutor {
|
|
|
294
260
|
// }
|
|
295
261
|
require(identifier) {
|
|
296
262
|
const ext = extname(identifier);
|
|
297
|
-
if (ext === ".node" ||
|
|
263
|
+
if (ext === ".node" || isBuiltin(identifier)) return this.requireCoreModule(identifier);
|
|
298
264
|
const module = new this.Module(identifier);
|
|
299
265
|
return this.loadCommonJSModule(module, identifier);
|
|
300
266
|
}
|
|
@@ -304,13 +270,10 @@ class CommonjsExecutor {
|
|
|
304
270
|
const moduleExports = _require(identifier);
|
|
305
271
|
if (identifier === "node:module" || identifier === "module") {
|
|
306
272
|
const module = new this.Module("/module.js");
|
|
307
|
-
module.exports = this.Module;
|
|
308
|
-
this.builtinCache[normalized] = module;
|
|
309
|
-
return module.exports;
|
|
273
|
+
return module.exports = this.Module, this.builtinCache[normalized] = module, module.exports;
|
|
310
274
|
}
|
|
311
|
-
this.builtinCache[normalized] = _require.cache[normalized];
|
|
312
275
|
// TODO: should we wrap module to rethrow context errors?
|
|
313
|
-
return moduleExports;
|
|
276
|
+
return this.builtinCache[normalized] = _require.cache[normalized], moduleExports;
|
|
314
277
|
}
|
|
315
278
|
}
|
|
316
279
|
|
|
@@ -321,21 +284,18 @@ class EsmExecutor {
|
|
|
321
284
|
context;
|
|
322
285
|
#httpIp = IPnumber("127.0.0.0");
|
|
323
286
|
constructor(executor, options) {
|
|
324
|
-
this.executor = executor;
|
|
325
|
-
this.context = options.context;
|
|
287
|
+
this.executor = executor, this.context = options.context;
|
|
326
288
|
}
|
|
327
289
|
async evaluateModule(m) {
|
|
328
290
|
if (m.status === "unlinked") this.esmLinkMap.set(m, m.link((identifier, referencer) => this.executor.resolveModule(identifier, referencer.identifier)));
|
|
329
|
-
await this.esmLinkMap.get(m);
|
|
330
|
-
if (m.status === "linked") await m.evaluate();
|
|
291
|
+
if (await this.esmLinkMap.get(m), m.status === "linked") await m.evaluate();
|
|
331
292
|
return m;
|
|
332
293
|
}
|
|
333
294
|
async createEsModule(fileURL, getCode) {
|
|
334
295
|
const cached = this.moduleCache.get(fileURL);
|
|
335
296
|
if (cached) return cached;
|
|
336
297
|
const promise = this.loadEsModule(fileURL, getCode);
|
|
337
|
-
this.moduleCache.set(fileURL, promise);
|
|
338
|
-
return promise;
|
|
298
|
+
return this.moduleCache.set(fileURL, promise), promise;
|
|
339
299
|
}
|
|
340
300
|
async loadEsModule(fileURL, getCode) {
|
|
341
301
|
const code = await getCode();
|
|
@@ -345,34 +305,29 @@ class EsmExecutor {
|
|
|
345
305
|
const result = JSON.parse(code);
|
|
346
306
|
this.setExport("default", result);
|
|
347
307
|
});
|
|
348
|
-
this.moduleCache.set(fileURL, m);
|
|
349
|
-
return m;
|
|
308
|
+
return this.moduleCache.set(fileURL, m), m;
|
|
350
309
|
}
|
|
351
310
|
const m = new SourceTextModule(code, {
|
|
352
311
|
identifier: fileURL,
|
|
353
312
|
context: this.context,
|
|
354
313
|
importModuleDynamically: this.executor.importModuleDynamically,
|
|
355
314
|
initializeImportMeta: (meta, mod) => {
|
|
356
|
-
meta.url = mod.identifier
|
|
357
|
-
if (mod.identifier.startsWith("file:")) {
|
|
315
|
+
if (meta.url = mod.identifier, mod.identifier.startsWith("file:")) {
|
|
358
316
|
const filename = fileURLToPath(mod.identifier);
|
|
359
|
-
meta.filename = filename;
|
|
360
|
-
meta.dirname = dirname$1(filename);
|
|
317
|
+
meta.filename = filename, meta.dirname = dirname$1(filename);
|
|
361
318
|
}
|
|
362
319
|
meta.resolve = (specifier, importer) => {
|
|
363
320
|
return this.executor.resolve(specifier, importer != null ? importer.toString() : mod.identifier);
|
|
364
321
|
};
|
|
365
322
|
}
|
|
366
323
|
});
|
|
367
|
-
this.moduleCache.set(fileURL, m);
|
|
368
|
-
return m;
|
|
324
|
+
return this.moduleCache.set(fileURL, m), m;
|
|
369
325
|
}
|
|
370
326
|
async createWebAssemblyModule(fileUrl, getCode) {
|
|
371
327
|
const cached = this.moduleCache.get(fileUrl);
|
|
372
328
|
if (cached) return cached;
|
|
373
329
|
const m = this.loadWebAssemblyModule(getCode(), fileUrl);
|
|
374
|
-
this.moduleCache.set(fileUrl, m);
|
|
375
|
-
return m;
|
|
330
|
+
return this.moduleCache.set(fileUrl, m), m;
|
|
376
331
|
}
|
|
377
332
|
async createNetworkModule(fileUrl) {
|
|
378
333
|
// https://nodejs.org/api/esm.html#https-and-http-imports
|
|
@@ -388,18 +343,13 @@ class EsmExecutor {
|
|
|
388
343
|
async loadWebAssemblyModule(source, identifier) {
|
|
389
344
|
const cached = this.moduleCache.get(identifier);
|
|
390
345
|
if (cached) return cached;
|
|
391
|
-
const wasmModule = await WebAssembly.compile(source);
|
|
392
|
-
const exports = WebAssembly.Module.exports(wasmModule);
|
|
393
|
-
const imports = WebAssembly.Module.imports(wasmModule);
|
|
394
|
-
const moduleLookup = {};
|
|
346
|
+
const wasmModule = await WebAssembly.compile(source), exports = WebAssembly.Module.exports(wasmModule), imports = WebAssembly.Module.imports(wasmModule), moduleLookup = {};
|
|
395
347
|
for (const { module } of imports) if (moduleLookup[module] === void 0) moduleLookup[module] = await this.executor.resolveModule(module, identifier);
|
|
396
|
-
const evaluateModule = (module) => this.evaluateModule(module)
|
|
397
|
-
const syntheticModule = new SyntheticModule(exports.map(({ name }) => name), async function() {
|
|
348
|
+
const evaluateModule = (module) => this.evaluateModule(module), syntheticModule = new SyntheticModule(exports.map(({ name }) => name), async function() {
|
|
398
349
|
const importsObject = {};
|
|
399
350
|
for (const { module, name } of imports) {
|
|
400
351
|
if (!importsObject[module]) importsObject[module] = {};
|
|
401
|
-
await evaluateModule(moduleLookup[module]);
|
|
402
|
-
importsObject[module][name] = moduleLookup[module].namespace[name];
|
|
352
|
+
await evaluateModule(moduleLookup[module]), importsObject[module][name] = moduleLookup[module].namespace[name];
|
|
403
353
|
}
|
|
404
354
|
const wasmInstance = new WebAssembly.Instance(wasmModule, importsObject);
|
|
405
355
|
for (const { name } of exports) this.setExport(name, wasmInstance.exports[name]);
|
|
@@ -420,14 +370,12 @@ class EsmExecutor {
|
|
|
420
370
|
if (cached) return cached;
|
|
421
371
|
const match = identifier.match(dataURIRegex);
|
|
422
372
|
if (!match || !match.groups) throw new Error("Invalid data URI");
|
|
423
|
-
const mime = match.groups.mime;
|
|
424
|
-
const encoding = match.groups.encoding;
|
|
373
|
+
const mime = match.groups.mime, encoding = match.groups.encoding;
|
|
425
374
|
if (mime === "application/wasm") {
|
|
426
375
|
if (!encoding) throw new Error("Missing data URI encoding");
|
|
427
376
|
if (encoding !== "base64") throw new Error(`Invalid data URI encoding: ${encoding}`);
|
|
428
377
|
const module = this.loadWebAssemblyModule(Buffer.from(match.groups.code, "base64"), identifier);
|
|
429
|
-
this.moduleCache.set(identifier, module);
|
|
430
|
-
return module;
|
|
378
|
+
return this.moduleCache.set(identifier, module), module;
|
|
431
379
|
}
|
|
432
380
|
let code = match.groups.code;
|
|
433
381
|
if (!encoding || encoding === "charset=utf-8") code = decodeURIComponent(code);
|
|
@@ -441,8 +389,7 @@ class EsmExecutor {
|
|
|
441
389
|
context: this.context,
|
|
442
390
|
identifier
|
|
443
391
|
});
|
|
444
|
-
this.moduleCache.set(identifier, module);
|
|
445
|
-
return module;
|
|
392
|
+
return this.moduleCache.set(identifier, module), module;
|
|
446
393
|
}
|
|
447
394
|
return this.createEsModule(identifier, () => code);
|
|
448
395
|
}
|
|
@@ -456,57 +403,39 @@ function IPmask(maskSize) {
|
|
|
456
403
|
return -1 << 32 - maskSize;
|
|
457
404
|
}
|
|
458
405
|
|
|
459
|
-
const CLIENT_ID = "/@vite/client";
|
|
460
|
-
const CLIENT_FILE = pathToFileURL(CLIENT_ID).href;
|
|
406
|
+
const CLIENT_ID = "/@vite/client", CLIENT_FILE = pathToFileURL(CLIENT_ID).href;
|
|
461
407
|
class ViteExecutor {
|
|
462
408
|
esm;
|
|
463
409
|
constructor(options) {
|
|
464
|
-
this.options = options;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
if (identifier === CLIENT_ID) {
|
|
469
|
-
if (this.workerState.environment.transformMode === "web") return identifier;
|
|
470
|
-
const packageName = this.getPackageName(parent);
|
|
471
|
-
throw new Error(`[vitest] Vitest cannot handle ${CLIENT_ID} imported in ${parent} when running in SSR environment. Add "${packageName}" to "ssr.noExternal" if you are using Vite SSR, or to "server.deps.inline" if you are using Vite Node.`);
|
|
472
|
-
}
|
|
410
|
+
this.options = options, this.esm = options.esmExecutor;
|
|
411
|
+
}
|
|
412
|
+
resolve = (identifier) => {
|
|
413
|
+
if (identifier === CLIENT_ID) return identifier;
|
|
473
414
|
};
|
|
474
415
|
get workerState() {
|
|
475
416
|
return this.options.context.__vitest_worker__;
|
|
476
417
|
}
|
|
477
|
-
getPackageName(modulePath) {
|
|
478
|
-
const path = normalize(modulePath);
|
|
479
|
-
let name = path.split("/node_modules/").pop() || "";
|
|
480
|
-
if (name?.startsWith("@")) name = name.split("/").slice(0, 2).join("/");
|
|
481
|
-
else name = name.split("/")[0];
|
|
482
|
-
return name;
|
|
483
|
-
}
|
|
484
418
|
async createViteModule(fileUrl) {
|
|
485
|
-
if (fileUrl === CLIENT_FILE) return this.createViteClientModule();
|
|
419
|
+
if (fileUrl === CLIENT_FILE || fileUrl === CLIENT_ID) return this.createViteClientModule();
|
|
486
420
|
const cached = this.esm.resolveCachedModule(fileUrl);
|
|
487
|
-
|
|
488
|
-
return this.esm.createEsModule(fileUrl, async () => {
|
|
421
|
+
return cached || this.esm.createEsModule(fileUrl, async () => {
|
|
489
422
|
try {
|
|
490
|
-
const result = await this.options.transform(fileUrl
|
|
423
|
+
const result = await this.options.transform(fileUrl);
|
|
491
424
|
if (result.code) return result.code;
|
|
492
425
|
} catch (cause) {
|
|
493
426
|
// rethrow vite error if it cannot load the module because it's not resolved
|
|
494
427
|
if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url")) {
|
|
495
428
|
const error = new Error(`Cannot find module '${fileUrl}'`, { cause });
|
|
496
|
-
error.code = "ERR_MODULE_NOT_FOUND";
|
|
497
|
-
throw error;
|
|
429
|
+
throw error.code = "ERR_MODULE_NOT_FOUND", error;
|
|
498
430
|
}
|
|
499
431
|
}
|
|
500
432
|
throw new Error(`[vitest] Failed to transform ${fileUrl}. Does the file exist?`);
|
|
501
433
|
});
|
|
502
434
|
}
|
|
503
435
|
createViteClientModule() {
|
|
504
|
-
const identifier = CLIENT_ID;
|
|
505
|
-
const cached = this.esm.resolveCachedModule(identifier);
|
|
436
|
+
const identifier = CLIENT_ID, cached = this.esm.resolveCachedModule(identifier);
|
|
506
437
|
if (cached) return cached;
|
|
507
|
-
const stub = this.options.viteClientModule
|
|
508
|
-
const moduleKeys = Object.keys(stub);
|
|
509
|
-
const module = new SyntheticModule(moduleKeys, function() {
|
|
438
|
+
const stub = this.options.viteClientModule, moduleKeys = Object.keys(stub), module = new SyntheticModule(moduleKeys, function() {
|
|
510
439
|
moduleKeys.forEach((key) => {
|
|
511
440
|
this.setExport(key, stub[key]);
|
|
512
441
|
});
|
|
@@ -514,25 +443,16 @@ class ViteExecutor {
|
|
|
514
443
|
context: this.options.context,
|
|
515
444
|
identifier
|
|
516
445
|
});
|
|
517
|
-
this.esm.cacheModule(identifier, module);
|
|
518
|
-
return module;
|
|
446
|
+
return this.esm.cacheModule(identifier, module), module;
|
|
519
447
|
}
|
|
520
448
|
canResolve = (fileUrl) => {
|
|
521
|
-
const transformMode = this.workerState.environment.transformMode;
|
|
522
|
-
if (transformMode !== "web") return false;
|
|
523
449
|
if (fileUrl === CLIENT_FILE) return true;
|
|
524
|
-
const config = this.workerState.config.deps?.web || {};
|
|
525
|
-
|
|
526
|
-
if (config.transformCss && CSS_LANGS_RE.test(modulePath)) return true;
|
|
527
|
-
if (config.transformAssets && KNOWN_ASSET_RE.test(modulePath)) return true;
|
|
528
|
-
if (toArray(config.transformGlobPattern).some((pattern) => pattern.test(modulePath))) return true;
|
|
529
|
-
return false;
|
|
450
|
+
const config = this.workerState.config.deps?.web || {}, [modulePath] = fileUrl.split("?");
|
|
451
|
+
return !!(config.transformCss && CSS_LANGS_RE.test(modulePath) || config.transformAssets && KNOWN_ASSET_RE.test(modulePath) || toArray(config.transformGlobPattern).some((pattern) => pattern.test(modulePath)));
|
|
530
452
|
};
|
|
531
453
|
}
|
|
532
454
|
|
|
533
|
-
const { existsSync
|
|
534
|
-
// always defined when we use vm pool
|
|
535
|
-
const nativeResolve = import.meta.resolve;
|
|
455
|
+
const { existsSync } = fs, nativeResolve = import.meta.resolve;
|
|
536
456
|
// TODO: improve Node.js strict mode support in #2854
|
|
537
457
|
class ExternalModulesExecutor {
|
|
538
458
|
cjs;
|
|
@@ -543,28 +463,21 @@ class ExternalModulesExecutor {
|
|
|
543
463
|
resolvers = [];
|
|
544
464
|
#networkSupported = null;
|
|
545
465
|
constructor(options) {
|
|
546
|
-
this.options = options
|
|
547
|
-
this.context = options.context;
|
|
548
|
-
this.fs = options.fileMap;
|
|
549
|
-
this.esm = new EsmExecutor(this, { context: this.context });
|
|
550
|
-
this.cjs = new CommonjsExecutor({
|
|
466
|
+
this.options = options, this.context = options.context, this.fs = options.fileMap, this.esm = new EsmExecutor(this, { context: this.context }), this.cjs = new CommonjsExecutor({
|
|
551
467
|
context: this.context,
|
|
552
468
|
importModuleDynamically: this.importModuleDynamically,
|
|
553
469
|
fileMap: options.fileMap,
|
|
554
470
|
interopDefault: options.interopDefault
|
|
555
|
-
})
|
|
556
|
-
this.vite = new ViteExecutor({
|
|
471
|
+
}), this.vite = new ViteExecutor({
|
|
557
472
|
esmExecutor: this.esm,
|
|
558
473
|
context: this.context,
|
|
559
474
|
transform: options.transform,
|
|
560
475
|
viteClientModule: options.viteClientModule
|
|
561
|
-
});
|
|
562
|
-
this.resolvers = [this.vite.resolve];
|
|
476
|
+
}), this.resolvers = [this.vite.resolve];
|
|
563
477
|
}
|
|
564
478
|
async import(identifier) {
|
|
565
479
|
const module = await this.createModule(identifier);
|
|
566
|
-
await this.esm.evaluateModule(module);
|
|
567
|
-
return module.namespace;
|
|
480
|
+
return await this.esm.evaluateModule(module), module.namespace;
|
|
568
481
|
}
|
|
569
482
|
require(identifier) {
|
|
570
483
|
return this.cjs.require(identifier);
|
|
@@ -590,26 +503,6 @@ class ExternalModulesExecutor {
|
|
|
590
503
|
// import.meta.resolve can be asynchronous in older +18 Node versions
|
|
591
504
|
return nativeResolve(specifier, parent);
|
|
592
505
|
}
|
|
593
|
-
findNearestPackageData(basedir) {
|
|
594
|
-
const originalBasedir = basedir;
|
|
595
|
-
const packageCache = this.options.packageCache;
|
|
596
|
-
while (basedir) {
|
|
597
|
-
const cached = getCachedData(packageCache, basedir, originalBasedir);
|
|
598
|
-
if (cached) return cached;
|
|
599
|
-
const pkgPath = join(basedir, "package.json");
|
|
600
|
-
try {
|
|
601
|
-
if (statSync(pkgPath, { throwIfNoEntry: false })?.isFile()) {
|
|
602
|
-
const pkgData = JSON.parse(this.fs.readFile(pkgPath));
|
|
603
|
-
if (packageCache) setCacheData(packageCache, pkgData, basedir, originalBasedir);
|
|
604
|
-
return pkgData;
|
|
605
|
-
}
|
|
606
|
-
} catch {}
|
|
607
|
-
const nextBasedir = dirname$1(basedir);
|
|
608
|
-
if (nextBasedir === basedir) break;
|
|
609
|
-
basedir = nextBasedir;
|
|
610
|
-
}
|
|
611
|
-
return {};
|
|
612
|
-
}
|
|
613
506
|
getModuleInformation(identifier) {
|
|
614
507
|
if (identifier.startsWith("data:")) return {
|
|
615
508
|
type: "data",
|
|
@@ -617,7 +510,7 @@ class ExternalModulesExecutor {
|
|
|
617
510
|
path: identifier
|
|
618
511
|
};
|
|
619
512
|
const extension = extname(identifier);
|
|
620
|
-
if (extension === ".node" ||
|
|
513
|
+
if (extension === ".node" || isBuiltin(identifier)) return {
|
|
621
514
|
type: "builtin",
|
|
622
515
|
url: identifier,
|
|
623
516
|
path: identifier
|
|
@@ -627,9 +520,7 @@ class ExternalModulesExecutor {
|
|
|
627
520
|
url: identifier,
|
|
628
521
|
path: identifier
|
|
629
522
|
};
|
|
630
|
-
const isFileUrl = identifier.startsWith("file://");
|
|
631
|
-
const pathUrl = isFileUrl ? fileURLToPath(identifier.split("?")[0]) : identifier;
|
|
632
|
-
const fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString();
|
|
523
|
+
const isFileUrl = identifier.startsWith("file://"), pathUrl = isFileUrl ? fileURLToPath(identifier.split("?")[0]) : identifier, fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString();
|
|
633
524
|
let type;
|
|
634
525
|
if (this.vite.canResolve(fileUrl)) type = "vite";
|
|
635
526
|
else if (extension === ".mjs") type = "module";
|
|
@@ -639,7 +530,7 @@ class ExternalModulesExecutor {
|
|
|
639
530
|
// cf. ESM_FILE_FORMAT(url) in https://nodejs.org/docs/latest-v20.x/api/esm.html#resolution-algorithm
|
|
640
531
|
type = "wasm";
|
|
641
532
|
else {
|
|
642
|
-
const pkgData =
|
|
533
|
+
const pkgData = findNearestPackageData(normalize(pathUrl));
|
|
643
534
|
type = pkgData.type === "module" ? "module" : "commonjs";
|
|
644
535
|
}
|
|
645
536
|
return {
|
|
@@ -654,8 +545,7 @@ class ExternalModulesExecutor {
|
|
|
654
545
|
// https://github.com/nodejs/node/pull/49038
|
|
655
546
|
if ((type === "module" || type === "commonjs" || type === "wasm") && !existsSync(path)) {
|
|
656
547
|
const error = /* @__PURE__ */ new Error(`Cannot find ${isBareImport(path) ? "package" : "module"} '${path}'`);
|
|
657
|
-
error.code = "ERR_MODULE_NOT_FOUND";
|
|
658
|
-
throw error;
|
|
548
|
+
throw error.code = "ERR_MODULE_NOT_FOUND", error;
|
|
659
549
|
}
|
|
660
550
|
switch (type) {
|
|
661
551
|
case "data": return this.esm.createDataModule(identifier);
|
|
@@ -687,77 +577,63 @@ class FileMap {
|
|
|
687
577
|
const cached = this.fsCache.get(path);
|
|
688
578
|
if (cached != null) return cached;
|
|
689
579
|
const source = await promises.readFile(path, "utf-8");
|
|
690
|
-
this.fsCache.set(path, source);
|
|
691
|
-
return source;
|
|
580
|
+
return this.fsCache.set(path, source), source;
|
|
692
581
|
}
|
|
693
582
|
readFile(path) {
|
|
694
583
|
const cached = this.fsCache.get(path);
|
|
695
584
|
if (cached != null) return cached;
|
|
696
585
|
const source = readFileSync(path, "utf-8");
|
|
697
|
-
this.fsCache.set(path, source);
|
|
698
|
-
return source;
|
|
586
|
+
return this.fsCache.set(path, source), source;
|
|
699
587
|
}
|
|
700
588
|
readBuffer(path) {
|
|
701
589
|
const cached = this.fsBufferCache.get(path);
|
|
702
590
|
if (cached != null) return cached;
|
|
703
591
|
const buffer = readFileSync(path);
|
|
704
|
-
this.fsBufferCache.set(path, buffer);
|
|
705
|
-
return buffer;
|
|
592
|
+
return this.fsBufferCache.set(path, buffer), buffer;
|
|
706
593
|
}
|
|
707
594
|
}
|
|
708
595
|
|
|
709
|
-
const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href;
|
|
710
|
-
const fileMap = new FileMap();
|
|
711
|
-
const packageCache = /* @__PURE__ */ new Map();
|
|
596
|
+
const entryFile = pathToFileURL(resolve(distDir, "workers/runVmTests.js")).href, fileMap = new FileMap(), packageCache = /* @__PURE__ */ new Map();
|
|
712
597
|
async function runVmTests(method, state) {
|
|
713
598
|
const { environment, ctx, rpc } = state;
|
|
714
599
|
if (!environment.setupVM) {
|
|
715
|
-
const envName = ctx.environment.name
|
|
716
|
-
const packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
|
|
600
|
+
const envName = ctx.environment.name, packageId = envName[0] === "." ? envName : `vitest-environment-${envName}`;
|
|
717
601
|
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.`);
|
|
718
602
|
}
|
|
719
603
|
const vm = await environment.setupVM(ctx.environment.options || ctx.config.environmentOptions || {});
|
|
720
|
-
state.durations.environment = performance.now() - state.durations.environment;
|
|
721
|
-
process.env.VITEST_VM_POOL = "1";
|
|
722
|
-
if (!vm.getVmContext) throw new TypeError(`Environment ${environment.name} doesn't provide "getVmContext" method. It should return a context created by "vm.createContext" method.`);
|
|
604
|
+
if (state.durations.environment = performance.now() - state.durations.environment, process.env.VITEST_VM_POOL = "1", !vm.getVmContext) throw new TypeError(`Environment ${environment.name} doesn't provide "getVmContext" method. It should return a context created by "vm.createContext" method.`);
|
|
723
605
|
const context = vm.getVmContext();
|
|
724
606
|
if (!isContext(context)) throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
|
|
725
|
-
provideWorkerState(context, state);
|
|
726
|
-
|
|
727
|
-
// we need to find a way to not rely on this by default
|
|
728
|
-
// because browser doesn't provide these globals
|
|
729
|
-
context.process = process;
|
|
730
|
-
context.global = context;
|
|
731
|
-
context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state);
|
|
732
|
-
// TODO: don't hardcode setImmediate in fake timers defaults
|
|
733
|
-
context.setImmediate = setImmediate;
|
|
734
|
-
context.clearImmediate = clearImmediate;
|
|
735
|
-
const stubs = getDefaultRequestStubs(context);
|
|
736
|
-
const externalModulesExecutor = new ExternalModulesExecutor({
|
|
607
|
+
provideWorkerState(context, state), context.process = process, context.global = context, context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state), context.setImmediate = setImmediate, context.clearImmediate = clearImmediate;
|
|
608
|
+
const stubs = getDefaultRequestStubs(context), externalModulesExecutor = new ExternalModulesExecutor({
|
|
737
609
|
context,
|
|
738
610
|
fileMap,
|
|
739
611
|
packageCache,
|
|
740
612
|
transform: rpc.transform,
|
|
741
613
|
viteClientModule: stubs["/@vite/client"]
|
|
742
|
-
})
|
|
743
|
-
const executor = await startVitestExecutor({
|
|
614
|
+
}), moduleRunner = await startVitestModuleRunner({
|
|
744
615
|
context,
|
|
745
|
-
|
|
616
|
+
evaluatedModules: state.evaluatedModules,
|
|
746
617
|
state,
|
|
747
|
-
externalModulesExecutor
|
|
748
|
-
requestStubs: stubs
|
|
618
|
+
externalModulesExecutor
|
|
749
619
|
});
|
|
750
|
-
context
|
|
751
|
-
|
|
752
|
-
|
|
620
|
+
Object.defineProperty(context, VITEST_VM_CONTEXT_SYMBOL, {
|
|
621
|
+
value: {
|
|
622
|
+
context,
|
|
623
|
+
externalModulesExecutor
|
|
624
|
+
},
|
|
625
|
+
configurable: true,
|
|
626
|
+
enumerable: false,
|
|
627
|
+
writable: false
|
|
628
|
+
}), context.__vitest_mocker__ = moduleRunner.mocker;
|
|
629
|
+
const { run } = await moduleRunner.import(entryFile), fileSpecs = ctx.files.map((f) => typeof f === "string" ? {
|
|
753
630
|
filepath: f,
|
|
754
631
|
testLocations: void 0
|
|
755
632
|
} : f);
|
|
756
633
|
try {
|
|
757
|
-
await run(method, fileSpecs, ctx.config,
|
|
634
|
+
await run(method, fileSpecs, ctx.config, moduleRunner);
|
|
758
635
|
} finally {
|
|
759
|
-
await vm.teardown?.();
|
|
760
|
-
state.environmentTeardownRun = true;
|
|
636
|
+
await vm.teardown?.(), state.environmentTeardownRun = true;
|
|
761
637
|
}
|
|
762
638
|
}
|
|
763
639
|
|