vitest 4.0.14 → 4.0.16
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 +2 -2
- package/dist/browser.js +2 -2
- package/dist/chunks/{base.BEv8sRbK.js → base.Bin-9uYm.js} +7 -6
- package/dist/chunks/browser.d.Bz3lxTX-.d.ts +57 -0
- package/dist/chunks/{cac.DnEx6DOX.js → cac.BGonGPac.js} +10 -25
- package/dist/chunks/{cli-api.CbjxIXjQ.js → cli-api.BKg19Fvw.js} +469 -124
- package/dist/chunks/{config.d.g6OOauRt.d.ts → config.d.CzIjkicf.d.ts} +1 -0
- package/dist/chunks/{coverage.CtyeYmKM.js → coverage.BuJUwVtg.js} +2 -1
- 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.CQwQ_SLL.js → index.6Qv1eEA6.js} +3 -3
- package/dist/chunks/index.Chj8NDwU.js +206 -0
- 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/{init-forks.DmvIFK4U.js → init-forks.v9UONQS6.js} +11 -2
- package/dist/chunks/{init-threads.De6b3S3g.js → init-threads.DqYg3Trk.js} +1 -1
- package/dist/chunks/{init.a5SCIJ0x.js → init.KmQZdqFg.js} +2 -2
- package/dist/chunks/modules.BJuCwlRJ.js +36 -0
- package/dist/chunks/{plugin.d.B6hlg3fN.d.ts → plugin.d.v1sC_bv1.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DeFcIuza.d.ts → reporters.d.Rsi0PyxX.d.ts} +27 -4
- package/dist/chunks/{rpc.BytlcPfC.js → rpc.BoxB0q7B.js} +1 -1
- package/dist/chunks/{setup-common.DGHc_BUK.js → setup-common.Cm-kSBVi.js} +1 -1
- package/dist/chunks/{startModuleRunner.W28wBIgJ.js → startModuleRunner.DpqpB8k3.js} +8 -9
- package/dist/chunks/{test.DqQZzsWf.js → test.B8ej_ZHS.js} +9 -4
- package/dist/chunks/{vi.BiaV1qII.js → vi.2VT5v0um.js} +40 -30
- package/dist/chunks/{vm.BbVD4fJ5.js → vm.qFl6P1nF.js} +2 -2
- package/dist/chunks/worker.d.5JNaocaN.d.ts +254 -0
- package/dist/cli.js +2 -2
- package/dist/config.d.ts +7 -7
- package/dist/coverage.d.ts +8 -8
- package/dist/coverage.js +1 -1
- 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 +23 -16
- package/dist/module-runner.js +2 -1
- package/dist/node.d.ts +17 -10
- package/dist/node.js +10 -9
- package/dist/reporters.d.ts +7 -7
- package/dist/reporters.js +2 -2
- package/dist/runners.d.ts +2 -1
- package/dist/runners.js +4 -4
- package/dist/worker.d.ts +5 -3
- package/dist/worker.js +11 -10
- package/dist/workers/forks.js +12 -11
- package/dist/workers/runVmTests.js +7 -7
- package/dist/workers/threads.js +12 -11
- package/dist/workers/vmForks.js +7 -6
- package/dist/workers/vmThreads.js +7 -6
- package/package.json +15 -15
- package/dist/chunks/browser.d.F6jMf15V.d.ts +0 -18
- package/dist/chunks/index.0kCJoeWi.js +0 -220
- package/dist/chunks/worker.d.DhEa3KzY.d.ts +0 -238
|
@@ -2,20 +2,20 @@ import fs, { promises, existsSync, mkdirSync, readFileSync, statSync, readdirSyn
|
|
|
2
2
|
import { relative, resolve, dirname, join, extname, normalize, basename, isAbsolute } from 'pathe';
|
|
3
3
|
import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
|
|
4
4
|
import path, { resolve as resolve$1 } from 'node:path';
|
|
5
|
-
import { noop, createDefer, slash,
|
|
5
|
+
import { noop, createDefer, slash, withTrailingSlash, cleanUrl, wrapId, isExternalUrl, unwrapId, toArray, deepMerge, nanoid, deepClone, isPrimitive, notNullish } from '@vitest/utils/helpers';
|
|
6
6
|
import { a as any, p as prompt } from './index.D4KonVSU.js';
|
|
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.
|
|
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.BuJUwVtg.js';
|
|
8
8
|
import * as vite from 'vite';
|
|
9
|
-
import { parseAst, searchForWorkspaceRoot, fetchModule, version, mergeConfig, createServer } from 'vite';
|
|
9
|
+
import { isFileServingAllowed as isFileServingAllowed$1, parseAst, searchForWorkspaceRoot, fetchModule, version, mergeConfig, createServer, isFileLoadingAllowed, normalizePath } 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.BGonGPac.js';
|
|
16
16
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
17
|
-
import { c as createBirpc } from './index.
|
|
18
|
-
import { p as parse, d as stringify, e as TraceMap, o as originalPositionFor,
|
|
17
|
+
import { c as createBirpc } from './index.Chj8NDwU.js';
|
|
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.BJuCwlRJ.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$1(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$1(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);
|
|
@@ -6074,16 +6082,37 @@ function tryStatSync(file) {
|
|
|
6074
6082
|
} catch {}
|
|
6075
6083
|
}
|
|
6076
6084
|
|
|
6085
|
+
// this is copy pasted from vite
|
|
6086
|
+
function normalizeResolvedIdToUrl(environment, resolvedId) {
|
|
6087
|
+
const root = environment.config.root;
|
|
6088
|
+
const depsOptimizer = environment.depsOptimizer;
|
|
6089
|
+
let url;
|
|
6090
|
+
// normalize all imports into resolved URLs
|
|
6091
|
+
// e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`
|
|
6092
|
+
if (resolvedId.startsWith(withTrailingSlash(root)))
|
|
6093
|
+
// in root: infer short absolute path from root
|
|
6094
|
+
url = resolvedId.slice(root.length);
|
|
6095
|
+
else if (depsOptimizer?.isOptimizedDepFile(resolvedId) || resolvedId !== "/@react-refresh" && path.isAbsolute(resolvedId) && existsSync(cleanUrl(resolvedId)))
|
|
6096
|
+
// an optimized deps may not yet exists in the filesystem, or
|
|
6097
|
+
// a regular file exists but is out of root: rewrite to absolute /@fs/ paths
|
|
6098
|
+
url = path.posix.join("/@fs/", resolvedId);
|
|
6099
|
+
else url = resolvedId;
|
|
6100
|
+
// if the resolved id is not a valid browser import specifier,
|
|
6101
|
+
// prefix it to make it valid. We will strip this before feeding it
|
|
6102
|
+
// back into the transform pipeline
|
|
6103
|
+
if (url[0] !== "." && url[0] !== "/") url = wrapId(resolvedId);
|
|
6104
|
+
return url;
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6077
6107
|
const saveCachePromises = /* @__PURE__ */ new Map();
|
|
6078
6108
|
const readFilePromises = /* @__PURE__ */ new Map();
|
|
6079
6109
|
class ModuleFetcher {
|
|
6080
6110
|
tmpDirectories = /* @__PURE__ */ new Set();
|
|
6081
6111
|
fsCacheEnabled;
|
|
6082
|
-
constructor(resolver, config, fsCache,
|
|
6112
|
+
constructor(resolver, config, fsCache, tmpProjectDir) {
|
|
6083
6113
|
this.resolver = resolver;
|
|
6084
6114
|
this.config = config;
|
|
6085
6115
|
this.fsCache = fsCache;
|
|
6086
|
-
this.traces = traces;
|
|
6087
6116
|
this.tmpProjectDir = tmpProjectDir;
|
|
6088
6117
|
this.fsCacheEnabled = config.experimental?.fsModuleCache === true;
|
|
6089
6118
|
}
|
|
@@ -6110,6 +6139,11 @@ class ModuleFetcher {
|
|
|
6110
6139
|
type: "network"
|
|
6111
6140
|
};
|
|
6112
6141
|
}
|
|
6142
|
+
// handle unresolved id of dynamic import skipped by Vite import analysis
|
|
6143
|
+
if (url[0] !== "/") {
|
|
6144
|
+
const resolved = await environment.pluginContainer.resolveId(url, importer);
|
|
6145
|
+
if (resolved) url = normalizeResolvedIdToUrl(environment, resolved.id);
|
|
6146
|
+
}
|
|
6113
6147
|
const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url));
|
|
6114
6148
|
const cached = !!moduleGraphModule.transformResult;
|
|
6115
6149
|
if (moduleGraphModule.file) trace.setAttribute("code.file.path", moduleGraphModule.file);
|
|
@@ -6151,10 +6185,20 @@ class ModuleFetcher {
|
|
|
6151
6185
|
}
|
|
6152
6186
|
const result = await this.fetchAndProcess(environment, url, importer, moduleGraphModule, options);
|
|
6153
6187
|
const importers = this.getSerializedDependencies(moduleGraphModule);
|
|
6188
|
+
const importedUrls = this.getSerializedImports(moduleGraphModule);
|
|
6154
6189
|
const map = moduleGraphModule.transformResult?.map;
|
|
6155
6190
|
const mappings = map && !("version" in map) && map.mappings === "";
|
|
6156
|
-
return this.cacheResult(result, cachePath, importers, !!mappings);
|
|
6191
|
+
return this.cacheResult(result, cachePath, importers, importedUrls, !!mappings);
|
|
6157
6192
|
}
|
|
6193
|
+
// we need this for UI to be able to show a module graph
|
|
6194
|
+
getSerializedImports(node) {
|
|
6195
|
+
const imports = [];
|
|
6196
|
+
node.importedModules.forEach((importer) => {
|
|
6197
|
+
imports.push(importer.url);
|
|
6198
|
+
});
|
|
6199
|
+
return imports;
|
|
6200
|
+
}
|
|
6201
|
+
// we need this for the watcher to be able to find the related test file
|
|
6158
6202
|
getSerializedDependencies(node) {
|
|
6159
6203
|
const dependencies = [];
|
|
6160
6204
|
node.importers.forEach((importer) => {
|
|
@@ -6186,7 +6230,7 @@ class ModuleFetcher {
|
|
|
6186
6230
|
// null means the file should not be cached
|
|
6187
6231
|
if (memoryCacheKey !== void 0) return memoryCacheKey;
|
|
6188
6232
|
const fileContent = await this.readFileContentToCache(environment, moduleGraphModule);
|
|
6189
|
-
return this.fsCache.generateCachePath(this.config, environment,
|
|
6233
|
+
return this.fsCache.generateCachePath(this.config, environment, moduleGraphModule.id, fileContent);
|
|
6190
6234
|
}
|
|
6191
6235
|
async readFileContentToCache(environment, moduleGraphModule) {
|
|
6192
6236
|
if (moduleGraphModule.file && !moduleGraphModule.file.startsWith("\0") && !moduleGraphModule.file.startsWith("virtual:")) {
|
|
@@ -6225,6 +6269,10 @@ class ModuleFetcher {
|
|
|
6225
6269
|
const environmentNode = environment.moduleGraph.getModuleById(importer);
|
|
6226
6270
|
if (environmentNode) moduleGraphModule.importers.add(environmentNode);
|
|
6227
6271
|
});
|
|
6272
|
+
await Promise.all(cachedModule.importedUrls.map(async (url) => {
|
|
6273
|
+
const moduleNode = await environment.moduleGraph.ensureEntryFromUrl(url).catch(() => null);
|
|
6274
|
+
if (moduleNode) moduleGraphModule.importedModules.add(moduleNode);
|
|
6275
|
+
}));
|
|
6228
6276
|
return {
|
|
6229
6277
|
cached: true,
|
|
6230
6278
|
file: cachedModule.file,
|
|
@@ -6240,13 +6288,13 @@ class ModuleFetcher {
|
|
|
6240
6288
|
inlineSourceMap: false
|
|
6241
6289
|
}).catch(handleRollupError));
|
|
6242
6290
|
}
|
|
6243
|
-
async cacheResult(result, cachePath, importers = [], mappings = false) {
|
|
6291
|
+
async cacheResult(result, cachePath, importers = [], importedUrls = [], mappings = false) {
|
|
6244
6292
|
const returnResult = "code" in result ? getCachedResult(result, cachePath) : result;
|
|
6245
6293
|
if (saveCachePromises.has(cachePath)) {
|
|
6246
6294
|
await saveCachePromises.get(cachePath);
|
|
6247
6295
|
return returnResult;
|
|
6248
6296
|
}
|
|
6249
|
-
const savePromise = this.fsCache.saveCachedModule(cachePath, result, importers, mappings).then(() => result).finally(() => {
|
|
6297
|
+
const savePromise = this.fsCache.saveCachedModule(cachePath, result, importers, importedUrls, mappings).then(() => result).finally(() => {
|
|
6250
6298
|
saveCachePromises.delete(cachePath);
|
|
6251
6299
|
});
|
|
6252
6300
|
saveCachePromises.set(cachePath, savePromise);
|
|
@@ -6265,7 +6313,7 @@ class ModuleFetcher {
|
|
|
6265
6313
|
}
|
|
6266
6314
|
}
|
|
6267
6315
|
function createFetchModuleFunction(resolver, config, fsCache, traces, tmpProjectDir) {
|
|
6268
|
-
const fetcher = new ModuleFetcher(resolver, config, fsCache,
|
|
6316
|
+
const fetcher = new ModuleFetcher(resolver, config, fsCache, tmpProjectDir);
|
|
6269
6317
|
return async (url, importer, environment, cacheFs, options, otelCarrier) => {
|
|
6270
6318
|
await traces.waitInit();
|
|
6271
6319
|
const context = otelCarrier ? traces.getContextFromCarrier(otelCarrier) : void 0;
|
|
@@ -6353,28 +6401,6 @@ function handleRollupError(e) {
|
|
|
6353
6401
|
throw e;
|
|
6354
6402
|
}
|
|
6355
6403
|
|
|
6356
|
-
// this is copy pasted from vite
|
|
6357
|
-
function normalizeResolvedIdToUrl(environment, resolvedId) {
|
|
6358
|
-
const root = environment.config.root;
|
|
6359
|
-
const depsOptimizer = environment.depsOptimizer;
|
|
6360
|
-
let url;
|
|
6361
|
-
// normalize all imports into resolved URLs
|
|
6362
|
-
// e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`
|
|
6363
|
-
if (resolvedId.startsWith(withTrailingSlash(root)))
|
|
6364
|
-
// in root: infer short absolute path from root
|
|
6365
|
-
url = resolvedId.slice(root.length);
|
|
6366
|
-
else if (depsOptimizer?.isOptimizedDepFile(resolvedId) || resolvedId !== "/@react-refresh" && path.isAbsolute(resolvedId) && existsSync(cleanUrl(resolvedId)))
|
|
6367
|
-
// an optimized deps may not yet exists in the filesystem, or
|
|
6368
|
-
// a regular file exists but is out of root: rewrite to absolute /@fs/ paths
|
|
6369
|
-
url = path.posix.join("/@fs/", resolvedId);
|
|
6370
|
-
else url = resolvedId;
|
|
6371
|
-
// if the resolved id is not a valid browser import specifier,
|
|
6372
|
-
// prefix it to make it valid. We will strip this before feeding it
|
|
6373
|
-
// back into the transform pipeline
|
|
6374
|
-
if (url[0] !== "." && url[0] !== "/") url = wrapId(resolvedId);
|
|
6375
|
-
return url;
|
|
6376
|
-
}
|
|
6377
|
-
|
|
6378
6404
|
class ServerModuleRunner extends ModuleRunner {
|
|
6379
6405
|
constructor(environment, fetcher, config) {
|
|
6380
6406
|
super({
|
|
@@ -6664,6 +6690,238 @@ This might cause false positive tests. Resolve unhandled errors to make sure you
|
|
|
6664
6690
|
}
|
|
6665
6691
|
}
|
|
6666
6692
|
|
|
6693
|
+
// this function recieves the module diagnostic with the location of imports
|
|
6694
|
+
// and populates it with collected import durations; the duration is injected
|
|
6695
|
+
// only if the current module is the one that imported the module
|
|
6696
|
+
// if testModule is not defined, then Vitest aggregates durations of ALL collected test modules
|
|
6697
|
+
function collectModuleDurationsDiagnostic(moduleId, state, moduleDiagnostic, testModule) {
|
|
6698
|
+
if (!moduleDiagnostic) return {
|
|
6699
|
+
modules: [],
|
|
6700
|
+
untrackedModules: []
|
|
6701
|
+
};
|
|
6702
|
+
const modules = [];
|
|
6703
|
+
const modulesById = {};
|
|
6704
|
+
const allModules = [...moduleDiagnostic.modules, ...moduleDiagnostic.untracked];
|
|
6705
|
+
const visitedByFiles = {};
|
|
6706
|
+
// this aggregates the times for _ALL_ tests if testModule is not passed
|
|
6707
|
+
// so if the module was imported in separate tests, the time will be accumulated
|
|
6708
|
+
for (const files of testModule ? [[testModule.task]] : state.filesMap.values()) for (const file of files) {
|
|
6709
|
+
const importDurations = file.importDurations;
|
|
6710
|
+
if (!importDurations) continue;
|
|
6711
|
+
const currentModule = state.getReportedEntity(file);
|
|
6712
|
+
if (!currentModule) continue;
|
|
6713
|
+
const visitedKey = currentModule.project.config.isolate === false ? "non-isolate" : file.id;
|
|
6714
|
+
if (!visitedByFiles[visitedKey]) visitedByFiles[visitedKey] = /* @__PURE__ */ new Set();
|
|
6715
|
+
const visited = visitedByFiles[visitedKey];
|
|
6716
|
+
allModules.forEach(({ resolvedId, resolvedUrl }) => {
|
|
6717
|
+
const durations = importDurations[resolvedId];
|
|
6718
|
+
// do not accumulate if module was already visited by suite (or suites in non-isolate mode)
|
|
6719
|
+
if (!durations || visited.has(resolvedId)) return;
|
|
6720
|
+
const importer = getModuleImporter(moduleId, durations, currentModule);
|
|
6721
|
+
modulesById[resolvedId] ??= {
|
|
6722
|
+
selfTime: 0,
|
|
6723
|
+
totalTime: 0,
|
|
6724
|
+
transformTime: 0,
|
|
6725
|
+
external: durations.external,
|
|
6726
|
+
importer
|
|
6727
|
+
};
|
|
6728
|
+
// only track if the current module imported this module,
|
|
6729
|
+
// otherwise it was imported instantly because it's cached
|
|
6730
|
+
if (importer === moduleId) {
|
|
6731
|
+
visited.add(resolvedId);
|
|
6732
|
+
modulesById[resolvedId].selfTime += durations.selfTime;
|
|
6733
|
+
modulesById[resolvedId].totalTime += durations.totalTime;
|
|
6734
|
+
// don't aggregate
|
|
6735
|
+
modulesById[resolvedId].transformTime = state.metadata[currentModule.project.name]?.duration[resolvedUrl]?.[0];
|
|
6736
|
+
}
|
|
6737
|
+
});
|
|
6738
|
+
}
|
|
6739
|
+
// if module was imported twice in the same file,
|
|
6740
|
+
// show only one time - the second should be shown as 0
|
|
6741
|
+
const visitedInFile = /* @__PURE__ */ new Set();
|
|
6742
|
+
moduleDiagnostic.modules.forEach((diagnostic) => {
|
|
6743
|
+
const durations = modulesById[diagnostic.resolvedId];
|
|
6744
|
+
if (!durations) return;
|
|
6745
|
+
if (visitedInFile.has(diagnostic.resolvedId)) modules.push({
|
|
6746
|
+
...diagnostic,
|
|
6747
|
+
selfTime: 0,
|
|
6748
|
+
totalTime: 0,
|
|
6749
|
+
transformTime: 0,
|
|
6750
|
+
external: durations.external,
|
|
6751
|
+
importer: durations.importer
|
|
6752
|
+
});
|
|
6753
|
+
else {
|
|
6754
|
+
visitedInFile.add(diagnostic.resolvedId);
|
|
6755
|
+
modules.push({
|
|
6756
|
+
...diagnostic,
|
|
6757
|
+
...durations
|
|
6758
|
+
});
|
|
6759
|
+
}
|
|
6760
|
+
});
|
|
6761
|
+
const untracked = [];
|
|
6762
|
+
moduleDiagnostic.untracked.forEach((diagnostic) => {
|
|
6763
|
+
const durations = modulesById[diagnostic.resolvedId];
|
|
6764
|
+
if (!durations) return;
|
|
6765
|
+
if (visitedInFile.has(diagnostic.resolvedId)) untracked.push({
|
|
6766
|
+
selfTime: 0,
|
|
6767
|
+
totalTime: 0,
|
|
6768
|
+
transformTime: 0,
|
|
6769
|
+
external: durations.external,
|
|
6770
|
+
importer: durations.importer,
|
|
6771
|
+
resolvedId: diagnostic.resolvedId,
|
|
6772
|
+
resolvedUrl: diagnostic.resolvedUrl,
|
|
6773
|
+
url: diagnostic.rawUrl
|
|
6774
|
+
});
|
|
6775
|
+
else {
|
|
6776
|
+
visitedInFile.add(diagnostic.resolvedId);
|
|
6777
|
+
untracked.push({
|
|
6778
|
+
...durations,
|
|
6779
|
+
resolvedId: diagnostic.resolvedId,
|
|
6780
|
+
resolvedUrl: diagnostic.resolvedUrl,
|
|
6781
|
+
url: diagnostic.rawUrl
|
|
6782
|
+
});
|
|
6783
|
+
}
|
|
6784
|
+
});
|
|
6785
|
+
return {
|
|
6786
|
+
modules,
|
|
6787
|
+
untrackedModules: untracked
|
|
6788
|
+
};
|
|
6789
|
+
}
|
|
6790
|
+
function getModuleImporter(moduleId, durations, testModule) {
|
|
6791
|
+
if (durations.importer === moduleId) return moduleId;
|
|
6792
|
+
if (!durations.importer) {
|
|
6793
|
+
if (moduleId === testModule.moduleId) return testModule.moduleId;
|
|
6794
|
+
return testModule.project.config.setupFiles.includes(moduleId) ? moduleId : durations.importer;
|
|
6795
|
+
}
|
|
6796
|
+
return durations.importer;
|
|
6797
|
+
}
|
|
6798
|
+
// the idea of this is very simple
|
|
6799
|
+
// it parses the source code to extract import/export statements
|
|
6800
|
+
// it parses SSR transformed file to extract __vite_ssr_import__ and __vite_ssr_dynamic_import__
|
|
6801
|
+
// it combines the two by looking at the original positions of SSR primitives
|
|
6802
|
+
// in the end, we are able to return a list of modules that were imported by this module
|
|
6803
|
+
// mapped to their IDs in Vite's module graph
|
|
6804
|
+
async function collectSourceModulesLocations(moduleId, moduleGraph) {
|
|
6805
|
+
const transformResult = moduleGraph.getModuleById(moduleId)?.transformResult;
|
|
6806
|
+
if (!transformResult || !transformResult.ssr) return;
|
|
6807
|
+
const map = transformResult.map;
|
|
6808
|
+
if (!map || !("version" in map) || !map.sources.length) return;
|
|
6809
|
+
const sourceImports = map.sources.reduce((acc, sourceId, index) => {
|
|
6810
|
+
const source = map.sourcesContent?.[index];
|
|
6811
|
+
if (source != null) acc[sourceId] = parseSourceImportsAndExports(source);
|
|
6812
|
+
return acc;
|
|
6813
|
+
}, {});
|
|
6814
|
+
const transformImports = await parseTransformResult(moduleGraph, transformResult);
|
|
6815
|
+
const traceMap = map && "version" in map && new TraceMap(map);
|
|
6816
|
+
const modules = {};
|
|
6817
|
+
const untracked = [];
|
|
6818
|
+
transformImports.forEach((row) => {
|
|
6819
|
+
const original = traceMap && originalPositionFor(traceMap, row.start);
|
|
6820
|
+
if (original && original.source != null) {
|
|
6821
|
+
// if there are several at the same position, this is a bug
|
|
6822
|
+
// probably caused by import.meta.glob imports returning incorrect positions
|
|
6823
|
+
// all the new import.meta.glob imports come first, so only the last module on this line is correct
|
|
6824
|
+
const sourceImport = sourceImports[original.source].get(`${original.line}:${original.column}`);
|
|
6825
|
+
if (sourceImport) {
|
|
6826
|
+
if (modules[sourceImport.rawUrl]) {
|
|
6827
|
+
// remove imports with a different resolvedId
|
|
6828
|
+
const differentImports = modules[sourceImport.rawUrl].filter((d) => d.resolvedId !== row.resolvedId);
|
|
6829
|
+
untracked.push(...differentImports);
|
|
6830
|
+
modules[sourceImport.rawUrl] = modules[sourceImport.rawUrl].filter((d) => d.resolvedId === row.resolvedId);
|
|
6831
|
+
}
|
|
6832
|
+
modules[sourceImport.rawUrl] ??= [];
|
|
6833
|
+
modules[sourceImport.rawUrl].push({
|
|
6834
|
+
start: sourceImport.start,
|
|
6835
|
+
end: sourceImport.end,
|
|
6836
|
+
startIndex: sourceImport.startIndex,
|
|
6837
|
+
endIndex: sourceImport.endIndex,
|
|
6838
|
+
rawUrl: sourceImport.rawUrl,
|
|
6839
|
+
resolvedId: row.resolvedId,
|
|
6840
|
+
resolvedUrl: row.resolvedUrl
|
|
6841
|
+
});
|
|
6842
|
+
}
|
|
6843
|
+
}
|
|
6844
|
+
});
|
|
6845
|
+
return {
|
|
6846
|
+
modules: Object.values(modules).flat(),
|
|
6847
|
+
untracked
|
|
6848
|
+
};
|
|
6849
|
+
}
|
|
6850
|
+
function fillSourcesMap(syntax, sourcesMap, source, indexMap) {
|
|
6851
|
+
const splitSeparator = `${syntax} `;
|
|
6852
|
+
const splitSources = source.split(splitSeparator);
|
|
6853
|
+
const chunks = [];
|
|
6854
|
+
let index = 0;
|
|
6855
|
+
for (const chunk of splitSources) {
|
|
6856
|
+
chunks.push({
|
|
6857
|
+
chunk,
|
|
6858
|
+
startIndex: index
|
|
6859
|
+
});
|
|
6860
|
+
index += chunk.length + splitSeparator.length;
|
|
6861
|
+
}
|
|
6862
|
+
chunks.forEach(({ chunk, startIndex }) => {
|
|
6863
|
+
const normalized = chunk.replace(/'/g, "\"");
|
|
6864
|
+
const startQuoteIdx = normalized.indexOf("\"");
|
|
6865
|
+
if (startQuoteIdx === -1) return;
|
|
6866
|
+
const endQuoteIdx = normalized.indexOf("\"", startQuoteIdx + 1);
|
|
6867
|
+
if (endQuoteIdx === -1) return;
|
|
6868
|
+
const staticSyntax = {
|
|
6869
|
+
startIndex: startIndex + startQuoteIdx,
|
|
6870
|
+
endIndex: startIndex + endQuoteIdx + 1,
|
|
6871
|
+
start: indexMap.get(startIndex + startQuoteIdx),
|
|
6872
|
+
end: indexMap.get(startIndex + endQuoteIdx + 1),
|
|
6873
|
+
rawUrl: normalized.slice(startQuoteIdx + 1, endQuoteIdx)
|
|
6874
|
+
};
|
|
6875
|
+
// -7 to include "import "
|
|
6876
|
+
for (let i = startIndex - 7; i < staticSyntax.endIndex; i++) {
|
|
6877
|
+
const location = indexMap.get(i);
|
|
6878
|
+
if (location) sourcesMap.set(`${location.line}:${location.column}`, staticSyntax);
|
|
6879
|
+
}
|
|
6880
|
+
});
|
|
6881
|
+
}
|
|
6882
|
+
// this function tries to parse ESM static import and export statements from
|
|
6883
|
+
// the source. if the source is not JS/TS, but supports static ESM syntax,
|
|
6884
|
+
// then this will also find them because it' only checks the strings, it doesn't parse the AST
|
|
6885
|
+
function parseSourceImportsAndExports(source) {
|
|
6886
|
+
if (!source.includes("import ") && !source.includes("export ")) return /* @__PURE__ */ new Map();
|
|
6887
|
+
const sourcesMap = /* @__PURE__ */ new Map();
|
|
6888
|
+
const indexMap = createIndexLocationsMap(source);
|
|
6889
|
+
fillSourcesMap("import", sourcesMap, source, indexMap);
|
|
6890
|
+
fillSourcesMap("export", sourcesMap, source, indexMap);
|
|
6891
|
+
return sourcesMap;
|
|
6892
|
+
}
|
|
6893
|
+
async function parseTransformResult(moduleGraph, transformResult) {
|
|
6894
|
+
const code = transformResult.code;
|
|
6895
|
+
const regexp = /(?:__vite_ssr_import__|__vite_ssr_dynamic_import__)\("([^"]+)"/g;
|
|
6896
|
+
const lineColumnMap = createIndexLocationsMap(code);
|
|
6897
|
+
const importPositions = [];
|
|
6898
|
+
let match;
|
|
6899
|
+
// eslint-disable-next-line no-cond-assign
|
|
6900
|
+
while (match = regexp.exec(code)) {
|
|
6901
|
+
const startIndex = match.index;
|
|
6902
|
+
const endIndex = match.index + match[0].length - 1;
|
|
6903
|
+
importPositions.push({
|
|
6904
|
+
raw: match[1],
|
|
6905
|
+
startIndex,
|
|
6906
|
+
endIndex
|
|
6907
|
+
});
|
|
6908
|
+
}
|
|
6909
|
+
return (await Promise.all(importPositions.map(async ({ startIndex, endIndex, raw }) => {
|
|
6910
|
+
const position = lineColumnMap.get(startIndex);
|
|
6911
|
+
const endPosition = lineColumnMap.get(endIndex);
|
|
6912
|
+
const moduleNode = await moduleGraph.getModuleByUrl(raw);
|
|
6913
|
+
if (!position || !endPosition || !moduleNode || !moduleNode.id) return;
|
|
6914
|
+
return {
|
|
6915
|
+
resolvedId: moduleNode.id,
|
|
6916
|
+
resolvedUrl: moduleNode.url,
|
|
6917
|
+
start: position,
|
|
6918
|
+
end: endPosition,
|
|
6919
|
+
startIndex,
|
|
6920
|
+
endIndex
|
|
6921
|
+
};
|
|
6922
|
+
}))).filter((n) => n != null);
|
|
6923
|
+
}
|
|
6924
|
+
|
|
6667
6925
|
const __dirname$1 = url.fileURLToPath(new URL(".", import.meta.url));
|
|
6668
6926
|
class VitestPackageInstaller {
|
|
6669
6927
|
isPackageExists(name, options) {
|
|
@@ -7042,7 +7300,7 @@ function createMethodsRPC(project, methodsOptions = {}) {
|
|
|
7042
7300
|
const file = cleanUrl(resolved.id);
|
|
7043
7301
|
if (resolved.external) return {
|
|
7044
7302
|
file,
|
|
7045
|
-
url:
|
|
7303
|
+
url: isBuiltin(resolved.id) ? toBuiltin(resolved.id) : resolved.id,
|
|
7046
7304
|
id: resolved.id
|
|
7047
7305
|
};
|
|
7048
7306
|
return {
|
|
@@ -7246,7 +7504,7 @@ class PoolRunner {
|
|
|
7246
7504
|
this._operationLock = null;
|
|
7247
7505
|
}
|
|
7248
7506
|
}
|
|
7249
|
-
async stop() {
|
|
7507
|
+
async stop(options) {
|
|
7250
7508
|
// Wait for any ongoing operation to complete
|
|
7251
7509
|
if (this._operationLock) await this._operationLock;
|
|
7252
7510
|
if (this._state === RunnerState.STOPPED || this._state === RunnerState.STOPPING) return;
|
|
@@ -7274,6 +7532,11 @@ class PoolRunner {
|
|
|
7274
7532
|
this.off("message", onStop);
|
|
7275
7533
|
}
|
|
7276
7534
|
};
|
|
7535
|
+
// Don't wait for graceful exit's response when force exiting
|
|
7536
|
+
if (options?.force) return onStop({
|
|
7537
|
+
type: "stopped",
|
|
7538
|
+
__vitest_worker_response__: true
|
|
7539
|
+
});
|
|
7277
7540
|
this.on("message", onStop);
|
|
7278
7541
|
this.postMessage({
|
|
7279
7542
|
type: "stop",
|
|
@@ -7733,7 +7996,8 @@ class Pool {
|
|
|
7733
7996
|
};
|
|
7734
7997
|
this.activeTasks.push(activeTask);
|
|
7735
7998
|
// active tasks receive cancel signal and shut down gracefully
|
|
7736
|
-
async function cancelTask() {
|
|
7999
|
+
async function cancelTask(options) {
|
|
8000
|
+
if (options?.force) await runner.stop({ force: true });
|
|
7737
8001
|
await runner.waitForTerminated();
|
|
7738
8002
|
resolver.reject(/* @__PURE__ */ new Error("Cancelled"));
|
|
7739
8003
|
}
|
|
@@ -7783,6 +8047,9 @@ catch (error) {
|
|
|
7783
8047
|
return this.schedule();
|
|
7784
8048
|
}
|
|
7785
8049
|
async cancel() {
|
|
8050
|
+
// Force exit if previous cancel is still on-going
|
|
8051
|
+
// for example when user does 'CTRL+c' twice in row
|
|
8052
|
+
const force = this._isCancelling;
|
|
7786
8053
|
// Set flag to prevent new tasks from being queued
|
|
7787
8054
|
this._isCancelling = true;
|
|
7788
8055
|
const pendingTasks = this.queue.splice(0);
|
|
@@ -7790,11 +8057,12 @@ catch (error) {
|
|
|
7790
8057
|
const error = /* @__PURE__ */ new Error("Cancelled");
|
|
7791
8058
|
pendingTasks.forEach((task) => task.resolver.reject(error));
|
|
7792
8059
|
}
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
await Promise.all(this.exitPromises
|
|
8060
|
+
await Promise.all(this.activeTasks.map((task) => task.cancelTask({ force })));
|
|
8061
|
+
this.activeTasks = [];
|
|
8062
|
+
await Promise.all(this.sharedRunners.map((runner) => runner.stop()));
|
|
8063
|
+
this.sharedRunners = [];
|
|
8064
|
+
await Promise.all(this.exitPromises);
|
|
8065
|
+
this.exitPromises = [];
|
|
7798
8066
|
this.workerIds.forEach((_, id) => this.freeWorkerId(id));
|
|
7799
8067
|
// Reset flag after cancellation completes
|
|
7800
8068
|
this._isCancelling = false;
|
|
@@ -8198,7 +8466,10 @@ function serializeConfig(project) {
|
|
|
8198
8466
|
printConsoleTrace: config.printConsoleTrace ?? globalConfig.printConsoleTrace,
|
|
8199
8467
|
benchmark: config.benchmark && { includeSamples: config.benchmark.includeSamples },
|
|
8200
8468
|
serializedDefines: config.browser.enabled ? "" : project._serializedDefines || "",
|
|
8201
|
-
experimental: {
|
|
8469
|
+
experimental: {
|
|
8470
|
+
fsModuleCache: config.experimental.fsModuleCache ?? false,
|
|
8471
|
+
printImportBreakdown: config.experimental.printImportBreakdown
|
|
8472
|
+
}
|
|
8202
8473
|
};
|
|
8203
8474
|
}
|
|
8204
8475
|
|
|
@@ -9118,7 +9389,10 @@ function ModuleRunnerTransform() {
|
|
|
9118
9389
|
environment.resolve.noExternal = true;
|
|
9119
9390
|
// Workaround `noExternal` merging bug on Vite 6
|
|
9120
9391
|
// https://github.com/vitejs/vite/pull/20502
|
|
9121
|
-
if (name === "ssr")
|
|
9392
|
+
if (name === "ssr") {
|
|
9393
|
+
delete config.ssr?.noExternal;
|
|
9394
|
+
delete config.ssr?.external;
|
|
9395
|
+
}
|
|
9122
9396
|
if (name === "__vitest_vm__" || name === "__vitest__") continue;
|
|
9123
9397
|
const currentOptimizeDeps = environment.optimizeDeps || (name === "client" ? config.optimizeDeps : name === "ssr" ? config.ssr?.optimizeDeps : void 0);
|
|
9124
9398
|
const optimizeDeps = resolveOptimizerConfig(testConfig.deps?.optimizer?.[name], currentOptimizeDeps);
|
|
@@ -9348,6 +9622,7 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9348
9622
|
|
|
9349
9623
|
class VitestResolver {
|
|
9350
9624
|
options;
|
|
9625
|
+
externalizeConcurrentCache = /* @__PURE__ */ new Map();
|
|
9351
9626
|
externalizeCache = /* @__PURE__ */ new Map();
|
|
9352
9627
|
constructor(cacheDir, config) {
|
|
9353
9628
|
// sorting to make cache consistent
|
|
@@ -9367,8 +9642,20 @@ class VitestResolver {
|
|
|
9367
9642
|
external
|
|
9368
9643
|
};
|
|
9369
9644
|
}
|
|
9370
|
-
|
|
9371
|
-
|
|
9645
|
+
wasExternalized(file) {
|
|
9646
|
+
const normalizedFile = normalizeId(file);
|
|
9647
|
+
if (!this.externalizeCache.has(normalizedFile)) return false;
|
|
9648
|
+
return this.externalizeCache.get(normalizedFile) ?? false;
|
|
9649
|
+
}
|
|
9650
|
+
async shouldExternalize(file) {
|
|
9651
|
+
const normalizedFile = normalizeId(file);
|
|
9652
|
+
if (this.externalizeCache.has(normalizedFile)) return this.externalizeCache.get(normalizedFile);
|
|
9653
|
+
return shouldExternalize(normalizeId(file), this.options, this.externalizeConcurrentCache).then((result) => {
|
|
9654
|
+
this.externalizeCache.set(normalizedFile, result);
|
|
9655
|
+
return result;
|
|
9656
|
+
}).finally(() => {
|
|
9657
|
+
this.externalizeConcurrentCache.delete(normalizedFile);
|
|
9658
|
+
});
|
|
9372
9659
|
}
|
|
9373
9660
|
}
|
|
9374
9661
|
function normalizeId(id) {
|
|
@@ -9413,6 +9700,9 @@ function guessCJSversion(id) {
|
|
|
9413
9700
|
}
|
|
9414
9701
|
// The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98
|
|
9415
9702
|
async function isValidNodeImport(id) {
|
|
9703
|
+
// clean url to strip off `?v=...` query etc.
|
|
9704
|
+
// node can natively import files with query params, so externalizing them is safe.
|
|
9705
|
+
id = cleanUrl(id);
|
|
9416
9706
|
const extension = extname(id);
|
|
9417
9707
|
if (BUILTIN_EXTENSIONS.has(extension)) return true;
|
|
9418
9708
|
if (extension !== ".js") return false;
|
|
@@ -9433,7 +9723,7 @@ async function shouldExternalize(id, options, cache) {
|
|
|
9433
9723
|
return cache.get(id);
|
|
9434
9724
|
}
|
|
9435
9725
|
async function _shouldExternalize(id, options) {
|
|
9436
|
-
if (isBuiltin(id)) return id;
|
|
9726
|
+
if (isBuiltin$1(id)) return id;
|
|
9437
9727
|
// data: should be processed by native import,
|
|
9438
9728
|
// since it is a feature of ESM.
|
|
9439
9729
|
// also externalize network imports since nodejs allows it when --experimental-network-imports
|
|
@@ -9450,7 +9740,6 @@ async function _shouldExternalize(id, options) {
|
|
|
9450
9740
|
if (matchPattern(id, moduleDirectories, defaultInline)) return false;
|
|
9451
9741
|
if (matchPattern(id, moduleDirectories, depsExternal)) return id;
|
|
9452
9742
|
if (isLibraryModule && await isValidNodeImport(id)) return id;
|
|
9453
|
-
return false;
|
|
9454
9743
|
}
|
|
9455
9744
|
function matchPattern(id, moduleDirectories, patterns) {
|
|
9456
9745
|
if (patterns == null) return false;
|
|
@@ -9527,6 +9816,21 @@ async function createViteServer(inlineConfig) {
|
|
|
9527
9816
|
console.error = error;
|
|
9528
9817
|
return server;
|
|
9529
9818
|
}
|
|
9819
|
+
function isFileServingAllowed(configOrUrl, urlOrServer) {
|
|
9820
|
+
const config = typeof urlOrServer === "string" ? configOrUrl : urlOrServer.config;
|
|
9821
|
+
const url = typeof urlOrServer === "string" ? urlOrServer : configOrUrl;
|
|
9822
|
+
if (!config.server.fs.strict) return true;
|
|
9823
|
+
return isFileLoadingAllowed(config, fsPathFromUrl(url));
|
|
9824
|
+
}
|
|
9825
|
+
const FS_PREFIX = "/@fs/";
|
|
9826
|
+
const VOLUME_RE = /^[A-Z]:/i;
|
|
9827
|
+
function fsPathFromId(id) {
|
|
9828
|
+
const fsPath = normalizePath(id.startsWith(FS_PREFIX) ? id.slice(5) : id);
|
|
9829
|
+
return fsPath[0] === "/" || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`;
|
|
9830
|
+
}
|
|
9831
|
+
function fsPathFromUrl(url) {
|
|
9832
|
+
return fsPathFromId(cleanUrl(url));
|
|
9833
|
+
}
|
|
9530
9834
|
|
|
9531
9835
|
class TestProject {
|
|
9532
9836
|
/**
|
|
@@ -10681,6 +10985,12 @@ class TestSuite extends SuiteImplementation {
|
|
|
10681
10985
|
class TestModule extends SuiteImplementation {
|
|
10682
10986
|
type = "module";
|
|
10683
10987
|
/**
|
|
10988
|
+
* The Vite environment that processes files on the server.
|
|
10989
|
+
*
|
|
10990
|
+
* Can be empty if test module did not run yet.
|
|
10991
|
+
*/
|
|
10992
|
+
viteEnvironment;
|
|
10993
|
+
/**
|
|
10684
10994
|
* This is usually an absolute UNIX file path.
|
|
10685
10995
|
* It can be a virtual ID if the file is not on the disk.
|
|
10686
10996
|
* This value corresponds to the ID in the Vite's module graph.
|
|
@@ -10695,6 +11005,8 @@ class TestModule extends SuiteImplementation {
|
|
|
10695
11005
|
super(task, project);
|
|
10696
11006
|
this.moduleId = task.filepath;
|
|
10697
11007
|
this.relativeModuleId = task.name;
|
|
11008
|
+
if (task.viteEnvironment === "__browser__") this.viteEnvironment = project.browser?.vite.environments.client;
|
|
11009
|
+
else if (typeof task.viteEnvironment === "string") this.viteEnvironment = project.vite.environments[task.viteEnvironment];
|
|
10698
11010
|
}
|
|
10699
11011
|
/**
|
|
10700
11012
|
* Checks the running state of the test file.
|
|
@@ -12247,6 +12559,39 @@ class Vitest {
|
|
|
12247
12559
|
return await this.runningPromise;
|
|
12248
12560
|
});
|
|
12249
12561
|
}
|
|
12562
|
+
/**
|
|
12563
|
+
* Returns module's diagnostic. If `testModule` is not provided, `selfTime` and `totalTime` will be aggregated across all tests.
|
|
12564
|
+
*
|
|
12565
|
+
* If the module was not transformed or executed, the diagnostic will be empty.
|
|
12566
|
+
* @experimental
|
|
12567
|
+
* @see {@link https://vitest.dev/api/advanced/vitest#getsourcemodulediagnostic}
|
|
12568
|
+
*/
|
|
12569
|
+
async experimental_getSourceModuleDiagnostic(moduleId, testModule) {
|
|
12570
|
+
if (testModule) {
|
|
12571
|
+
const viteEnvironment = testModule.viteEnvironment;
|
|
12572
|
+
// if there is no viteEnvironment, it means the file did not run yet
|
|
12573
|
+
if (!viteEnvironment) return {
|
|
12574
|
+
modules: [],
|
|
12575
|
+
untrackedModules: []
|
|
12576
|
+
};
|
|
12577
|
+
const moduleLocations = await collectSourceModulesLocations(moduleId, viteEnvironment.moduleGraph);
|
|
12578
|
+
return collectModuleDurationsDiagnostic(moduleId, this.state, moduleLocations, testModule);
|
|
12579
|
+
}
|
|
12580
|
+
const environments = this.projects.flatMap((p) => {
|
|
12581
|
+
return Object.values(p.vite.environments);
|
|
12582
|
+
});
|
|
12583
|
+
const aggregatedLocationsResult = await Promise.all(environments.map((environment) => collectSourceModulesLocations(moduleId, environment.moduleGraph)));
|
|
12584
|
+
return collectModuleDurationsDiagnostic(moduleId, this.state, aggregatedLocationsResult.reduce((acc, locations) => {
|
|
12585
|
+
if (locations) {
|
|
12586
|
+
acc.modules.push(...locations.modules);
|
|
12587
|
+
acc.untracked.push(...locations.untracked);
|
|
12588
|
+
}
|
|
12589
|
+
return acc;
|
|
12590
|
+
}, {
|
|
12591
|
+
modules: [],
|
|
12592
|
+
untracked: []
|
|
12593
|
+
}));
|
|
12594
|
+
}
|
|
12250
12595
|
async experimental_parseSpecifications(specifications, options) {
|
|
12251
12596
|
if (this.mode !== "test") throw new Error(`The \`experimental_parseSpecifications\` does not support "${this.mode}" mode.`);
|
|
12252
12597
|
const limit = limitConcurrency(options?.concurrency ?? (typeof nodeos__default.availableParallelism === "function" ? nodeos__default.availableParallelism() : nodeos__default.cpus().length));
|
|
@@ -13242,4 +13587,4 @@ var cliApi = /*#__PURE__*/Object.freeze({
|
|
|
13242
13587
|
startVitest: startVitest
|
|
13243
13588
|
});
|
|
13244
13589
|
|
|
13245
|
-
export { FilesNotFoundError as F, GitNotFoundError as G, ThreadsPoolWorker as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, createMethodsRPC as d, escapeTestName as e, ForksPoolWorker as f, getFilePoolName as g, TypecheckPoolWorker as h, isValidApiRequest as i, VmForksPoolWorker as j, VmThreadsPoolWorker as k, experimental_getRunnerTask as l, registerConsoleShortcuts as m,
|
|
13590
|
+
export { FilesNotFoundError as F, GitNotFoundError as G, ThreadsPoolWorker as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, createMethodsRPC as d, escapeTestName as e, ForksPoolWorker as f, getFilePoolName as g, TypecheckPoolWorker as h, isValidApiRequest as i, VmForksPoolWorker as j, VmThreadsPoolWorker as k, experimental_getRunnerTask as l, registerConsoleShortcuts as m, isFileServingAllowed as n, createViteLogger as o, createDebugger as p, cliApi as q, resolveFsAllow as r, startVitest as s };
|