vitest 3.2.0-beta.3 → 3.2.0

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.
Files changed (65) hide show
  1. package/LICENSE.md +29 -0
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +2 -2
  4. package/dist/chunks/{base.D4119yLM.js → base.Cg0miDlQ.js} +10 -14
  5. package/dist/chunks/{benchmark.Cf_PACH1.js → benchmark.CYdenmiT.js} +4 -6
  6. package/dist/chunks/{cac.DWaWHIIE.js → cac.6rXCxFY1.js} +66 -136
  7. package/dist/chunks/{cli-api.CnmEXkxs.js → cli-api.Cej3MBjA.js} +1250 -1335
  8. package/dist/chunks/{console.Cwr-MFPV.js → console.CtFJOzRO.js} +24 -45
  9. package/dist/chunks/{coverage.0iPg4Wrz.js → coverage.DVF1vEu8.js} +4 -12
  10. package/dist/chunks/{coverage.C73DaDgS.js → coverage.EIiagJJP.js} +484 -1003
  11. package/dist/chunks/{creator.C8WKy2eW.js → creator.GK6I-cL4.js} +29 -76
  12. package/dist/chunks/{date.ByMsSlOr.js → date.Bq6ZW5rf.js} +3 -8
  13. package/dist/chunks/{defaults.DpVH7vbg.js → defaults.B7q_naMc.js} +1 -1
  14. package/dist/chunks/{env.Dq0hM4Xv.js → env.D4Lgay0q.js} +1 -1
  15. package/dist/chunks/{execute.B3q-2LPV.js → execute.B7h3T_Hc.js} +104 -220
  16. package/dist/chunks/{git.DXfdBEfR.js → git.BVQ8w_Sw.js} +1 -3
  17. package/dist/chunks/{global.d.BNLIi6yo.d.ts → global.d.MAmajcmJ.d.ts} +2 -0
  18. package/dist/chunks/{globals.CI21aWXF.js → globals.DEHgCU4V.js} +5 -5
  19. package/dist/chunks/{index.Bter3jj9.js → index.BZ0g1JD2.js} +366 -628
  20. package/dist/chunks/{index.CbT4iuwc.js → index.BbB8_kAK.js} +22 -24
  21. package/dist/chunks/{index.JOzufsrU.js → index.CIyJn3t1.js} +37 -82
  22. package/dist/chunks/{index.DNgLEKsQ.js → index.CdQS2e2Q.js} +2 -2
  23. package/dist/chunks/{index.2jgTs_Q5.js → index.CmSc2RE5.js} +69 -107
  24. package/dist/chunks/{inspector.BFsh5KO0.js → inspector.C914Efll.js} +1 -1
  25. package/dist/chunks/{node.Be-ntJnD.js → node.fjCdwEIl.js} +1 -1
  26. package/dist/chunks/{reporters.d.Bt4IGtsa.d.ts → reporters.d.C1ogPriE.d.ts} +24 -4
  27. package/dist/chunks/{rpc.BKExFSRG.js → rpc.Iovn4oWe.js} +9 -19
  28. package/dist/chunks/{runBaseTests.B_M1TTsK.js → runBaseTests.Dd85QTll.js} +18 -31
  29. package/dist/chunks/{setup-common.CF-O-dZX.js → setup-common.Dd054P77.js} +15 -42
  30. package/dist/chunks/{typechecker.BgzF-6iO.js → typechecker.DRKU1-1g.js} +106 -186
  31. package/dist/chunks/{utils.DPCq3gzW.js → utils.CAioKnHs.js} +6 -14
  32. package/dist/chunks/{utils.BlI4TC7Y.js → utils.XdZDrNZV.js} +5 -13
  33. package/dist/chunks/{vi.pkoYCV6A.js → vi.bdSIJ99Y.js} +118 -267
  34. package/dist/chunks/{vite.d.B-Kx3KCF.d.ts → vite.d.DqE4-hhK.d.ts} +1 -1
  35. package/dist/chunks/{vm.DPYem2so.js → vm.BThCzidc.js} +98 -214
  36. package/dist/chunks/{worker.d.Bl1O4kuf.d.ts → worker.d.DvqK5Vmu.d.ts} +1 -1
  37. package/dist/chunks/{worker.d.BKbBp2ga.d.ts → worker.d.tQu2eJQy.d.ts} +3 -1
  38. package/dist/cli.js +4 -4
  39. package/dist/config.cjs +1 -1
  40. package/dist/config.d.ts +4 -4
  41. package/dist/config.js +2 -2
  42. package/dist/coverage.d.ts +2 -2
  43. package/dist/coverage.js +5 -5
  44. package/dist/environments.js +1 -1
  45. package/dist/execute.d.ts +1 -1
  46. package/dist/execute.js +1 -1
  47. package/dist/index.d.ts +11 -10
  48. package/dist/index.js +5 -5
  49. package/dist/node.d.ts +7 -7
  50. package/dist/node.js +12 -14
  51. package/dist/reporters.d.ts +2 -2
  52. package/dist/reporters.js +4 -4
  53. package/dist/runners.d.ts +5 -2
  54. package/dist/runners.js +51 -80
  55. package/dist/snapshot.js +2 -2
  56. package/dist/suite.js +2 -2
  57. package/dist/worker.js +36 -42
  58. package/dist/workers/forks.js +4 -4
  59. package/dist/workers/runVmTests.js +15 -21
  60. package/dist/workers/threads.js +4 -4
  61. package/dist/workers/vmForks.js +6 -6
  62. package/dist/workers/vmThreads.js +6 -6
  63. package/dist/workers.d.ts +2 -2
  64. package/dist/workers.js +10 -10
  65. package/package.json +16 -14
@@ -1,12 +1,12 @@
1
1
  import fs, { statSync, realpathSync, promises as promises$1, mkdirSync, existsSync, readdirSync, writeFileSync } from 'node:fs';
2
- import { relative, resolve, dirname, isAbsolute, join as join$1, normalize } from 'pathe';
2
+ import { isAbsolute, join as join$1, dirname as dirname$1, resolve as resolve$1, relative, normalize } from 'pathe';
3
3
  import pm from 'picomatch';
4
4
  import c from 'tinyrainbow';
5
- import { c as configDefaults, e as benchmarkConfigDefaults, a as coverageConfigDefaults } from './defaults.DpVH7vbg.js';
5
+ import { c as configDefaults, e as benchmarkConfigDefaults, a as coverageConfigDefaults } from './defaults.B7q_naMc.js';
6
6
  import crypto from 'node:crypto';
7
- import { slash, createDefer, shuffle, toArray } from '@vitest/utils';
7
+ import { createDefer, shuffle, toArray } from '@vitest/utils';
8
8
  import { builtinModules, createRequire } from 'node:module';
9
- import path, { win32, dirname as dirname$1, join, resolve as resolve$1 } from 'node:path';
9
+ import path, { win32, dirname, join, resolve } from 'node:path';
10
10
  import process$1 from 'node:process';
11
11
  import fs$1, { writeFile, rename, stat, unlink } from 'node:fs/promises';
12
12
  import { fileURLToPath as fileURLToPath$1, pathToFileURL as pathToFileURL$1, URL as URL$1 } from 'node:url';
@@ -15,20 +15,20 @@ import v8 from 'node:v8';
15
15
  import { format, inspect } from 'node:util';
16
16
  import { version, mergeConfig } from 'vite';
17
17
  import { e as extraInlineDeps, d as defaultBrowserPort, b as defaultInspectPort, a as defaultPort } from './constants.DnKduX2e.js';
18
- import { a as isWindows } from './env.Dq0hM4Xv.js';
18
+ import { a as isWindows } from './env.D4Lgay0q.js';
19
19
  import * as nodeos from 'node:os';
20
20
  import nodeos__default from 'node:os';
21
21
  import { isatty } from 'node:tty';
22
22
  import EventEmitter from 'node:events';
23
23
  import { c as createBirpc } from './index.CJ0plNrh.js';
24
24
  import Tinypool$1, { Tinypool } from 'tinypool';
25
- import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.BgzF-6iO.js';
25
+ import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.DRKU1-1g.js';
26
26
  import { MessageChannel } from 'node:worker_threads';
27
27
  import { hasFailed } from '@vitest/runner/utils';
28
28
  import { rootDir } from '../path.js';
29
- import { slash as slash$1 } from 'vite-node/utils';
29
+ import { slash } from 'vite-node/utils';
30
30
  import { isCI, provider } from 'std-env';
31
- import { r as resolveCoverageProviderModule } from './coverage.0iPg4Wrz.js';
31
+ import { r as resolveCoverageProviderModule } from './coverage.DVF1vEu8.js';
32
32
 
33
33
  function groupBy(collection, iteratee) {
34
34
  return collection.reduce((acc, item) => {
@@ -49,146 +49,14 @@ function escapeRegExp(s) {
49
49
  }
50
50
  function wildcardPatternToRegExp(pattern) {
51
51
  const negated = pattern.startsWith("!");
52
- if (negated) {
53
- pattern = pattern.slice(1);
54
- }
52
+ if (negated) pattern = pattern.slice(1);
55
53
  let regexp = `${pattern.split("*").map(escapeRegExp).join(".*")}$`;
56
- if (negated) {
57
- regexp = `(?!${regexp})`;
58
- }
54
+ if (negated) regexp = `(?!${regexp})`;
59
55
  return new RegExp(`^${regexp}`, "i");
60
56
  }
61
57
 
62
58
  const hash = crypto.hash ?? ((algorithm, data, outputEncoding) => crypto.createHash(algorithm).update(data).digest(outputEncoding));
63
59
 
64
- class FilesStatsCache {
65
- cache = new Map();
66
- getStats(key) {
67
- return this.cache.get(key);
68
- }
69
- async populateStats(root, specs) {
70
- const promises = specs.map((spec) => {
71
- const key = `${spec[0].name}:${relative(root, spec.moduleId)}`;
72
- return this.updateStats(spec.moduleId, key);
73
- });
74
- await Promise.all(promises);
75
- }
76
- async updateStats(fsPath, key) {
77
- if (!fs.existsSync(fsPath)) {
78
- return;
79
- }
80
- const stats = await fs.promises.stat(fsPath);
81
- this.cache.set(key, { size: stats.size });
82
- }
83
- removeStats(fsPath) {
84
- this.cache.forEach((_, key) => {
85
- if (key.endsWith(fsPath)) {
86
- this.cache.delete(key);
87
- }
88
- });
89
- }
90
- }
91
-
92
- class ResultsCache {
93
- cache = new Map();
94
- workspacesKeyMap = new Map();
95
- cachePath = null;
96
- version;
97
- root = "/";
98
- constructor(version) {
99
- this.version = version;
100
- }
101
- getCachePath() {
102
- return this.cachePath;
103
- }
104
- setConfig(root, config) {
105
- this.root = root;
106
- if (config) {
107
- this.cachePath = resolve(config.dir, "results.json");
108
- }
109
- }
110
- getResults(key) {
111
- return this.cache.get(key);
112
- }
113
- async readFromCache() {
114
- if (!this.cachePath) {
115
- return;
116
- }
117
- if (!fs.existsSync(this.cachePath)) {
118
- return;
119
- }
120
- const resultsCache = await fs.promises.readFile(this.cachePath, "utf8");
121
- const { results, version } = JSON.parse(resultsCache || "[]");
122
- const [major, minor] = version.split(".");
123
- // handling changed in 0.30.0
124
- if (major > 0 || Number(minor) >= 30) {
125
- this.cache = new Map(results);
126
- this.version = version;
127
- results.forEach(([spec]) => {
128
- const [projectName, relativePath] = spec.split(":");
129
- const keyMap = this.workspacesKeyMap.get(relativePath) || [];
130
- keyMap.push(projectName);
131
- this.workspacesKeyMap.set(relativePath, keyMap);
132
- });
133
- }
134
- }
135
- updateResults(files) {
136
- files.forEach((file) => {
137
- const result = file.result;
138
- if (!result) {
139
- return;
140
- }
141
- const duration = result.duration || 0;
142
- // store as relative, so cache would be the same in CI and locally
143
- const relativePath = relative(this.root, file.filepath);
144
- this.cache.set(`${file.projectName || ""}:${relativePath}`, {
145
- duration: duration >= 0 ? duration : 0,
146
- failed: result.state === "fail"
147
- });
148
- });
149
- }
150
- removeFromCache(filepath) {
151
- this.cache.forEach((_, key) => {
152
- if (key.endsWith(filepath)) {
153
- this.cache.delete(key);
154
- }
155
- });
156
- }
157
- async writeToCache() {
158
- if (!this.cachePath) {
159
- return;
160
- }
161
- const results = Array.from(this.cache.entries());
162
- const cacheDirname = dirname(this.cachePath);
163
- if (!fs.existsSync(cacheDirname)) {
164
- await fs.promises.mkdir(cacheDirname, { recursive: true });
165
- }
166
- const cache = JSON.stringify({
167
- version: this.version,
168
- results
169
- });
170
- await fs.promises.writeFile(this.cachePath, cache);
171
- }
172
- }
173
-
174
- class VitestCache {
175
- results;
176
- stats = new FilesStatsCache();
177
- constructor(version) {
178
- this.results = new ResultsCache(version);
179
- }
180
- getFileTestResults(key) {
181
- return this.results.getResults(key);
182
- }
183
- getFileStats(key) {
184
- return this.stats.getStats(key);
185
- }
186
- static resolveCacheDir(root, dir, projectName) {
187
- const baseDir = slash(dir || "node_modules/.vite/vitest");
188
- return projectName ? resolve(root, baseDir, hash("md5", projectName, "hex")) : resolve(root, baseDir);
189
- }
190
- }
191
-
192
60
  const JOIN_LEADING_SLASH_RE = /^\.?\//;
193
61
  function withTrailingSlash(input = "", respectQueryAndFragment) {
194
62
  {
@@ -2459,7 +2327,7 @@ const getPackageInfo = quansync(function* (name, options = {}) {
2459
2327
  return {
2460
2328
  name,
2461
2329
  version: packageJson.version,
2462
- rootPath: dirname$1(packageJsonPath),
2330
+ rootPath: dirname(packageJsonPath),
2463
2331
  packageJsonPath,
2464
2332
  packageJson
2465
2333
  };
@@ -2483,7 +2351,7 @@ function searchPackageJSON(dir) {
2483
2351
  while (true) {
2484
2352
  if (!dir)
2485
2353
  return;
2486
- const newDir = dirname$1(dir);
2354
+ const newDir = dirname(dir);
2487
2355
  if (newDir === dir)
2488
2356
  return;
2489
2357
  dir = newDir;
@@ -2523,13 +2391,9 @@ const envsOrder = [
2523
2391
  "edge-runtime"
2524
2392
  ];
2525
2393
  function getTransformMode(patterns, filename) {
2526
- if (patterns.web && pm.isMatch(filename, patterns.web)) {
2527
- return "web";
2528
- }
2529
- if (patterns.ssr && pm.isMatch(filename, patterns.ssr)) {
2530
- return "ssr";
2531
- }
2532
- return undefined;
2394
+ if (patterns.web && pm.isMatch(filename, patterns.web)) return "web";
2395
+ if (patterns.ssr && pm.isMatch(filename, patterns.ssr)) return "ssr";
2396
+ return void 0;
2533
2397
  }
2534
2398
  async function groupFilesByEnv(files) {
2535
2399
  const filesWithEnv = await Promise.all(files.map(async ({ moduleId: filepath, project, testLines }) => {
@@ -2538,21 +2402,18 @@ async function groupFilesByEnv(files) {
2538
2402
  let env = code.match(/@(?:vitest|jest)-environment\s+([\w-]+)\b/)?.[1];
2539
2403
  // 2. Check for globals
2540
2404
  if (!env) {
2541
- for (const [glob, target] of project.config.environmentMatchGlobs || []) {
2542
- if (pm.isMatch(filepath, glob, { cwd: project.config.root })) {
2543
- env = target;
2544
- break;
2545
- }
2405
+ for (const [glob, target] of project.config.environmentMatchGlobs || []) if (pm.isMatch(filepath, glob, { cwd: project.config.root })) {
2406
+ env = target;
2407
+ break;
2546
2408
  }
2547
2409
  }
2548
2410
  // 3. Fallback to global env
2549
2411
  env ||= project.config.environment || "node";
2550
2412
  const transformMode = getTransformMode(project.config.testTransformMode, filepath);
2551
2413
  let envOptionsJson = code.match(/@(?:vitest|jest)-environment-options\s+(.+)/)?.[1];
2552
- if (envOptionsJson?.endsWith("*/")) {
2553
- // Trim closing Docblock characters the above regex might have captured
2554
- envOptionsJson = envOptionsJson.slice(0, -2);
2555
- }
2414
+ if (envOptionsJson?.endsWith("*/"))
2415
+ // Trim closing Docblock characters the above regex might have captured
2416
+ envOptionsJson = envOptionsJson.slice(0, -2);
2556
2417
  const envOptions = JSON.parse(envOptionsJson || "null");
2557
2418
  const envKey = env === "happy-dom" ? "happyDOM" : env;
2558
2419
  const environment = {
@@ -2572,8 +2433,8 @@ async function groupFilesByEnv(files) {
2572
2433
  return groupBy(filesWithEnv, ({ environment }) => environment.name);
2573
2434
  }
2574
2435
 
2575
- const created = new Set();
2576
- const promises = new Map();
2436
+ const created = /* @__PURE__ */ new Set();
2437
+ const promises = /* @__PURE__ */ new Map();
2577
2438
  function createMethodsRPC(project, options = {}) {
2578
2439
  const ctx = project.vitest;
2579
2440
  const cacheFs = options.cacheFs ?? false;
@@ -2587,9 +2448,7 @@ function createMethodsRPC(project, options = {}) {
2587
2448
  async getSourceMap(id, force) {
2588
2449
  if (force) {
2589
2450
  const mod = project.vite.moduleGraph.getModuleById(id);
2590
- if (mod) {
2591
- project.vite.moduleGraph.invalidateModule(mod);
2592
- }
2451
+ if (mod) project.vite.moduleGraph.invalidateModule(mod);
2593
2452
  }
2594
2453
  const r = await project.vitenode.transformRequest(id);
2595
2454
  return r?.map;
@@ -2597,15 +2456,9 @@ function createMethodsRPC(project, options = {}) {
2597
2456
  async fetch(id, transformMode) {
2598
2457
  const result = await project.vitenode.fetchResult(id, transformMode).catch(handleRollupError);
2599
2458
  const code = result.code;
2600
- if (!cacheFs || result.externalize) {
2601
- return result;
2602
- }
2603
- if ("id" in result && typeof result.id === "string") {
2604
- return { id: result.id };
2605
- }
2606
- if (code == null) {
2607
- throw new Error(`Failed to fetch module ${id}`);
2608
- }
2459
+ if (!cacheFs || result.externalize) return result;
2460
+ if ("id" in result && typeof result.id === "string") return { id: result.id };
2461
+ if (code == null) throw new Error(`Failed to fetch module ${id}`);
2609
2462
  const dir = join$1(project.tmpDir, transformMode);
2610
2463
  const name = hash("sha1", id, "hex");
2611
2464
  const tmp = join$1(dir, name);
@@ -2629,35 +2482,26 @@ function createMethodsRPC(project, options = {}) {
2629
2482
  return project.vitenode.transformModule(id, environment).catch(handleRollupError);
2630
2483
  },
2631
2484
  async onQueued(file) {
2632
- if (options.collect) {
2633
- ctx.state.collectFiles(project, [file]);
2634
- } else {
2635
- await ctx._testRun.enqueued(project, file);
2636
- }
2485
+ if (options.collect) ctx.state.collectFiles(project, [file]);
2486
+ else await ctx._testRun.enqueued(project, file);
2637
2487
  },
2638
2488
  async onCollected(files) {
2639
- if (options.collect) {
2640
- ctx.state.collectFiles(project, files);
2641
- } else {
2642
- await ctx._testRun.collected(project, files);
2643
- }
2489
+ if (options.collect) ctx.state.collectFiles(project, files);
2490
+ else await ctx._testRun.collected(project, files);
2644
2491
  },
2645
2492
  onAfterSuiteRun(meta) {
2646
2493
  ctx.coverageProvider?.onAfterSuiteRun(meta);
2647
2494
  },
2495
+ async onTaskAnnotate(testId, annotation) {
2496
+ return ctx._testRun.annotate(testId, annotation);
2497
+ },
2648
2498
  async onTaskUpdate(packs, events) {
2649
- if (options.collect) {
2650
- ctx.state.updateTasks(packs);
2651
- } else {
2652
- await ctx._testRun.updated(packs, events);
2653
- }
2499
+ if (options.collect) ctx.state.updateTasks(packs);
2500
+ else await ctx._testRun.updated(packs, events);
2654
2501
  },
2655
2502
  async onUserConsoleLog(log) {
2656
- if (options.collect) {
2657
- ctx.state.updateUserLog(log);
2658
- } else {
2659
- await ctx._testRun.log(log);
2660
- }
2503
+ if (options.collect) ctx.state.updateUserLog(log);
2504
+ else await ctx._testRun.log(log);
2661
2505
  },
2662
2506
  onUnhandledError(err, type) {
2663
2507
  ctx.state.catchError(err, type);
@@ -2672,21 +2516,20 @@ function createMethodsRPC(project, options = {}) {
2672
2516
  }
2673
2517
  // serialize rollup error on server to preserve details as a test error
2674
2518
  function handleRollupError(e) {
2675
- if (e instanceof Error && ("plugin" in e || "frame" in e || "id" in e)) {
2676
- // eslint-disable-next-line no-throw-literal
2677
- throw {
2678
- name: e.name,
2679
- message: e.message,
2680
- stack: e.stack,
2681
- cause: e.cause,
2682
- __vitest_rollup_error__: {
2683
- plugin: e.plugin,
2684
- id: e.id,
2685
- loc: e.loc,
2686
- frame: e.frame
2687
- }
2688
- };
2689
- }
2519
+ if (e instanceof Error && ("plugin" in e || "frame" in e || "id" in e))
2520
+ // eslint-disable-next-line no-throw-literal
2521
+ throw {
2522
+ name: e.name,
2523
+ message: e.message,
2524
+ stack: e.stack,
2525
+ cause: e.cause,
2526
+ __vitest_rollup_error__: {
2527
+ plugin: e.plugin,
2528
+ id: e.id,
2529
+ loc: e.loc,
2530
+ frame: e.frame
2531
+ }
2532
+ };
2690
2533
  throw e;
2691
2534
  }
2692
2535
  /**
@@ -2704,30 +2547,28 @@ function handleRollupError(e) {
2704
2547
  * Added in https://github.com/vitest-dev/vitest/pull/7531
2705
2548
  */
2706
2549
  async function atomicWriteFile(realFilePath, data) {
2707
- const dir = dirname(realFilePath);
2550
+ const dir = dirname$1(realFilePath);
2708
2551
  const tmpFilePath = join$1(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2709
2552
  try {
2710
2553
  await writeFile(tmpFilePath, data, "utf-8");
2711
2554
  await rename(tmpFilePath, realFilePath);
2712
2555
  } finally {
2713
2556
  try {
2714
- if (await stat(tmpFilePath)) {
2715
- await unlink(tmpFilePath);
2716
- }
2557
+ if (await stat(tmpFilePath)) await unlink(tmpFilePath);
2717
2558
  } catch {}
2718
2559
  }
2719
2560
  }
2720
2561
 
2721
2562
  function createChildProcessChannel$1(project, collect = false) {
2722
2563
  const emitter = new EventEmitter();
2723
- const cleanup = () => emitter.removeAllListeners();
2724
2564
  const events = {
2725
2565
  message: "message",
2726
2566
  response: "response"
2727
2567
  };
2728
2568
  const channel = {
2729
2569
  onMessage: (callback) => emitter.on(events.message, callback),
2730
- postMessage: (message) => emitter.emit(events.response, message)
2570
+ postMessage: (message) => emitter.emit(events.response, message),
2571
+ onClose: () => emitter.removeAllListeners()
2731
2572
  };
2732
2573
  const rpc = createBirpc(createMethodsRPC(project, {
2733
2574
  cacheFs: true,
@@ -2746,34 +2587,30 @@ function createChildProcessChannel$1(project, collect = false) {
2746
2587
  throw new Error(`[vitest-pool]: Timeout calling "${functionName}"`);
2747
2588
  }
2748
2589
  });
2749
- project.ctx.onCancel((reason) => rpc.onCancel(reason));
2750
- return {
2751
- channel,
2752
- cleanup
2753
- };
2590
+ project.vitest.onCancel((reason) => rpc.onCancel(reason));
2591
+ return channel;
2754
2592
  }
2755
- function createForksPool(ctx, { execArgv, env }) {
2593
+ function createForksPool(vitest, { execArgv, env }) {
2756
2594
  const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
2757
- const threadsCount = ctx.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2758
- const poolOptions = ctx.config.poolOptions?.forks ?? {};
2759
- const maxThreads = poolOptions.maxForks ?? ctx.config.maxWorkers ?? threadsCount;
2760
- const minThreads = poolOptions.minForks ?? ctx.config.minWorkers ?? threadsCount;
2761
- const worker = resolve$1(ctx.distPath, "workers/forks.js");
2595
+ const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2596
+ const poolOptions = vitest.config.poolOptions?.forks ?? {};
2597
+ const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
2598
+ const minThreads = poolOptions.minForks ?? vitest.config.minWorkers ?? threadsCount;
2599
+ const worker = resolve(vitest.distPath, "workers/forks.js");
2762
2600
  const options = {
2763
2601
  runtime: "child_process",
2764
- filename: resolve$1(ctx.distPath, "worker.js"),
2602
+ filename: resolve(vitest.distPath, "worker.js"),
2603
+ teardown: "teardown",
2765
2604
  maxThreads,
2766
2605
  minThreads,
2767
2606
  env,
2768
2607
  execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
2769
- terminateTimeout: ctx.config.teardownTimeout,
2608
+ terminateTimeout: vitest.config.teardownTimeout,
2770
2609
  concurrentTasksPerWorker: 1
2771
2610
  };
2772
2611
  const isolated = poolOptions.isolate ?? true;
2773
- if (isolated) {
2774
- options.isolateWorkers = true;
2775
- }
2776
- if (poolOptions.singleFork || !ctx.config.fileParallelism) {
2612
+ if (isolated) options.isolateWorkers = true;
2613
+ if (poolOptions.singleFork || !vitest.config.fileParallelism) {
2777
2614
  options.maxThreads = 1;
2778
2615
  options.minThreads = 1;
2779
2616
  }
@@ -2782,8 +2619,8 @@ function createForksPool(ctx, { execArgv, env }) {
2782
2619
  let id = 0;
2783
2620
  async function runFiles(project, config, files, environment, invalidates = []) {
2784
2621
  const paths = files.map((f) => f.filepath);
2785
- ctx.state.clearFiles(project, paths);
2786
- const { channel, cleanup } = createChildProcessChannel$1(project, name === "collect");
2622
+ vitest.state.clearFiles(project, paths);
2623
+ const channel = createChildProcessChannel$1(project, name === "collect");
2787
2624
  const workerId = ++id;
2788
2625
  const data = {
2789
2626
  pool: "forks",
@@ -2803,25 +2640,17 @@ function createForksPool(ctx, { execArgv, env }) {
2803
2640
  });
2804
2641
  } catch (error) {
2805
2642
  // Worker got stuck and won't terminate - this may cause process to hang
2806
- if (error instanceof Error && /Failed to terminate worker/.test(error.message)) {
2807
- ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}.`);
2808
- } else if (ctx.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) {
2809
- ctx.state.cancelFiles(paths, project);
2810
- } else {
2811
- throw error;
2812
- }
2813
- } finally {
2814
- cleanup();
2643
+ if (error instanceof Error && /Failed to terminate worker/.test(error.message)) vitest.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}.`);
2644
+ else if (vitest.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) vitest.state.cancelFiles(paths, project);
2645
+ else throw error;
2815
2646
  }
2816
2647
  }
2817
2648
  return async (specs, invalidates) => {
2818
2649
  // Cancel pending tasks from pool when possible
2819
- ctx.onCancel(() => pool.cancelPendingTasks());
2820
- const configs = new WeakMap();
2650
+ vitest.onCancel(() => pool.cancelPendingTasks());
2651
+ const configs = /* @__PURE__ */ new WeakMap();
2821
2652
  const getConfig = (project) => {
2822
- if (configs.has(project)) {
2823
- return configs.get(project);
2824
- }
2653
+ if (configs.has(project)) return configs.get(project);
2825
2654
  const _config = project.getSerializableConfig();
2826
2655
  const config = wrapSerializableConfig(_config);
2827
2656
  configs.set(project, config);
@@ -2833,9 +2662,8 @@ function createForksPool(ctx, { execArgv, env }) {
2833
2662
  const filesByEnv = await groupFilesByEnv(multipleForks);
2834
2663
  const files = Object.values(filesByEnv).flat();
2835
2664
  const results = [];
2836
- if (isolated) {
2837
- results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2838
- } else {
2665
+ if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2666
+ else {
2839
2667
  // When isolation is disabled, we still need to isolate environments and workspace projects from each other.
2840
2668
  // Tasks are still running parallel but environments are isolated between tasks.
2841
2669
  const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
@@ -2849,18 +2677,14 @@ function createForksPool(ctx, { execArgv, env }) {
2849
2677
  }
2850
2678
  }
2851
2679
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
2852
- if (errors.length > 0) {
2853
- throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
2854
- }
2680
+ if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
2855
2681
  }
2856
2682
  if (singleFork.length) {
2857
2683
  const filesByEnv = await groupFilesByEnv(singleFork);
2858
2684
  const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
2859
2685
  for (const env of envs) {
2860
2686
  const files = filesByEnv[env];
2861
- if (!files?.length) {
2862
- continue;
2863
- }
2687
+ if (!files?.length) continue;
2864
2688
  const filesByOptions = groupBy(files, ({ project, environment }) => project.name + JSON.stringify(environment.options));
2865
2689
  for (const files of Object.values(filesByOptions)) {
2866
2690
  // Always run environments isolated between each other
@@ -2896,34 +2720,33 @@ function createWorkerChannel$1(project, collect) {
2896
2720
  throw new Error(`[vitest-pool]: Timeout calling "${functionName}"`);
2897
2721
  }
2898
2722
  });
2899
- project.ctx.onCancel((reason) => rpc.onCancel(reason));
2723
+ project.vitest.onCancel((reason) => rpc.onCancel(reason));
2900
2724
  return {
2901
2725
  workerPort,
2902
2726
  port
2903
2727
  };
2904
2728
  }
2905
- function createThreadsPool(ctx, { execArgv, env }) {
2729
+ function createThreadsPool(vitest, { execArgv, env }) {
2906
2730
  const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
2907
- const threadsCount = ctx.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2908
- const poolOptions = ctx.config.poolOptions?.threads ?? {};
2909
- const maxThreads = poolOptions.maxThreads ?? ctx.config.maxWorkers ?? threadsCount;
2910
- const minThreads = poolOptions.minThreads ?? ctx.config.minWorkers ?? threadsCount;
2911
- const worker = resolve$1(ctx.distPath, "workers/threads.js");
2731
+ const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2732
+ const poolOptions = vitest.config.poolOptions?.threads ?? {};
2733
+ const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
2734
+ const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? threadsCount;
2735
+ const worker = resolve(vitest.distPath, "workers/threads.js");
2912
2736
  const options = {
2913
- filename: resolve$1(ctx.distPath, "worker.js"),
2737
+ filename: resolve(vitest.distPath, "worker.js"),
2738
+ teardown: "teardown",
2914
2739
  useAtomics: poolOptions.useAtomics ?? false,
2915
2740
  maxThreads,
2916
2741
  minThreads,
2917
2742
  env,
2918
2743
  execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
2919
- terminateTimeout: ctx.config.teardownTimeout,
2744
+ terminateTimeout: vitest.config.teardownTimeout,
2920
2745
  concurrentTasksPerWorker: 1
2921
2746
  };
2922
2747
  const isolated = poolOptions.isolate ?? true;
2923
- if (isolated) {
2924
- options.isolateWorkers = true;
2925
- }
2926
- if (poolOptions.singleThread || !ctx.config.fileParallelism) {
2748
+ if (isolated) options.isolateWorkers = true;
2749
+ if (poolOptions.singleThread || !vitest.config.fileParallelism) {
2927
2750
  options.maxThreads = 1;
2928
2751
  options.minThreads = 1;
2929
2752
  }
@@ -2932,8 +2755,12 @@ function createThreadsPool(ctx, { execArgv, env }) {
2932
2755
  let id = 0;
2933
2756
  async function runFiles(project, config, files, environment, invalidates = []) {
2934
2757
  const paths = files.map((f) => f.filepath);
2935
- ctx.state.clearFiles(project, paths);
2758
+ vitest.state.clearFiles(project, paths);
2936
2759
  const { workerPort, port } = createWorkerChannel$1(project, name === "collect");
2760
+ const onClose = () => {
2761
+ port.close();
2762
+ workerPort.close();
2763
+ };
2937
2764
  const workerId = ++id;
2938
2765
  const data = {
2939
2766
  pool: "threads",
@@ -2950,31 +2777,23 @@ function createThreadsPool(ctx, { execArgv, env }) {
2950
2777
  try {
2951
2778
  await pool.run(data, {
2952
2779
  transferList: [workerPort],
2953
- name
2780
+ name,
2781
+ channel: { onClose }
2954
2782
  });
2955
2783
  } catch (error) {
2956
2784
  // Worker got stuck and won't terminate - this may cause process to hang
2957
- if (error instanceof Error && /Failed to terminate worker/.test(error.message)) {
2958
- ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}. \nSee https://vitest.dev/guide/common-errors.html#failed-to-terminate-worker for troubleshooting.`);
2959
- } else if (ctx.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) {
2960
- ctx.state.cancelFiles(paths, project);
2961
- } else {
2962
- throw error;
2963
- }
2964
- } finally {
2965
- port.close();
2966
- workerPort.close();
2785
+ if (error instanceof Error && /Failed to terminate worker/.test(error.message)) vitest.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}. \nSee https://vitest.dev/guide/common-errors.html#failed-to-terminate-worker for troubleshooting.`);
2786
+ else if (vitest.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) vitest.state.cancelFiles(paths, project);
2787
+ else throw error;
2967
2788
  }
2968
2789
  }
2969
2790
  return async (specs, invalidates) => {
2970
2791
  // Cancel pending tasks from pool when possible
2971
- ctx.onCancel(() => pool.cancelPendingTasks());
2972
- const configs = new WeakMap();
2792
+ vitest.onCancel(() => pool.cancelPendingTasks());
2793
+ const configs = /* @__PURE__ */ new WeakMap();
2973
2794
  const getConfig = (project) => {
2974
- if (configs.has(project)) {
2975
- return configs.get(project);
2976
- }
2977
- const config = project.getSerializableConfig();
2795
+ if (configs.has(project)) return configs.get(project);
2796
+ const config = project.serializedConfig;
2978
2797
  configs.set(project, config);
2979
2798
  return config;
2980
2799
  };
@@ -2984,9 +2803,8 @@ function createThreadsPool(ctx, { execArgv, env }) {
2984
2803
  const filesByEnv = await groupFilesByEnv(multipleThreads);
2985
2804
  const files = Object.values(filesByEnv).flat();
2986
2805
  const results = [];
2987
- if (isolated) {
2988
- results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2989
- } else {
2806
+ if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2807
+ else {
2990
2808
  // When isolation is disabled, we still need to isolate environments and workspace projects from each other.
2991
2809
  // Tasks are still running parallel but environments are isolated between tasks.
2992
2810
  const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
@@ -3000,18 +2818,14 @@ function createThreadsPool(ctx, { execArgv, env }) {
3000
2818
  }
3001
2819
  }
3002
2820
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3003
- if (errors.length > 0) {
3004
- throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3005
- }
2821
+ if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3006
2822
  }
3007
2823
  if (singleThreads.length) {
3008
2824
  const filesByEnv = await groupFilesByEnv(singleThreads);
3009
2825
  const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
3010
2826
  for (const env of envs) {
3011
2827
  const files = filesByEnv[env];
3012
- if (!files?.length) {
3013
- continue;
3014
- }
2828
+ if (!files?.length) continue;
3015
2829
  const filesByOptions = groupBy(files, ({ project, environment }) => project.name + JSON.stringify(environment.options));
3016
2830
  for (const files of Object.values(filesByOptions)) {
3017
2831
  // Always run environments isolated between each other
@@ -3032,15 +2846,13 @@ function createThreadsPool(ctx, { execArgv, env }) {
3032
2846
  }
3033
2847
 
3034
2848
  function createTypecheckPool(vitest) {
3035
- const promisesMap = new WeakMap();
3036
- const rerunTriggered = new WeakSet();
2849
+ const promisesMap = /* @__PURE__ */ new WeakMap();
2850
+ const rerunTriggered = /* @__PURE__ */ new WeakSet();
3037
2851
  async function onParseEnd(project, { files, sourceErrors }) {
3038
2852
  const checker = project.typechecker;
3039
2853
  const { packs, events } = checker.getTestPacksAndEvents();
3040
2854
  await vitest._testRun.updated(packs, events);
3041
- if (!project.config.typecheck.ignoreSourceErrors) {
3042
- sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
3043
- }
2855
+ if (!project.config.typecheck.ignoreSourceErrors) sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
3044
2856
  const processError = !hasFailed(files) && !sourceErrors.length && checker.getExitCode();
3045
2857
  if (processError) {
3046
2858
  const error = new Error(checker.getOutput());
@@ -3057,16 +2869,12 @@ function createTypecheckPool(vitest) {
3057
2869
  }
3058
2870
  async function createWorkspaceTypechecker(project, files) {
3059
2871
  const checker = project.typechecker ?? new Typechecker(project);
3060
- if (project.typechecker) {
3061
- return checker;
3062
- }
2872
+ if (project.typechecker) return checker;
3063
2873
  project.typechecker = checker;
3064
2874
  checker.setFiles(files);
3065
2875
  checker.onParseStart(async () => {
3066
2876
  const files = checker.getTestFiles();
3067
- for (const file of files) {
3068
- await vitest._testRun.enqueued(project, file);
3069
- }
2877
+ for (const file of files) await vitest._testRun.enqueued(project, file);
3070
2878
  await vitest._testRun.collected(project, files);
3071
2879
  });
3072
2880
  checker.onParseEnd((result) => onParseEnd(project, result));
@@ -3078,9 +2886,7 @@ function createTypecheckPool(vitest) {
3078
2886
  }
3079
2887
  await checker.collectTests();
3080
2888
  const testFiles = checker.getTestFiles();
3081
- for (const file of testFiles) {
3082
- await vitest._testRun.enqueued(project, file);
3083
- }
2889
+ for (const file of testFiles) await vitest._testRun.enqueued(project, file);
3084
2890
  await vitest._testRun.collected(project, testFiles);
3085
2891
  const { packs, events } = checker.getTestPacksAndEvents();
3086
2892
  await vitest._testRun.updated(packs, events);
@@ -3088,9 +2894,7 @@ function createTypecheckPool(vitest) {
3088
2894
  return checker;
3089
2895
  }
3090
2896
  async function startTypechecker(project, files) {
3091
- if (project.typechecker) {
3092
- return;
3093
- }
2897
+ if (project.typechecker) return;
3094
2898
  const checker = await createWorkspaceTypechecker(project, files);
3095
2899
  await checker.collectTests();
3096
2900
  await checker.start();
@@ -3130,9 +2934,7 @@ function createTypecheckPool(vitest) {
3130
2934
  const triggered = await _p;
3131
2935
  if (project.typechecker && !triggered) {
3132
2936
  const testFiles = project.typechecker.getTestFiles();
3133
- for (const file of testFiles) {
3134
- await vitest._testRun.enqueued(project, file);
3135
- }
2937
+ for (const file of testFiles) await vitest._testRun.enqueued(project, file);
3136
2938
  await vitest._testRun.collected(project, testFiles);
3137
2939
  await onParseEnd(project, project.typechecker.getResult());
3138
2940
  continue;
@@ -3161,16 +2963,12 @@ function getDefaultThreadsCount(config) {
3161
2963
  function getWorkerMemoryLimit(config, pool) {
3162
2964
  if (pool === "vmForks") {
3163
2965
  const opts = config.poolOptions?.vmForks ?? {};
3164
- if (opts.memoryLimit) {
3165
- return opts.memoryLimit;
3166
- }
2966
+ if (opts.memoryLimit) return opts.memoryLimit;
3167
2967
  const workers = opts.maxForks ?? getDefaultThreadsCount(config);
3168
2968
  return 1 / workers;
3169
2969
  } else {
3170
2970
  const opts = config.poolOptions?.vmThreads ?? {};
3171
- if (opts.memoryLimit) {
3172
- return opts.memoryLimit;
3173
- }
2971
+ if (opts.memoryLimit) return opts.memoryLimit;
3174
2972
  const workers = opts.maxThreads ?? getDefaultThreadsCount(config);
3175
2973
  return 1 / workers;
3176
2974
  }
@@ -3182,51 +2980,36 @@ function getWorkerMemoryLimit(config, pool) {
3182
2980
  * @param percentageReference The reference value to use when a '%' value is supplied.
3183
2981
  */
3184
2982
  function stringToBytes(input, percentageReference) {
3185
- if (input === null || input === undefined) {
3186
- return input;
3187
- }
3188
- if (typeof input === "string") {
3189
- if (Number.isNaN(Number.parseFloat(input.slice(-1)))) {
3190
- let [, numericString, trailingChars] = input.match(/(.*?)([^0-9.-]+)$/) || [];
3191
- if (trailingChars && numericString) {
3192
- const numericValue = Number.parseFloat(numericString);
3193
- trailingChars = trailingChars.toLowerCase();
3194
- switch (trailingChars) {
3195
- case "%":
3196
- input = numericValue / 100;
3197
- break;
3198
- case "kb":
3199
- case "k": return numericValue * 1e3;
3200
- case "kib": return numericValue * 1024;
3201
- case "mb":
3202
- case "m": return numericValue * 1e3 * 1e3;
3203
- case "mib": return numericValue * 1024 * 1024;
3204
- case "gb":
3205
- case "g": return numericValue * 1e3 * 1e3 * 1e3;
3206
- case "gib": return numericValue * 1024 * 1024 * 1024;
3207
- }
3208
- }
3209
- } else {
3210
- input = Number.parseFloat(input);
3211
- }
3212
- }
3213
- if (typeof input === "number") {
3214
- if (input <= 1 && input > 0) {
3215
- if (percentageReference) {
3216
- return Math.floor(input * percentageReference);
3217
- } else {
3218
- throw new Error("For a percentage based memory limit a percentageReference must be supplied");
2983
+ if (input === null || input === void 0) return input;
2984
+ if (typeof input === "string") if (Number.isNaN(Number.parseFloat(input.slice(-1)))) {
2985
+ let [, numericString, trailingChars] = input.match(/(.*?)([^0-9.-]+)$/) || [];
2986
+ if (trailingChars && numericString) {
2987
+ const numericValue = Number.parseFloat(numericString);
2988
+ trailingChars = trailingChars.toLowerCase();
2989
+ switch (trailingChars) {
2990
+ case "%":
2991
+ input = numericValue / 100;
2992
+ break;
2993
+ case "kb":
2994
+ case "k": return numericValue * 1e3;
2995
+ case "kib": return numericValue * 1024;
2996
+ case "mb":
2997
+ case "m": return numericValue * 1e3 * 1e3;
2998
+ case "mib": return numericValue * 1024 * 1024;
2999
+ case "gb":
3000
+ case "g": return numericValue * 1e3 * 1e3 * 1e3;
3001
+ case "gib": return numericValue * 1024 * 1024 * 1024;
3219
3002
  }
3220
- } else if (input > 1) {
3221
- return Math.floor(input);
3222
- } else {
3223
- throw new Error("Unexpected numerical input for \"memoryLimit\"");
3224
3003
  }
3225
- }
3004
+ } else input = Number.parseFloat(input);
3005
+ if (typeof input === "number") if (input <= 1 && input > 0) if (percentageReference) return Math.floor(input * percentageReference);
3006
+ else throw new Error("For a percentage based memory limit a percentageReference must be supplied");
3007
+ else if (input > 1) return Math.floor(input);
3008
+ else throw new Error("Unexpected numerical input for \"memoryLimit\"");
3226
3009
  return null;
3227
3010
  }
3228
3011
 
3229
- const suppressWarningsPath$1 = resolve$1(rootDir, "./suppress-warnings.cjs");
3012
+ const suppressWarningsPath$1 = resolve(rootDir, "./suppress-warnings.cjs");
3230
3013
  function createChildProcessChannel(project, collect) {
3231
3014
  const emitter = new EventEmitter();
3232
3015
  const cleanup = () => emitter.removeAllListeners();
@@ -3255,22 +3038,22 @@ function createChildProcessChannel(project, collect) {
3255
3038
  throw new Error(`[vitest-pool]: Timeout calling "${functionName}"`);
3256
3039
  }
3257
3040
  });
3258
- project.ctx.onCancel((reason) => rpc.onCancel(reason));
3041
+ project.vitest.onCancel((reason) => rpc.onCancel(reason));
3259
3042
  return {
3260
3043
  channel,
3261
3044
  cleanup
3262
3045
  };
3263
3046
  }
3264
- function createVmForksPool(ctx, { execArgv, env }) {
3047
+ function createVmForksPool(vitest, { execArgv, env }) {
3265
3048
  const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
3266
- const threadsCount = ctx.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3267
- const poolOptions = ctx.config.poolOptions?.vmForks ?? {};
3268
- const maxThreads = poolOptions.maxForks ?? ctx.config.maxWorkers ?? threadsCount;
3269
- const minThreads = poolOptions.maxForks ?? ctx.config.minWorkers ?? threadsCount;
3270
- const worker = resolve$1(ctx.distPath, "workers/vmForks.js");
3049
+ const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3050
+ const poolOptions = vitest.config.poolOptions?.vmForks ?? {};
3051
+ const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
3052
+ const minThreads = poolOptions.maxForks ?? vitest.config.minWorkers ?? threadsCount;
3053
+ const worker = resolve(vitest.distPath, "workers/vmForks.js");
3271
3054
  const options = {
3272
3055
  runtime: "child_process",
3273
- filename: resolve$1(ctx.distPath, "worker.js"),
3056
+ filename: resolve(vitest.distPath, "worker.js"),
3274
3057
  maxThreads,
3275
3058
  minThreads,
3276
3059
  env,
@@ -3282,11 +3065,11 @@ function createVmForksPool(ctx, { execArgv, env }) {
3282
3065
  ...poolOptions.execArgv ?? [],
3283
3066
  ...execArgv
3284
3067
  ],
3285
- terminateTimeout: ctx.config.teardownTimeout,
3068
+ terminateTimeout: vitest.config.teardownTimeout,
3286
3069
  concurrentTasksPerWorker: 1,
3287
- maxMemoryLimitBeforeRecycle: getMemoryLimit$1(ctx.config) || undefined
3070
+ maxMemoryLimitBeforeRecycle: getMemoryLimit$1(vitest.config) || void 0
3288
3071
  };
3289
- if (poolOptions.singleFork || !ctx.config.fileParallelism) {
3072
+ if (poolOptions.singleFork || !vitest.config.fileParallelism) {
3290
3073
  options.maxThreads = 1;
3291
3074
  options.minThreads = 1;
3292
3075
  }
@@ -3295,7 +3078,7 @@ function createVmForksPool(ctx, { execArgv, env }) {
3295
3078
  let id = 0;
3296
3079
  async function runFiles(project, config, files, environment, invalidates = []) {
3297
3080
  const paths = files.map((f) => f.filepath);
3298
- ctx.state.clearFiles(project, paths);
3081
+ vitest.state.clearFiles(project, paths);
3299
3082
  const { channel, cleanup } = createChildProcessChannel(project, name === "collect");
3300
3083
  const workerId = ++id;
3301
3084
  const data = {
@@ -3316,26 +3099,20 @@ function createVmForksPool(ctx, { execArgv, env }) {
3316
3099
  });
3317
3100
  } catch (error) {
3318
3101
  // Worker got stuck and won't terminate - this may cause process to hang
3319
- if (error instanceof Error && /Failed to terminate worker/.test(error.message)) {
3320
- ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}.`);
3321
- } else if (ctx.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) {
3322
- ctx.state.cancelFiles(paths, project);
3323
- } else {
3324
- throw error;
3325
- }
3102
+ if (error instanceof Error && /Failed to terminate worker/.test(error.message)) vitest.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}.`);
3103
+ else if (vitest.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) vitest.state.cancelFiles(paths, project);
3104
+ else throw error;
3326
3105
  } finally {
3327
3106
  cleanup();
3328
3107
  }
3329
3108
  }
3330
3109
  return async (specs, invalidates) => {
3331
3110
  // Cancel pending tasks from pool when possible
3332
- ctx.onCancel(() => pool.cancelPendingTasks());
3333
- const configs = new Map();
3111
+ vitest.onCancel(() => pool.cancelPendingTasks());
3112
+ const configs = /* @__PURE__ */ new Map();
3334
3113
  const getConfig = (project) => {
3335
- if (configs.has(project)) {
3336
- return configs.get(project);
3337
- }
3338
- const _config = project.getSerializableConfig();
3114
+ if (configs.has(project)) return configs.get(project);
3115
+ const _config = project.serializedConfig;
3339
3116
  const config = wrapSerializableConfig(_config);
3340
3117
  configs.set(project, config);
3341
3118
  return config;
@@ -3344,9 +3121,7 @@ function createVmForksPool(ctx, { execArgv, env }) {
3344
3121
  const promises = Object.values(filesByEnv).flat();
3345
3122
  const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
3346
3123
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3347
- if (errors.length > 0) {
3348
- throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3349
- }
3124
+ if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3350
3125
  };
3351
3126
  };
3352
3127
  return {
@@ -3359,18 +3134,14 @@ function createVmForksPool(ctx, { execArgv, env }) {
3359
3134
  function getMemoryLimit$1(config) {
3360
3135
  const memory = nodeos.totalmem();
3361
3136
  const limit = getWorkerMemoryLimit(config, "vmForks");
3362
- if (typeof memory === "number") {
3363
- return stringToBytes(limit, config.watch ? memory / 2 : memory);
3364
- }
3137
+ if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
3365
3138
  // If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
3366
- if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") {
3367
- return stringToBytes(limit);
3368
- }
3139
+ if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
3369
3140
  // just ignore "memoryLimit" value because we cannot detect memory limit
3370
3141
  return null;
3371
3142
  }
3372
3143
 
3373
- const suppressWarningsPath = resolve$1(rootDir, "./suppress-warnings.cjs");
3144
+ const suppressWarningsPath = resolve(rootDir, "./suppress-warnings.cjs");
3374
3145
  function createWorkerChannel(project, collect) {
3375
3146
  const channel = new MessageChannel();
3376
3147
  const port = channel.port2;
@@ -3387,21 +3158,21 @@ function createWorkerChannel(project, collect) {
3387
3158
  throw new Error(`[vitest-pool]: Timeout calling "${functionName}"`);
3388
3159
  }
3389
3160
  });
3390
- project.ctx.onCancel((reason) => rpc.onCancel(reason));
3161
+ project.vitest.onCancel((reason) => rpc.onCancel(reason));
3391
3162
  return {
3392
3163
  workerPort,
3393
3164
  port
3394
3165
  };
3395
3166
  }
3396
- function createVmThreadsPool(ctx, { execArgv, env }) {
3167
+ function createVmThreadsPool(vitest, { execArgv, env }) {
3397
3168
  const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
3398
- const threadsCount = ctx.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3399
- const poolOptions = ctx.config.poolOptions?.vmThreads ?? {};
3400
- const maxThreads = poolOptions.maxThreads ?? ctx.config.maxWorkers ?? threadsCount;
3401
- const minThreads = poolOptions.minThreads ?? ctx.config.minWorkers ?? threadsCount;
3402
- const worker = resolve$1(ctx.distPath, "workers/vmThreads.js");
3169
+ const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3170
+ const poolOptions = vitest.config.poolOptions?.vmThreads ?? {};
3171
+ const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
3172
+ const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? threadsCount;
3173
+ const worker = resolve(vitest.distPath, "workers/vmThreads.js");
3403
3174
  const options = {
3404
- filename: resolve$1(ctx.distPath, "worker.js"),
3175
+ filename: resolve(vitest.distPath, "worker.js"),
3405
3176
  useAtomics: poolOptions.useAtomics ?? false,
3406
3177
  maxThreads,
3407
3178
  minThreads,
@@ -3414,11 +3185,11 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3414
3185
  ...poolOptions.execArgv ?? [],
3415
3186
  ...execArgv
3416
3187
  ],
3417
- terminateTimeout: ctx.config.teardownTimeout,
3188
+ terminateTimeout: vitest.config.teardownTimeout,
3418
3189
  concurrentTasksPerWorker: 1,
3419
- maxMemoryLimitBeforeRecycle: getMemoryLimit(ctx.config) || undefined
3190
+ maxMemoryLimitBeforeRecycle: getMemoryLimit(vitest.config) || void 0
3420
3191
  };
3421
- if (poolOptions.singleThread || !ctx.config.fileParallelism) {
3192
+ if (poolOptions.singleThread || !vitest.config.fileParallelism) {
3422
3193
  options.maxThreads = 1;
3423
3194
  options.minThreads = 1;
3424
3195
  }
@@ -3427,7 +3198,7 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3427
3198
  let id = 0;
3428
3199
  async function runFiles(project, config, files, environment, invalidates = []) {
3429
3200
  const paths = files.map((f) => f.filepath);
3430
- ctx.state.clearFiles(project, paths);
3201
+ vitest.state.clearFiles(project, paths);
3431
3202
  const { workerPort, port } = createWorkerChannel(project, name === "collect");
3432
3203
  const workerId = ++id;
3433
3204
  const data = {
@@ -3449,13 +3220,9 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3449
3220
  });
3450
3221
  } catch (error) {
3451
3222
  // Worker got stuck and won't terminate - this may cause process to hang
3452
- if (error instanceof Error && /Failed to terminate worker/.test(error.message)) {
3453
- ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}. \nSee https://vitest.dev/guide/common-errors.html#failed-to-terminate-worker for troubleshooting.`);
3454
- } else if (ctx.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) {
3455
- ctx.state.cancelFiles(paths, project);
3456
- } else {
3457
- throw error;
3458
- }
3223
+ if (error instanceof Error && /Failed to terminate worker/.test(error.message)) vitest.state.addProcessTimeoutCause(`Failed to terminate worker while running ${paths.join(", ")}. \nSee https://vitest.dev/guide/common-errors.html#failed-to-terminate-worker for troubleshooting.`);
3224
+ else if (vitest.isCancelling && error instanceof Error && /The task has been cancelled/.test(error.message)) vitest.state.cancelFiles(paths, project);
3225
+ else throw error;
3459
3226
  } finally {
3460
3227
  port.close();
3461
3228
  workerPort.close();
@@ -3463,12 +3230,10 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3463
3230
  }
3464
3231
  return async (specs, invalidates) => {
3465
3232
  // Cancel pending tasks from pool when possible
3466
- ctx.onCancel(() => pool.cancelPendingTasks());
3467
- const configs = new Map();
3233
+ vitest.onCancel(() => pool.cancelPendingTasks());
3234
+ const configs = /* @__PURE__ */ new Map();
3468
3235
  const getConfig = (project) => {
3469
- if (configs.has(project)) {
3470
- return configs.get(project);
3471
- }
3236
+ if (configs.has(project)) return configs.get(project);
3472
3237
  const config = project.serializedConfig;
3473
3238
  configs.set(project, config);
3474
3239
  return config;
@@ -3477,9 +3242,7 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3477
3242
  const promises = Object.values(filesByEnv).flat();
3478
3243
  const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
3479
3244
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3480
- if (errors.length > 0) {
3481
- throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3482
- }
3245
+ if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3483
3246
  };
3484
3247
  };
3485
3248
  return {
@@ -3492,13 +3255,9 @@ function createVmThreadsPool(ctx, { execArgv, env }) {
3492
3255
  function getMemoryLimit(config) {
3493
3256
  const memory = nodeos.totalmem();
3494
3257
  const limit = getWorkerMemoryLimit(config, "vmThreads");
3495
- if (typeof memory === "number") {
3496
- return stringToBytes(limit, config.watch ? memory / 2 : memory);
3497
- }
3258
+ if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
3498
3259
  // If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
3499
- if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") {
3500
- return stringToBytes(limit);
3501
- }
3260
+ if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
3502
3261
  // just ignore "memoryLimit" value because we cannot detect memory limit
3503
3262
  return null;
3504
3263
  }
@@ -3512,19 +3271,13 @@ const builtinPools = [
3512
3271
  "typescript"
3513
3272
  ];
3514
3273
  function getDefaultPoolName(project) {
3515
- if (project.config.browser.enabled) {
3516
- return "browser";
3517
- }
3274
+ if (project.config.browser.enabled) return "browser";
3518
3275
  return project.config.pool;
3519
3276
  }
3520
3277
  function getFilePoolName(project, file) {
3521
3278
  for (const [glob, pool] of project.config.poolMatchGlobs) {
3522
- if (pool === "browser") {
3523
- throw new Error("Since Vitest 0.31.0 \"browser\" pool is not supported in \"poolMatchGlobs\". You can create a project to run some of your tests in browser in parallel. Read more: https://vitest.dev/guide/projects");
3524
- }
3525
- if (pm.isMatch(file, glob, { cwd: project.config.root })) {
3526
- return pool;
3527
- }
3279
+ if (pool === "browser") throw new Error("Since Vitest 0.31.0 \"browser\" pool is not supported in \"poolMatchGlobs\". You can create a project to run some of your tests in browser in parallel. Read more: https://vitest.dev/guide/projects");
3280
+ if (pm.isMatch(file, glob, { cwd: project.config.root })) return pool;
3528
3281
  }
3529
3282
  return getDefaultPoolName(project);
3530
3283
  }
@@ -3546,17 +3299,11 @@ function createPool(ctx) {
3546
3299
  ...ctx.vite.config.resolve.conditions
3547
3300
  ]);
3548
3301
  const conditions = [...potentialConditions].filter((condition) => {
3549
- if (condition === "production") {
3550
- return ctx.vite.config.isProduction;
3551
- }
3552
- if (condition === "development") {
3553
- return !ctx.vite.config.isProduction;
3554
- }
3302
+ if (condition === "production") return ctx.vite.config.isProduction;
3303
+ if (condition === "development") return !ctx.vite.config.isProduction;
3555
3304
  return true;
3556
3305
  }).map((condition) => {
3557
- if (viteMajor >= 6 && condition === "development|production") {
3558
- return ctx.vite.config.isProduction ? "production" : "development";
3559
- }
3306
+ if (viteMajor >= 6 && condition === "development|production") return ctx.vite.config.isProduction ? "production" : "development";
3560
3307
  return condition;
3561
3308
  }).flatMap((c) => ["--conditions", c]);
3562
3309
  // Instead of passing whole process.execArgv to the workers, pick allowed options.
@@ -3576,35 +3323,21 @@ function createPool(ctx) {
3576
3323
  }
3577
3324
  };
3578
3325
  // env are case-insensitive on Windows, but spawned processes don't support it
3579
- if (isWindows) {
3580
- for (const name in options.env) {
3581
- options.env[name.toUpperCase()] = options.env[name];
3582
- }
3583
- }
3584
- const poolConcurrentPromises = new Map();
3585
- const customPools = new Map();
3326
+ if (isWindows) for (const name in options.env) options.env[name.toUpperCase()] = options.env[name];
3327
+ const poolConcurrentPromises = /* @__PURE__ */ new Map();
3328
+ const customPools = /* @__PURE__ */ new Map();
3586
3329
  async function resolveCustomPool(filepath) {
3587
- if (customPools.has(filepath)) {
3588
- return customPools.get(filepath);
3589
- }
3330
+ if (customPools.has(filepath)) return customPools.get(filepath);
3590
3331
  const pool = await ctx.runner.executeId(filepath);
3591
- if (typeof pool.default !== "function") {
3592
- throw new TypeError(`Custom pool "${filepath}" must export a function as default export`);
3593
- }
3332
+ if (typeof pool.default !== "function") throw new TypeError(`Custom pool "${filepath}" must export a function as default export`);
3594
3333
  const poolInstance = await pool.default(ctx, options);
3595
- if (typeof poolInstance?.name !== "string") {
3596
- throw new TypeError(`Custom pool "${filepath}" should return an object with "name" property`);
3597
- }
3598
- if (typeof poolInstance?.[method] !== "function") {
3599
- throw new TypeError(`Custom pool "${filepath}" should return an object with "${method}" method`);
3600
- }
3334
+ if (typeof poolInstance?.name !== "string") throw new TypeError(`Custom pool "${filepath}" should return an object with "name" property`);
3335
+ if (typeof poolInstance?.[method] !== "function") throw new TypeError(`Custom pool "${filepath}" should return an object with "${method}" method`);
3601
3336
  customPools.set(filepath, poolInstance);
3602
3337
  return poolInstance;
3603
3338
  }
3604
3339
  function getConcurrentPool(pool, fn) {
3605
- if (poolConcurrentPromises.has(pool)) {
3606
- return poolConcurrentPromises.get(pool);
3607
- }
3340
+ if (poolConcurrentPromises.has(pool)) return poolConcurrentPromises.get(pool);
3608
3341
  const promise = fn().finally(() => {
3609
3342
  poolConcurrentPromises.delete(pool);
3610
3343
  });
@@ -3621,7 +3354,7 @@ function createPool(ctx) {
3621
3354
  });
3622
3355
  }
3623
3356
  const groupedSpecifications = {};
3624
- const groups = new Set();
3357
+ const groups = /* @__PURE__ */ new Set();
3625
3358
  const factories = {
3626
3359
  vmThreads: () => createVmThreadsPool(ctx, options),
3627
3360
  vmForks: () => createVmForksPool(ctx, options),
@@ -3638,17 +3371,13 @@ function createPool(ctx) {
3638
3371
  const Sequencer = ctx.config.sequence.sequencer;
3639
3372
  const sequencer = new Sequencer(ctx);
3640
3373
  async function sortSpecs(specs) {
3641
- if (ctx.config.shard) {
3642
- specs = await sequencer.shard(specs);
3643
- }
3374
+ if (ctx.config.shard) specs = await sequencer.shard(specs);
3644
3375
  return sequencer.sort(specs);
3645
3376
  }
3646
3377
  const sortedGroups = Array.from(groups).sort();
3647
3378
  for (const group of sortedGroups) {
3648
3379
  const specifications = groupedSpecifications[group];
3649
- if (!specifications?.length) {
3650
- continue;
3651
- }
3380
+ if (!specifications?.length) continue;
3652
3381
  const filesByPool = {
3653
3382
  forks: [],
3654
3383
  threads: [],
@@ -3663,9 +3392,7 @@ function createPool(ctx) {
3663
3392
  });
3664
3393
  await Promise.all(Object.entries(filesByPool).map(async (entry) => {
3665
3394
  const [pool, files] = entry;
3666
- if (!files.length) {
3667
- return null;
3668
- }
3395
+ if (!files.length) return null;
3669
3396
  const specs = await sortSpecs(files);
3670
3397
  if (pool in factories) {
3671
3398
  const factory = factories[pool];
@@ -3705,7 +3432,7 @@ class BaseSequencer {
3705
3432
  const shardStart = shardSize * (index - 1);
3706
3433
  const shardEnd = shardSize * index;
3707
3434
  return [...files].map((spec) => {
3708
- const fullPath = resolve(slash$1(config.root), slash$1(spec.moduleId));
3435
+ const fullPath = resolve$1(slash(config.root), slash(spec.moduleId));
3709
3436
  const specPath = fullPath?.slice(config.root.length);
3710
3437
  return {
3711
3438
  spec,
@@ -3725,19 +3452,13 @@ class BaseSequencer {
3725
3452
  const statsA = cache.getFileStats(keyA);
3726
3453
  const statsB = cache.getFileStats(keyB);
3727
3454
  // run unknown first
3728
- if (!statsA || !statsB) {
3729
- return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0;
3730
- }
3455
+ if (!statsA || !statsB) return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0;
3731
3456
  // run larger files first
3732
3457
  return statsB.size - statsA.size;
3733
3458
  }
3734
3459
  // run failed first
3735
- if (aState.failed && !bState.failed) {
3736
- return -1;
3737
- }
3738
- if (!aState.failed && bState.failed) {
3739
- return 1;
3740
- }
3460
+ if (aState.failed && !bState.failed) return -1;
3461
+ if (!aState.failed && bState.failed) return 1;
3741
3462
  // run longer first
3742
3463
  return bState.duration - aState.duration;
3743
3464
  });
@@ -3752,22 +3473,14 @@ class RandomSequencer extends BaseSequencer {
3752
3473
  }
3753
3474
 
3754
3475
  function resolvePath(path, root) {
3755
- return normalize(/* @__PURE__ */ resolveModule(path, { paths: [root] }) ?? resolve(root, path));
3476
+ return normalize(/* @__PURE__ */ resolveModule(path, { paths: [root] }) ?? resolve$1(root, path));
3756
3477
  }
3757
3478
  function parseInspector(inspect) {
3758
- if (typeof inspect === "boolean" || inspect === undefined) {
3759
- return {};
3760
- }
3761
- if (typeof inspect === "number") {
3762
- return { port: inspect };
3763
- }
3764
- if (inspect.match(/https?:\//)) {
3765
- throw new Error(`Inspector host cannot be a URL. Use "host:port" instead of "${inspect}"`);
3766
- }
3479
+ if (typeof inspect === "boolean" || inspect === void 0) return {};
3480
+ if (typeof inspect === "number") return { port: inspect };
3481
+ if (inspect.match(/https?:\//)) throw new Error(`Inspector host cannot be a URL. Use "host:port" instead of "${inspect}"`);
3767
3482
  const [host, port] = inspect.split(":");
3768
- if (!port) {
3769
- return { host };
3770
- }
3483
+ if (!port) return { host };
3771
3484
  return {
3772
3485
  host,
3773
3486
  port: Number(port) || defaultInspectPort
@@ -3775,51 +3488,28 @@ function parseInspector(inspect) {
3775
3488
  }
3776
3489
  function resolveApiServerConfig(options, defaultPort) {
3777
3490
  let api;
3778
- if (options.ui && !options.api) {
3779
- api = { port: defaultPort };
3780
- } else if (options.api === true) {
3781
- api = { port: defaultPort };
3782
- } else if (typeof options.api === "number") {
3783
- api = { port: options.api };
3784
- }
3785
- if (typeof options.api === "object") {
3786
- if (api) {
3787
- if (options.api.port) {
3788
- api.port = options.api.port;
3789
- }
3790
- if (options.api.strictPort) {
3791
- api.strictPort = options.api.strictPort;
3792
- }
3793
- if (options.api.host) {
3794
- api.host = options.api.host;
3795
- }
3796
- } else {
3797
- api = { ...options.api };
3798
- }
3799
- }
3491
+ if (options.ui && !options.api) api = { port: defaultPort };
3492
+ else if (options.api === true) api = { port: defaultPort };
3493
+ else if (typeof options.api === "number") api = { port: options.api };
3494
+ if (typeof options.api === "object") if (api) {
3495
+ if (options.api.port) api.port = options.api.port;
3496
+ if (options.api.strictPort) api.strictPort = options.api.strictPort;
3497
+ if (options.api.host) api.host = options.api.host;
3498
+ } else api = { ...options.api };
3800
3499
  if (api) {
3801
- if (!api.port && !api.middlewareMode) {
3802
- api.port = defaultPort;
3803
- }
3804
- } else {
3805
- api = { middlewareMode: true };
3806
- }
3500
+ if (!api.port && !api.middlewareMode) api.port = defaultPort;
3501
+ } else api = { middlewareMode: true };
3807
3502
  return api;
3808
3503
  }
3809
3504
  function resolveInlineWorkerOption(value) {
3810
- if (typeof value === "string" && value.trim().endsWith("%")) {
3811
- return getWorkersCountByPercentage(value);
3812
- } else {
3813
- return Number(value);
3814
- }
3505
+ if (typeof value === "string" && value.trim().endsWith("%")) return getWorkersCountByPercentage(value);
3506
+ else return Number(value);
3815
3507
  }
3816
3508
  function resolveConfig$1(vitest, options, viteConfig) {
3817
3509
  const mode = vitest.mode;
3818
3510
  const logger = vitest.logger;
3819
3511
  if (options.dom) {
3820
- if (viteConfig.test?.environment != null && viteConfig.test.environment !== "happy-dom") {
3821
- logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} Your config.test.environment ("${viteConfig.test.environment}") conflicts with --dom flag ("happy-dom"), ignoring "${viteConfig.test.environment}"`));
3822
- }
3512
+ if (viteConfig.test?.environment != null && viteConfig.test.environment !== "happy-dom") logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} Your config.test.environment ("${viteConfig.test.environment}") conflicts with --dom flag ("happy-dom"), ignoring "${viteConfig.test.environment}"`));
3823
3513
  options.environment = "happy-dom";
3824
3514
  }
3825
3515
  const resolved = {
@@ -3831,7 +3521,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
3831
3521
  resolved.project = toArray(resolved.project);
3832
3522
  resolved.provide ??= {};
3833
3523
  resolved.name = typeof options.name === "string" ? options.name : options.name?.label || "";
3834
- resolved.color = typeof options.name !== "string" ? options.name?.color : undefined;
3524
+ resolved.color = typeof options.name !== "string" ? options.name?.color : void 0;
3835
3525
  const inspector = resolved.inspect || resolved.inspectBrk;
3836
3526
  resolved.inspector = {
3837
3527
  ...resolved.inspector,
@@ -3839,40 +3529,24 @@ function resolveConfig$1(vitest, options, viteConfig) {
3839
3529
  enabled: !!inspector,
3840
3530
  waitForDebugger: options.inspector?.waitForDebugger ?? !!resolved.inspectBrk
3841
3531
  };
3842
- if (viteConfig.base !== "/") {
3843
- resolved.base = viteConfig.base;
3844
- }
3532
+ if (viteConfig.base !== "/") resolved.base = viteConfig.base;
3845
3533
  resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true;
3846
3534
  if (options.shard) {
3847
- if (resolved.watch) {
3848
- throw new Error("You cannot use --shard option with enabled watch");
3849
- }
3535
+ if (resolved.watch) throw new Error("You cannot use --shard option with enabled watch");
3850
3536
  const [indexString, countString] = options.shard.split("/");
3851
3537
  const index = Math.abs(Number.parseInt(indexString, 10));
3852
3538
  const count = Math.abs(Number.parseInt(countString, 10));
3853
- if (Number.isNaN(count) || count <= 0) {
3854
- throw new Error("--shard <count> must be a positive number");
3855
- }
3856
- if (Number.isNaN(index) || index <= 0 || index > count) {
3857
- throw new Error("--shard <index> must be a positive number less then <count>");
3858
- }
3539
+ if (Number.isNaN(count) || count <= 0) throw new Error("--shard <count> must be a positive number");
3540
+ if (Number.isNaN(index) || index <= 0 || index > count) throw new Error("--shard <index> must be a positive number less then <count>");
3859
3541
  resolved.shard = {
3860
3542
  index,
3861
3543
  count
3862
3544
  };
3863
3545
  }
3864
- if (resolved.standalone && !resolved.watch) {
3865
- throw new Error(`Vitest standalone mode requires --watch`);
3866
- }
3867
- if (resolved.mergeReports && resolved.watch) {
3868
- throw new Error(`Cannot merge reports with --watch enabled`);
3869
- }
3870
- if (resolved.maxWorkers) {
3871
- resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers);
3872
- }
3873
- if (resolved.minWorkers) {
3874
- resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers);
3875
- }
3546
+ if (resolved.standalone && !resolved.watch) throw new Error(`Vitest standalone mode requires --watch`);
3547
+ if (resolved.mergeReports && resolved.watch) throw new Error(`Cannot merge reports with --watch enabled`);
3548
+ if (resolved.maxWorkers) resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers);
3549
+ if (resolved.minWorkers) resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers);
3876
3550
  // run benchmark sequentially by default
3877
3551
  resolved.fileParallelism ??= mode !== "benchmark";
3878
3552
  if (!resolved.fileParallelism) {
@@ -3893,23 +3567,16 @@ function resolveConfig$1(vitest, options, viteConfig) {
3893
3567
  }
3894
3568
  }
3895
3569
  // apply browser CLI options only if the config already has the browser config and not disabled manually
3896
- if (vitest._cliOptions.browser && resolved.browser && (resolved.browser.enabled !== false || vitest._cliOptions.browser.enabled)) {
3897
- resolved.browser = mergeConfig(resolved.browser, vitest._cliOptions.browser);
3898
- }
3570
+ if (vitest._cliOptions.browser && resolved.browser && (resolved.browser.enabled !== false || vitest._cliOptions.browser.enabled)) resolved.browser = mergeConfig(resolved.browser, vitest._cliOptions.browser);
3899
3571
  resolved.browser ??= {};
3900
3572
  const browser = resolved.browser;
3901
3573
  if (browser.enabled) {
3902
- if (!browser.name && !browser.instances) {
3903
- throw new Error(`Vitest Browser Mode requires "browser.name" (deprecated) or "browser.instances" options, none were set.`);
3904
- }
3574
+ if (!browser.name && !browser.instances) throw new Error(`Vitest Browser Mode requires "browser.name" (deprecated) or "browser.instances" options, none were set.`);
3905
3575
  const instances = browser.instances;
3906
- if (browser.name && browser.instances) {
3907
- // --browser=chromium filters configs to a single one
3908
- browser.instances = browser.instances.filter((instance) => instance.browser === browser.name);
3909
- }
3910
- if (browser.instances && !browser.instances.length) {
3911
- throw new Error([`"browser.instances" was set in the config, but the array is empty. Define at least one browser config.`, browser.name && instances?.length ? ` The "browser.name" was set to "${browser.name}" which filtered all configs (${instances.map((c) => c.browser).join(", ")}). Did you mean to use another name?` : ""].join(""));
3912
- }
3576
+ if (browser.name && browser.instances)
3577
+ // --browser=chromium filters configs to a single one
3578
+ browser.instances = browser.instances.filter((instance) => instance.browser === browser.name);
3579
+ if (browser.instances && !browser.instances.length) throw new Error([`"browser.instances" was set in the config, but the array is empty. Define at least one browser config.`, browser.name && instances?.length ? ` The "browser.name" was set to "${browser.name}" which filtered all configs (${instances.map((c) => c.browser).join(", ")}). Did you mean to use another name?` : ""].join(""));
3913
3580
  }
3914
3581
  const playwrightChromiumOnly = isPlaywrightChromiumOnly(vitest, resolved);
3915
3582
  // Browser-mode "Playwright + Chromium" only features:
@@ -3919,45 +3586,33 @@ function resolveConfig$1(vitest, options, viteConfig) {
3919
3586
  name: browser.name,
3920
3587
  instances: browser.instances?.map((i) => ({ browser: i.browser }))
3921
3588
  } };
3922
- if (resolved.coverage.enabled && resolved.coverage.provider === "v8") {
3923
- throw new Error(`@vitest/coverage-v8 does not work with\n${JSON.stringify(browserConfig, null, 2)}\n` + `\nUse either:\n${JSON.stringify({ browser: {
3924
- provider: "playwright",
3925
- instances: [{ browser: "chromium" }]
3926
- } }, null, 2)}` + `\n\n...or change your coverage provider to:\n${JSON.stringify({ coverage: { provider: "istanbul" } }, null, 2)}\n`);
3927
- }
3589
+ if (resolved.coverage.enabled && resolved.coverage.provider === "v8") throw new Error(`@vitest/coverage-v8 does not work with\n${JSON.stringify(browserConfig, null, 2)}\n\nUse either:\n${JSON.stringify({ browser: {
3590
+ provider: "playwright",
3591
+ instances: [{ browser: "chromium" }]
3592
+ } }, null, 2)}\n\n...or change your coverage provider to:\n${JSON.stringify({ coverage: { provider: "istanbul" } }, null, 2)}\n`);
3928
3593
  if (resolved.inspect || resolved.inspectBrk) {
3929
3594
  const inspectOption = `--inspect${resolved.inspectBrk ? "-brk" : ""}`;
3930
- throw new Error(`${inspectOption} does not work with\n${JSON.stringify(browserConfig, null, 2)}\n` + `\nUse either:\n${JSON.stringify({ browser: {
3595
+ throw new Error(`${inspectOption} does not work with\n${JSON.stringify(browserConfig, null, 2)}\n\nUse either:\n${JSON.stringify({ browser: {
3931
3596
  provider: "playwright",
3932
3597
  instances: [{ browser: "chromium" }]
3933
- } }, null, 2)}` + `\n\n...or disable ${inspectOption}\n`);
3598
+ } }, null, 2)}\n\n...or disable ${inspectOption}\n`);
3934
3599
  }
3935
3600
  }
3936
3601
  resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter);
3937
3602
  if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
3938
- const reportsDirectory = resolve(resolved.root, resolved.coverage.reportsDirectory);
3939
- if (reportsDirectory === resolved.root || reportsDirectory === process.cwd()) {
3940
- throw new Error(`You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`);
3941
- }
3942
- }
3943
- if (resolved.coverage.enabled && resolved.coverage.provider === "custom" && resolved.coverage.customProviderModule) {
3944
- resolved.coverage.customProviderModule = resolvePath(resolved.coverage.customProviderModule, resolved.root);
3603
+ const reportsDirectory = resolve$1(resolved.root, resolved.coverage.reportsDirectory);
3604
+ if (reportsDirectory === resolved.root || reportsDirectory === process.cwd()) throw new Error(`You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`);
3945
3605
  }
3606
+ if (resolved.coverage.enabled && resolved.coverage.provider === "custom" && resolved.coverage.customProviderModule) resolved.coverage.customProviderModule = resolvePath(resolved.coverage.customProviderModule, resolved.root);
3946
3607
  resolved.expect ??= {};
3947
3608
  resolved.deps ??= {};
3948
3609
  resolved.deps.moduleDirectories ??= [];
3949
3610
  resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
3950
- if (!dir.startsWith("/")) {
3951
- dir = `/${dir}`;
3952
- }
3953
- if (!dir.endsWith("/")) {
3954
- dir += "/";
3955
- }
3611
+ if (!dir.startsWith("/")) dir = `/${dir}`;
3612
+ if (!dir.endsWith("/")) dir += "/";
3956
3613
  return normalize(dir);
3957
3614
  });
3958
- if (!resolved.deps.moduleDirectories.includes("/node_modules/")) {
3959
- resolved.deps.moduleDirectories.push("/node_modules/");
3960
- }
3615
+ if (!resolved.deps.moduleDirectories.includes("/node_modules/")) resolved.deps.moduleDirectories.push("/node_modules/");
3961
3616
  resolved.deps.optimizer ??= {};
3962
3617
  resolved.deps.optimizer.ssr ??= {};
3963
3618
  resolved.deps.optimizer.ssr.enabled ??= true;
@@ -3984,29 +3639,21 @@ function resolveConfig$1(vitest, options, viteConfig) {
3984
3639
  "fallbackCJS"
3985
3640
  ];
3986
3641
  deprecatedDepsOptions.forEach((option) => {
3987
- if (resolved.deps[option] === undefined) {
3988
- return;
3989
- }
3990
- if (option === "fallbackCJS") {
3991
- logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "deps.${option}" is deprecated. Use "server.deps.${option}" instead`));
3992
- } else {
3642
+ if (resolved.deps[option] === void 0) return;
3643
+ if (option === "fallbackCJS") logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "deps.${option}" is deprecated. Use "server.deps.${option}" instead`));
3644
+ else {
3993
3645
  const transformMode = resolved.environment === "happy-dom" || resolved.environment === "jsdom" ? "web" : "ssr";
3994
3646
  logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "deps.${option}" is deprecated. If you rely on vite-node directly, use "server.deps.${option}" instead. Otherwise, consider using "deps.optimizer.${transformMode}.${option === "external" ? "exclude" : "include"}"`));
3995
3647
  }
3996
- if (resolved.server.deps[option] === undefined) {
3997
- resolved.server.deps[option] = resolved.deps[option];
3998
- }
3648
+ if (resolved.server.deps[option] === void 0) resolved.server.deps[option] = resolved.deps[option];
3999
3649
  });
4000
- if (resolved.cliExclude) {
4001
- resolved.exclude.push(...resolved.cliExclude);
4002
- }
3650
+ if (resolved.cliExclude) resolved.exclude.push(...resolved.cliExclude);
4003
3651
  // vitenode will try to import such file with native node,
4004
3652
  // but then our mocker will not work properly
4005
3653
  if (resolved.server.deps.inline !== true) {
4006
3654
  const ssrOptions = viteConfig.ssr;
4007
- if (ssrOptions?.noExternal === true && resolved.server.deps.inline == null) {
4008
- resolved.server.deps.inline = true;
4009
- } else {
3655
+ if (ssrOptions?.noExternal === true && resolved.server.deps.inline == null) resolved.server.deps.inline = true;
3656
+ else {
4010
3657
  resolved.server.deps.inline ??= [];
4011
3658
  resolved.server.deps.inline.push(...extraInlineDeps);
4012
3659
  }
@@ -4015,16 +3662,11 @@ function resolveConfig$1(vitest, options, viteConfig) {
4015
3662
  resolved.server.deps.inlineFiles.push(...resolved.setupFiles);
4016
3663
  resolved.server.deps.moduleDirectories ??= [];
4017
3664
  resolved.server.deps.moduleDirectories.push(...resolved.deps.moduleDirectories);
4018
- if (resolved.runner) {
4019
- resolved.runner = resolvePath(resolved.runner, resolved.root);
4020
- }
4021
- if (resolved.snapshotEnvironment) {
4022
- resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
4023
- }
4024
- resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : undefined;
4025
- if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
4026
- resolved.snapshotFormat.plugins = [];
4027
- }
3665
+ if (resolved.runner) resolved.runner = resolvePath(resolved.runner, resolved.root);
3666
+ resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments");
3667
+ if (resolved.snapshotEnvironment) resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
3668
+ resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
3669
+ if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) resolved.snapshotFormat.plugins = [];
4028
3670
  const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
4029
3671
  resolved.snapshotOptions = {
4030
3672
  expand: resolved.expandSnapshotDiff ?? false,
@@ -4036,98 +3678,73 @@ function resolveConfig$1(vitest, options, viteConfig) {
4036
3678
  resolved.snapshotSerializers ??= [];
4037
3679
  resolved.snapshotSerializers = resolved.snapshotSerializers.map((file) => resolvePath(file, resolved.root));
4038
3680
  resolved.forceRerunTriggers.push(...resolved.snapshotSerializers);
4039
- if (options.resolveSnapshotPath) {
4040
- delete resolved.resolveSnapshotPath;
4041
- }
3681
+ if (options.resolveSnapshotPath) delete resolved.resolveSnapshotPath;
4042
3682
  resolved.pool ??= "threads";
4043
- if (process.env.VITEST_MAX_THREADS) {
4044
- resolved.poolOptions = {
4045
- ...resolved.poolOptions,
4046
- threads: {
4047
- ...resolved.poolOptions?.threads,
4048
- maxThreads: Number.parseInt(process.env.VITEST_MAX_THREADS)
4049
- },
4050
- vmThreads: {
4051
- ...resolved.poolOptions?.vmThreads,
4052
- maxThreads: Number.parseInt(process.env.VITEST_MAX_THREADS)
4053
- }
4054
- };
4055
- }
4056
- if (process.env.VITEST_MIN_THREADS) {
4057
- resolved.poolOptions = {
4058
- ...resolved.poolOptions,
4059
- threads: {
4060
- ...resolved.poolOptions?.threads,
4061
- minThreads: Number.parseInt(process.env.VITEST_MIN_THREADS)
4062
- },
4063
- vmThreads: {
4064
- ...resolved.poolOptions?.vmThreads,
4065
- minThreads: Number.parseInt(process.env.VITEST_MIN_THREADS)
4066
- }
4067
- };
4068
- }
4069
- if (process.env.VITEST_MAX_FORKS) {
4070
- resolved.poolOptions = {
4071
- ...resolved.poolOptions,
4072
- forks: {
4073
- ...resolved.poolOptions?.forks,
4074
- maxForks: Number.parseInt(process.env.VITEST_MAX_FORKS)
4075
- },
4076
- vmForks: {
4077
- ...resolved.poolOptions?.vmForks,
4078
- maxForks: Number.parseInt(process.env.VITEST_MAX_FORKS)
4079
- }
4080
- };
4081
- }
4082
- if (process.env.VITEST_MIN_FORKS) {
4083
- resolved.poolOptions = {
4084
- ...resolved.poolOptions,
4085
- forks: {
4086
- ...resolved.poolOptions?.forks,
4087
- minForks: Number.parseInt(process.env.VITEST_MIN_FORKS)
4088
- },
4089
- vmForks: {
4090
- ...resolved.poolOptions?.vmForks,
4091
- minForks: Number.parseInt(process.env.VITEST_MIN_FORKS)
4092
- }
4093
- };
4094
- }
3683
+ if (process.env.VITEST_MAX_THREADS) resolved.poolOptions = {
3684
+ ...resolved.poolOptions,
3685
+ threads: {
3686
+ ...resolved.poolOptions?.threads,
3687
+ maxThreads: Number.parseInt(process.env.VITEST_MAX_THREADS)
3688
+ },
3689
+ vmThreads: {
3690
+ ...resolved.poolOptions?.vmThreads,
3691
+ maxThreads: Number.parseInt(process.env.VITEST_MAX_THREADS)
3692
+ }
3693
+ };
3694
+ if (process.env.VITEST_MIN_THREADS) resolved.poolOptions = {
3695
+ ...resolved.poolOptions,
3696
+ threads: {
3697
+ ...resolved.poolOptions?.threads,
3698
+ minThreads: Number.parseInt(process.env.VITEST_MIN_THREADS)
3699
+ },
3700
+ vmThreads: {
3701
+ ...resolved.poolOptions?.vmThreads,
3702
+ minThreads: Number.parseInt(process.env.VITEST_MIN_THREADS)
3703
+ }
3704
+ };
3705
+ if (process.env.VITEST_MAX_FORKS) resolved.poolOptions = {
3706
+ ...resolved.poolOptions,
3707
+ forks: {
3708
+ ...resolved.poolOptions?.forks,
3709
+ maxForks: Number.parseInt(process.env.VITEST_MAX_FORKS)
3710
+ },
3711
+ vmForks: {
3712
+ ...resolved.poolOptions?.vmForks,
3713
+ maxForks: Number.parseInt(process.env.VITEST_MAX_FORKS)
3714
+ }
3715
+ };
3716
+ if (process.env.VITEST_MIN_FORKS) resolved.poolOptions = {
3717
+ ...resolved.poolOptions,
3718
+ forks: {
3719
+ ...resolved.poolOptions?.forks,
3720
+ minForks: Number.parseInt(process.env.VITEST_MIN_FORKS)
3721
+ },
3722
+ vmForks: {
3723
+ ...resolved.poolOptions?.vmForks,
3724
+ minForks: Number.parseInt(process.env.VITEST_MIN_FORKS)
3725
+ }
3726
+ };
4095
3727
  const poolThreadsOptions = [
4096
3728
  ["threads", "minThreads"],
4097
3729
  ["threads", "maxThreads"],
4098
3730
  ["vmThreads", "minThreads"],
4099
3731
  ["vmThreads", "maxThreads"]
4100
3732
  ];
4101
- for (const [poolOptionKey, workerOptionKey] of poolThreadsOptions) {
4102
- if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) {
4103
- resolved.poolOptions[poolOptionKey][workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey][workerOptionKey]);
4104
- }
4105
- }
3733
+ for (const [poolOptionKey, workerOptionKey] of poolThreadsOptions) if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) resolved.poolOptions[poolOptionKey][workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey][workerOptionKey]);
4106
3734
  const poolForksOptions = [
4107
3735
  ["forks", "minForks"],
4108
3736
  ["forks", "maxForks"],
4109
3737
  ["vmForks", "minForks"],
4110
3738
  ["vmForks", "maxForks"]
4111
3739
  ];
4112
- for (const [poolOptionKey, workerOptionKey] of poolForksOptions) {
4113
- if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) {
4114
- resolved.poolOptions[poolOptionKey][workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey][workerOptionKey]);
4115
- }
4116
- }
4117
- if (typeof resolved.workspace === "string") {
4118
- // if passed down from the CLI and it's relative, resolve relative to CWD
4119
- resolved.workspace = typeof options.workspace === "string" && options.workspace[0] === "." ? resolve(process.cwd(), options.workspace) : resolvePath(resolved.workspace, resolved.root);
4120
- }
4121
- if (!builtinPools.includes(resolved.pool)) {
4122
- resolved.pool = resolvePath(resolved.pool, resolved.root);
4123
- }
4124
- if (resolved.poolMatchGlobs) {
4125
- logger.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "poolMatchGlobs" is deprecated. Use "workspace" to define different configurations instead.`));
4126
- }
3740
+ for (const [poolOptionKey, workerOptionKey] of poolForksOptions) if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) resolved.poolOptions[poolOptionKey][workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey][workerOptionKey]);
3741
+ if (typeof resolved.workspace === "string")
3742
+ // if passed down from the CLI and it's relative, resolve relative to CWD
3743
+ resolved.workspace = typeof options.workspace === "string" && options.workspace[0] === "." ? resolve$1(process.cwd(), options.workspace) : resolvePath(resolved.workspace, resolved.root);
3744
+ if (!builtinPools.includes(resolved.pool)) resolved.pool = resolvePath(resolved.pool, resolved.root);
3745
+ if (resolved.poolMatchGlobs) logger.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "poolMatchGlobs" is deprecated. Use "workspace" to define different configurations instead.`));
4127
3746
  resolved.poolMatchGlobs = (resolved.poolMatchGlobs || []).map(([glob, pool]) => {
4128
- if (!builtinPools.includes(pool)) {
4129
- pool = resolvePath(pool, resolved.root);
4130
- }
3747
+ if (!builtinPools.includes(pool)) pool = resolvePath(pool, resolved.root);
4131
3748
  return [glob, pool];
4132
3749
  });
4133
3750
  if (mode === "benchmark") {
@@ -4142,21 +3759,12 @@ function resolveConfig$1(vitest, options, viteConfig) {
4142
3759
  resolved.exclude = resolved.benchmark.exclude;
4143
3760
  resolved.includeSource = resolved.benchmark.includeSource;
4144
3761
  const reporters = Array.from(new Set([...toArray(resolved.benchmark.reporters), ...toArray(options.reporter)])).filter(Boolean);
4145
- if (reporters.length) {
4146
- resolved.benchmark.reporters = reporters;
4147
- } else {
4148
- resolved.benchmark.reporters = ["default"];
4149
- }
4150
- if (options.outputFile) {
4151
- resolved.benchmark.outputFile = options.outputFile;
4152
- }
3762
+ if (reporters.length) resolved.benchmark.reporters = reporters;
3763
+ else resolved.benchmark.reporters = ["default"];
3764
+ if (options.outputFile) resolved.benchmark.outputFile = options.outputFile;
4153
3765
  // --compare from cli
4154
- if (options.compare) {
4155
- resolved.benchmark.compare = options.compare;
4156
- }
4157
- if (options.outputJson) {
4158
- resolved.benchmark.outputJson = options.outputJson;
4159
- }
3766
+ if (options.compare) resolved.benchmark.compare = options.compare;
3767
+ if (options.outputJson) resolved.benchmark.outputJson = options.outputJson;
4160
3768
  }
4161
3769
  if (typeof resolved.diff === "string") {
4162
3770
  resolved.diff = resolvePath(resolved.diff, resolved.root);
@@ -4168,9 +3776,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
4168
3776
  ...api,
4169
3777
  token: crypto.randomUUID()
4170
3778
  };
4171
- if (options.related) {
4172
- resolved.related = toArray(options.related).map((file) => resolve(resolved.root, file));
4173
- }
3779
+ if (options.related) resolved.related = toArray(options.related).map((file) => resolve$1(resolved.root, file));
4174
3780
  /*
4175
3781
  * Reporters can be defined in many different ways:
4176
3782
  * { reporter: 'json' }
@@ -4180,29 +3786,21 @@ function resolveConfig$1(vitest, options, viteConfig) {
4180
3786
  * { reporter: [[ 'json' ], 'html'] }
4181
3787
  * { reporter: [[ 'json', { outputFile: 'test.json' } ], 'html'] }
4182
3788
  */
4183
- if (options.reporters) {
4184
- if (!Array.isArray(options.reporters)) {
4185
- // Reporter name, e.g. { reporters: 'json' }
4186
- if (typeof options.reporters === "string") {
4187
- resolved.reporters = [[options.reporters, {}]];
4188
- } else {
4189
- resolved.reporters = [options.reporters];
4190
- }
4191
- } else {
4192
- resolved.reporters = [];
4193
- for (const reporter of options.reporters) {
4194
- if (Array.isArray(reporter)) {
4195
- // Reporter with options, e.g. { reporters: [ [ 'json', { outputFile: 'test.json' } ] ] }
4196
- resolved.reporters.push([reporter[0], reporter[1] || {}]);
4197
- } else if (typeof reporter === "string") {
4198
- // Reporter name in array, e.g. { reporters: ["html", "json"]}
4199
- resolved.reporters.push([reporter, {}]);
4200
- } else {
4201
- // Inline reporter, e.g. { reporter: [{ onFinish() { method() } }] }
4202
- resolved.reporters.push(reporter);
4203
- }
4204
- }
4205
- }
3789
+ if (options.reporters) if (!Array.isArray(options.reporters))
3790
+ // Reporter name, e.g. { reporters: 'json' }
3791
+ if (typeof options.reporters === "string") resolved.reporters = [[options.reporters, {}]];
3792
+ else resolved.reporters = [options.reporters];
3793
+ else {
3794
+ resolved.reporters = [];
3795
+ for (const reporter of options.reporters) if (Array.isArray(reporter))
3796
+ // Reporter with options, e.g. { reporters: [ [ 'json', { outputFile: 'test.json' } ] ] }
3797
+ resolved.reporters.push([reporter[0], reporter[1] || {}]);
3798
+ else if (typeof reporter === "string")
3799
+ // Reporter name in array, e.g. { reporters: ["html", "json"]}
3800
+ resolved.reporters.push([reporter, {}]);
3801
+ else
3802
+ // Inline reporter, e.g. { reporter: [{ onFinish() { method() } }] }
3803
+ resolved.reporters.push(reporter);
4206
3804
  }
4207
3805
  if (mode !== "benchmark") {
4208
3806
  // @ts-expect-error "reporter" is from CLI, should be absolute to the running directory
@@ -4210,37 +3808,25 @@ function resolveConfig$1(vitest, options, viteConfig) {
4210
3808
  const reportersFromCLI = resolved.reporter;
4211
3809
  const cliReporters = toArray(reportersFromCLI || []).map((reporter) => {
4212
3810
  // ./reporter.js || ../reporter.js, but not .reporters/reporter.js
4213
- if (/^\.\.?\//.test(reporter)) {
4214
- return resolve(process.cwd(), reporter);
4215
- }
3811
+ if (/^\.\.?\//.test(reporter)) return resolve$1(process.cwd(), reporter);
4216
3812
  return reporter;
4217
3813
  });
4218
- if (cliReporters.length) {
4219
- resolved.reporters = Array.from(new Set(toArray(cliReporters))).filter(Boolean).map((reporter) => [reporter, {}]);
4220
- }
3814
+ if (cliReporters.length) resolved.reporters = Array.from(new Set(toArray(cliReporters))).filter(Boolean).map((reporter) => [reporter, {}]);
4221
3815
  }
4222
3816
  if (!resolved.reporters.length) {
4223
3817
  resolved.reporters.push(["default", {}]);
4224
3818
  // also enable github-actions reporter as a default
4225
- if (process.env.GITHUB_ACTIONS === "true") {
4226
- resolved.reporters.push(["github-actions", {}]);
4227
- }
4228
- }
4229
- if (resolved.changed) {
4230
- resolved.passWithNoTests ??= true;
3819
+ if (process.env.GITHUB_ACTIONS === "true") resolved.reporters.push(["github-actions", {}]);
4231
3820
  }
3821
+ if (resolved.changed) resolved.passWithNoTests ??= true;
4232
3822
  resolved.css ??= {};
4233
3823
  if (typeof resolved.css === "object") {
4234
3824
  resolved.css.modules ??= {};
4235
3825
  resolved.css.modules.classNameStrategy ??= "stable";
4236
3826
  }
4237
3827
  if (resolved.cache !== false) {
4238
- let cacheDir = VitestCache.resolveCacheDir("", viteConfig.cacheDir, resolved.name);
4239
- if (resolved.cache && resolved.cache.dir) {
4240
- logger.console.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "cache.dir" is deprecated, use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest"`));
4241
- cacheDir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir, resolved.name);
4242
- }
4243
- resolved.cache = { dir: cacheDir };
3828
+ if (resolved.cache && typeof resolved.cache.dir === "string") vitest.logger.deprecate(`"cache.dir" is deprecated, use Vite's "cacheDir" instead if you want to change the cache director. Note caches will be written to "cacheDir\/vitest"`);
3829
+ resolved.cache = { dir: viteConfig.cacheDir };
4244
3830
  }
4245
3831
  resolved.sequence ??= {};
4246
3832
  if (resolved.sequence.shuffle && typeof resolved.sequence.shuffle === "object") {
@@ -4248,37 +3834,28 @@ function resolveConfig$1(vitest, options, viteConfig) {
4248
3834
  resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer;
4249
3835
  resolved.sequence.shuffle = tests;
4250
3836
  }
4251
- if (!resolved.sequence?.sequencer) {
4252
- // CLI flag has higher priority
4253
- resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
4254
- }
3837
+ if (!resolved.sequence?.sequencer)
3838
+ // CLI flag has higher priority
3839
+ resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
4255
3840
  resolved.sequence.groupOrder ??= 0;
4256
3841
  resolved.sequence.hooks ??= "stack";
4257
- if (resolved.sequence.sequencer === RandomSequencer) {
4258
- resolved.sequence.seed ??= Date.now();
4259
- }
3842
+ if (resolved.sequence.sequencer === RandomSequencer) resolved.sequence.seed ??= Date.now();
4260
3843
  resolved.typecheck = {
4261
3844
  ...configDefaults.typecheck,
4262
3845
  ...resolved.typecheck
4263
3846
  };
4264
- if (resolved.environmentMatchGlobs) {
4265
- logger.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "environmentMatchGlobs" is deprecated. Use "workspace" to define different configurations instead.`));
4266
- }
4267
- resolved.environmentMatchGlobs = (resolved.environmentMatchGlobs || []).map((i) => [resolve(resolved.root, i[0]), i[1]]);
3847
+ if (resolved.environmentMatchGlobs) logger.warn(c.yellow(`${c.inverse(c.yellow(" Vitest "))} "environmentMatchGlobs" is deprecated. Use "workspace" to define different configurations instead.`));
3848
+ resolved.environmentMatchGlobs = (resolved.environmentMatchGlobs || []).map((i) => [resolve$1(resolved.root, i[0]), i[1]]);
4268
3849
  resolved.typecheck ??= {};
4269
3850
  resolved.typecheck.enabled ??= false;
4270
- if (resolved.typecheck.enabled) {
4271
- logger.console.warn(c.yellow("Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it."));
4272
- }
3851
+ if (resolved.typecheck.enabled) logger.console.warn(c.yellow("Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it."));
4273
3852
  resolved.browser.enabled ??= false;
4274
3853
  resolved.browser.headless ??= isCI;
4275
3854
  resolved.browser.isolate ??= true;
4276
3855
  resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark";
4277
3856
  // disable in headless mode by default, and if CI is detected
4278
3857
  resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI;
4279
- if (resolved.browser.screenshotDirectory) {
4280
- resolved.browser.screenshotDirectory = resolve(resolved.root, resolved.browser.screenshotDirectory);
4281
- }
3858
+ if (resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve$1(resolved.root, resolved.browser.screenshotDirectory);
4282
3859
  const isPreview = resolved.browser.provider === "preview";
4283
3860
  if (isPreview && resolved.browser.screenshotFailures === true) {
4284
3861
  console.warn(c.yellow([
@@ -4287,35 +3864,23 @@ function resolveConfig$1(vitest, options, viteConfig) {
4287
3864
  `Set "browser.screenshotFailures" to false or remove it from the config to suppress this warning.`
4288
3865
  ].join("")));
4289
3866
  resolved.browser.screenshotFailures = false;
4290
- } else {
4291
- resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
4292
- }
3867
+ } else resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
4293
3868
  resolved.browser.viewport ??= {};
4294
3869
  resolved.browser.viewport.width ??= 414;
4295
3870
  resolved.browser.viewport.height ??= 896;
4296
3871
  resolved.browser.locators ??= {};
4297
3872
  resolved.browser.locators.testIdAttribute ??= "data-testid";
4298
- if (resolved.browser.enabled && provider === "stackblitz") {
4299
- resolved.browser.provider = "preview";
4300
- }
3873
+ if (resolved.browser.enabled && provider === "stackblitz") resolved.browser.provider = "preview";
4301
3874
  resolved.browser.api = resolveApiServerConfig(resolved.browser, defaultBrowserPort) || { port: defaultBrowserPort };
4302
3875
  // enable includeTaskLocation by default in UI mode
4303
3876
  if (resolved.browser.enabled) {
4304
- if (resolved.browser.ui) {
4305
- resolved.includeTaskLocation ??= true;
4306
- }
4307
- } else if (resolved.ui) {
4308
- resolved.includeTaskLocation ??= true;
4309
- }
3877
+ if (resolved.browser.ui) resolved.includeTaskLocation ??= true;
3878
+ } else if (resolved.ui) resolved.includeTaskLocation ??= true;
4310
3879
  const htmlReporter = toArray(resolved.reporters).some((reporter) => {
4311
- if (Array.isArray(reporter)) {
4312
- return reporter[0] === "html";
4313
- }
3880
+ if (Array.isArray(reporter)) return reporter[0] === "html";
4314
3881
  return false;
4315
3882
  });
4316
- if (htmlReporter) {
4317
- resolved.includeTaskLocation ??= true;
4318
- }
3883
+ if (htmlReporter) resolved.includeTaskLocation ??= true;
4319
3884
  resolved.testTransformMode ??= {};
4320
3885
  resolved.testTimeout ??= resolved.browser.enabled ? 15e3 : 5e3;
4321
3886
  resolved.hookTimeout ??= resolved.browser.enabled ? 3e4 : 1e4;
@@ -4326,41 +3891,26 @@ function isBrowserEnabled(config) {
4326
3891
  }
4327
3892
  function resolveCoverageReporters(configReporters) {
4328
3893
  // E.g. { reporter: "html" }
4329
- if (!Array.isArray(configReporters)) {
4330
- return [[configReporters, {}]];
4331
- }
3894
+ if (!Array.isArray(configReporters)) return [[configReporters, {}]];
4332
3895
  const resolvedReporters = [];
4333
- for (const reporter of configReporters) {
4334
- if (Array.isArray(reporter)) {
4335
- // E.g. { reporter: [ ["html", { skipEmpty: true }], ["lcov"], ["json", { file: "map.json" }] ]}
4336
- resolvedReporters.push([reporter[0], reporter[1] || {}]);
4337
- } else {
4338
- // E.g. { reporter: ["html", "json"]}
4339
- resolvedReporters.push([reporter, {}]);
4340
- }
4341
- }
3896
+ for (const reporter of configReporters) if (Array.isArray(reporter))
3897
+ // E.g. { reporter: [ ["html", { skipEmpty: true }], ["lcov"], ["json", { file: "map.json" }] ]}
3898
+ resolvedReporters.push([reporter[0], reporter[1] || {}]);
3899
+ else
3900
+ // E.g. { reporter: ["html", "json"]}
3901
+ resolvedReporters.push([reporter, {}]);
4342
3902
  return resolvedReporters;
4343
3903
  }
4344
3904
  function isPlaywrightChromiumOnly(vitest, config) {
4345
3905
  const browser = config.browser;
4346
- if (!browser || browser.provider !== "playwright" || !browser.enabled) {
4347
- return false;
4348
- }
4349
- if (browser.name) {
4350
- return browser.name === "chromium";
4351
- }
4352
- if (!browser.instances) {
4353
- return false;
4354
- }
3906
+ if (!browser || browser.provider !== "playwright" || !browser.enabled) return false;
3907
+ if (browser.name) return browser.name === "chromium";
3908
+ if (!browser.instances) return false;
4355
3909
  for (const instance of browser.instances) {
4356
3910
  const name = instance.name || (config.name ? `${config.name} (${instance.browser})` : instance.browser);
4357
3911
  // browser config is filtered out
4358
- if (!vitest.matchesProjectFilter(name)) {
4359
- continue;
4360
- }
4361
- if (instance.browser !== "chromium") {
4362
- return false;
4363
- }
3912
+ if (!vitest.matchesProjectFilter(name)) continue;
3913
+ if (instance.browser !== "chromium") return false;
4364
3914
  }
4365
3915
  return true;
4366
3916
  }
@@ -4376,9 +3926,7 @@ const DEFAULT_PROJECT = Symbol.for("default-project");
4376
3926
  let uniqueId = 0;
4377
3927
  async function getCoverageProvider(options, loader) {
4378
3928
  const coverageModule = await resolveCoverageProviderModule(options, loader);
4379
- if (coverageModule) {
4380
- return coverageModule.getProvider();
4381
- }
3929
+ if (coverageModule) return coverageModule.getProvider();
4382
3930
  return null;
4383
3931
  }
4384
3932
  class BaseCoverageProvider {
@@ -4386,20 +3934,20 @@ class BaseCoverageProvider {
4386
3934
  name;
4387
3935
  version;
4388
3936
  options;
4389
- coverageFiles = new Map();
3937
+ coverageFiles = /* @__PURE__ */ new Map();
4390
3938
  pendingPromises = [];
4391
3939
  coverageFilesDirectory;
4392
3940
  _initialize(ctx) {
4393
3941
  this.ctx = ctx;
4394
- if (ctx.version !== this.version) {
4395
- ctx.logger.warn(c.yellow(`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.` + "\nRunning mixed versions is not supported and may lead into bugs" + "\nUpdate your dependencies and make sure the versions match."));
4396
- }
3942
+ if (ctx.version !== this.version) ctx.logger.warn(c.yellow(`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
3943
+ Running mixed versions is not supported and may lead into bugs
3944
+ Update your dependencies and make sure the versions match.`));
4397
3945
  const config = ctx.config.coverage;
4398
3946
  this.options = {
4399
3947
  ...coverageConfigDefaults,
4400
3948
  ...config,
4401
3949
  provider: this.name,
4402
- reportsDirectory: resolve(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
3950
+ reportsDirectory: resolve$1(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
4403
3951
  reporter: resolveCoverageReporters(config.reporter || coverageConfigDefaults.reporter),
4404
3952
  thresholds: config.thresholds && {
4405
3953
  ...config.thresholds,
@@ -4411,7 +3959,7 @@ class BaseCoverageProvider {
4411
3959
  };
4412
3960
  const shard = this.ctx.config.shard;
4413
3961
  const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
4414
- this.coverageFilesDirectory = resolve(this.options.reportsDirectory, tempDirectory);
3962
+ this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory);
4415
3963
  }
4416
3964
  createCoverageMap() {
4417
3965
  throw new Error("BaseReporter's createCoverageMap was not overwritten");
@@ -4426,31 +3974,23 @@ class BaseCoverageProvider {
4426
3974
  return this.options;
4427
3975
  }
4428
3976
  async clean(clean = true) {
4429
- if (clean && existsSync(this.options.reportsDirectory)) {
4430
- await promises$1.rm(this.options.reportsDirectory, {
4431
- recursive: true,
4432
- force: true,
4433
- maxRetries: 10
4434
- });
4435
- }
4436
- if (existsSync(this.coverageFilesDirectory)) {
4437
- await promises$1.rm(this.coverageFilesDirectory, {
4438
- recursive: true,
4439
- force: true,
4440
- maxRetries: 10
4441
- });
4442
- }
3977
+ if (clean && existsSync(this.options.reportsDirectory)) await promises$1.rm(this.options.reportsDirectory, {
3978
+ recursive: true,
3979
+ force: true,
3980
+ maxRetries: 10
3981
+ });
3982
+ if (existsSync(this.coverageFilesDirectory)) await promises$1.rm(this.coverageFilesDirectory, {
3983
+ recursive: true,
3984
+ force: true,
3985
+ maxRetries: 10
3986
+ });
4443
3987
  await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true });
4444
- this.coverageFiles = new Map();
3988
+ this.coverageFiles = /* @__PURE__ */ new Map();
4445
3989
  this.pendingPromises = [];
4446
3990
  }
4447
3991
  onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }) {
4448
- if (!coverage) {
4449
- return;
4450
- }
4451
- if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") {
4452
- throw new Error(`Invalid transform mode: ${transformMode}`);
4453
- }
3992
+ if (!coverage) return;
3993
+ if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") throw new Error(`Invalid transform mode: ${transformMode}`);
4454
3994
  let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
4455
3995
  if (!entry) {
4456
3996
  entry = {
@@ -4461,7 +4001,7 @@ class BaseCoverageProvider {
4461
4001
  this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
4462
4002
  }
4463
4003
  const testFilenames = testFiles.join();
4464
- const filename = resolve(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
4004
+ const filename = resolve$1(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
4465
4005
  // If there's a result from previous run, overwrite it
4466
4006
  entry[transformMode][testFilenames] = filename;
4467
4007
  const promise = promises$1.writeFile(filename, JSON.stringify(coverage), "utf-8");
@@ -4472,53 +4012,43 @@ class BaseCoverageProvider {
4472
4012
  const total = this.pendingPromises.length;
4473
4013
  await Promise.all(this.pendingPromises);
4474
4014
  this.pendingPromises = [];
4475
- for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) {
4476
- for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject)) {
4477
- const filenames = Object.values(coverageByTestfiles);
4478
- const project = this.ctx.getProjectByName(projectName);
4479
- for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
4480
- if (onDebug.enabled) {
4481
- index += chunk.length;
4482
- onDebug(`Reading coverage results ${index}/${total}`);
4483
- }
4484
- await Promise.all(chunk.map(async (filename) => {
4485
- const contents = await promises$1.readFile(filename, "utf-8");
4486
- const coverage = JSON.parse(contents);
4487
- onFileRead(coverage);
4488
- }));
4015
+ for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject)) {
4016
+ const filenames = Object.values(coverageByTestfiles);
4017
+ const project = this.ctx.getProjectByName(projectName);
4018
+ for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
4019
+ if (onDebug.enabled) {
4020
+ index += chunk.length;
4021
+ onDebug(`Reading coverage results ${index}/${total}`);
4489
4022
  }
4490
- await onFinished(project, transformMode);
4023
+ await Promise.all(chunk.map(async (filename) => {
4024
+ const contents = await promises$1.readFile(filename, "utf-8");
4025
+ const coverage = JSON.parse(contents);
4026
+ onFileRead(coverage);
4027
+ }));
4491
4028
  }
4029
+ await onFinished(project, transformMode);
4492
4030
  }
4493
4031
  }
4494
4032
  async cleanAfterRun() {
4495
- this.coverageFiles = new Map();
4033
+ this.coverageFiles = /* @__PURE__ */ new Map();
4496
4034
  await promises$1.rm(this.coverageFilesDirectory, { recursive: true });
4497
4035
  // Remove empty reports directory, e.g. when only text-reporter is used
4498
- if (readdirSync(this.options.reportsDirectory).length === 0) {
4499
- await promises$1.rm(this.options.reportsDirectory, { recursive: true });
4500
- }
4036
+ if (readdirSync(this.options.reportsDirectory).length === 0) await promises$1.rm(this.options.reportsDirectory, { recursive: true });
4501
4037
  }
4502
4038
  async onTestFailure() {
4503
- if (!this.options.reportOnFailure) {
4504
- await this.cleanAfterRun();
4505
- }
4039
+ if (!this.options.reportOnFailure) await this.cleanAfterRun();
4506
4040
  }
4507
4041
  async reportCoverage(coverageMap, { allTestsRun }) {
4508
4042
  await this.generateReports(coverageMap || this.createCoverageMap(), allTestsRun);
4509
4043
  // In watch mode we need to preserve the previous results if cleanOnRerun is disabled
4510
4044
  const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch;
4511
- if (!keepResults) {
4512
- await this.cleanAfterRun();
4513
- }
4045
+ if (!keepResults) await this.cleanAfterRun();
4514
4046
  }
4515
4047
  async reportThresholds(coverageMap, allTestsRun) {
4516
4048
  const resolvedThresholds = this.resolveThresholds(coverageMap);
4517
4049
  this.checkThresholds(resolvedThresholds);
4518
4050
  if (this.options.thresholds?.autoUpdate && allTestsRun) {
4519
- if (!this.ctx.server.config.configFile) {
4520
- throw new Error("Missing configurationFile. The \"coverage.thresholds.autoUpdate\" can only be enabled when configuration file is used.");
4521
- }
4051
+ if (!this.ctx.server.config.configFile) throw new Error("Missing configurationFile. The \"coverage.thresholds.autoUpdate\" can only be enabled when configuration file is used.");
4522
4052
  const configFilePath = this.ctx.server.config.configFile;
4523
4053
  const configModule = await this.parseConfigModule(configFilePath);
4524
4054
  await this.updateThresholds({
@@ -4538,9 +4068,7 @@ class BaseCoverageProvider {
4538
4068
  const files = coverageMap.files();
4539
4069
  const globalCoverageMap = this.createCoverageMap();
4540
4070
  for (const key of Object.keys(this.options.thresholds)) {
4541
- if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) {
4542
- continue;
4543
- }
4071
+ if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) continue;
4544
4072
  const glob = key;
4545
4073
  const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]);
4546
4074
  const globCoverageMap = this.createCoverageMap();
@@ -4578,9 +4106,7 @@ class BaseCoverageProvider {
4578
4106
  */
4579
4107
  checkThresholds(allThresholds) {
4580
4108
  for (const { coverageMap, thresholds, name } of allThresholds) {
4581
- if (thresholds.branches === undefined && thresholds.functions === undefined && thresholds.lines === undefined && thresholds.statements === undefined) {
4582
- continue;
4583
- }
4109
+ if (thresholds.branches === void 0 && thresholds.functions === void 0 && thresholds.lines === void 0 && thresholds.statements === void 0) continue;
4584
4110
  // Construct list of coverage summaries where thresholds are compared against
4585
4111
  const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => ({
4586
4112
  file,
@@ -4590,47 +4116,39 @@ class BaseCoverageProvider {
4590
4116
  summary: coverageMap.getCoverageSummary()
4591
4117
  }];
4592
4118
  // Check thresholds of each summary
4593
- for (const { summary, file } of summaries) {
4594
- for (const thresholdKey of THRESHOLD_KEYS) {
4595
- const threshold = thresholds[thresholdKey];
4596
- if (threshold === undefined) {
4597
- continue;
4119
+ for (const { summary, file } of summaries) for (const thresholdKey of THRESHOLD_KEYS) {
4120
+ const threshold = thresholds[thresholdKey];
4121
+ if (threshold === void 0) continue;
4122
+ /**
4123
+ * Positive thresholds are treated as minimum coverage percentages (X means: X% of lines must be covered),
4124
+ * while negative thresholds are treated as maximum uncovered counts (-X means: X lines may be uncovered).
4125
+ */
4126
+ if (threshold >= 0) {
4127
+ const coverage = summary.data[thresholdKey].pct;
4128
+ if (coverage < threshold) {
4129
+ process.exitCode = 1;
4130
+ /**
4131
+ * Generate error message based on perFile flag:
4132
+ * - ERROR: Coverage for statements (33.33%) does not meet threshold (85%) for src/math.ts
4133
+ * - ERROR: Coverage for statements (50%) does not meet global threshold (85%)
4134
+ */
4135
+ let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`;
4136
+ if (this.options.thresholds?.perFile && file) errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
4137
+ this.ctx.logger.error(errorMessage);
4598
4138
  }
4599
- /**
4600
- * Positive thresholds are treated as minimum coverage percentages (X means: X% of lines must be covered),
4601
- * while negative thresholds are treated as maximum uncovered counts (-X means: X lines may be uncovered).
4602
- */
4603
- if (threshold >= 0) {
4604
- const coverage = summary.data[thresholdKey].pct;
4605
- if (coverage < threshold) {
4606
- process.exitCode = 1;
4607
- /**
4608
- * Generate error message based on perFile flag:
4609
- * - ERROR: Coverage for statements (33.33%) does not meet threshold (85%) for src/math.ts
4610
- * - ERROR: Coverage for statements (50%) does not meet global threshold (85%)
4611
- */
4612
- let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`;
4613
- if (this.options.thresholds?.perFile && file) {
4614
- errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
4615
- }
4616
- this.ctx.logger.error(errorMessage);
4617
- }
4618
- } else {
4619
- const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered;
4620
- const absoluteThreshold = threshold * -1;
4621
- if (uncovered > absoluteThreshold) {
4622
- process.exitCode = 1;
4623
- /**
4624
- * Generate error message based on perFile flag:
4625
- * - ERROR: Uncovered statements (33) exceed threshold (30) for src/math.ts
4626
- * - ERROR: Uncovered statements (33) exceed global threshold (30)
4627
- */
4628
- let errorMessage = `ERROR: Uncovered ${thresholdKey} (${uncovered}) exceed ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${absoluteThreshold})`;
4629
- if (this.options.thresholds?.perFile && file) {
4630
- errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
4631
- }
4632
- this.ctx.logger.error(errorMessage);
4633
- }
4139
+ } else {
4140
+ const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered;
4141
+ const absoluteThreshold = threshold * -1;
4142
+ if (uncovered > absoluteThreshold) {
4143
+ process.exitCode = 1;
4144
+ /**
4145
+ * Generate error message based on perFile flag:
4146
+ * - ERROR: Uncovered statements (33) exceed threshold (30) for src/math.ts
4147
+ * - ERROR: Uncovered statements (33) exceed global threshold (30)
4148
+ */
4149
+ let errorMessage = `ERROR: Uncovered ${thresholdKey} (${uncovered}) exceed ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${absoluteThreshold})`;
4150
+ if (this.options.thresholds?.perFile && file) errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
4151
+ this.ctx.logger.error(errorMessage);
4634
4152
  }
4635
4153
  }
4636
4154
  }
@@ -4654,9 +4172,7 @@ class BaseCoverageProvider {
4654
4172
  */
4655
4173
  if (threshold >= 0) {
4656
4174
  const actual = Math.min(...summaries.map((summary) => summary[key].pct));
4657
- if (actual > threshold) {
4658
- thresholdsToUpdate.push([key, actual]);
4659
- }
4175
+ if (actual > threshold) thresholdsToUpdate.push([key, actual]);
4660
4176
  } else {
4661
4177
  const absoluteThreshold = threshold * -1;
4662
4178
  const actual = Math.max(...summaries.map((summary) => summary[key].total - summary[key].covered));
@@ -4667,17 +4183,12 @@ class BaseCoverageProvider {
4667
4183
  }
4668
4184
  }
4669
4185
  }
4670
- if (thresholdsToUpdate.length === 0) {
4671
- continue;
4672
- }
4186
+ if (thresholdsToUpdate.length === 0) continue;
4673
4187
  updatedThresholds = true;
4674
- for (const [threshold, newValue] of thresholdsToUpdate) {
4675
- if (name === GLOBAL_THRESHOLDS_KEY) {
4676
- config.test.coverage.thresholds[threshold] = newValue;
4677
- } else {
4678
- const glob = config.test.coverage.thresholds[name];
4679
- glob[threshold] = newValue;
4680
- }
4188
+ for (const [threshold, newValue] of thresholdsToUpdate) if (name === GLOBAL_THRESHOLDS_KEY) config.test.coverage.thresholds[threshold] = newValue;
4189
+ else {
4190
+ const glob = config.test.coverage.thresholds[name];
4191
+ glob[threshold] = newValue;
4681
4192
  }
4682
4193
  }
4683
4194
  if (updatedThresholds) {
@@ -4687,9 +4198,7 @@ class BaseCoverageProvider {
4687
4198
  }
4688
4199
  async mergeReports(coverageMaps) {
4689
4200
  const coverageMap = this.createCoverageMap();
4690
- for (const coverage of coverageMaps) {
4691
- coverageMap.merge(coverage);
4692
- }
4201
+ for (const coverage of coverageMaps) coverageMap.merge(coverage);
4693
4202
  await this.generateReports(coverageMap, true);
4694
4203
  }
4695
4204
  hasTerminalReporter(reporters) {
@@ -4700,11 +4209,8 @@ class BaseCoverageProvider {
4700
4209
  const index = Math.max(0, chunks.length - 1);
4701
4210
  const lastChunk = chunks[index] || [];
4702
4211
  chunks[index] = lastChunk;
4703
- if (lastChunk.length >= size) {
4704
- chunks.push([item]);
4705
- } else {
4706
- lastChunk.push(item);
4707
- }
4212
+ if (lastChunk.length >= size) chunks.push([item]);
4213
+ else lastChunk.push(item);
4708
4214
  return chunks;
4709
4215
  }, []);
4710
4216
  }
@@ -4722,14 +4228,10 @@ class BaseCoverageProvider {
4722
4228
  let lastError;
4723
4229
  for (const { root, vitenode, isBrowserEnabled } of servers) {
4724
4230
  // On Windows root doesn't start with "/" while filenames do
4725
- if (!filename.startsWith(root) && !filename.startsWith(`/${root}`)) {
4726
- continue;
4727
- }
4231
+ if (!filename.startsWith(root) && !filename.startsWith(`/${root}`)) continue;
4728
4232
  if (isBrowserEnabled) {
4729
- const result = await vitenode.transformRequest(filename, undefined, "web").catch(() => null);
4730
- if (result) {
4731
- return result;
4732
- }
4233
+ const result = await vitenode.transformRequest(filename, void 0, "web").catch(() => null);
4234
+ if (result) return result;
4733
4235
  }
4734
4236
  try {
4735
4237
  return await vitenode.transformRequest(filename);
@@ -4746,30 +4248,24 @@ class BaseCoverageProvider {
4746
4248
  * Narrow down `unknown` glob thresholds to resolved ones
4747
4249
  */
4748
4250
  function resolveGlobThresholds(thresholds) {
4749
- if (!thresholds || typeof thresholds !== "object") {
4750
- return {};
4751
- }
4752
- if (100 in thresholds && thresholds[100] === true) {
4753
- return {
4754
- lines: 100,
4755
- branches: 100,
4756
- functions: 100,
4757
- statements: 100
4758
- };
4759
- }
4251
+ if (!thresholds || typeof thresholds !== "object") return {};
4252
+ if (100 in thresholds && thresholds[100] === true) return {
4253
+ lines: 100,
4254
+ branches: 100,
4255
+ functions: 100,
4256
+ statements: 100
4257
+ };
4760
4258
  return {
4761
- lines: "lines" in thresholds && typeof thresholds.lines === "number" ? thresholds.lines : undefined,
4762
- branches: "branches" in thresholds && typeof thresholds.branches === "number" ? thresholds.branches : undefined,
4763
- functions: "functions" in thresholds && typeof thresholds.functions === "number" ? thresholds.functions : undefined,
4764
- statements: "statements" in thresholds && typeof thresholds.statements === "number" ? thresholds.statements : undefined
4259
+ lines: "lines" in thresholds && typeof thresholds.lines === "number" ? thresholds.lines : void 0,
4260
+ branches: "branches" in thresholds && typeof thresholds.branches === "number" ? thresholds.branches : void 0,
4261
+ functions: "functions" in thresholds && typeof thresholds.functions === "number" ? thresholds.functions : void 0,
4262
+ statements: "statements" in thresholds && typeof thresholds.statements === "number" ? thresholds.statements : void 0
4765
4263
  };
4766
4264
  }
4767
4265
  function assertConfigurationModule(config) {
4768
4266
  try {
4769
4267
  // @ts-expect-error -- Intentional unsafe null pointer check as wrapped in try-catch
4770
- if (typeof config.test.coverage.thresholds !== "object") {
4771
- throw new TypeError("Expected config.test.coverage.thresholds to be an object");
4772
- }
4268
+ if (typeof config.test.coverage.thresholds !== "object") throw new TypeError("Expected config.test.coverage.thresholds to be an object");
4773
4269
  } catch (error) {
4774
4270
  const message = error instanceof Error ? error.message : String(error);
4775
4271
  throw new Error(`Unable to parse thresholds from configuration file: ${message}`);
@@ -4779,20 +4275,14 @@ function resolveConfig(configModule) {
4779
4275
  const mod = configModule.exports.default;
4780
4276
  try {
4781
4277
  // Check for "export default { test: {...} }"
4782
- if (mod.$type === "object") {
4783
- return mod;
4784
- }
4278
+ if (mod.$type === "object") return mod;
4785
4279
  // "export default defineConfig(...)"
4786
4280
  let config = resolveDefineConfig(mod);
4787
- if (config) {
4788
- return config;
4789
- }
4281
+ if (config) return config;
4790
4282
  // "export default mergeConfig(..., defineConfig(...))"
4791
4283
  if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
4792
4284
  config = resolveMergeConfig(mod);
4793
- if (config) {
4794
- return config;
4795
- }
4285
+ if (config) return config;
4796
4286
  }
4797
4287
  } catch (error) {
4798
4288
  // Reduce magicast's verbose errors to readable ones
@@ -4803,31 +4293,22 @@ function resolveConfig(configModule) {
4803
4293
  function resolveDefineConfig(mod) {
4804
4294
  if (mod.$type === "function-call" && mod.$callee === "defineConfig") {
4805
4295
  // "export default defineConfig({ test: {...} })"
4806
- if (mod.$args[0].$type === "object") {
4807
- return mod.$args[0];
4808
- }
4296
+ if (mod.$args[0].$type === "object") return mod.$args[0];
4809
4297
  if (mod.$args[0].$type === "arrow-function-expression") {
4810
- if (mod.$args[0].$body.$type === "object") {
4811
- // "export default defineConfig(() => ({ test: {...} }))"
4812
- return mod.$args[0].$body;
4813
- }
4298
+ if (mod.$args[0].$body.$type === "object")
4299
+ // "export default defineConfig(() => ({ test: {...} }))"
4300
+ return mod.$args[0].$body;
4814
4301
  // "export default defineConfig(() => mergeConfig({...}, ...))"
4815
4302
  const config = resolveMergeConfig(mod.$args[0].$body);
4816
- if (config) {
4817
- return config;
4818
- }
4303
+ if (config) return config;
4819
4304
  }
4820
4305
  }
4821
4306
  }
4822
4307
  function resolveMergeConfig(mod) {
4823
- if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
4824
- for (const arg of mod.$args) {
4825
- const config = resolveDefineConfig(arg);
4826
- if (config) {
4827
- return config;
4828
- }
4829
- }
4308
+ if (mod.$type === "function-call" && mod.$callee === "mergeConfig") for (const arg of mod.$args) {
4309
+ const config = resolveDefineConfig(arg);
4310
+ if (config) return config;
4830
4311
  }
4831
4312
  }
4832
4313
 
4833
- export { BaseCoverageProvider as B, RandomSequencer as R, VitestCache as V, resolveApiServerConfig as a, BaseSequencer as b, createMethodsRPC as c, isBrowserEnabled as d, groupBy as e, getCoverageProvider as f, getFilePoolName as g, hash as h, isPackageExists as i, createPool as j, resolveConfig$1 as r, stdout as s, wildcardPatternToRegExp as w };
4314
+ export { BaseCoverageProvider as B, RandomSequencer as R, resolveApiServerConfig as a, BaseSequencer as b, createMethodsRPC as c, isBrowserEnabled as d, groupBy as e, getCoverageProvider as f, getFilePoolName as g, hash as h, isPackageExists as i, createPool as j, resolveConfig$1 as r, stdout as s, wildcardPatternToRegExp as w };