vitest 4.0.14 → 4.0.15
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 +1 -1
- package/dist/browser.js +1 -1
- package/dist/chunks/{base.BEv8sRbK.js → base.CTp-EStD.js} +6 -6
- package/dist/chunks/browser.d.DBzUq_Na.d.ts +57 -0
- package/dist/chunks/{cac.DnEx6DOX.js → cac.BNNpZQl7.js} +10 -25
- package/dist/chunks/{cli-api.CbjxIXjQ.js → cli-api.C7sYjHmQ.js} +423 -98
- package/dist/chunks/{config.d.g6OOauRt.d.ts → config.d.CzIjkicf.d.ts} +1 -0
- package/dist/chunks/evaluatedModules.d.BxJ5omdx.d.ts +7 -0
- package/dist/chunks/{globals.C0izxiX3.js → globals.DOayXfHP.js} +3 -3
- package/dist/chunks/{index.D6PC4Dpu.js → index.456_DGfR.js} +128 -18
- package/dist/chunks/{index.B88tjlE5.js → index.Drsj_6e7.js} +1 -1
- package/dist/chunks/{index.DBx1AtPJ.js → index.Z5E_ObnR.js} +1 -1
- package/dist/chunks/{index.CQwQ_SLL.js → index.bFLgAE-Z.js} +2 -2
- package/dist/chunks/{init-forks.DmvIFK4U.js → init-forks.CKEYp90N.js} +11 -2
- package/dist/chunks/{init-threads.De6b3S3g.js → init-threads.D8Ok07M7.js} +1 -1
- package/dist/chunks/{init.a5SCIJ0x.js → init.B04saIIg.js} +1 -1
- package/dist/chunks/modules.DJPjQW6m.js +35 -0
- package/dist/chunks/{plugin.d.B6hlg3fN.d.ts → plugin.d.CY7CUjf-.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DeFcIuza.d.ts → reporters.d.OXEK7y4s.d.ts} +27 -4
- package/dist/chunks/{setup-common.DGHc_BUK.js → setup-common.Cm-kSBVi.js} +1 -1
- package/dist/chunks/{startModuleRunner.W28wBIgJ.js → startModuleRunner.Iz2V0ESw.js} +8 -9
- package/dist/chunks/{test.DqQZzsWf.js → test.BT8LKgU9.js} +8 -3
- package/dist/chunks/{vi.BiaV1qII.js → vi.2VT5v0um.js} +40 -30
- package/dist/chunks/{vm.BbVD4fJ5.js → vm.BwmD1Rql.js} +2 -2
- package/dist/chunks/{worker.d.DhEa3KzY.d.ts → worker.d.B4A26qg6.d.ts} +1 -1
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +7 -7
- package/dist/coverage.d.ts +8 -8
- package/dist/index.d.ts +22 -14
- package/dist/index.js +3 -3
- package/dist/module-evaluator.d.ts +5 -0
- package/dist/module-evaluator.js +21 -6
- package/dist/module-runner.js +2 -1
- package/dist/node.d.ts +7 -7
- package/dist/node.js +6 -5
- package/dist/reporters.d.ts +7 -7
- package/dist/reporters.js +2 -2
- package/dist/runners.d.ts +2 -1
- package/dist/runners.js +2 -2
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +9 -8
- package/dist/workers/forks.js +10 -9
- package/dist/workers/runVmTests.js +5 -5
- package/dist/workers/threads.js +10 -9
- package/dist/workers/vmForks.js +5 -4
- package/dist/workers/vmThreads.js +5 -4
- package/package.json +14 -14
- package/dist/chunks/browser.d.F6jMf15V.d.ts +0 -18
|
@@ -6,16 +6,16 @@ import { noop, createDefer, slash, isExternalUrl, unwrapId, withTrailingSlash, c
|
|
|
6
6
|
import { a as any, p as prompt } from './index.D4KonVSU.js';
|
|
7
7
|
import { h as hash, R as RandomSequencer, i as isPackageExists, c as isBrowserEnabled, r as resolveConfig, g as getCoverageProvider, a as resolveApiServerConfig, d as resolveModule } from './coverage.CtyeYmKM.js';
|
|
8
8
|
import * as vite from 'vite';
|
|
9
|
-
import { parseAst, searchForWorkspaceRoot, fetchModule, version, mergeConfig, createServer } from 'vite';
|
|
9
|
+
import { isFileServingAllowed, parseAst, searchForWorkspaceRoot, fetchModule, version, mergeConfig, createServer } from 'vite';
|
|
10
10
|
import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
|
|
11
11
|
import * as nodeos from 'node:os';
|
|
12
12
|
import nodeos__default, { tmpdir } from 'node:os';
|
|
13
13
|
import { generateHash as generateHash$1, createTaskName, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, hasFailed, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, getTasks, isTestCase } from '@vitest/runner/utils';
|
|
14
14
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
15
|
-
import { v as version$1 } from './cac.
|
|
15
|
+
import { v as version$1 } from './cac.BNNpZQl7.js';
|
|
16
16
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
17
17
|
import { c as createBirpc } from './index.0kCJoeWi.js';
|
|
18
|
-
import { p as parse, d as stringify, e as TraceMap, o as originalPositionFor,
|
|
18
|
+
import { p as parse, d as stringify, e as createIndexLocationsMap, h as TraceMap, o as originalPositionFor, i as ancestor, j as printError, f as formatProjectName, w as withLabel, k as errorBanner, l as divider, m as Typechecker, n as generateCodeFrame, q as escapeRegExp, r as createDefinesScript, R as ReportersMap, u as groupBy, B as BlobReporter, v as readBlobs, x as convertTasksToEvents, H as HangingProcessReporter, y as wildcardPatternToRegExp, z as stdout } from './index.456_DGfR.js';
|
|
19
19
|
import require$$0$3 from 'events';
|
|
20
20
|
import require$$1$1 from 'https';
|
|
21
21
|
import require$$2 from 'http';
|
|
@@ -37,11 +37,12 @@ import { VitestModuleEvaluator } from '#module-evaluator';
|
|
|
37
37
|
import { ModuleRunner } from 'vite/module-runner';
|
|
38
38
|
import { Console } from 'node:console';
|
|
39
39
|
import { highlight } from '@vitest/utils/highlight';
|
|
40
|
-
import { createRequire,
|
|
40
|
+
import { createRequire, builtinModules, isBuiltin as isBuiltin$1 } from 'node:module';
|
|
41
41
|
import url, { fileURLToPath, pathToFileURL } from 'node:url';
|
|
42
42
|
import { i as isTTY, a as isWindows } from './env.D4Lgay0q.js';
|
|
43
43
|
import { isatty } from 'node:tty';
|
|
44
44
|
import EventEmitter$1, { EventEmitter } from 'node:events';
|
|
45
|
+
import { t as toBuiltin, i as isBuiltin } from './modules.DJPjQW6m.js';
|
|
45
46
|
import { fork } from 'node:child_process';
|
|
46
47
|
import { Worker } from 'node:worker_threads';
|
|
47
48
|
import pm from 'picomatch';
|
|
@@ -52,7 +53,7 @@ import { c as configDefaults } from './defaults.BOqNVLsY.js';
|
|
|
52
53
|
import { KNOWN_ASSET_RE } from '@vitest/utils/constants';
|
|
53
54
|
import { findNearestPackageData } from '@vitest/utils/resolver';
|
|
54
55
|
import * as esModuleLexer from 'es-module-lexer';
|
|
55
|
-
import { a as BenchmarkReportsMap } from './index.
|
|
56
|
+
import { a as BenchmarkReportsMap } from './index.Drsj_6e7.js';
|
|
56
57
|
import assert$1 from 'node:assert';
|
|
57
58
|
import { serializeValue } from '@vitest/utils/serialize';
|
|
58
59
|
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
@@ -5025,30 +5026,55 @@ function requireWebsocketServer () {
|
|
|
5025
5026
|
var websocketServerExports = requireWebsocketServer();
|
|
5026
5027
|
var WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServerExports);
|
|
5027
5028
|
|
|
5028
|
-
|
|
5029
|
+
function getTestFileEnvironment(project, testFile, browser = false) {
|
|
5030
|
+
let environment;
|
|
5031
|
+
if (browser) environment = project.browser?.vite.environments.client;
|
|
5032
|
+
else for (const name in project.vite.environments) {
|
|
5033
|
+
const env = project.vite.environments[name];
|
|
5034
|
+
if (env.moduleGraph.getModuleById(testFile)) {
|
|
5035
|
+
environment = env;
|
|
5036
|
+
break;
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
return environment;
|
|
5040
|
+
}
|
|
5041
|
+
|
|
5042
|
+
async function getModuleGraph(ctx, projectName, testFilePath, browser = false) {
|
|
5029
5043
|
const graph = {};
|
|
5030
5044
|
const externalized = /* @__PURE__ */ new Set();
|
|
5031
5045
|
const inlined = /* @__PURE__ */ new Set();
|
|
5032
5046
|
const project = ctx.getProjectByName(projectName);
|
|
5033
|
-
|
|
5047
|
+
const environment = getTestFileEnvironment(project, testFilePath, browser);
|
|
5048
|
+
if (!environment) throw new Error(`Cannot find environment for ${testFilePath}`);
|
|
5049
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5050
|
+
function get(mod) {
|
|
5034
5051
|
if (!mod || !mod.id) return;
|
|
5035
|
-
if (mod.id === "\0vitest/browser") return;
|
|
5052
|
+
if (mod.id === "\0vitest/browser" || mod.id.includes("plugin-vue:export-helper")) return;
|
|
5036
5053
|
if (seen.has(mod)) return seen.get(mod);
|
|
5037
|
-
|
|
5054
|
+
const id = clearId(mod.id);
|
|
5038
5055
|
seen.set(mod, id);
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5056
|
+
if (id.startsWith("__vite-browser-external:")) {
|
|
5057
|
+
const external = id.slice(24);
|
|
5058
|
+
externalized.add(external);
|
|
5059
|
+
return external;
|
|
5060
|
+
}
|
|
5061
|
+
const external = project._resolver.wasExternalized(id);
|
|
5062
|
+
if (typeof external === "string") {
|
|
5063
|
+
externalized.add(external);
|
|
5064
|
+
return external;
|
|
5065
|
+
}
|
|
5066
|
+
if (browser && mod.file?.includes(project.browser.vite.config.cacheDir)) {
|
|
5067
|
+
externalized.add(mod.id);
|
|
5068
|
+
return id;
|
|
5069
|
+
}
|
|
5070
|
+
inlined.add(id);
|
|
5071
|
+
graph[id] = Array.from(mod.importedModules).filter((i) => i.id && !i.id.includes("/vitest/dist/")).map((m) => get(m)).filter(Boolean);
|
|
5048
5072
|
return id;
|
|
5049
5073
|
}
|
|
5050
|
-
|
|
5051
|
-
|
|
5074
|
+
get(environment.moduleGraph.getModuleById(testFilePath));
|
|
5075
|
+
project.config.setupFiles.forEach((setupFile) => {
|
|
5076
|
+
get(environment.moduleGraph.getModuleById(setupFile));
|
|
5077
|
+
});
|
|
5052
5078
|
return {
|
|
5053
5079
|
graph,
|
|
5054
5080
|
externalized: Array.from(externalized),
|
|
@@ -5146,15 +5172,36 @@ function setup(ctx, _server) {
|
|
|
5146
5172
|
color: p.color
|
|
5147
5173
|
}));
|
|
5148
5174
|
},
|
|
5149
|
-
async
|
|
5175
|
+
async getExternalResult(moduleId, testFileTaskId) {
|
|
5176
|
+
const testModule = ctx.state.getReportedEntityById(testFileTaskId);
|
|
5177
|
+
if (!testModule) return;
|
|
5178
|
+
if (!isFileServingAllowed(testModule.project.vite.config, moduleId)) return;
|
|
5179
|
+
const result = {};
|
|
5180
|
+
try {
|
|
5181
|
+
result.source = await promises.readFile(moduleId, "utf-8");
|
|
5182
|
+
} catch {}
|
|
5183
|
+
return result;
|
|
5184
|
+
},
|
|
5185
|
+
async getTransformResult(projectName, moduleId, testFileTaskId, browser = false) {
|
|
5150
5186
|
const project = ctx.getProjectByName(projectName);
|
|
5151
|
-
const
|
|
5152
|
-
if (
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5187
|
+
const testModule = ctx.state.getReportedEntityById(testFileTaskId);
|
|
5188
|
+
if (!testModule || !isFileServingAllowed(project.vite.config, moduleId)) return;
|
|
5189
|
+
const environment = getTestFileEnvironment(project, testModule.moduleId, browser);
|
|
5190
|
+
const moduleNode = environment?.moduleGraph.getModuleById(moduleId);
|
|
5191
|
+
if (!environment || !moduleNode?.transformResult) return;
|
|
5192
|
+
const result = moduleNode.transformResult;
|
|
5193
|
+
try {
|
|
5194
|
+
result.source = result.source || (moduleNode.file ? await promises.readFile(moduleNode.file, "utf-8") : void 0);
|
|
5195
|
+
} catch {}
|
|
5196
|
+
// TODO: store this in HTML reporter separetly
|
|
5197
|
+
const transformDuration = ctx.state.metadata[projectName]?.duration[moduleNode.url]?.[0];
|
|
5198
|
+
if (transformDuration != null) result.transformTime = transformDuration;
|
|
5199
|
+
try {
|
|
5200
|
+
const diagnostic = await ctx.experimental_getSourceModuleDiagnostic(moduleId, testModule);
|
|
5201
|
+
result.modules = diagnostic.modules;
|
|
5202
|
+
result.untrackedModules = diagnostic.untrackedModules;
|
|
5203
|
+
} catch {}
|
|
5204
|
+
return result;
|
|
5158
5205
|
},
|
|
5159
5206
|
async getModuleGraph(project, id, browser) {
|
|
5160
5207
|
return getModuleGraph(ctx, project, id, browser);
|
|
@@ -5273,31 +5320,6 @@ var setup$1 = /*#__PURE__*/Object.freeze({
|
|
|
5273
5320
|
setup: setup
|
|
5274
5321
|
});
|
|
5275
5322
|
|
|
5276
|
-
function groupBy(collection, iteratee) {
|
|
5277
|
-
return collection.reduce((acc, item) => {
|
|
5278
|
-
const key = iteratee(item);
|
|
5279
|
-
acc[key] ||= [];
|
|
5280
|
-
acc[key].push(item);
|
|
5281
|
-
return acc;
|
|
5282
|
-
}, {});
|
|
5283
|
-
}
|
|
5284
|
-
function stdout() {
|
|
5285
|
-
// @ts-expect-error Node.js maps process.stdout to console._stdout
|
|
5286
|
-
// eslint-disable-next-line no-console
|
|
5287
|
-
return console._stdout || process.stdout;
|
|
5288
|
-
}
|
|
5289
|
-
function escapeRegExp(s) {
|
|
5290
|
-
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
5291
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5292
|
-
}
|
|
5293
|
-
function wildcardPatternToRegExp(pattern) {
|
|
5294
|
-
const negated = pattern[0] === "!";
|
|
5295
|
-
if (negated) pattern = pattern.slice(1);
|
|
5296
|
-
let regexp = `${pattern.split("*").map(escapeRegExp).join(".*")}$`;
|
|
5297
|
-
if (negated) regexp = `(?!${regexp})`;
|
|
5298
|
-
return new RegExp(`^${regexp}`, "i");
|
|
5299
|
-
}
|
|
5300
|
-
|
|
5301
5323
|
function createDebugger(namespace) {
|
|
5302
5324
|
const debug = createDebug(namespace);
|
|
5303
5325
|
if (debug.enabled) return debug;
|
|
@@ -5450,7 +5472,7 @@ function createFileTask(testFilepath, code, requestMap, options) {
|
|
|
5450
5472
|
file: null
|
|
5451
5473
|
};
|
|
5452
5474
|
file.file = file;
|
|
5453
|
-
const indexMap =
|
|
5475
|
+
const indexMap = createIndexLocationsMap(code);
|
|
5454
5476
|
const map = requestMap && new TraceMap(requestMap);
|
|
5455
5477
|
let lastSuite = file;
|
|
5456
5478
|
const updateLatestSuite = (index) => {
|
|
@@ -5552,23 +5574,6 @@ async function transformSSR(project, filepath) {
|
|
|
5552
5574
|
if (!request) return null;
|
|
5553
5575
|
return await project.vite.ssrTransform(request.code, request.map, filepath);
|
|
5554
5576
|
}
|
|
5555
|
-
function createIndexMap(source) {
|
|
5556
|
-
const map = /* @__PURE__ */ new Map();
|
|
5557
|
-
let index = 0;
|
|
5558
|
-
let line = 1;
|
|
5559
|
-
let column = 1;
|
|
5560
|
-
for (const char of source) {
|
|
5561
|
-
map.set(index++, {
|
|
5562
|
-
line,
|
|
5563
|
-
column
|
|
5564
|
-
});
|
|
5565
|
-
if (char === "\n" || char === "\r\n") {
|
|
5566
|
-
line++;
|
|
5567
|
-
column = 0;
|
|
5568
|
-
} else column++;
|
|
5569
|
-
}
|
|
5570
|
-
return map;
|
|
5571
|
-
}
|
|
5572
5577
|
function markDynamicTests(tasks) {
|
|
5573
5578
|
for (const task of tasks) {
|
|
5574
5579
|
if (task.dynamic) task.id += "-dynamic";
|
|
@@ -5766,7 +5771,7 @@ class FileSystemModuleCache {
|
|
|
5766
5771
|
*/
|
|
5767
5772
|
rootCache;
|
|
5768
5773
|
metadataFilePath;
|
|
5769
|
-
version = "1.0.0-beta.
|
|
5774
|
+
version = "1.0.0-beta.3";
|
|
5770
5775
|
fsCacheRoots = /* @__PURE__ */ new WeakMap();
|
|
5771
5776
|
fsEnvironmentHashMap = /* @__PURE__ */ new WeakMap();
|
|
5772
5777
|
fsCacheKeyGenerators = /* @__PURE__ */ new Set();
|
|
@@ -5811,7 +5816,7 @@ class FileSystemModuleCache {
|
|
|
5811
5816
|
}
|
|
5812
5817
|
async getCachedModule(cachedFilePath) {
|
|
5813
5818
|
if (!existsSync(cachedFilePath)) {
|
|
5814
|
-
debugFs?.(`${c.red("[empty]")} ${cachedFilePath} doesn't exist, transforming by vite
|
|
5819
|
+
debugFs?.(`${c.red("[empty]")} ${cachedFilePath} doesn't exist, transforming by vite first`);
|
|
5815
5820
|
return;
|
|
5816
5821
|
}
|
|
5817
5822
|
const fileResult = await this.readCachedFileConcurrently(cachedFilePath);
|
|
@@ -5824,16 +5829,18 @@ class FileSystemModuleCache {
|
|
|
5824
5829
|
file: meta.file,
|
|
5825
5830
|
code,
|
|
5826
5831
|
importers: meta.importers,
|
|
5832
|
+
importedUrls: meta.importedUrls,
|
|
5827
5833
|
mappings: meta.mappings
|
|
5828
5834
|
};
|
|
5829
5835
|
}
|
|
5830
|
-
async saveCachedModule(cachedFilePath, fetchResult, importers = [], mappings = false) {
|
|
5836
|
+
async saveCachedModule(cachedFilePath, fetchResult, importers = [], importedUrls = [], mappings = false) {
|
|
5831
5837
|
if ("code" in fetchResult) {
|
|
5832
5838
|
const result = {
|
|
5833
5839
|
file: fetchResult.file,
|
|
5834
5840
|
id: fetchResult.id,
|
|
5835
5841
|
url: fetchResult.url,
|
|
5836
5842
|
importers,
|
|
5843
|
+
importedUrls,
|
|
5837
5844
|
mappings
|
|
5838
5845
|
};
|
|
5839
5846
|
debugFs?.(`${c.yellow("[write]")} ${fetchResult.id} is cached in ${cachedFilePath}`);
|
|
@@ -5861,12 +5868,12 @@ class FileSystemModuleCache {
|
|
|
5861
5868
|
else if (result === null) debugMemory?.(`${c.green("[read]")} ${id} was bailed out`);
|
|
5862
5869
|
return result;
|
|
5863
5870
|
}
|
|
5864
|
-
generateCachePath(vitestConfig, environment,
|
|
5871
|
+
generateCachePath(vitestConfig, environment, id, fileContent) {
|
|
5865
5872
|
// bail out if file has import.meta.glob because it depends on other files
|
|
5866
5873
|
// TODO: figure out a way to still support it
|
|
5867
5874
|
if (fileContent.includes("import.meta.glob(")) {
|
|
5868
5875
|
this.saveMemoryCache(environment, id, null);
|
|
5869
|
-
debugMemory?.(`${c.yellow("[write]")} ${id} was bailed out`);
|
|
5876
|
+
debugMemory?.(`${c.yellow("[write]")} ${id} was bailed out because it has "import.meta.glob"`);
|
|
5870
5877
|
return null;
|
|
5871
5878
|
}
|
|
5872
5879
|
let hashString = "";
|
|
@@ -5895,7 +5902,7 @@ class FileSystemModuleCache {
|
|
|
5895
5902
|
mode: config.mode,
|
|
5896
5903
|
consumer: config.consumer,
|
|
5897
5904
|
resolve: config.resolve,
|
|
5898
|
-
plugins: config.plugins.map((p) => p.name),
|
|
5905
|
+
plugins: config.plugins.filter((p) => p.api?.vitest?.experimental?.ignoreFsModuleCache !== true).map((p) => p.name),
|
|
5899
5906
|
configFileDependencies: config.configFileDependencies.map((file) => tryReadFileSync(file)),
|
|
5900
5907
|
environment: environment.name,
|
|
5901
5908
|
css: vitestConfig.css
|
|
@@ -5910,6 +5917,7 @@ class FileSystemModuleCache {
|
|
|
5910
5917
|
let cacheRoot = this.fsCacheRoots.get(vitestConfig);
|
|
5911
5918
|
if (cacheRoot == null) {
|
|
5912
5919
|
cacheRoot = vitestConfig.experimental.fsModuleCachePath || this.rootCache;
|
|
5920
|
+
this.fsCacheRoots.set(vitestConfig, cacheRoot);
|
|
5913
5921
|
if (!existsSync(cacheRoot)) mkdirSync(cacheRoot, { recursive: true });
|
|
5914
5922
|
}
|
|
5915
5923
|
const fsResultPath = join(cacheRoot, cacheKey);
|
|
@@ -6079,11 +6087,10 @@ const readFilePromises = /* @__PURE__ */ new Map();
|
|
|
6079
6087
|
class ModuleFetcher {
|
|
6080
6088
|
tmpDirectories = /* @__PURE__ */ new Set();
|
|
6081
6089
|
fsCacheEnabled;
|
|
6082
|
-
constructor(resolver, config, fsCache,
|
|
6090
|
+
constructor(resolver, config, fsCache, tmpProjectDir) {
|
|
6083
6091
|
this.resolver = resolver;
|
|
6084
6092
|
this.config = config;
|
|
6085
6093
|
this.fsCache = fsCache;
|
|
6086
|
-
this.traces = traces;
|
|
6087
6094
|
this.tmpProjectDir = tmpProjectDir;
|
|
6088
6095
|
this.fsCacheEnabled = config.experimental?.fsModuleCache === true;
|
|
6089
6096
|
}
|
|
@@ -6151,10 +6158,20 @@ class ModuleFetcher {
|
|
|
6151
6158
|
}
|
|
6152
6159
|
const result = await this.fetchAndProcess(environment, url, importer, moduleGraphModule, options);
|
|
6153
6160
|
const importers = this.getSerializedDependencies(moduleGraphModule);
|
|
6161
|
+
const importedUrls = this.getSerializedImports(moduleGraphModule);
|
|
6154
6162
|
const map = moduleGraphModule.transformResult?.map;
|
|
6155
6163
|
const mappings = map && !("version" in map) && map.mappings === "";
|
|
6156
|
-
return this.cacheResult(result, cachePath, importers, !!mappings);
|
|
6164
|
+
return this.cacheResult(result, cachePath, importers, importedUrls, !!mappings);
|
|
6165
|
+
}
|
|
6166
|
+
// we need this for UI to be able to show a module graph
|
|
6167
|
+
getSerializedImports(node) {
|
|
6168
|
+
const imports = [];
|
|
6169
|
+
node.importedModules.forEach((importer) => {
|
|
6170
|
+
imports.push(importer.url);
|
|
6171
|
+
});
|
|
6172
|
+
return imports;
|
|
6157
6173
|
}
|
|
6174
|
+
// we need this for the watcher to be able to find the related test file
|
|
6158
6175
|
getSerializedDependencies(node) {
|
|
6159
6176
|
const dependencies = [];
|
|
6160
6177
|
node.importers.forEach((importer) => {
|
|
@@ -6186,7 +6203,7 @@ class ModuleFetcher {
|
|
|
6186
6203
|
// null means the file should not be cached
|
|
6187
6204
|
if (memoryCacheKey !== void 0) return memoryCacheKey;
|
|
6188
6205
|
const fileContent = await this.readFileContentToCache(environment, moduleGraphModule);
|
|
6189
|
-
return this.fsCache.generateCachePath(this.config, environment,
|
|
6206
|
+
return this.fsCache.generateCachePath(this.config, environment, moduleGraphModule.id, fileContent);
|
|
6190
6207
|
}
|
|
6191
6208
|
async readFileContentToCache(environment, moduleGraphModule) {
|
|
6192
6209
|
if (moduleGraphModule.file && !moduleGraphModule.file.startsWith("\0") && !moduleGraphModule.file.startsWith("virtual:")) {
|
|
@@ -6225,6 +6242,10 @@ class ModuleFetcher {
|
|
|
6225
6242
|
const environmentNode = environment.moduleGraph.getModuleById(importer);
|
|
6226
6243
|
if (environmentNode) moduleGraphModule.importers.add(environmentNode);
|
|
6227
6244
|
});
|
|
6245
|
+
await Promise.all(cachedModule.importedUrls.map(async (url) => {
|
|
6246
|
+
const moduleNode = await environment.moduleGraph.ensureEntryFromUrl(url).catch(() => null);
|
|
6247
|
+
if (moduleNode) moduleGraphModule.importedModules.add(moduleNode);
|
|
6248
|
+
}));
|
|
6228
6249
|
return {
|
|
6229
6250
|
cached: true,
|
|
6230
6251
|
file: cachedModule.file,
|
|
@@ -6240,13 +6261,13 @@ class ModuleFetcher {
|
|
|
6240
6261
|
inlineSourceMap: false
|
|
6241
6262
|
}).catch(handleRollupError));
|
|
6242
6263
|
}
|
|
6243
|
-
async cacheResult(result, cachePath, importers = [], mappings = false) {
|
|
6264
|
+
async cacheResult(result, cachePath, importers = [], importedUrls = [], mappings = false) {
|
|
6244
6265
|
const returnResult = "code" in result ? getCachedResult(result, cachePath) : result;
|
|
6245
6266
|
if (saveCachePromises.has(cachePath)) {
|
|
6246
6267
|
await saveCachePromises.get(cachePath);
|
|
6247
6268
|
return returnResult;
|
|
6248
6269
|
}
|
|
6249
|
-
const savePromise = this.fsCache.saveCachedModule(cachePath, result, importers, mappings).then(() => result).finally(() => {
|
|
6270
|
+
const savePromise = this.fsCache.saveCachedModule(cachePath, result, importers, importedUrls, mappings).then(() => result).finally(() => {
|
|
6250
6271
|
saveCachePromises.delete(cachePath);
|
|
6251
6272
|
});
|
|
6252
6273
|
saveCachePromises.set(cachePath, savePromise);
|
|
@@ -6265,7 +6286,7 @@ class ModuleFetcher {
|
|
|
6265
6286
|
}
|
|
6266
6287
|
}
|
|
6267
6288
|
function createFetchModuleFunction(resolver, config, fsCache, traces, tmpProjectDir) {
|
|
6268
|
-
const fetcher = new ModuleFetcher(resolver, config, fsCache,
|
|
6289
|
+
const fetcher = new ModuleFetcher(resolver, config, fsCache, tmpProjectDir);
|
|
6269
6290
|
return async (url, importer, environment, cacheFs, options, otelCarrier) => {
|
|
6270
6291
|
await traces.waitInit();
|
|
6271
6292
|
const context = otelCarrier ? traces.getContextFromCarrier(otelCarrier) : void 0;
|
|
@@ -6664,6 +6685,238 @@ This might cause false positive tests. Resolve unhandled errors to make sure you
|
|
|
6664
6685
|
}
|
|
6665
6686
|
}
|
|
6666
6687
|
|
|
6688
|
+
// this function recieves the module diagnostic with the location of imports
|
|
6689
|
+
// and populates it with collected import durations; the duration is injected
|
|
6690
|
+
// only if the current module is the one that imported the module
|
|
6691
|
+
// if testModule is not defined, then Vitest aggregates durations of ALL collected test modules
|
|
6692
|
+
function collectModuleDurationsDiagnostic(moduleId, state, moduleDiagnostic, testModule) {
|
|
6693
|
+
if (!moduleDiagnostic) return {
|
|
6694
|
+
modules: [],
|
|
6695
|
+
untrackedModules: []
|
|
6696
|
+
};
|
|
6697
|
+
const modules = [];
|
|
6698
|
+
const modulesById = {};
|
|
6699
|
+
const allModules = [...moduleDiagnostic.modules, ...moduleDiagnostic.untracked];
|
|
6700
|
+
const visitedByFiles = {};
|
|
6701
|
+
// this aggregates the times for _ALL_ tests if testModule is not passed
|
|
6702
|
+
// so if the module was imported in separate tests, the time will be accumulated
|
|
6703
|
+
for (const files of testModule ? [[testModule.task]] : state.filesMap.values()) for (const file of files) {
|
|
6704
|
+
const importDurations = file.importDurations;
|
|
6705
|
+
if (!importDurations) continue;
|
|
6706
|
+
const currentModule = state.getReportedEntity(file);
|
|
6707
|
+
if (!currentModule) continue;
|
|
6708
|
+
const visitedKey = currentModule.project.config.isolate === false ? "non-isolate" : file.id;
|
|
6709
|
+
if (!visitedByFiles[visitedKey]) visitedByFiles[visitedKey] = /* @__PURE__ */ new Set();
|
|
6710
|
+
const visited = visitedByFiles[visitedKey];
|
|
6711
|
+
allModules.forEach(({ resolvedId, resolvedUrl }) => {
|
|
6712
|
+
const durations = importDurations[resolvedId];
|
|
6713
|
+
// do not accumulate if module was already visited by suite (or suites in non-isolate mode)
|
|
6714
|
+
if (!durations || visited.has(resolvedId)) return;
|
|
6715
|
+
const importer = getModuleImporter(moduleId, durations, currentModule);
|
|
6716
|
+
modulesById[resolvedId] ??= {
|
|
6717
|
+
selfTime: 0,
|
|
6718
|
+
totalTime: 0,
|
|
6719
|
+
transformTime: 0,
|
|
6720
|
+
external: durations.external,
|
|
6721
|
+
importer
|
|
6722
|
+
};
|
|
6723
|
+
// only track if the current module imported this module,
|
|
6724
|
+
// otherwise it was imported instantly because it's cached
|
|
6725
|
+
if (importer === moduleId) {
|
|
6726
|
+
visited.add(resolvedId);
|
|
6727
|
+
modulesById[resolvedId].selfTime += durations.selfTime;
|
|
6728
|
+
modulesById[resolvedId].totalTime += durations.totalTime;
|
|
6729
|
+
// don't aggregate
|
|
6730
|
+
modulesById[resolvedId].transformTime = state.metadata[currentModule.project.name]?.duration[resolvedUrl]?.[0];
|
|
6731
|
+
}
|
|
6732
|
+
});
|
|
6733
|
+
}
|
|
6734
|
+
// if module was imported twice in the same file,
|
|
6735
|
+
// show only one time - the second should be shown as 0
|
|
6736
|
+
const visitedInFile = /* @__PURE__ */ new Set();
|
|
6737
|
+
moduleDiagnostic.modules.forEach((diagnostic) => {
|
|
6738
|
+
const durations = modulesById[diagnostic.resolvedId];
|
|
6739
|
+
if (!durations) return;
|
|
6740
|
+
if (visitedInFile.has(diagnostic.resolvedId)) modules.push({
|
|
6741
|
+
...diagnostic,
|
|
6742
|
+
selfTime: 0,
|
|
6743
|
+
totalTime: 0,
|
|
6744
|
+
transformTime: 0,
|
|
6745
|
+
external: durations.external,
|
|
6746
|
+
importer: durations.importer
|
|
6747
|
+
});
|
|
6748
|
+
else {
|
|
6749
|
+
visitedInFile.add(diagnostic.resolvedId);
|
|
6750
|
+
modules.push({
|
|
6751
|
+
...diagnostic,
|
|
6752
|
+
...durations
|
|
6753
|
+
});
|
|
6754
|
+
}
|
|
6755
|
+
});
|
|
6756
|
+
const untracked = [];
|
|
6757
|
+
moduleDiagnostic.untracked.forEach((diagnostic) => {
|
|
6758
|
+
const durations = modulesById[diagnostic.resolvedId];
|
|
6759
|
+
if (!durations) return;
|
|
6760
|
+
if (visitedInFile.has(diagnostic.resolvedId)) untracked.push({
|
|
6761
|
+
selfTime: 0,
|
|
6762
|
+
totalTime: 0,
|
|
6763
|
+
transformTime: 0,
|
|
6764
|
+
external: durations.external,
|
|
6765
|
+
importer: durations.importer,
|
|
6766
|
+
resolvedId: diagnostic.resolvedId,
|
|
6767
|
+
resolvedUrl: diagnostic.resolvedUrl,
|
|
6768
|
+
url: diagnostic.rawUrl
|
|
6769
|
+
});
|
|
6770
|
+
else {
|
|
6771
|
+
visitedInFile.add(diagnostic.resolvedId);
|
|
6772
|
+
untracked.push({
|
|
6773
|
+
...durations,
|
|
6774
|
+
resolvedId: diagnostic.resolvedId,
|
|
6775
|
+
resolvedUrl: diagnostic.resolvedUrl,
|
|
6776
|
+
url: diagnostic.rawUrl
|
|
6777
|
+
});
|
|
6778
|
+
}
|
|
6779
|
+
});
|
|
6780
|
+
return {
|
|
6781
|
+
modules,
|
|
6782
|
+
untrackedModules: untracked
|
|
6783
|
+
};
|
|
6784
|
+
}
|
|
6785
|
+
function getModuleImporter(moduleId, durations, testModule) {
|
|
6786
|
+
if (durations.importer === moduleId) return moduleId;
|
|
6787
|
+
if (!durations.importer) {
|
|
6788
|
+
if (moduleId === testModule.moduleId) return testModule.moduleId;
|
|
6789
|
+
return testModule.project.config.setupFiles.includes(moduleId) ? moduleId : durations.importer;
|
|
6790
|
+
}
|
|
6791
|
+
return durations.importer;
|
|
6792
|
+
}
|
|
6793
|
+
// the idea of this is very simple
|
|
6794
|
+
// it parses the source code to extract import/export statements
|
|
6795
|
+
// it parses SSR transformed file to extract __vite_ssr_import__ and __vite_ssr_dynamic_import__
|
|
6796
|
+
// it combines the two by looking at the original positions of SSR primitives
|
|
6797
|
+
// in the end, we are able to return a list of modules that were imported by this module
|
|
6798
|
+
// mapped to their IDs in Vite's module graph
|
|
6799
|
+
async function collectSourceModulesLocations(moduleId, moduleGraph) {
|
|
6800
|
+
const transformResult = moduleGraph.getModuleById(moduleId)?.transformResult;
|
|
6801
|
+
if (!transformResult || !transformResult.ssr) return;
|
|
6802
|
+
const map = transformResult.map;
|
|
6803
|
+
if (!map || !("version" in map) || !map.sources.length) return;
|
|
6804
|
+
const sourceImports = map.sources.reduce((acc, sourceId, index) => {
|
|
6805
|
+
const source = map.sourcesContent?.[index];
|
|
6806
|
+
if (source != null) acc[sourceId] = parseSourceImportsAndExports(source);
|
|
6807
|
+
return acc;
|
|
6808
|
+
}, {});
|
|
6809
|
+
const transformImports = await parseTransformResult(moduleGraph, transformResult);
|
|
6810
|
+
const traceMap = map && "version" in map && new TraceMap(map);
|
|
6811
|
+
const modules = {};
|
|
6812
|
+
const untracked = [];
|
|
6813
|
+
transformImports.forEach((row) => {
|
|
6814
|
+
const original = traceMap && originalPositionFor(traceMap, row.start);
|
|
6815
|
+
if (original && original.source != null) {
|
|
6816
|
+
// if there are several at the same position, this is a bug
|
|
6817
|
+
// probably caused by import.meta.glob imports returning incorrect positions
|
|
6818
|
+
// all the new import.meta.glob imports come first, so only the last module on this line is correct
|
|
6819
|
+
const sourceImport = sourceImports[original.source].get(`${original.line}:${original.column}`);
|
|
6820
|
+
if (sourceImport) {
|
|
6821
|
+
if (modules[sourceImport.rawUrl]) {
|
|
6822
|
+
// remove imports with a different resolvedId
|
|
6823
|
+
const differentImports = modules[sourceImport.rawUrl].filter((d) => d.resolvedId !== row.resolvedId);
|
|
6824
|
+
untracked.push(...differentImports);
|
|
6825
|
+
modules[sourceImport.rawUrl] = modules[sourceImport.rawUrl].filter((d) => d.resolvedId === row.resolvedId);
|
|
6826
|
+
}
|
|
6827
|
+
modules[sourceImport.rawUrl] ??= [];
|
|
6828
|
+
modules[sourceImport.rawUrl].push({
|
|
6829
|
+
start: sourceImport.start,
|
|
6830
|
+
end: sourceImport.end,
|
|
6831
|
+
startIndex: sourceImport.startIndex,
|
|
6832
|
+
endIndex: sourceImport.endIndex,
|
|
6833
|
+
rawUrl: sourceImport.rawUrl,
|
|
6834
|
+
resolvedId: row.resolvedId,
|
|
6835
|
+
resolvedUrl: row.resolvedUrl
|
|
6836
|
+
});
|
|
6837
|
+
}
|
|
6838
|
+
}
|
|
6839
|
+
});
|
|
6840
|
+
return {
|
|
6841
|
+
modules: Object.values(modules).flat(),
|
|
6842
|
+
untracked
|
|
6843
|
+
};
|
|
6844
|
+
}
|
|
6845
|
+
function fillSourcesMap(syntax, sourcesMap, source, indexMap) {
|
|
6846
|
+
const splitSeparator = `${syntax} `;
|
|
6847
|
+
const splitSources = source.split(splitSeparator);
|
|
6848
|
+
const chunks = [];
|
|
6849
|
+
let index = 0;
|
|
6850
|
+
for (const chunk of splitSources) {
|
|
6851
|
+
chunks.push({
|
|
6852
|
+
chunk,
|
|
6853
|
+
startIndex: index
|
|
6854
|
+
});
|
|
6855
|
+
index += chunk.length + splitSeparator.length;
|
|
6856
|
+
}
|
|
6857
|
+
chunks.forEach(({ chunk, startIndex }) => {
|
|
6858
|
+
const normalized = chunk.replace(/'/g, "\"");
|
|
6859
|
+
const startQuoteIdx = normalized.indexOf("\"");
|
|
6860
|
+
if (startQuoteIdx === -1) return;
|
|
6861
|
+
const endQuoteIdx = normalized.indexOf("\"", startQuoteIdx + 1);
|
|
6862
|
+
if (endQuoteIdx === -1) return;
|
|
6863
|
+
const staticSyntax = {
|
|
6864
|
+
startIndex: startIndex + startQuoteIdx,
|
|
6865
|
+
endIndex: startIndex + endQuoteIdx + 1,
|
|
6866
|
+
start: indexMap.get(startIndex + startQuoteIdx),
|
|
6867
|
+
end: indexMap.get(startIndex + endQuoteIdx + 1),
|
|
6868
|
+
rawUrl: normalized.slice(startQuoteIdx + 1, endQuoteIdx)
|
|
6869
|
+
};
|
|
6870
|
+
// -7 to include "import "
|
|
6871
|
+
for (let i = startIndex - 7; i < staticSyntax.endIndex; i++) {
|
|
6872
|
+
const location = indexMap.get(i);
|
|
6873
|
+
if (location) sourcesMap.set(`${location.line}:${location.column}`, staticSyntax);
|
|
6874
|
+
}
|
|
6875
|
+
});
|
|
6876
|
+
}
|
|
6877
|
+
// this function tries to parse ESM static import and export statements from
|
|
6878
|
+
// the source. if the source is not JS/TS, but supports static ESM syntax,
|
|
6879
|
+
// then this will also find them because it' only checks the strings, it doesn't parse the AST
|
|
6880
|
+
function parseSourceImportsAndExports(source) {
|
|
6881
|
+
if (!source.includes("import ") && !source.includes("export ")) return /* @__PURE__ */ new Map();
|
|
6882
|
+
const sourcesMap = /* @__PURE__ */ new Map();
|
|
6883
|
+
const indexMap = createIndexLocationsMap(source);
|
|
6884
|
+
fillSourcesMap("import", sourcesMap, source, indexMap);
|
|
6885
|
+
fillSourcesMap("export", sourcesMap, source, indexMap);
|
|
6886
|
+
return sourcesMap;
|
|
6887
|
+
}
|
|
6888
|
+
async function parseTransformResult(moduleGraph, transformResult) {
|
|
6889
|
+
const code = transformResult.code;
|
|
6890
|
+
const regexp = /(?:__vite_ssr_import__|__vite_ssr_dynamic_import__)\("([^"]+)"/g;
|
|
6891
|
+
const lineColumnMap = createIndexLocationsMap(code);
|
|
6892
|
+
const importPositions = [];
|
|
6893
|
+
let match;
|
|
6894
|
+
// eslint-disable-next-line no-cond-assign
|
|
6895
|
+
while (match = regexp.exec(code)) {
|
|
6896
|
+
const startIndex = match.index;
|
|
6897
|
+
const endIndex = match.index + match[0].length - 1;
|
|
6898
|
+
importPositions.push({
|
|
6899
|
+
raw: match[1],
|
|
6900
|
+
startIndex,
|
|
6901
|
+
endIndex
|
|
6902
|
+
});
|
|
6903
|
+
}
|
|
6904
|
+
return (await Promise.all(importPositions.map(async ({ startIndex, endIndex, raw }) => {
|
|
6905
|
+
const position = lineColumnMap.get(startIndex);
|
|
6906
|
+
const endPosition = lineColumnMap.get(endIndex);
|
|
6907
|
+
const moduleNode = await moduleGraph.getModuleByUrl(raw);
|
|
6908
|
+
if (!position || !endPosition || !moduleNode || !moduleNode.id) return;
|
|
6909
|
+
return {
|
|
6910
|
+
resolvedId: moduleNode.id,
|
|
6911
|
+
resolvedUrl: moduleNode.url,
|
|
6912
|
+
start: position,
|
|
6913
|
+
end: endPosition,
|
|
6914
|
+
startIndex,
|
|
6915
|
+
endIndex
|
|
6916
|
+
};
|
|
6917
|
+
}))).filter((n) => n != null);
|
|
6918
|
+
}
|
|
6919
|
+
|
|
6667
6920
|
const __dirname$1 = url.fileURLToPath(new URL(".", import.meta.url));
|
|
6668
6921
|
class VitestPackageInstaller {
|
|
6669
6922
|
isPackageExists(name, options) {
|
|
@@ -7042,7 +7295,7 @@ function createMethodsRPC(project, methodsOptions = {}) {
|
|
|
7042
7295
|
const file = cleanUrl(resolved.id);
|
|
7043
7296
|
if (resolved.external) return {
|
|
7044
7297
|
file,
|
|
7045
|
-
url:
|
|
7298
|
+
url: isBuiltin(resolved.id) ? toBuiltin(resolved.id) : resolved.id,
|
|
7046
7299
|
id: resolved.id
|
|
7047
7300
|
};
|
|
7048
7301
|
return {
|
|
@@ -7246,7 +7499,7 @@ class PoolRunner {
|
|
|
7246
7499
|
this._operationLock = null;
|
|
7247
7500
|
}
|
|
7248
7501
|
}
|
|
7249
|
-
async stop() {
|
|
7502
|
+
async stop(options) {
|
|
7250
7503
|
// Wait for any ongoing operation to complete
|
|
7251
7504
|
if (this._operationLock) await this._operationLock;
|
|
7252
7505
|
if (this._state === RunnerState.STOPPED || this._state === RunnerState.STOPPING) return;
|
|
@@ -7274,6 +7527,11 @@ class PoolRunner {
|
|
|
7274
7527
|
this.off("message", onStop);
|
|
7275
7528
|
}
|
|
7276
7529
|
};
|
|
7530
|
+
// Don't wait for graceful exit's response when force exiting
|
|
7531
|
+
if (options?.force) return onStop({
|
|
7532
|
+
type: "stopped",
|
|
7533
|
+
__vitest_worker_response__: true
|
|
7534
|
+
});
|
|
7277
7535
|
this.on("message", onStop);
|
|
7278
7536
|
this.postMessage({
|
|
7279
7537
|
type: "stop",
|
|
@@ -7733,7 +7991,8 @@ class Pool {
|
|
|
7733
7991
|
};
|
|
7734
7992
|
this.activeTasks.push(activeTask);
|
|
7735
7993
|
// active tasks receive cancel signal and shut down gracefully
|
|
7736
|
-
async function cancelTask() {
|
|
7994
|
+
async function cancelTask(options) {
|
|
7995
|
+
if (options?.force) await runner.stop({ force: true });
|
|
7737
7996
|
await runner.waitForTerminated();
|
|
7738
7997
|
resolver.reject(/* @__PURE__ */ new Error("Cancelled"));
|
|
7739
7998
|
}
|
|
@@ -7783,6 +8042,9 @@ catch (error) {
|
|
|
7783
8042
|
return this.schedule();
|
|
7784
8043
|
}
|
|
7785
8044
|
async cancel() {
|
|
8045
|
+
// Force exit if previous cancel is still on-going
|
|
8046
|
+
// for example when user does 'CTRL+c' twice in row
|
|
8047
|
+
const force = this._isCancelling;
|
|
7786
8048
|
// Set flag to prevent new tasks from being queued
|
|
7787
8049
|
this._isCancelling = true;
|
|
7788
8050
|
const pendingTasks = this.queue.splice(0);
|
|
@@ -7790,11 +8052,12 @@ catch (error) {
|
|
|
7790
8052
|
const error = /* @__PURE__ */ new Error("Cancelled");
|
|
7791
8053
|
pendingTasks.forEach((task) => task.resolver.reject(error));
|
|
7792
8054
|
}
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
await Promise.all(this.exitPromises
|
|
8055
|
+
await Promise.all(this.activeTasks.map((task) => task.cancelTask({ force })));
|
|
8056
|
+
this.activeTasks = [];
|
|
8057
|
+
await Promise.all(this.sharedRunners.map((runner) => runner.stop()));
|
|
8058
|
+
this.sharedRunners = [];
|
|
8059
|
+
await Promise.all(this.exitPromises);
|
|
8060
|
+
this.exitPromises = [];
|
|
7798
8061
|
this.workerIds.forEach((_, id) => this.freeWorkerId(id));
|
|
7799
8062
|
// Reset flag after cancellation completes
|
|
7800
8063
|
this._isCancelling = false;
|
|
@@ -8198,7 +8461,10 @@ function serializeConfig(project) {
|
|
|
8198
8461
|
printConsoleTrace: config.printConsoleTrace ?? globalConfig.printConsoleTrace,
|
|
8199
8462
|
benchmark: config.benchmark && { includeSamples: config.benchmark.includeSamples },
|
|
8200
8463
|
serializedDefines: config.browser.enabled ? "" : project._serializedDefines || "",
|
|
8201
|
-
experimental: {
|
|
8464
|
+
experimental: {
|
|
8465
|
+
fsModuleCache: config.experimental.fsModuleCache ?? false,
|
|
8466
|
+
printImportBreakdown: config.experimental.printImportBreakdown
|
|
8467
|
+
}
|
|
8202
8468
|
};
|
|
8203
8469
|
}
|
|
8204
8470
|
|
|
@@ -9118,7 +9384,10 @@ function ModuleRunnerTransform() {
|
|
|
9118
9384
|
environment.resolve.noExternal = true;
|
|
9119
9385
|
// Workaround `noExternal` merging bug on Vite 6
|
|
9120
9386
|
// https://github.com/vitejs/vite/pull/20502
|
|
9121
|
-
if (name === "ssr")
|
|
9387
|
+
if (name === "ssr") {
|
|
9388
|
+
delete config.ssr?.noExternal;
|
|
9389
|
+
delete config.ssr?.external;
|
|
9390
|
+
}
|
|
9122
9391
|
if (name === "__vitest_vm__" || name === "__vitest__") continue;
|
|
9123
9392
|
const currentOptimizeDeps = environment.optimizeDeps || (name === "client" ? config.optimizeDeps : name === "ssr" ? config.ssr?.optimizeDeps : void 0);
|
|
9124
9393
|
const optimizeDeps = resolveOptimizerConfig(testConfig.deps?.optimizer?.[name], currentOptimizeDeps);
|
|
@@ -9348,6 +9617,7 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9348
9617
|
|
|
9349
9618
|
class VitestResolver {
|
|
9350
9619
|
options;
|
|
9620
|
+
externalizeConcurrentCache = /* @__PURE__ */ new Map();
|
|
9351
9621
|
externalizeCache = /* @__PURE__ */ new Map();
|
|
9352
9622
|
constructor(cacheDir, config) {
|
|
9353
9623
|
// sorting to make cache consistent
|
|
@@ -9367,8 +9637,20 @@ class VitestResolver {
|
|
|
9367
9637
|
external
|
|
9368
9638
|
};
|
|
9369
9639
|
}
|
|
9370
|
-
|
|
9371
|
-
|
|
9640
|
+
wasExternalized(file) {
|
|
9641
|
+
const normalizedFile = normalizeId(file);
|
|
9642
|
+
if (!this.externalizeCache.has(normalizedFile)) return false;
|
|
9643
|
+
return this.externalizeCache.get(normalizedFile) ?? false;
|
|
9644
|
+
}
|
|
9645
|
+
async shouldExternalize(file) {
|
|
9646
|
+
const normalizedFile = normalizeId(file);
|
|
9647
|
+
if (this.externalizeCache.has(normalizedFile)) return this.externalizeCache.get(normalizedFile);
|
|
9648
|
+
return shouldExternalize(normalizeId(file), this.options, this.externalizeConcurrentCache).then((result) => {
|
|
9649
|
+
this.externalizeCache.set(normalizedFile, result);
|
|
9650
|
+
return result;
|
|
9651
|
+
}).finally(() => {
|
|
9652
|
+
this.externalizeConcurrentCache.delete(normalizedFile);
|
|
9653
|
+
});
|
|
9372
9654
|
}
|
|
9373
9655
|
}
|
|
9374
9656
|
function normalizeId(id) {
|
|
@@ -9413,6 +9695,9 @@ function guessCJSversion(id) {
|
|
|
9413
9695
|
}
|
|
9414
9696
|
// The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98
|
|
9415
9697
|
async function isValidNodeImport(id) {
|
|
9698
|
+
// clean url to strip off `?v=...` query etc.
|
|
9699
|
+
// node can natively import files with query params, so externalizing them is safe.
|
|
9700
|
+
id = cleanUrl(id);
|
|
9416
9701
|
const extension = extname(id);
|
|
9417
9702
|
if (BUILTIN_EXTENSIONS.has(extension)) return true;
|
|
9418
9703
|
if (extension !== ".js") return false;
|
|
@@ -9433,7 +9718,7 @@ async function shouldExternalize(id, options, cache) {
|
|
|
9433
9718
|
return cache.get(id);
|
|
9434
9719
|
}
|
|
9435
9720
|
async function _shouldExternalize(id, options) {
|
|
9436
|
-
if (isBuiltin(id)) return id;
|
|
9721
|
+
if (isBuiltin$1(id)) return id;
|
|
9437
9722
|
// data: should be processed by native import,
|
|
9438
9723
|
// since it is a feature of ESM.
|
|
9439
9724
|
// also externalize network imports since nodejs allows it when --experimental-network-imports
|
|
@@ -9450,7 +9735,6 @@ async function _shouldExternalize(id, options) {
|
|
|
9450
9735
|
if (matchPattern(id, moduleDirectories, defaultInline)) return false;
|
|
9451
9736
|
if (matchPattern(id, moduleDirectories, depsExternal)) return id;
|
|
9452
9737
|
if (isLibraryModule && await isValidNodeImport(id)) return id;
|
|
9453
|
-
return false;
|
|
9454
9738
|
}
|
|
9455
9739
|
function matchPattern(id, moduleDirectories, patterns) {
|
|
9456
9740
|
if (patterns == null) return false;
|
|
@@ -10681,6 +10965,12 @@ class TestSuite extends SuiteImplementation {
|
|
|
10681
10965
|
class TestModule extends SuiteImplementation {
|
|
10682
10966
|
type = "module";
|
|
10683
10967
|
/**
|
|
10968
|
+
* The Vite environment that processes files on the server.
|
|
10969
|
+
*
|
|
10970
|
+
* Can be empty if test module did not run yet.
|
|
10971
|
+
*/
|
|
10972
|
+
viteEnvironment;
|
|
10973
|
+
/**
|
|
10684
10974
|
* This is usually an absolute UNIX file path.
|
|
10685
10975
|
* It can be a virtual ID if the file is not on the disk.
|
|
10686
10976
|
* This value corresponds to the ID in the Vite's module graph.
|
|
@@ -10695,6 +10985,8 @@ class TestModule extends SuiteImplementation {
|
|
|
10695
10985
|
super(task, project);
|
|
10696
10986
|
this.moduleId = task.filepath;
|
|
10697
10987
|
this.relativeModuleId = task.name;
|
|
10988
|
+
if (task.viteEnvironment === "__browser__") this.viteEnvironment = project.browser?.vite.environments.client;
|
|
10989
|
+
else if (typeof task.viteEnvironment === "string") this.viteEnvironment = project.vite.environments[task.viteEnvironment];
|
|
10698
10990
|
}
|
|
10699
10991
|
/**
|
|
10700
10992
|
* Checks the running state of the test file.
|
|
@@ -12247,6 +12539,39 @@ class Vitest {
|
|
|
12247
12539
|
return await this.runningPromise;
|
|
12248
12540
|
});
|
|
12249
12541
|
}
|
|
12542
|
+
/**
|
|
12543
|
+
* Returns module's diagnostic. If `testModule` is not provided, `selfTime` and `totalTime` will be aggregated across all tests.
|
|
12544
|
+
*
|
|
12545
|
+
* If the module was not transformed or executed, the diagnostic will be empty.
|
|
12546
|
+
* @experimental
|
|
12547
|
+
* @see {@link https://vitest.dev/api/advanced/vitest#getsourcemodulediagnostic}
|
|
12548
|
+
*/
|
|
12549
|
+
async experimental_getSourceModuleDiagnostic(moduleId, testModule) {
|
|
12550
|
+
if (testModule) {
|
|
12551
|
+
const viteEnvironment = testModule.viteEnvironment;
|
|
12552
|
+
// if there is no viteEnvironment, it means the file did not run yet
|
|
12553
|
+
if (!viteEnvironment) return {
|
|
12554
|
+
modules: [],
|
|
12555
|
+
untrackedModules: []
|
|
12556
|
+
};
|
|
12557
|
+
const moduleLocations = await collectSourceModulesLocations(moduleId, viteEnvironment.moduleGraph);
|
|
12558
|
+
return collectModuleDurationsDiagnostic(moduleId, this.state, moduleLocations, testModule);
|
|
12559
|
+
}
|
|
12560
|
+
const environments = this.projects.flatMap((p) => {
|
|
12561
|
+
return Object.values(p.vite.environments);
|
|
12562
|
+
});
|
|
12563
|
+
const aggregatedLocationsResult = await Promise.all(environments.map((environment) => collectSourceModulesLocations(moduleId, environment.moduleGraph)));
|
|
12564
|
+
return collectModuleDurationsDiagnostic(moduleId, this.state, aggregatedLocationsResult.reduce((acc, locations) => {
|
|
12565
|
+
if (locations) {
|
|
12566
|
+
acc.modules.push(...locations.modules);
|
|
12567
|
+
acc.untracked.push(...locations.untracked);
|
|
12568
|
+
}
|
|
12569
|
+
return acc;
|
|
12570
|
+
}, {
|
|
12571
|
+
modules: [],
|
|
12572
|
+
untracked: []
|
|
12573
|
+
}));
|
|
12574
|
+
}
|
|
12250
12575
|
async experimental_parseSpecifications(specifications, options) {
|
|
12251
12576
|
if (this.mode !== "test") throw new Error(`The \`experimental_parseSpecifications\` does not support "${this.mode}" mode.`);
|
|
12252
12577
|
const limit = limitConcurrency(options?.concurrency ?? (typeof nodeos__default.availableParallelism === "function" ? nodeos__default.availableParallelism() : nodeos__default.cpus().length));
|