vitest 4.0.0-beta.4 → 4.0.0-beta.5
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/dist/browser.d.ts +8 -9
- package/dist/browser.js +3 -2
- package/dist/chunks/base.DMfOuRWD.js +48 -0
- package/dist/chunks/{benchmark.CYdenmiT.js → benchmark.CtuRzf-i.js} +4 -1
- package/dist/chunks/{browser.d.BRP8scJf.d.ts → browser.d.Cawq_X_N.d.ts} +1 -1
- package/dist/chunks/{cac.CY0IAxC4.js → cac.CKnbxhn2.js} +8 -9
- package/dist/chunks/{cli-api.B8xRY9Zt.js → cli-api.COn58yrl.js} +540 -342
- package/dist/chunks/{config.d.DZo8c7fw.d.ts → config.d.CKNVOKm0.d.ts} +3 -8
- package/dist/chunks/{console.DoJHFxmj.js → console.Duv2dVIC.js} +1 -1
- package/dist/chunks/{constants.CXzqaLmq.js → constants.D_Q9UYh-.js} +1 -6
- package/dist/chunks/{coverage.C84l9G-M.js → coverage.B6cReEn1.js} +232 -133
- 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.DUVZ6rfm.js} +1 -1
- package/dist/chunks/{environment.d.Bhm9oc0v.d.ts → environment.d.2fYMoz3o.d.ts} +26 -4
- package/dist/chunks/{global.d.DAhT2emn.d.ts → global.d.K6uBQHzY.d.ts} +1 -1
- package/dist/chunks/{globals.Dgo-vS5G.js → globals.CJQ63oO0.js} +6 -5
- package/dist/chunks/{index.CmSc2RE5.js → index.BRtIe7r8.js} +4 -4
- package/dist/chunks/{index.Bz6b0Ib7.js → index.DQhAfQQU.js} +12 -4
- package/dist/chunks/{index.D3SKT3tv.js → index.DgN0Zk9a.js} +1 -1
- package/dist/chunks/{index.D1_MsKEt.js → index.QZr3S3vQ.js} +4 -2
- package/dist/chunks/{index.CtUvr1c8.js → index.oWRWx-nj.js} +18 -18
- package/dist/chunks/moduleRunner.d.mmOmOGrW.d.ts +202 -0
- package/dist/chunks/moduleTransport.I-bgQy0S.js +19 -0
- package/dist/chunks/{node.fjCdwEIl.js → node.4JV5OXkt.js} +1 -1
- package/dist/chunks/{plugin.d.CLhMcYdD.d.ts → plugin.d.CvOlgjxK.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DWg40D2B.d.ts → reporters.d.CYE9sT5z.d.ts} +37 -69
- package/dist/chunks/resolver.D5bG4zy5.js +162 -0
- package/dist/chunks/{rpc.jnQO9F8a.js → rpc.DGoW_Vl-.js} +1 -1
- package/dist/chunks/{runBaseTests.DBVVLMSb.js → runBaseTests.B3KcKqlF.js} +22 -23
- package/dist/chunks/{setup-common.Ebx5x0eP.js → setup-common.lgPs-bYv.js} +11 -10
- package/dist/chunks/{execute.Dt-pCVcL.js → startModuleRunner.C8FtT_BY.js} +381 -312
- package/dist/chunks/{typechecker.CMNPqJOo.js → typechecker.BgoW4nTA.js} +1 -1
- package/dist/chunks/{utils.XdZDrNZV.js → utils.B9FY3b73.js} +7 -8
- package/dist/chunks/{vi.CA0EPI9Y.js → vi.DGAfBY4R.js} +12 -8
- package/dist/chunks/{vm.BUnLJt_P.js → vm.BKfKvaKl.js} +36 -56
- 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 +5 -4
- package/dist/module-evaluator.d.ts +12 -0
- package/dist/module-evaluator.js +327 -0
- package/dist/module-runner.js +15 -0
- package/dist/node.d.ts +12 -13
- package/dist/node.js +15 -14
- package/dist/reporters.d.ts +7 -8
- package/dist/reporters.js +3 -3
- package/dist/runners.d.ts +3 -3
- package/dist/runners.js +16 -10
- package/dist/snapshot.js +2 -2
- package/dist/suite.js +2 -2
- package/dist/worker.js +84 -31
- package/dist/workers/forks.js +10 -9
- package/dist/workers/runVmTests.js +16 -17
- package/dist/workers/threads.js +10 -9
- package/dist/workers/vmForks.js +9 -8
- package/dist/workers/vmThreads.js +9 -8
- package/dist/workers.d.ts +5 -4
- package/dist/workers.js +14 -13
- package/package.json +21 -16
- package/dist/chunks/base.BaCDDRPG.js +0 -38
- package/dist/execute.d.ts +0 -148
- package/dist/execute.js +0 -13
|
@@ -1,15 +1,86 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import { builtinModules, isBuiltin } from 'node:module';
|
|
3
|
+
import { highlight, isBareImport } from '@vitest/utils';
|
|
2
4
|
import { pathToFileURL } from 'node:url';
|
|
3
|
-
import
|
|
4
|
-
import { processError } from '@vitest/utils/error';
|
|
5
|
-
import { normalize as normalize$1 } from 'pathe';
|
|
6
|
-
import { ViteNodeRunner, DEFAULT_REQUEST_STUBS } from 'vite-node/client';
|
|
7
|
-
import { isInternalRequest, isNodeBuiltin as isNodeBuiltin$1, isPrimitive, toFilePath } from 'vite-node/utils';
|
|
5
|
+
import { normalize as normalize$1, join as join$1 } from 'pathe';
|
|
8
6
|
import { distDir } from '../path.js';
|
|
7
|
+
import { processError } from '@vitest/utils/error';
|
|
8
|
+
import { VitestModuleEvaluator, unwrapId } from '../module-evaluator.js';
|
|
9
9
|
import { resolve as resolve$1, isAbsolute as isAbsolute$1 } from 'node:path';
|
|
10
|
+
import vm from 'node:vm';
|
|
10
11
|
import { MockerRegistry, mockObject, RedirectedModule, AutomockedModule } from '@vitest/mocker';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
12
|
+
import { ModuleRunner } from 'vite/module-runner';
|
|
13
|
+
import { V as VitestTransport } from './moduleTransport.I-bgQy0S.js';
|
|
14
|
+
|
|
15
|
+
const bareVitestRegexp = /^@?vitest(?:\/|$)/;
|
|
16
|
+
const normalizedDistDir = normalize$1(distDir);
|
|
17
|
+
const relativeIds = {};
|
|
18
|
+
const externalizeMap = /* @__PURE__ */ new Map();
|
|
19
|
+
// all Vitest imports always need to be externalized
|
|
20
|
+
function getCachedVitestImport(id, state) {
|
|
21
|
+
if (id.startsWith("/@fs/") || id.startsWith("\\@fs\\")) id = id.slice(process.platform === "win32" ? 5 : 4);
|
|
22
|
+
if (externalizeMap.has(id)) return {
|
|
23
|
+
externalize: externalizeMap.get(id),
|
|
24
|
+
type: "module"
|
|
25
|
+
};
|
|
26
|
+
// always externalize Vitest because we import from there before running tests
|
|
27
|
+
// so we already have it cached by Node.js
|
|
28
|
+
const root = state().config.root;
|
|
29
|
+
const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length));
|
|
30
|
+
if (id.includes(distDir) || id.includes(normalizedDistDir)) {
|
|
31
|
+
const externalize = id.startsWith("file://") ? id : pathToFileURL(id).toString();
|
|
32
|
+
externalizeMap.set(id, externalize);
|
|
33
|
+
return {
|
|
34
|
+
externalize,
|
|
35
|
+
type: "module"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (relativeRoot && relativeRoot !== "/" && id.startsWith(relativeRoot)) {
|
|
39
|
+
const path = join$1(root, id);
|
|
40
|
+
const externalize = pathToFileURL(path).toString();
|
|
41
|
+
externalizeMap.set(id, externalize);
|
|
42
|
+
return {
|
|
43
|
+
externalize,
|
|
44
|
+
type: "module"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (bareVitestRegexp.test(id)) {
|
|
48
|
+
externalizeMap.set(id, id);
|
|
49
|
+
return {
|
|
50
|
+
externalize: id,
|
|
51
|
+
type: "module"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const dispose = [];
|
|
58
|
+
function listenForErrors(state) {
|
|
59
|
+
dispose.forEach((fn) => fn());
|
|
60
|
+
dispose.length = 0;
|
|
61
|
+
function catchError(err, type, event) {
|
|
62
|
+
const worker = state();
|
|
63
|
+
const listeners = process.listeners(event);
|
|
64
|
+
// if there is another listener, assume that it's handled by user code
|
|
65
|
+
// one is Vitest's own listener
|
|
66
|
+
if (listeners.length > 1) return;
|
|
67
|
+
const error = processError(err);
|
|
68
|
+
if (typeof error === "object" && error != null) {
|
|
69
|
+
error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
|
|
70
|
+
if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
|
71
|
+
error.VITEST_AFTER_ENV_TEARDOWN = worker.environmentTeardownRun;
|
|
72
|
+
}
|
|
73
|
+
state().rpc.onUnhandledError(error, type);
|
|
74
|
+
}
|
|
75
|
+
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
|
|
76
|
+
const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
|
|
77
|
+
process.on("uncaughtException", uncaughtException);
|
|
78
|
+
process.on("unhandledRejection", unhandledRejection);
|
|
79
|
+
dispose.push(() => {
|
|
80
|
+
process.off("uncaughtException", uncaughtException);
|
|
81
|
+
process.off("unhandledRejection", unhandledRejection);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
13
84
|
|
|
14
85
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
15
86
|
function normalizeWindowsPath(input = "") {
|
|
@@ -53,7 +124,7 @@ const join = function(...segments) {
|
|
|
53
124
|
}
|
|
54
125
|
return normalize(path);
|
|
55
126
|
};
|
|
56
|
-
function cwd() {
|
|
127
|
+
function cwd$1() {
|
|
57
128
|
if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
|
|
58
129
|
return "/";
|
|
59
130
|
}
|
|
@@ -62,7 +133,7 @@ const resolve = function(...arguments_) {
|
|
|
62
133
|
let resolvedPath = "";
|
|
63
134
|
let resolvedAbsolute = false;
|
|
64
135
|
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
65
|
-
const path = index >= 0 ? arguments_[index] : cwd();
|
|
136
|
+
const path = index >= 0 ? arguments_[index] : cwd$1();
|
|
66
137
|
if (!path || path.length === 0) continue;
|
|
67
138
|
resolvedPath = `${path}/${resolvedPath}`;
|
|
68
139
|
resolvedAbsolute = isAbsolute(path);
|
|
@@ -198,7 +269,7 @@ const builtins = new Set([
|
|
|
198
269
|
"wasi"
|
|
199
270
|
]);
|
|
200
271
|
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
201
|
-
const prefixedBuiltins = new Set([
|
|
272
|
+
const prefixedBuiltins$1 = new Set([
|
|
202
273
|
"node:sea",
|
|
203
274
|
"node:sqlite",
|
|
204
275
|
"node:test",
|
|
@@ -206,7 +277,7 @@ const prefixedBuiltins = new Set([
|
|
|
206
277
|
]);
|
|
207
278
|
const NODE_BUILTIN_NAMESPACE = "node:";
|
|
208
279
|
function isNodeBuiltin(id) {
|
|
209
|
-
if (prefixedBuiltins.has(id)) return true;
|
|
280
|
+
if (prefixedBuiltins$1.has(id)) return true;
|
|
210
281
|
return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
|
|
211
282
|
}
|
|
212
283
|
|
|
@@ -218,9 +289,10 @@ class VitestMocker {
|
|
|
218
289
|
filterPublicKeys;
|
|
219
290
|
registries = /* @__PURE__ */ new Map();
|
|
220
291
|
mockContext = { callstack: null };
|
|
221
|
-
constructor(
|
|
222
|
-
this.
|
|
223
|
-
|
|
292
|
+
constructor(moduleRunner, options) {
|
|
293
|
+
this.moduleRunner = moduleRunner;
|
|
294
|
+
this.options = options;
|
|
295
|
+
const context = this.options.context;
|
|
224
296
|
if (context) this.primitives = vm.runInContext("({ Object, Error, Function, RegExp, Symbol, Array, Map })", context);
|
|
225
297
|
else this.primitives = {
|
|
226
298
|
Object,
|
|
@@ -250,16 +322,17 @@ class VitestMocker {
|
|
|
250
322
|
];
|
|
251
323
|
}
|
|
252
324
|
get root() {
|
|
253
|
-
return this.
|
|
325
|
+
return this.options.root;
|
|
254
326
|
}
|
|
255
|
-
get
|
|
256
|
-
return this.
|
|
327
|
+
get evaluatedModules() {
|
|
328
|
+
return this.moduleRunner.evaluatedModules;
|
|
257
329
|
}
|
|
258
330
|
get moduleDirectories() {
|
|
259
|
-
return this.
|
|
331
|
+
return this.options.moduleDirectories || [];
|
|
260
332
|
}
|
|
261
333
|
async initializeSpyModule() {
|
|
262
|
-
this.spyModule
|
|
334
|
+
if (this.spyModule) return;
|
|
335
|
+
this.spyModule = await this.moduleRunner.import(spyModulePath);
|
|
263
336
|
}
|
|
264
337
|
getMockerRegistry() {
|
|
265
338
|
const suite = this.getSuiteFilepath();
|
|
@@ -269,15 +342,19 @@ class VitestMocker {
|
|
|
269
342
|
reset() {
|
|
270
343
|
this.registries.clear();
|
|
271
344
|
}
|
|
272
|
-
|
|
345
|
+
invalidateModuleById(id) {
|
|
273
346
|
const mockId = this.getMockPath(id);
|
|
274
|
-
|
|
347
|
+
const node = this.evaluatedModules.getModuleById(mockId);
|
|
348
|
+
if (node) {
|
|
349
|
+
this.evaluatedModules.invalidateModule(node);
|
|
350
|
+
node.mockedExports = void 0;
|
|
351
|
+
}
|
|
275
352
|
}
|
|
276
353
|
isModuleDirectory(path) {
|
|
277
354
|
return this.moduleDirectories.some((dir) => path.includes(dir));
|
|
278
355
|
}
|
|
279
356
|
getSuiteFilepath() {
|
|
280
|
-
return this.
|
|
357
|
+
return this.options.getCurrentTestFilepath() || "global";
|
|
281
358
|
}
|
|
282
359
|
createError(message, codeFrame) {
|
|
283
360
|
const Error = this.primitives.Error;
|
|
@@ -285,40 +362,49 @@ class VitestMocker {
|
|
|
285
362
|
Object.assign(error, { codeFrame });
|
|
286
363
|
return error;
|
|
287
364
|
}
|
|
288
|
-
async
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
id = unresolvedId;
|
|
298
|
-
fsPath = unresolvedId;
|
|
299
|
-
} else throw error;
|
|
365
|
+
async resolveId(rawId, importer) {
|
|
366
|
+
const result = await this.options.resolveId(rawId, importer);
|
|
367
|
+
if (!result) {
|
|
368
|
+
const id = normalizeModuleId(rawId);
|
|
369
|
+
return {
|
|
370
|
+
id,
|
|
371
|
+
url: rawId,
|
|
372
|
+
external: id
|
|
373
|
+
};
|
|
300
374
|
}
|
|
301
375
|
// external is node_module or unresolved module
|
|
302
376
|
// for example, some people mock "vscode" and don't have it installed
|
|
303
|
-
const external = !isAbsolute$1(
|
|
377
|
+
const external = !isAbsolute$1(result.file) || this.isModuleDirectory(result.file) ? normalizeModuleId(rawId) : null;
|
|
304
378
|
return {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
external
|
|
379
|
+
...result,
|
|
380
|
+
id: normalizeModuleId(result.id),
|
|
381
|
+
external
|
|
308
382
|
};
|
|
309
383
|
}
|
|
310
384
|
async resolveMocks() {
|
|
311
385
|
if (!VitestMocker.pendingIds.length) return;
|
|
312
386
|
await Promise.all(VitestMocker.pendingIds.map(async (mock) => {
|
|
313
|
-
const {
|
|
314
|
-
if (mock.action === "unmock") this.unmockPath(
|
|
315
|
-
if (mock.action === "mock") this.mockPath(mock.id,
|
|
387
|
+
const { id, url, external } = await this.resolveId(mock.id, mock.importer);
|
|
388
|
+
if (mock.action === "unmock") this.unmockPath(id);
|
|
389
|
+
if (mock.action === "mock") this.mockPath(mock.id, id, url, external, mock.type, mock.factory);
|
|
316
390
|
}));
|
|
317
391
|
VitestMocker.pendingIds = [];
|
|
318
392
|
}
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
393
|
+
ensureModule(id, url) {
|
|
394
|
+
const node = this.evaluatedModules.ensureModule(id, url);
|
|
395
|
+
// TODO
|
|
396
|
+
node.meta = {
|
|
397
|
+
id,
|
|
398
|
+
url,
|
|
399
|
+
code: "",
|
|
400
|
+
file: null,
|
|
401
|
+
invalidate: false
|
|
402
|
+
};
|
|
403
|
+
return node;
|
|
404
|
+
}
|
|
405
|
+
async callFunctionMock(id, url, mock) {
|
|
406
|
+
const node = this.ensureModule(id, url);
|
|
407
|
+
if (node.exports) return node.exports;
|
|
322
408
|
const exports = await mock.resolve();
|
|
323
409
|
const moduleExports = new Proxy(exports, { get: (target, prop) => {
|
|
324
410
|
const val = target[prop];
|
|
@@ -339,7 +425,7 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
339
425
|
}
|
|
340
426
|
return val;
|
|
341
427
|
} });
|
|
342
|
-
|
|
428
|
+
node.exports = moduleExports;
|
|
343
429
|
return moduleExports;
|
|
344
430
|
}
|
|
345
431
|
// public method to avoid circular dependency
|
|
@@ -352,12 +438,9 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
352
438
|
}
|
|
353
439
|
getDependencyMock(id) {
|
|
354
440
|
const registry = this.getMockerRegistry();
|
|
355
|
-
return registry.
|
|
356
|
-
}
|
|
357
|
-
normalizePath(path) {
|
|
358
|
-
return this.moduleCache.normalizePath(path);
|
|
441
|
+
return registry.getById(fixLeadingSlashes(id));
|
|
359
442
|
}
|
|
360
|
-
|
|
443
|
+
findMockRedirect(mockPath, external) {
|
|
361
444
|
return findMockRedirect(this.root, mockPath, external);
|
|
362
445
|
}
|
|
363
446
|
mockObject(object, mockExports = {}, behavior = "automock") {
|
|
@@ -369,75 +452,88 @@ If you need to partially mock a module, you can use "importOriginal" helper insi
|
|
|
369
452
|
type: behavior
|
|
370
453
|
}, object, mockExports);
|
|
371
454
|
}
|
|
372
|
-
unmockPath(
|
|
455
|
+
unmockPath(id) {
|
|
373
456
|
const registry = this.getMockerRegistry();
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
this.deleteCachedItem(id);
|
|
457
|
+
registry.deleteById(id);
|
|
458
|
+
this.invalidateModuleById(id);
|
|
377
459
|
}
|
|
378
|
-
mockPath(originalId,
|
|
460
|
+
mockPath(originalId, id, url, external, mockType, factory) {
|
|
379
461
|
const registry = this.getMockerRegistry();
|
|
380
|
-
|
|
381
|
-
if (mockType === "
|
|
382
|
-
else if (mockType === "autospy") registry.register("autospy", originalId, id, id);
|
|
462
|
+
if (mockType === "manual") registry.register("manual", originalId, id, url, factory);
|
|
463
|
+
else if (mockType === "autospy") registry.register("autospy", originalId, id, url);
|
|
383
464
|
else {
|
|
384
|
-
const redirect = this.
|
|
385
|
-
if (redirect) registry.register("redirect", originalId, id,
|
|
386
|
-
else registry.register("automock", originalId, id,
|
|
465
|
+
const redirect = this.findMockRedirect(id, external);
|
|
466
|
+
if (redirect) registry.register("redirect", originalId, id, url, redirect);
|
|
467
|
+
else registry.register("automock", originalId, id, url);
|
|
387
468
|
}
|
|
388
469
|
// every time the mock is registered, we remove the previous one from the cache
|
|
389
|
-
this.
|
|
470
|
+
this.invalidateModuleById(id);
|
|
390
471
|
}
|
|
391
472
|
async importActual(rawId, importer, callstack) {
|
|
392
|
-
const {
|
|
393
|
-
const
|
|
473
|
+
const { url } = await this.resolveId(rawId, importer);
|
|
474
|
+
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
475
|
+
const result = await this.moduleRunner.cachedRequest(node.url, node, callstack || [importer], void 0, true);
|
|
394
476
|
return result;
|
|
395
477
|
}
|
|
396
|
-
async importMock(rawId,
|
|
397
|
-
const { id,
|
|
398
|
-
|
|
399
|
-
let mock = this.getDependencyMock(normalizedId);
|
|
478
|
+
async importMock(rawId, importer) {
|
|
479
|
+
const { id, url, external } = await this.resolveId(rawId, importer);
|
|
480
|
+
let mock = this.getDependencyMock(id);
|
|
400
481
|
if (!mock) {
|
|
401
|
-
const redirect = this.
|
|
402
|
-
if (redirect) mock = new RedirectedModule(rawId,
|
|
403
|
-
else mock = new AutomockedModule(rawId,
|
|
482
|
+
const redirect = this.findMockRedirect(id, external);
|
|
483
|
+
if (redirect) mock = new RedirectedModule(rawId, id, rawId, redirect);
|
|
484
|
+
else mock = new AutomockedModule(rawId, id, rawId);
|
|
404
485
|
}
|
|
405
486
|
if (mock.type === "automock" || mock.type === "autospy") {
|
|
406
|
-
const
|
|
407
|
-
|
|
487
|
+
const node = await this.moduleRunner.fetchModule(url, importer);
|
|
488
|
+
const mod = await this.moduleRunner.cachedRequest(url, node, [importer], void 0, true);
|
|
489
|
+
const Object = this.primitives.Object;
|
|
490
|
+
return this.mockObject(mod, Object.create(Object.prototype), mock.type);
|
|
408
491
|
}
|
|
409
|
-
if (mock.type === "manual") return this.callFunctionMock(
|
|
410
|
-
|
|
492
|
+
if (mock.type === "manual") return this.callFunctionMock(id, url, mock);
|
|
493
|
+
const node = await this.moduleRunner.fetchModule(mock.redirect);
|
|
494
|
+
return this.moduleRunner.cachedRequest(mock.redirect, node, [importer], void 0, true);
|
|
411
495
|
}
|
|
412
|
-
async
|
|
413
|
-
const
|
|
414
|
-
const mock = this.getDependencyMock(id);
|
|
415
|
-
if (!mock) return;
|
|
416
|
-
const mockPath = this.getMockPath(id);
|
|
496
|
+
async requestWithMockedModule(url, evaluatedNode, callstack, mock) {
|
|
497
|
+
const mockId = this.getMockPath(evaluatedNode.id);
|
|
417
498
|
if (mock.type === "automock" || mock.type === "autospy") {
|
|
418
|
-
const cache = this.
|
|
419
|
-
if (cache.
|
|
420
|
-
const
|
|
421
|
-
//
|
|
422
|
-
|
|
423
|
-
const
|
|
499
|
+
const cache = this.evaluatedModules.getModuleById(mockId);
|
|
500
|
+
if (cache && cache.mockedExports) return cache.mockedExports;
|
|
501
|
+
const Object = this.primitives.Object;
|
|
502
|
+
// we have to define a separate object that will copy all properties into itself
|
|
503
|
+
// and can't just use the same `exports` define automatically by Vite before the evaluator
|
|
504
|
+
const exports = Object.create(null);
|
|
505
|
+
Object.defineProperty(exports, Symbol.toStringTag, {
|
|
506
|
+
value: "Module",
|
|
507
|
+
configurable: true,
|
|
508
|
+
writable: true
|
|
509
|
+
});
|
|
510
|
+
const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url));
|
|
511
|
+
node.meta = evaluatedNode.meta;
|
|
512
|
+
node.file = evaluatedNode.file;
|
|
513
|
+
node.mockedExports = exports;
|
|
514
|
+
const mod = await this.moduleRunner.cachedRequest(url, node, callstack, void 0, true);
|
|
424
515
|
this.mockObject(mod, exports, mock.type);
|
|
425
516
|
return exports;
|
|
426
517
|
}
|
|
427
|
-
if (mock.type === "manual" && !callstack.includes(
|
|
428
|
-
callstack.push(
|
|
518
|
+
if (mock.type === "manual" && !callstack.includes(mockId) && !callstack.includes(url)) try {
|
|
519
|
+
callstack.push(mockId);
|
|
429
520
|
// this will not work if user does Promise.all(import(), import())
|
|
430
521
|
// we can also use AsyncLocalStorage to store callstack, but this won't work in the browser
|
|
431
522
|
// maybe we should improve mock API in the future?
|
|
432
523
|
this.mockContext.callstack = callstack;
|
|
433
|
-
return await this.callFunctionMock(
|
|
524
|
+
return await this.callFunctionMock(mockId, this.getMockPath(url), mock);
|
|
434
525
|
} finally {
|
|
435
526
|
this.mockContext.callstack = null;
|
|
436
|
-
const indexMock = callstack.indexOf(
|
|
527
|
+
const indexMock = callstack.indexOf(mockId);
|
|
437
528
|
callstack.splice(indexMock, 1);
|
|
438
529
|
}
|
|
439
530
|
else if (mock.type === "redirect" && !callstack.includes(mock.redirect)) return mock.redirect;
|
|
440
531
|
}
|
|
532
|
+
async mockedRequest(url, evaluatedNode, callstack) {
|
|
533
|
+
const mock = this.getDependencyMock(evaluatedNode.id);
|
|
534
|
+
if (!mock) return;
|
|
535
|
+
return this.requestWithMockedModule(url, evaluatedNode, callstack, mock);
|
|
536
|
+
}
|
|
441
537
|
queueMock(id, importer, factoryOrOptions) {
|
|
442
538
|
const mockType = getMockType(factoryOrOptions);
|
|
443
539
|
VitestMocker.pendingIds.push({
|
|
@@ -461,248 +557,221 @@ function getMockType(factoryOrOptions) {
|
|
|
461
557
|
if (typeof factoryOrOptions === "function") return "manual";
|
|
462
558
|
return factoryOrOptions.spy ? "autospy" : "automock";
|
|
463
559
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
560
|
+
// unique id that is not available as "$bare_import" like "test"
|
|
561
|
+
// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix
|
|
562
|
+
const prefixedBuiltins = new Set([
|
|
563
|
+
"node:sea",
|
|
564
|
+
"node:sqlite",
|
|
565
|
+
"node:test",
|
|
566
|
+
"node:test/reporters"
|
|
567
|
+
]);
|
|
568
|
+
const isWindows$1 = process.platform === "win32";
|
|
569
|
+
// transform file url to id
|
|
570
|
+
// virtual:custom -> virtual:custom
|
|
571
|
+
// \0custom -> \0custom
|
|
572
|
+
// /root/id -> /id
|
|
573
|
+
// /root/id.js -> /id.js
|
|
574
|
+
// C:/root/id.js -> /id.js
|
|
575
|
+
// C:\root\id.js -> /id.js
|
|
576
|
+
// TODO: expose this in vite/module-runner
|
|
577
|
+
function normalizeModuleId(file) {
|
|
578
|
+
if (prefixedBuiltins.has(file)) return file;
|
|
579
|
+
// unix style, but Windows path still starts with the drive letter to check the root
|
|
580
|
+
const unixFile = slash(file).replace(/^\/@fs\//, isWindows$1 ? "" : "/").replace(/^node:/, "").replace(/^\/+/, "/");
|
|
581
|
+
// if it's not in the root, keep it as a path, not a URL
|
|
582
|
+
return unixFile.replace(/^file:\//, "/");
|
|
472
583
|
}
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
function listenForErrors(state) {
|
|
477
|
-
dispose.forEach((fn) => fn());
|
|
478
|
-
dispose.length = 0;
|
|
479
|
-
function catchError(err, type, event) {
|
|
480
|
-
const worker = state();
|
|
481
|
-
const listeners = process.listeners(event);
|
|
482
|
-
// if there is another listener, assume that it's handled by user code
|
|
483
|
-
// one is Vitest's own listener
|
|
484
|
-
if (listeners.length > 1) return;
|
|
485
|
-
const error = processError(err);
|
|
486
|
-
if (!isPrimitive(error)) {
|
|
487
|
-
error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
|
|
488
|
-
if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
|
489
|
-
error.VITEST_AFTER_ENV_TEARDOWN = worker.environmentTeardownRun;
|
|
490
|
-
}
|
|
491
|
-
state().rpc.onUnhandledError(error, type);
|
|
492
|
-
}
|
|
493
|
-
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
|
|
494
|
-
const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
|
|
495
|
-
process.on("uncaughtException", uncaughtException);
|
|
496
|
-
process.on("unhandledRejection", unhandledRejection);
|
|
497
|
-
dispose.push(() => {
|
|
498
|
-
process.off("uncaughtException", uncaughtException);
|
|
499
|
-
process.off("unhandledRejection", unhandledRejection);
|
|
500
|
-
});
|
|
584
|
+
const windowsSlashRE = /\\/g;
|
|
585
|
+
function slash(p) {
|
|
586
|
+
return p.replace(windowsSlashRE, "/");
|
|
501
587
|
}
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
//
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
588
|
+
const multipleSlashRe = /^\/+/;
|
|
589
|
+
// module-runner incorrectly replaces file:///path with `///path`
|
|
590
|
+
function fixLeadingSlashes(id) {
|
|
591
|
+
if (id.startsWith("//")) return id.replace(multipleSlashRe, "/");
|
|
592
|
+
return id;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// @ts-expect-error overriding private method
|
|
596
|
+
class VitestModuleRunner extends ModuleRunner {
|
|
597
|
+
mocker;
|
|
598
|
+
moduleExecutionInfo;
|
|
599
|
+
constructor(options) {
|
|
600
|
+
const transport = new VitestTransport(options.transport);
|
|
601
|
+
const evaluatedModules = options.evaluatedModules;
|
|
602
|
+
super({
|
|
603
|
+
transport,
|
|
604
|
+
hmr: false,
|
|
605
|
+
evaluatedModules,
|
|
606
|
+
sourcemapInterceptor: "prepareStackTrace"
|
|
607
|
+
}, options.evaluator);
|
|
608
|
+
this.options = options;
|
|
609
|
+
this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo;
|
|
610
|
+
this.mocker = options.mocker || new VitestMocker(this, {
|
|
611
|
+
context: options.vm?.context,
|
|
612
|
+
resolveId: options.transport.resolveId,
|
|
613
|
+
get root() {
|
|
614
|
+
return options.getWorkerState().config.root;
|
|
615
|
+
},
|
|
616
|
+
get moduleDirectories() {
|
|
617
|
+
return options.getWorkerState().config.deps.moduleDirectories || [];
|
|
618
|
+
},
|
|
619
|
+
getCurrentTestFilepath() {
|
|
620
|
+
return options.getWorkerState().filepath;
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
if (options.vm) options.vm.context.__vitest_mocker__ = this.mocker;
|
|
624
|
+
else Object.defineProperty(globalThis, "__vitest_mocker__", {
|
|
625
|
+
configurable: true,
|
|
626
|
+
writable: true,
|
|
627
|
+
value: this.mocker
|
|
628
|
+
});
|
|
514
629
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
630
|
+
async import(rawId) {
|
|
631
|
+
const resolved = await this.options.transport.resolveId(rawId);
|
|
632
|
+
if (!resolved) return super.import(rawId);
|
|
633
|
+
return super.import(resolved.url);
|
|
634
|
+
}
|
|
635
|
+
async fetchModule(url, importer) {
|
|
636
|
+
const module = await this.cachedModule(url, importer);
|
|
637
|
+
return module;
|
|
638
|
+
}
|
|
639
|
+
_cachedRequest(url, module, callstack = [], metadata) {
|
|
640
|
+
// @ts-expect-error "cachedRequest" is private
|
|
641
|
+
return super.cachedRequest(url, module, callstack, metadata);
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* @internal
|
|
645
|
+
*/
|
|
646
|
+
async cachedRequest(url, mod, callstack = [], metadata, ignoreMock = false) {
|
|
647
|
+
if (ignoreMock) return this._cachedRequest(url, mod, callstack, metadata);
|
|
648
|
+
let mocked;
|
|
649
|
+
if (mod.meta && "mockedModule" in mod.meta) mocked = await this.mocker.requestWithMockedModule(url, mod, callstack, mod.meta.mockedModule);
|
|
650
|
+
else mocked = await this.mocker.mockedRequest(url, mod, callstack);
|
|
651
|
+
if (typeof mocked === "string") {
|
|
652
|
+
const node = await this.fetchModule(mocked);
|
|
653
|
+
return this._cachedRequest(mocked, node, callstack, metadata);
|
|
654
|
+
}
|
|
655
|
+
if (mocked != null && typeof mocked === "object") return mocked;
|
|
656
|
+
return this._cachedRequest(url, mod, callstack, metadata);
|
|
657
|
+
}
|
|
658
|
+
/** @internal */
|
|
659
|
+
_invalidateSubTreeById(ids, invalidated = /* @__PURE__ */ new Set()) {
|
|
660
|
+
for (const id of ids) {
|
|
661
|
+
if (invalidated.has(id)) continue;
|
|
662
|
+
const node = this.evaluatedModules.getModuleById(id);
|
|
663
|
+
if (!node) continue;
|
|
664
|
+
invalidated.add(id);
|
|
665
|
+
const subIds = Array.from(this.evaluatedModules.idToModuleMap).filter(([, mod]) => mod.importers.has(id)).map(([key]) => key);
|
|
666
|
+
if (subIds.length) this._invalidateSubTreeById(subIds, invalidated);
|
|
667
|
+
this.evaluatedModules.invalidateModule(node);
|
|
668
|
+
}
|
|
518
669
|
}
|
|
519
|
-
return null;
|
|
520
670
|
}
|
|
521
|
-
|
|
671
|
+
|
|
672
|
+
const { readFileSync } = fs;
|
|
673
|
+
const browserExternalId = "__vite-browser-external";
|
|
674
|
+
const browserExternalLength = 24;
|
|
675
|
+
const VITEST_VM_CONTEXT_SYMBOL = "__vitest_vm_context__";
|
|
676
|
+
const cwd = process.cwd();
|
|
677
|
+
const isWindows = process.platform === "win32";
|
|
678
|
+
async function startVitestModuleRunner(options) {
|
|
522
679
|
const state = () => globalThis.__vitest_worker__ || options.state;
|
|
523
680
|
const rpc = () => state().rpc;
|
|
524
681
|
process.exit = (code = process.exitCode || 0) => {
|
|
525
682
|
throw new Error(`process.exit unexpectedly called with "${code}"`);
|
|
526
683
|
};
|
|
527
684
|
listenForErrors(state);
|
|
528
|
-
const
|
|
529
|
-
|
|
685
|
+
const environment = () => {
|
|
686
|
+
const environment = state().environment;
|
|
687
|
+
return environment.viteEnvironment || environment.name;
|
|
530
688
|
};
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
if (result.id && !result.externalize) {
|
|
537
|
-
const code = readFileSync(result.id, "utf-8");
|
|
538
|
-
return { code };
|
|
539
|
-
}
|
|
540
|
-
return result;
|
|
541
|
-
},
|
|
542
|
-
resolveId(id, importer) {
|
|
543
|
-
return rpc().resolveId(id, importer, getTransformMode());
|
|
544
|
-
},
|
|
545
|
-
get moduleCache() {
|
|
546
|
-
return state().moduleCache;
|
|
547
|
-
},
|
|
689
|
+
const vm = options.context && options.externalModulesExecutor ? {
|
|
690
|
+
context: options.context,
|
|
691
|
+
externalModulesExecutor: options.externalModulesExecutor
|
|
692
|
+
} : void 0;
|
|
693
|
+
const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
|
|
548
694
|
get moduleExecutionInfo() {
|
|
549
695
|
return state().moduleExecutionInfo;
|
|
550
696
|
},
|
|
551
697
|
get interopDefault() {
|
|
552
698
|
return state().config.deps.interopDefault;
|
|
553
699
|
},
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
700
|
+
getCurrentTestFilepath: () => state().filepath
|
|
701
|
+
});
|
|
702
|
+
const moduleRunner = new VitestModuleRunner({
|
|
703
|
+
evaluatedModules: options.evaluatedModules,
|
|
704
|
+
evaluator,
|
|
705
|
+
mocker: options.mocker,
|
|
706
|
+
transport: {
|
|
707
|
+
async fetchModule(id, importer, options) {
|
|
708
|
+
const resolvingModules = state().resolvingModules;
|
|
709
|
+
if (isWindows) {
|
|
710
|
+
if (id[1] === ":") {
|
|
711
|
+
// The drive letter is different for whatever reason, we need to normalize it to CWD
|
|
712
|
+
if (id[0] !== cwd[0] && id[0].toUpperCase() === cwd[0].toUpperCase()) {
|
|
713
|
+
const isUpperCase = cwd[0].toUpperCase() === cwd[0];
|
|
714
|
+
id = (isUpperCase ? id[0].toUpperCase() : id[0].toLowerCase()) + id.slice(1);
|
|
715
|
+
}
|
|
716
|
+
// always mark absolute windows paths, otherwise Vite will externalize it
|
|
717
|
+
id = `/@id/${id}`;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
const vitest = getCachedVitestImport(id, state);
|
|
721
|
+
if (vitest) return vitest;
|
|
722
|
+
const rawId = unwrapId(id);
|
|
723
|
+
resolvingModules.add(rawId);
|
|
724
|
+
try {
|
|
725
|
+
if (VitestMocker.pendingIds.length) await moduleRunner.mocker.resolveMocks();
|
|
726
|
+
const resolvedMock = moduleRunner.mocker.getDependencyMock(rawId);
|
|
727
|
+
if (resolvedMock?.type === "manual" || resolvedMock?.type === "redirect") return {
|
|
728
|
+
code: "",
|
|
729
|
+
file: null,
|
|
730
|
+
id,
|
|
731
|
+
url: id,
|
|
732
|
+
invalidate: false,
|
|
733
|
+
mockedModule: resolvedMock
|
|
734
|
+
};
|
|
735
|
+
if (isBuiltin(rawId) || rawId.startsWith(browserExternalId)) return {
|
|
736
|
+
externalize: toBuiltin(rawId),
|
|
737
|
+
type: "builtin"
|
|
738
|
+
};
|
|
739
|
+
const result = await rpc().fetch(id, importer, environment(), options);
|
|
740
|
+
if ("cached" in result) {
|
|
741
|
+
const code = readFileSync(result.tmp, "utf-8");
|
|
742
|
+
return {
|
|
743
|
+
code,
|
|
744
|
+
...result
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
return result;
|
|
748
|
+
} catch (cause) {
|
|
749
|
+
// rethrow vite error if it cannot load the module because it's not resolved
|
|
750
|
+
if (typeof cause === "object" && cause != null && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url") || typeof cause?.message === "string" && cause.message.startsWith("Cannot find module '")) {
|
|
751
|
+
const error = new Error(`Cannot find ${isBareImport(id) ? "package" : "module"} '${id}'${importer ? ` imported from '${importer}'` : ""}`, { cause });
|
|
752
|
+
error.code = "ERR_MODULE_NOT_FOUND";
|
|
753
|
+
throw error;
|
|
754
|
+
}
|
|
755
|
+
throw cause;
|
|
756
|
+
} finally {
|
|
757
|
+
resolvingModules.delete(rawId);
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
resolveId(id, importer) {
|
|
761
|
+
return rpc().resolve(id, importer, environment());
|
|
762
|
+
}
|
|
562
763
|
},
|
|
563
|
-
|
|
764
|
+
getWorkerState: state,
|
|
765
|
+
vm
|
|
564
766
|
});
|
|
767
|
+
await moduleRunner.import("/@vite/env");
|
|
768
|
+
await moduleRunner.mocker.initializeSpyModule();
|
|
769
|
+
return moduleRunner;
|
|
565
770
|
}
|
|
566
|
-
function
|
|
567
|
-
if (
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
element.textContent = css;
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
const head = document.querySelector("head");
|
|
574
|
-
const style = document.createElement("style");
|
|
575
|
-
style.setAttribute("type", "text/css");
|
|
576
|
-
style.setAttribute("data-vite-dev-id", id);
|
|
577
|
-
style.textContent = css;
|
|
578
|
-
head?.appendChild(style);
|
|
579
|
-
}
|
|
580
|
-
function removeStyle(id) {
|
|
581
|
-
if (typeof document === "undefined") return;
|
|
582
|
-
const sheet = document.querySelector(`[data-vite-dev-id="${id}"]`);
|
|
583
|
-
if (sheet) document.head.removeChild(sheet);
|
|
584
|
-
}
|
|
585
|
-
function getDefaultRequestStubs(context) {
|
|
586
|
-
if (!context) {
|
|
587
|
-
const clientStub = {
|
|
588
|
-
...DEFAULT_REQUEST_STUBS["@vite/client"],
|
|
589
|
-
updateStyle,
|
|
590
|
-
removeStyle
|
|
591
|
-
};
|
|
592
|
-
return {
|
|
593
|
-
"/@vite/client": clientStub,
|
|
594
|
-
"@vite/client": clientStub
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
const clientStub = vm.runInContext(`(defaultClient) => ({ ...defaultClient, updateStyle: ${updateStyle.toString()}, removeStyle: ${removeStyle.toString()} })`, context)(DEFAULT_REQUEST_STUBS["@vite/client"]);
|
|
598
|
-
return {
|
|
599
|
-
"/@vite/client": clientStub,
|
|
600
|
-
"@vite/client": clientStub
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
class VitestExecutor extends ViteNodeRunner {
|
|
604
|
-
mocker;
|
|
605
|
-
externalModules;
|
|
606
|
-
primitives;
|
|
607
|
-
constructor(options) {
|
|
608
|
-
super({
|
|
609
|
-
...options,
|
|
610
|
-
interopDefault: options.context ? false : options.interopDefault
|
|
611
|
-
});
|
|
612
|
-
this.options = options;
|
|
613
|
-
this.mocker = new VitestMocker(this);
|
|
614
|
-
if (!options.context) {
|
|
615
|
-
Object.defineProperty(globalThis, "__vitest_mocker__", {
|
|
616
|
-
value: this.mocker,
|
|
617
|
-
writable: true,
|
|
618
|
-
configurable: true
|
|
619
|
-
});
|
|
620
|
-
this.primitives = {
|
|
621
|
-
Object,
|
|
622
|
-
Reflect,
|
|
623
|
-
Symbol
|
|
624
|
-
};
|
|
625
|
-
} else if (options.externalModulesExecutor) {
|
|
626
|
-
this.primitives = vm.runInContext("({ Object, Reflect, Symbol })", options.context);
|
|
627
|
-
this.externalModules = options.externalModulesExecutor;
|
|
628
|
-
} else throw new Error("When context is provided, externalModulesExecutor must be provided as well.");
|
|
629
|
-
}
|
|
630
|
-
getContextPrimitives() {
|
|
631
|
-
return this.primitives;
|
|
632
|
-
}
|
|
633
|
-
get state() {
|
|
634
|
-
// @ts-expect-error injected untyped global
|
|
635
|
-
return globalThis.__vitest_worker__ || this.options.state;
|
|
636
|
-
}
|
|
637
|
-
get moduleExecutionInfo() {
|
|
638
|
-
return this.options.moduleExecutionInfo;
|
|
639
|
-
}
|
|
640
|
-
shouldResolveId(id, _importee) {
|
|
641
|
-
if (isInternalRequest(id) || id.startsWith("data:")) return false;
|
|
642
|
-
const transformMode = this.state.environment?.transformMode ?? "ssr";
|
|
643
|
-
// do not try and resolve node builtins in Node
|
|
644
|
-
// import('url') returns Node internal even if 'url' package is installed
|
|
645
|
-
return transformMode === "ssr" ? !isNodeBuiltin$1(id) : !id.startsWith("node:");
|
|
646
|
-
}
|
|
647
|
-
async originalResolveUrl(id, importer) {
|
|
648
|
-
return super.resolveUrl(id, importer);
|
|
649
|
-
}
|
|
650
|
-
async resolveUrl(id, importer) {
|
|
651
|
-
if (VitestMocker.pendingIds.length) await this.mocker.resolveMocks();
|
|
652
|
-
if (importer && importer.startsWith("mock:")) importer = importer.slice(5);
|
|
653
|
-
try {
|
|
654
|
-
return await super.resolveUrl(id, importer);
|
|
655
|
-
} catch (error) {
|
|
656
|
-
if (error.code === "ERR_MODULE_NOT_FOUND") {
|
|
657
|
-
const { id } = error[Symbol.for("vitest.error.not_found.data")];
|
|
658
|
-
const path = this.mocker.normalizePath(id);
|
|
659
|
-
const mock = this.mocker.getDependencyMock(path);
|
|
660
|
-
if (mock !== void 0) return [id, id];
|
|
661
|
-
}
|
|
662
|
-
throw error;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
async runModule(context, transformed) {
|
|
666
|
-
const vmContext = this.options.context;
|
|
667
|
-
if (!vmContext || !this.externalModules) return super.runModule(context, transformed);
|
|
668
|
-
// add 'use strict' since ESM enables it by default
|
|
669
|
-
const codeDefinition = `'use strict';async (${Object.keys(context).join(",")})=>{{`;
|
|
670
|
-
const code = `${codeDefinition}${transformed}\n}}`;
|
|
671
|
-
const options = {
|
|
672
|
-
filename: context.__filename,
|
|
673
|
-
lineOffset: 0,
|
|
674
|
-
columnOffset: -codeDefinition.length
|
|
675
|
-
};
|
|
676
|
-
const finishModuleExecutionInfo = this.startCalculateModuleExecutionInfo(options.filename, codeDefinition.length);
|
|
677
|
-
try {
|
|
678
|
-
const fn = vm.runInContext(code, vmContext, {
|
|
679
|
-
...options,
|
|
680
|
-
importModuleDynamically: this.externalModules.importModuleDynamically
|
|
681
|
-
});
|
|
682
|
-
await fn(...Object.values(context));
|
|
683
|
-
} finally {
|
|
684
|
-
this.options.moduleExecutionInfo?.set(options.filename, finishModuleExecutionInfo());
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
async importExternalModule(path) {
|
|
688
|
-
if (this.externalModules) return this.externalModules.import(path);
|
|
689
|
-
return super.importExternalModule(path);
|
|
690
|
-
}
|
|
691
|
-
async dependencyRequest(id, fsPath, callstack) {
|
|
692
|
-
const mocked = await this.mocker.requestWithMock(fsPath, callstack);
|
|
693
|
-
if (typeof mocked === "string") return super.dependencyRequest(mocked, mocked, callstack);
|
|
694
|
-
if (mocked && typeof mocked === "object") return mocked;
|
|
695
|
-
return super.dependencyRequest(id, fsPath, callstack);
|
|
696
|
-
}
|
|
697
|
-
prepareContext(context) {
|
|
698
|
-
// support `import.meta.vitest` for test entry
|
|
699
|
-
if (this.state.filepath && normalize$1(this.state.filepath) === normalize$1(context.__filename)) {
|
|
700
|
-
const globalNamespace = this.options.context || globalThis;
|
|
701
|
-
Object.defineProperty(context.__vite_ssr_import_meta__, "vitest", { get: () => globalNamespace.__vitest_index__ });
|
|
702
|
-
}
|
|
703
|
-
if (this.options.context && this.externalModules) context.require = this.externalModules.createRequire(context.__filename);
|
|
704
|
-
return context;
|
|
705
|
-
}
|
|
771
|
+
function toBuiltin(id) {
|
|
772
|
+
if (id.startsWith(browserExternalId)) id = id.slice(browserExternalLength);
|
|
773
|
+
if (!id.startsWith("node:")) id = `node:${id}`;
|
|
774
|
+
return id;
|
|
706
775
|
}
|
|
707
776
|
|
|
708
|
-
export {
|
|
777
|
+
export { VitestModuleRunner as V, VITEST_VM_CONTEXT_SYMBOL as a, startVitestModuleRunner as s };
|