vitest 4.0.0-beta.5 → 4.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +2 -2
  4. package/dist/chunks/{base.DMfOuRWD.js → base.BXI97p6t.js} +7 -16
  5. package/dist/chunks/{benchmark.CtuRzf-i.js → benchmark.UW6Ezvxy.js} +4 -9
  6. package/dist/chunks/{cac.CKnbxhn2.js → cac.WE-urWw5.js} +37 -113
  7. package/dist/chunks/{cli-api.COn58yrl.js → cli-api.CZz3evYC.js} +505 -1211
  8. package/dist/chunks/{console.Duv2dVIC.js → console.B0quX7yH.js} +32 -68
  9. package/dist/chunks/{coverage.B6cReEn1.js → coverage.BPRS6xgn.js} +210 -579
  10. package/dist/chunks/{creator.DUVZ6rfm.js → creator.KEg6n5IC.js} +28 -74
  11. package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
  12. package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
  13. package/dist/chunks/{globals.CJQ63oO0.js → globals.lgsmH00r.js} +5 -5
  14. package/dist/chunks/{index.DgN0Zk9a.js → index.7w0eqmYM.js} +14 -24
  15. package/dist/chunks/{index.QZr3S3vQ.js → index.AR8aAkCC.js} +2 -2
  16. package/dist/chunks/{index.BRtIe7r8.js → index.BG0gqZH-.js} +39 -102
  17. package/dist/chunks/{index.oWRWx-nj.js → index.CsFXYRkW.js} +17 -36
  18. package/dist/chunks/{index.DQhAfQQU.js → index.VNI-1z5c.js} +270 -606
  19. package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
  20. package/dist/chunks/{moduleRunner.d.mmOmOGrW.d.ts → moduleRunner.d.8kKUsuDg.d.ts} +1 -1
  21. package/dist/chunks/{node.4JV5OXkt.js → node.BOqcT2jW.js} +1 -1
  22. package/dist/chunks/{plugin.d.CvOlgjxK.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
  23. package/dist/chunks/{reporters.d.CYE9sT5z.d.ts → reporters.d.CqR9-CDJ.d.ts} +16 -33
  24. package/dist/chunks/{resolver.D5bG4zy5.js → resolver.Bx6lE0iq.js} +21 -64
  25. package/dist/chunks/{rpc.DGoW_Vl-.js → rpc.RpPylpp0.js} +7 -21
  26. package/dist/chunks/{runBaseTests.B3KcKqlF.js → runBaseTests.D6sfuWBM.js} +25 -54
  27. package/dist/chunks/{setup-common.lgPs-bYv.js → setup-common.hLGRxhC8.js} +9 -22
  28. package/dist/chunks/{startModuleRunner.C8FtT_BY.js → startModuleRunner.C8TW8zTN.js} +83 -205
  29. package/dist/chunks/{typechecker.BgoW4nTA.js → typechecker.Cd1wvxUM.js} +96 -208
  30. package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
  31. package/dist/chunks/{utils.B9FY3b73.js → utils.C7__0Iv5.js} +5 -14
  32. package/dist/chunks/{vi.DGAfBY4R.js → vi.BfdOiD4j.js} +110 -267
  33. package/dist/chunks/{vm.BKfKvaKl.js → vm.BHBje7cC.js} +73 -177
  34. package/dist/cli.js +3 -3
  35. package/dist/config.d.ts +4 -4
  36. package/dist/coverage.d.ts +1 -1
  37. package/dist/coverage.js +2 -2
  38. package/dist/environments.js +1 -1
  39. package/dist/index.js +5 -5
  40. package/dist/module-evaluator.d.ts +1 -1
  41. package/dist/module-evaluator.js +33 -84
  42. package/dist/module-runner.js +2 -2
  43. package/dist/node.d.ts +3 -3
  44. package/dist/node.js +13 -19
  45. package/dist/reporters.d.ts +2 -2
  46. package/dist/reporters.js +3 -3
  47. package/dist/runners.js +23 -51
  48. package/dist/snapshot.js +2 -2
  49. package/dist/suite.js +2 -2
  50. package/dist/worker.js +18 -34
  51. package/dist/workers/forks.js +4 -4
  52. package/dist/workers/runVmTests.js +19 -37
  53. package/dist/workers/threads.js +4 -4
  54. package/dist/workers/vmForks.js +7 -7
  55. package/dist/workers/vmThreads.js +7 -7
  56. package/dist/workers.js +11 -11
  57. package/package.json +11 -11
@@ -23,7 +23,7 @@ import { isatty } from 'node:tty';
23
23
  import EventEmitter from 'node:events';
24
24
  import { c as createBirpc } from './index.Bgo3tNWt.js';
25
25
  import Tinypool$1, { Tinypool } from 'tinypool';
26
- import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.BgoW4nTA.js';
26
+ import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.Cd1wvxUM.js';
27
27
  import { MessageChannel } from 'node:worker_threads';
28
28
  import { hasFailed } from '@vitest/runner/utils';
29
29
  import { rootDir } from '../path.js';
@@ -33,9 +33,7 @@ import { r as resolveCoverageProviderModule } from './coverage.D_JHT54q.js';
33
33
  function groupBy(collection, iteratee) {
34
34
  return collection.reduce((acc, item) => {
35
35
  const key = iteratee(item);
36
- acc[key] ||= [];
37
- acc[key].push(item);
38
- return acc;
36
+ return acc[key] ||= [], acc[key].push(item), acc;
39
37
  }, {});
40
38
  }
41
39
  function stdout() {
@@ -2384,8 +2382,7 @@ const isPackageListed = quansync(function* (name, cwd) {
2384
2382
  isPackageListed.sync;
2385
2383
 
2386
2384
  function getWorkersCountByPercentage(percent) {
2387
- const maxWorkersCount = nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length;
2388
- const workersCountByPercentage = Math.round(Number.parseInt(percent) / 100 * maxWorkersCount);
2385
+ const maxWorkersCount = nodeos__default.availableParallelism?.() ?? nodeos__default.cpus().length, workersCountByPercentage = Math.round(Number.parseInt(percent) / 100 * maxWorkersCount);
2389
2386
  return Math.max(1, Math.min(maxWorkersCount, workersCountByPercentage));
2390
2387
  }
2391
2388
 
@@ -2406,9 +2403,7 @@ async function groupFilesByEnv(files) {
2406
2403
  if (envOptionsJson?.endsWith("*/"))
2407
2404
  // Trim closing Docblock characters the above regex might have captured
2408
2405
  envOptionsJson = envOptionsJson.slice(0, -2);
2409
- const envOptions = JSON.parse(envOptionsJson || "null");
2410
- const envKey = env === "happy-dom" ? "happyDOM" : env;
2411
- const environment = {
2406
+ const envOptions = JSON.parse(envOptionsJson || "null"), envKey = env === "happy-dom" ? "happyDOM" : env, environment = {
2412
2407
  name: env,
2413
2408
  options: envOptions ? { [envKey]: envOptions } : null
2414
2409
  };
@@ -2424,8 +2419,7 @@ async function groupFilesByEnv(files) {
2424
2419
  return groupBy(filesWithEnv, ({ environment }) => environment.name);
2425
2420
  }
2426
2421
 
2427
- const created = /* @__PURE__ */ new Set();
2428
- const promises = /* @__PURE__ */ new Map();
2422
+ const created = /* @__PURE__ */ new Set(), promises = /* @__PURE__ */ new Map();
2429
2423
  function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tmpdir(), nanoid())) {
2430
2424
  const cachedFsResults = /* @__PURE__ */ new Map();
2431
2425
  return async (url, importer, environment, options) => {
@@ -2451,8 +2445,7 @@ function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tm
2451
2445
  // so we do this first to resolve the module and check its `id`. The next call of
2452
2446
  // `ensureEntryFromUrl` inside `fetchModule` is cached and should take no time
2453
2447
  // This also makes it so externalized modules are inside the module graph.
2454
- const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url));
2455
- const cached = !!moduleGraphModule.transformResult;
2448
+ const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url)), cached = !!moduleGraphModule.transformResult;
2456
2449
  // if url is already cached, we can just confirm it's also cached on the server
2457
2450
  if (options?.cached && cached) return { cache: true };
2458
2451
  if (moduleGraphModule.id) {
@@ -2465,29 +2458,15 @@ function createFetchModuleFunction(resolver, cacheFs = false, tmpDir = join$1(tm
2465
2458
  const moduleRunnerModule = await fetchModule(environment, url, importer, {
2466
2459
  ...options,
2467
2460
  inlineSourceMap: false
2468
- }).catch(handleRollupError);
2469
- const result = processResultSource(environment, moduleRunnerModule);
2461
+ }).catch(handleRollupError), result = processResultSource(environment, moduleRunnerModule);
2470
2462
  if (!cacheFs || !("code" in result)) return result;
2471
2463
  const code = result.code;
2472
2464
  // to avoid serialising large chunks of code,
2473
2465
  // we store them in a tmp file and read in the test thread
2474
2466
  if (cachedFsResults.has(result.id)) return getCachedResult(result, cachedFsResults);
2475
- const dir = join$1(tmpDir, environment.name);
2476
- const name = hash("sha1", result.id, "hex");
2477
- const tmp = join$1(dir, name);
2478
- if (!created.has(dir)) {
2479
- mkdirSync(dir, { recursive: true });
2480
- created.add(dir);
2481
- }
2482
- if (promises.has(tmp)) {
2483
- await promises.get(tmp);
2484
- cachedFsResults.set(result.id, tmp);
2485
- return getCachedResult(result, cachedFsResults);
2486
- }
2487
- promises.set(tmp, atomicWriteFile(tmp, code).catch(() => writeFile(tmp, code, "utf-8")).finally(() => promises.delete(tmp)));
2488
- await promises.get(tmp);
2489
- cachedFsResults.set(result.id, tmp);
2490
- return getCachedResult(result, cachedFsResults);
2467
+ const dir = join$1(tmpDir, environment.name), name = hash("sha1", result.id, "hex"), tmp = join$1(dir, name);
2468
+ if (!created.has(dir)) mkdirSync(dir, { recursive: true }), created.add(dir);
2469
+ return promises.has(tmp) ? (await promises.get(tmp), cachedFsResults.set(result.id, tmp), getCachedResult(result, cachedFsResults)) : (promises.set(tmp, atomicWriteFile(tmp, code).catch(() => writeFile(tmp, code, "utf-8")).finally(() => promises.delete(tmp))), await promises.get(tmp), cachedFsResults.set(result.id, tmp), getCachedResult(result, cachedFsResults));
2491
2470
  };
2492
2471
  }
2493
2472
  let SOURCEMAPPING_URL = "sourceMa";
@@ -2514,15 +2493,12 @@ function inlineSourceMap(result) {
2514
2493
  const map = result.map;
2515
2494
  let code = result.code;
2516
2495
  if (!map || !("version" in map) || code.includes(MODULE_RUNNER_SOURCEMAPPING_SOURCE)) return result;
2517
- // to reduce the payload size, we only inline vite node source map, because it's also the only one we use
2518
- OTHER_SOURCE_MAP_REGEXP.lastIndex = 0;
2519
- if (OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
2496
+ if (OTHER_SOURCE_MAP_REGEXP.lastIndex = 0, OTHER_SOURCE_MAP_REGEXP.test(code)) code = code.replace(OTHER_SOURCE_MAP_REGEXP, "");
2520
2497
  const sourceMap = { ...map };
2521
2498
  // If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])
2522
2499
  // so that debuggers can be set to break on first line
2523
2500
  if (sourceMap.mappings.startsWith(";")) sourceMap.mappings = `AAAA,CAAA${sourceMap.mappings}`;
2524
- result.code = `${code.trimEnd()}\n${MODULE_RUNNER_SOURCEMAPPING_SOURCE}\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\n`;
2525
- return result;
2501
+ return result.code = `${code.trimEnd()}\n${MODULE_RUNNER_SOURCEMAPPING_SOURCE}\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\n`, result;
2526
2502
  }
2527
2503
  function genSourceMapUrl(map) {
2528
2504
  if (typeof map !== "string") map = JSON.stringify(map);
@@ -2542,9 +2518,7 @@ function getCachedResult(result, cachedFsResults) {
2542
2518
  }
2543
2519
  // serialize rollup error on server to preserve details as a test error
2544
2520
  function handleRollupError(e) {
2545
- if (e instanceof Error && ("plugin" in e || "frame" in e || "id" in e))
2546
- // eslint-disable-next-line no-throw-literal
2547
- throw {
2521
+ throw e instanceof Error && ("plugin" in e || "frame" in e || "id" in e) ? {
2548
2522
  name: e.name,
2549
2523
  message: e.message,
2550
2524
  stack: e.stack,
@@ -2555,8 +2529,7 @@ function handleRollupError(e) {
2555
2529
  loc: e.loc,
2556
2530
  frame: e.frame
2557
2531
  }
2558
- };
2559
- throw e;
2532
+ } : e;
2560
2533
  }
2561
2534
  /**
2562
2535
  * Performs an atomic write operation using the write-then-rename pattern.
@@ -2573,11 +2546,9 @@ function handleRollupError(e) {
2573
2546
  * Added in https://github.com/vitest-dev/vitest/pull/7531
2574
2547
  */
2575
2548
  async function atomicWriteFile(realFilePath, data) {
2576
- const dir = dirname$1(realFilePath);
2577
- const tmpFilePath = join$1(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2549
+ const dir = dirname$1(realFilePath), tmpFilePath = join$1(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2578
2550
  try {
2579
- await writeFile(tmpFilePath, data, "utf-8");
2580
- await rename(tmpFilePath, realFilePath);
2551
+ await writeFile(tmpFilePath, data, "utf-8"), await rename(tmpFilePath, realFilePath);
2581
2552
  } finally {
2582
2553
  try {
2583
2554
  if (await stat(tmpFilePath)) await unlink(tmpFilePath);
@@ -2587,8 +2558,7 @@ async function atomicWriteFile(realFilePath, data) {
2587
2558
 
2588
2559
  // this is copy pasted from vite
2589
2560
  function normalizeResolvedIdToUrl(environment, resolvedId) {
2590
- const root = environment.config.root;
2591
- const depsOptimizer = environment.depsOptimizer;
2561
+ const root = environment.config.root, depsOptimizer = environment.depsOptimizer;
2592
2562
  let url;
2593
2563
  // normalize all imports into resolved URLs
2594
2564
  // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`
@@ -2608,9 +2578,7 @@ function normalizeResolvedIdToUrl(environment, resolvedId) {
2608
2578
  }
2609
2579
 
2610
2580
  function createMethodsRPC(project, options = {}) {
2611
- const ctx = project.vitest;
2612
- const cacheFs = options.cacheFs ?? false;
2613
- const fetch = createFetchModuleFunction(project._resolver, cacheFs, project.tmpDir);
2581
+ const ctx = project.vitest, cacheFs = options.cacheFs ?? false, fetch = createFetchModuleFunction(project._resolver, cacheFs, project.tmpDir);
2614
2582
  return {
2615
2583
  async fetch(url, importer, environmentName, options) {
2616
2584
  const environment = project.vite.environments[environmentName];
@@ -2626,12 +2594,11 @@ function createMethodsRPC(project, options = {}) {
2626
2594
  const environment = project.vite.environments[environmentName];
2627
2595
  if (!environment) throw new Error(`The environment ${environmentName} was not defined in the Vite config.`);
2628
2596
  const resolved = await environment.pluginContainer.resolveId(id, importer);
2629
- if (!resolved) return null;
2630
- return {
2597
+ return resolved ? {
2631
2598
  file: cleanUrl(resolved.id),
2632
2599
  url: normalizeResolvedIdToUrl(environment, resolved.id),
2633
2600
  id: resolved.id
2634
- };
2601
+ } : null;
2635
2602
  },
2636
2603
  snapshotSaved(snapshot) {
2637
2604
  ctx.snapshot.add(snapshot);
@@ -2642,8 +2609,7 @@ function createMethodsRPC(project, options = {}) {
2642
2609
  async transform(id) {
2643
2610
  const environment = project.vite.environments.__vitest_vm__;
2644
2611
  if (!environment) throw new Error(`The VM environment was not defined in the Vite config. This is a bug in Vitest. Please, open a new issue with reproduction.`);
2645
- const url = normalizeResolvedIdToUrl(environment, fileURLToPath$1(id));
2646
- const result = await environment.transformRequest(url).catch(handleRollupError);
2612
+ const url = normalizeResolvedIdToUrl(environment, fileURLToPath$1(id)), result = await environment.transformRequest(url).catch(handleRollupError);
2647
2613
  return { code: result?.code };
2648
2614
  },
2649
2615
  async onQueued(file) {
@@ -2681,12 +2647,10 @@ function createMethodsRPC(project, options = {}) {
2681
2647
  }
2682
2648
 
2683
2649
  function createChildProcessChannel$1(project, collect = false) {
2684
- const emitter = new EventEmitter();
2685
- const events = {
2650
+ const emitter = new EventEmitter(), events = {
2686
2651
  message: "message",
2687
2652
  response: "response"
2688
- };
2689
- const rpc = createBirpc(createMethodsRPC(project, {
2653
+ }, rpc = createBirpc(createMethodsRPC(project, {
2690
2654
  cacheFs: true,
2691
2655
  collect
2692
2656
  }), {
@@ -2716,20 +2680,13 @@ function createChildProcessChannel$1(project, collect = false) {
2716
2680
  onMessage: (callback) => emitter.on(events.message, callback),
2717
2681
  postMessage: (message) => emitter.emit(events.response, message),
2718
2682
  onClose: () => {
2719
- emitter.removeAllListeners();
2720
- rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
2683
+ emitter.removeAllListeners(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
2721
2684
  }
2722
2685
  };
2723
2686
  return channel;
2724
2687
  }
2725
2688
  function createForksPool(vitest, { execArgv, env }) {
2726
- const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
2727
- const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2728
- const poolOptions = vitest.config.poolOptions?.forks ?? {};
2729
- const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
2730
- const minThreads = poolOptions.minForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
2731
- const worker = resolve(vitest.distPath, "workers/forks.js");
2732
- const options = {
2689
+ const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.forks ?? {}, maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/forks.js"), options = {
2733
2690
  runtime: "child_process",
2734
2691
  filename: resolve(vitest.distPath, "worker.js"),
2735
2692
  teardown: "teardown",
@@ -2739,22 +2696,15 @@ function createForksPool(vitest, { execArgv, env }) {
2739
2696
  execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
2740
2697
  terminateTimeout: vitest.config.teardownTimeout,
2741
2698
  concurrentTasksPerWorker: 1
2742
- };
2743
- const isolated = poolOptions.isolate ?? true;
2699
+ }, isolated = poolOptions.isolate ?? true;
2744
2700
  if (isolated) options.isolateWorkers = true;
2745
- if (poolOptions.singleFork || !vitest.config.fileParallelism) {
2746
- options.maxThreads = 1;
2747
- options.minThreads = 1;
2748
- }
2749
- const pool = new Tinypool(options);
2750
- const runWithFiles = (name) => {
2701
+ if (poolOptions.singleFork || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
2702
+ const pool = new Tinypool(options), runWithFiles = (name) => {
2751
2703
  let id = 0;
2752
2704
  async function runFiles(project, config, files, environment, invalidates = []) {
2753
2705
  const paths = files.map((f) => f.filepath);
2754
2706
  vitest.state.clearFiles(project, paths);
2755
- const channel = createChildProcessChannel$1(project, name === "collect");
2756
- const workerId = ++id;
2757
- const data = {
2707
+ const channel = createChildProcessChannel$1(project, name === "collect"), workerId = ++id, data = {
2758
2708
  pool: "forks",
2759
2709
  worker,
2760
2710
  config,
@@ -2780,40 +2730,25 @@ function createForksPool(vitest, { execArgv, env }) {
2780
2730
  return async (specs, invalidates) => {
2781
2731
  // Cancel pending tasks from pool when possible
2782
2732
  vitest.onCancel(() => pool.cancelPendingTasks());
2783
- const configs = /* @__PURE__ */ new WeakMap();
2784
- const getConfig = (project) => {
2733
+ const configs = /* @__PURE__ */ new WeakMap(), getConfig = (project) => {
2785
2734
  if (configs.has(project)) return configs.get(project);
2786
- const _config = project.getSerializableConfig();
2787
- const config = wrapSerializableConfig(_config);
2788
- configs.set(project, config);
2789
- return config;
2790
- };
2791
- const singleFork = specs.filter((spec) => spec.project.config.poolOptions?.forks?.singleFork);
2792
- const multipleForks = specs.filter((spec) => !spec.project.config.poolOptions?.forks?.singleFork);
2735
+ const _config = project.getSerializableConfig(), config = wrapSerializableConfig(_config);
2736
+ return configs.set(project, config), config;
2737
+ }, singleFork = specs.filter((spec) => spec.project.config.poolOptions?.forks?.singleFork), multipleForks = specs.filter((spec) => !spec.project.config.poolOptions?.forks?.singleFork);
2793
2738
  if (multipleForks.length) {
2794
- const filesByEnv = await groupFilesByEnv(multipleForks);
2795
- const files = Object.values(filesByEnv).flat();
2796
- const results = [];
2739
+ const filesByEnv = await groupFilesByEnv(multipleForks), files = Object.values(filesByEnv).flat(), results = [];
2797
2740
  if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2798
2741
  else {
2799
2742
  // When isolation is disabled, we still need to isolate environments and workspace projects from each other.
2800
2743
  // Tasks are still running parallel but environments are isolated between tasks.
2801
2744
  const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
2802
- for (const group of Object.values(grouped)) {
2803
- // Push all files to pool's queue
2804
- results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2805
- // Once all tasks are running or finished, recycle worker for isolation.
2806
- // On-going workers will run in the previous environment.
2807
- await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve));
2808
- await pool.recycleWorkers();
2809
- }
2745
+ for (const group of Object.values(grouped)) results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)))), await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve)), await pool.recycleWorkers();
2810
2746
  }
2811
2747
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
2812
2748
  if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
2813
2749
  }
2814
2750
  if (singleFork.length) {
2815
- const filesByEnv = await groupFilesByEnv(singleFork);
2816
- const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
2751
+ const filesByEnv = await groupFilesByEnv(singleFork), envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
2817
2752
  for (const env of envs) {
2818
2753
  const files = filesByEnv[env];
2819
2754
  if (!files?.length) continue;
@@ -2837,10 +2772,7 @@ function createForksPool(vitest, { execArgv, env }) {
2837
2772
  }
2838
2773
 
2839
2774
  function createWorkerChannel$1(project, collect) {
2840
- const channel = new MessageChannel();
2841
- const port = channel.port2;
2842
- const workerPort = channel.port1;
2843
- const rpc = createBirpc(createMethodsRPC(project, { collect }), {
2775
+ const channel = new MessageChannel(), port = channel.port2, workerPort = channel.port1, rpc = createBirpc(createMethodsRPC(project, { collect }), {
2844
2776
  eventNames: ["onCancel"],
2845
2777
  post(v) {
2846
2778
  port.postMessage(v);
@@ -2852,9 +2784,7 @@ function createWorkerChannel$1(project, collect) {
2852
2784
  });
2853
2785
  project.vitest.onCancel((reason) => rpc.onCancel(reason));
2854
2786
  const onClose = () => {
2855
- port.close();
2856
- workerPort.close();
2857
- rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
2787
+ port.close(), workerPort.close(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
2858
2788
  };
2859
2789
  return {
2860
2790
  workerPort,
@@ -2863,13 +2793,7 @@ function createWorkerChannel$1(project, collect) {
2863
2793
  };
2864
2794
  }
2865
2795
  function createThreadsPool(vitest, { execArgv, env }) {
2866
- const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
2867
- const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
2868
- const poolOptions = vitest.config.poolOptions?.threads ?? {};
2869
- const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
2870
- const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
2871
- const worker = resolve(vitest.distPath, "workers/threads.js");
2872
- const options = {
2796
+ const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.threads ?? {}, maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/threads.js"), options = {
2873
2797
  filename: resolve(vitest.distPath, "worker.js"),
2874
2798
  teardown: "teardown",
2875
2799
  useAtomics: poolOptions.useAtomics ?? false,
@@ -2879,22 +2803,15 @@ function createThreadsPool(vitest, { execArgv, env }) {
2879
2803
  execArgv: [...poolOptions.execArgv ?? [], ...execArgv],
2880
2804
  terminateTimeout: vitest.config.teardownTimeout,
2881
2805
  concurrentTasksPerWorker: 1
2882
- };
2883
- const isolated = poolOptions.isolate ?? true;
2806
+ }, isolated = poolOptions.isolate ?? true;
2884
2807
  if (isolated) options.isolateWorkers = true;
2885
- if (poolOptions.singleThread || !vitest.config.fileParallelism) {
2886
- options.maxThreads = 1;
2887
- options.minThreads = 1;
2888
- }
2889
- const pool = new Tinypool$1(options);
2890
- const runWithFiles = (name) => {
2808
+ if (poolOptions.singleThread || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
2809
+ const pool = new Tinypool$1(options), runWithFiles = (name) => {
2891
2810
  let id = 0;
2892
2811
  async function runFiles(project, config, files, environment, invalidates = []) {
2893
2812
  const paths = files.map((f) => f.filepath);
2894
2813
  vitest.state.clearFiles(project, paths);
2895
- const { workerPort, onClose } = createWorkerChannel$1(project, name === "collect");
2896
- const workerId = ++id;
2897
- const data = {
2814
+ const { workerPort, onClose } = createWorkerChannel$1(project, name === "collect"), workerId = ++id, data = {
2898
2815
  pool: "threads",
2899
2816
  worker,
2900
2817
  port: workerPort,
@@ -2922,39 +2839,25 @@ function createThreadsPool(vitest, { execArgv, env }) {
2922
2839
  return async (specs, invalidates) => {
2923
2840
  // Cancel pending tasks from pool when possible
2924
2841
  vitest.onCancel(() => pool.cancelPendingTasks());
2925
- const configs = /* @__PURE__ */ new WeakMap();
2926
- const getConfig = (project) => {
2842
+ const configs = /* @__PURE__ */ new WeakMap(), getConfig = (project) => {
2927
2843
  if (configs.has(project)) return configs.get(project);
2928
2844
  const config = project.serializedConfig;
2929
- configs.set(project, config);
2930
- return config;
2931
- };
2932
- const singleThreads = specs.filter((spec) => spec.project.config.poolOptions?.threads?.singleThread);
2933
- const multipleThreads = specs.filter((spec) => !spec.project.config.poolOptions?.threads?.singleThread);
2845
+ return configs.set(project, config), config;
2846
+ }, singleThreads = specs.filter((spec) => spec.project.config.poolOptions?.threads?.singleThread), multipleThreads = specs.filter((spec) => !spec.project.config.poolOptions?.threads?.singleThread);
2934
2847
  if (multipleThreads.length) {
2935
- const filesByEnv = await groupFilesByEnv(multipleThreads);
2936
- const files = Object.values(filesByEnv).flat();
2937
- const results = [];
2848
+ const filesByEnv = await groupFilesByEnv(multipleThreads), files = Object.values(filesByEnv).flat(), results = [];
2938
2849
  if (isolated) results.push(...await Promise.allSettled(files.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2939
2850
  else {
2940
2851
  // When isolation is disabled, we still need to isolate environments and workspace projects from each other.
2941
2852
  // Tasks are still running parallel but environments are isolated between tasks.
2942
2853
  const grouped = groupBy(files, ({ project, environment }) => project.name + environment.name + JSON.stringify(environment.options));
2943
- for (const group of Object.values(grouped)) {
2944
- // Push all files to pool's queue
2945
- results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))));
2946
- // Once all tasks are running or finished, recycle worker for isolation.
2947
- // On-going workers will run in the previous environment.
2948
- await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve));
2949
- await pool.recycleWorkers();
2950
- }
2854
+ for (const group of Object.values(grouped)) results.push(...await Promise.allSettled(group.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)))), await new Promise((resolve) => pool.queueSize === 0 ? resolve() : pool.once("drain", resolve)), await pool.recycleWorkers();
2951
2855
  }
2952
2856
  const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
2953
2857
  if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
2954
2858
  }
2955
2859
  if (singleThreads.length) {
2956
- const filesByEnv = await groupFilesByEnv(singleThreads);
2957
- const envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
2860
+ const filesByEnv = await groupFilesByEnv(singleThreads), envs = envsOrder.concat(Object.keys(filesByEnv).filter((env) => !envsOrder.includes(env)));
2958
2861
  for (const env of envs) {
2959
2862
  const files = filesByEnv[env];
2960
2863
  if (!files?.length) continue;
@@ -2978,102 +2881,69 @@ function createThreadsPool(vitest, { execArgv, env }) {
2978
2881
  }
2979
2882
 
2980
2883
  function createTypecheckPool(vitest) {
2981
- const promisesMap = /* @__PURE__ */ new WeakMap();
2982
- const rerunTriggered = /* @__PURE__ */ new WeakSet();
2884
+ const promisesMap = /* @__PURE__ */ new WeakMap(), rerunTriggered = /* @__PURE__ */ new WeakSet();
2983
2885
  async function onParseEnd(project, { files, sourceErrors }) {
2984
- const checker = project.typechecker;
2985
- const { packs, events } = checker.getTestPacksAndEvents();
2986
- await vitest._testRun.updated(packs, events);
2987
- if (!project.config.typecheck.ignoreSourceErrors) sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
2886
+ const checker = project.typechecker, { packs, events } = checker.getTestPacksAndEvents();
2887
+ if (await vitest._testRun.updated(packs, events), !project.config.typecheck.ignoreSourceErrors) sourceErrors.forEach((error) => vitest.state.catchError(error, "Unhandled Source Error"));
2988
2888
  const processError = !hasFailed(files) && !sourceErrors.length && checker.getExitCode();
2989
2889
  if (processError) {
2990
2890
  const error = new Error(checker.getOutput());
2991
- error.stack = "";
2992
- vitest.state.catchError(error, "Typecheck Error");
2891
+ error.stack = "", vitest.state.catchError(error, "Typecheck Error");
2993
2892
  }
2994
- promisesMap.get(project)?.resolve();
2995
- rerunTriggered.delete(project);
2996
2893
  // triggered by TSC watcher, not Vitest watcher, so we need to emulate what Vitest does in this case
2997
- if (vitest.config.watch && !vitest.runningPromise) {
2998
- await vitest.report("onFinished", files, []);
2999
- await vitest.report("onWatcherStart", files, [...project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors, ...vitest.state.getUnhandledErrors()]);
2894
+ if (promisesMap.get(project)?.resolve(), rerunTriggered.delete(project), vitest.config.watch && !vitest.runningPromise) {
2895
+ const modules = files.map((file) => vitest.state.getReportedEntity(file)).filter((e) => e?.type === "module"), state = vitest.isCancelling ? "interrupted" : modules.some((m) => !m.ok()) ? "failed" : "passed";
2896
+ await vitest.report("onTestRunEnd", modules, [], state), await vitest.report("onWatcherStart", files, [...project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors, ...vitest.state.getUnhandledErrors()]);
3000
2897
  }
3001
2898
  }
3002
2899
  async function createWorkspaceTypechecker(project, files) {
3003
2900
  const checker = project.typechecker ?? new Typechecker(project);
3004
- if (project.typechecker) return checker;
3005
- project.typechecker = checker;
3006
- checker.setFiles(files);
3007
- checker.onParseStart(async () => {
2901
+ return project.typechecker ? checker : (project.typechecker = checker, checker.setFiles(files), checker.onParseStart(async () => {
3008
2902
  const files = checker.getTestFiles();
3009
2903
  for (const file of files) await vitest._testRun.enqueued(project, file);
3010
2904
  await vitest._testRun.collected(project, files);
3011
- });
3012
- checker.onParseEnd((result) => onParseEnd(project, result));
3013
- checker.onWatcherRerun(async () => {
3014
- rerunTriggered.add(project);
3015
- if (!vitest.runningPromise) {
3016
- vitest.state.clearErrors();
3017
- await vitest.report("onWatcherRerun", files, "File change detected. Triggering rerun.");
3018
- }
2905
+ }), checker.onParseEnd((result) => onParseEnd(project, result)), checker.onWatcherRerun(async () => {
2906
+ if (rerunTriggered.add(project), !vitest.runningPromise) vitest.state.clearErrors(), await vitest.report("onWatcherRerun", files, "File change detected. Triggering rerun.");
3019
2907
  await checker.collectTests();
3020
2908
  const testFiles = checker.getTestFiles();
3021
2909
  for (const file of testFiles) await vitest._testRun.enqueued(project, file);
3022
2910
  await vitest._testRun.collected(project, testFiles);
3023
2911
  const { packs, events } = checker.getTestPacksAndEvents();
3024
2912
  await vitest._testRun.updated(packs, events);
3025
- });
3026
- return checker;
2913
+ }), checker);
3027
2914
  }
3028
2915
  async function startTypechecker(project, files) {
3029
2916
  if (project.typechecker) return;
3030
2917
  const checker = await createWorkspaceTypechecker(project, files);
3031
- await checker.collectTests();
3032
- await checker.start();
2918
+ await checker.collectTests(), await checker.start();
3033
2919
  }
3034
2920
  async function collectTests(specs) {
3035
2921
  const specsByProject = groupBy(specs, (spec) => spec.project.name);
3036
2922
  for (const name in specsByProject) {
3037
- const project = specsByProject[name][0].project;
3038
- const files = specsByProject[name].map((spec) => spec.moduleId);
3039
- const checker = await createWorkspaceTypechecker(project, files);
3040
- checker.setFiles(files);
3041
- await checker.collectTests();
2923
+ const project = specsByProject[name][0].project, files = specsByProject[name].map((spec) => spec.moduleId), checker = await createWorkspaceTypechecker(project, files);
2924
+ checker.setFiles(files), await checker.collectTests();
3042
2925
  const testFiles = checker.getTestFiles();
3043
2926
  vitest.state.collectFiles(project, testFiles);
3044
2927
  }
3045
2928
  }
3046
2929
  async function runTests(specs) {
3047
- const specsByProject = groupBy(specs, (spec) => spec.project.name);
3048
- const promises = [];
2930
+ const specsByProject = groupBy(specs, (spec) => spec.project.name), promises = [];
3049
2931
  for (const name in specsByProject) {
3050
- const project = specsByProject[name][0].project;
3051
- const files = specsByProject[name].map((spec) => spec.moduleId);
3052
- const promise = createDefer();
3053
- // check that watcher actually triggered rerun
3054
- const _p = new Promise((resolve) => {
2932
+ const project = specsByProject[name][0].project, files = specsByProject[name].map((spec) => spec.moduleId), promise = createDefer(), _p = new Promise((resolve) => {
3055
2933
  const _i = setInterval(() => {
3056
- if (!project.typechecker || rerunTriggered.has(project)) {
3057
- resolve(true);
3058
- clearInterval(_i);
3059
- }
2934
+ if (!project.typechecker || rerunTriggered.has(project)) resolve(true), clearInterval(_i);
3060
2935
  });
3061
2936
  setTimeout(() => {
3062
- resolve(false);
3063
- clearInterval(_i);
2937
+ resolve(false), clearInterval(_i);
3064
2938
  }, 500).unref();
3065
- });
3066
- const triggered = await _p;
2939
+ }), triggered = await _p;
3067
2940
  if (project.typechecker && !triggered) {
3068
2941
  const testFiles = project.typechecker.getTestFiles();
3069
2942
  for (const file of testFiles) await vitest._testRun.enqueued(project, file);
3070
- await vitest._testRun.collected(project, testFiles);
3071
- await onParseEnd(project, project.typechecker.getResult());
2943
+ await vitest._testRun.collected(project, testFiles), await onParseEnd(project, project.typechecker.getResult());
3072
2944
  continue;
3073
2945
  }
3074
- promises.push(promise);
3075
- promisesMap.set(project, promise);
3076
- promises.push(startTypechecker(project, files));
2946
+ promises.push(promise), promisesMap.set(project, promise), promises.push(startTypechecker(project, files));
3077
2947
  }
3078
2948
  await Promise.all(promises);
3079
2949
  }
@@ -3117,8 +2987,7 @@ function stringToBytes(input, percentageReference) {
3117
2987
  let [, numericString, trailingChars] = input.match(/(.*?)([^0-9.-]+)$/) || [];
3118
2988
  if (trailingChars && numericString) {
3119
2989
  const numericValue = Number.parseFloat(numericString);
3120
- trailingChars = trailingChars.toLowerCase();
3121
- switch (trailingChars) {
2990
+ switch (trailingChars = trailingChars.toLowerCase(), trailingChars) {
3122
2991
  case "%":
3123
2992
  input = numericValue / 100;
3124
2993
  break;
@@ -3134,21 +3003,20 @@ function stringToBytes(input, percentageReference) {
3134
3003
  }
3135
3004
  }
3136
3005
  } else input = Number.parseFloat(input);
3137
- if (typeof input === "number") if (input <= 1 && input > 0) if (percentageReference) return Math.floor(input * percentageReference);
3138
- else throw new Error("For a percentage based memory limit a percentageReference must be supplied");
3139
- else if (input > 1) return Math.floor(input);
3006
+ if (typeof input === "number") if (input <= 1 && input > 0) {
3007
+ if (percentageReference) return Math.floor(input * percentageReference);
3008
+ throw new Error("For a percentage based memory limit a percentageReference must be supplied");
3009
+ } else if (input > 1) return Math.floor(input);
3140
3010
  else throw new Error("Unexpected numerical input for \"memoryLimit\"");
3141
3011
  return null;
3142
3012
  }
3143
3013
 
3144
3014
  const suppressWarningsPath$1 = resolve(rootDir, "./suppress-warnings.cjs");
3145
3015
  function createChildProcessChannel(project, collect) {
3146
- const emitter = new EventEmitter();
3147
- const events = {
3016
+ const emitter = new EventEmitter(), events = {
3148
3017
  message: "message",
3149
3018
  response: "response"
3150
- };
3151
- const rpc = createBirpc(createMethodsRPC(project, {
3019
+ }, rpc = createBirpc(createMethodsRPC(project, {
3152
3020
  cacheFs: true,
3153
3021
  collect
3154
3022
  }), {
@@ -3178,20 +3046,13 @@ function createChildProcessChannel(project, collect) {
3178
3046
  onMessage: (callback) => emitter.on(events.message, callback),
3179
3047
  postMessage: (message) => emitter.emit(events.response, message),
3180
3048
  onClose: () => {
3181
- emitter.removeAllListeners();
3182
- rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
3049
+ emitter.removeAllListeners(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
3183
3050
  }
3184
3051
  };
3185
3052
  return { channel };
3186
3053
  }
3187
3054
  function createVmForksPool(vitest, { execArgv, env }) {
3188
- const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
3189
- const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3190
- const poolOptions = vitest.config.poolOptions?.vmForks ?? {};
3191
- const maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount;
3192
- const minThreads = poolOptions.maxForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
3193
- const worker = resolve(vitest.distPath, "workers/vmForks.js");
3194
- const options = {
3055
+ const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.vmForks ?? {}, maxThreads = poolOptions.maxForks ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.maxForks ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/vmForks.js"), options = {
3195
3056
  runtime: "child_process",
3196
3057
  filename: resolve(vitest.distPath, "worker.js"),
3197
3058
  maxThreads,
@@ -3209,19 +3070,13 @@ function createVmForksPool(vitest, { execArgv, env }) {
3209
3070
  concurrentTasksPerWorker: 1,
3210
3071
  maxMemoryLimitBeforeRecycle: getMemoryLimit$1(vitest.config) || void 0
3211
3072
  };
3212
- if (poolOptions.singleFork || !vitest.config.fileParallelism) {
3213
- options.maxThreads = 1;
3214
- options.minThreads = 1;
3215
- }
3216
- const pool = new Tinypool$1(options);
3217
- const runWithFiles = (name) => {
3073
+ if (poolOptions.singleFork || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
3074
+ const pool = new Tinypool$1(options), runWithFiles = (name) => {
3218
3075
  let id = 0;
3219
3076
  async function runFiles(project, config, files, environment, invalidates = []) {
3220
3077
  const paths = files.map((f) => f.filepath);
3221
3078
  vitest.state.clearFiles(project, paths);
3222
- const { channel } = createChildProcessChannel(project, name === "collect");
3223
- const workerId = ++id;
3224
- const data = {
3079
+ const { channel } = createChildProcessChannel(project, name === "collect"), workerId = ++id, data = {
3225
3080
  pool: "forks",
3226
3081
  worker,
3227
3082
  config,
@@ -3249,18 +3104,11 @@ function createVmForksPool(vitest, { execArgv, env }) {
3249
3104
  return async (specs, invalidates) => {
3250
3105
  // Cancel pending tasks from pool when possible
3251
3106
  vitest.onCancel(() => pool.cancelPendingTasks());
3252
- const configs = /* @__PURE__ */ new Map();
3253
- const getConfig = (project) => {
3107
+ const configs = /* @__PURE__ */ new Map(), getConfig = (project) => {
3254
3108
  if (configs.has(project)) return configs.get(project);
3255
- const _config = project.serializedConfig;
3256
- const config = wrapSerializableConfig(_config);
3257
- configs.set(project, config);
3258
- return config;
3259
- };
3260
- const filesByEnv = await groupFilesByEnv(specs);
3261
- const promises = Object.values(filesByEnv).flat();
3262
- const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
3263
- const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3109
+ const _config = project.serializedConfig, config = wrapSerializableConfig(_config);
3110
+ return configs.set(project, config), config;
3111
+ }, filesByEnv = await groupFilesByEnv(specs), promises = Object.values(filesByEnv).flat(), results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))), errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3264
3112
  if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3265
3113
  };
3266
3114
  };
@@ -3272,21 +3120,14 @@ function createVmForksPool(vitest, { execArgv, env }) {
3272
3120
  };
3273
3121
  }
3274
3122
  function getMemoryLimit$1(config) {
3275
- const memory = nodeos.totalmem();
3276
- const limit = getWorkerMemoryLimit(config, "vmForks");
3277
- if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
3278
- // If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
3279
- if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
3123
+ const memory = nodeos.totalmem(), limit = getWorkerMemoryLimit(config, "vmForks");
3280
3124
  // just ignore "memoryLimit" value because we cannot detect memory limit
3281
- return null;
3125
+ return typeof memory === "number" ? stringToBytes(limit, config.watch ? memory / 2 : memory) : typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%" ? stringToBytes(limit) : null;
3282
3126
  }
3283
3127
 
3284
3128
  const suppressWarningsPath = resolve(rootDir, "./suppress-warnings.cjs");
3285
3129
  function createWorkerChannel(project, collect) {
3286
- const channel = new MessageChannel();
3287
- const port = channel.port2;
3288
- const workerPort = channel.port1;
3289
- const rpc = createBirpc(createMethodsRPC(project, { collect }), {
3130
+ const channel = new MessageChannel(), port = channel.port2, workerPort = channel.port1, rpc = createBirpc(createMethodsRPC(project, { collect }), {
3290
3131
  eventNames: ["onCancel"],
3291
3132
  post(v) {
3292
3133
  port.postMessage(v);
@@ -3298,9 +3139,7 @@ function createWorkerChannel(project, collect) {
3298
3139
  });
3299
3140
  project.vitest.onCancel((reason) => rpc.onCancel(reason));
3300
3141
  function onClose() {
3301
- workerPort.close();
3302
- port.close();
3303
- rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
3142
+ workerPort.close(), port.close(), rpc.$close(/* @__PURE__ */ new Error("[vitest-pool]: Pending methods while closing rpc"));
3304
3143
  }
3305
3144
  return {
3306
3145
  workerPort,
@@ -3308,13 +3147,7 @@ function createWorkerChannel(project, collect) {
3308
3147
  };
3309
3148
  }
3310
3149
  function createVmThreadsPool(vitest, { execArgv, env }) {
3311
- const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length;
3312
- const threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
3313
- const poolOptions = vitest.config.poolOptions?.vmThreads ?? {};
3314
- const maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount;
3315
- const minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads);
3316
- const worker = resolve(vitest.distPath, "workers/vmThreads.js");
3317
- const options = {
3150
+ const numCpus = typeof nodeos.availableParallelism === "function" ? nodeos.availableParallelism() : nodeos.cpus().length, threadsCount = vitest.config.watch ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1), poolOptions = vitest.config.poolOptions?.vmThreads ?? {}, maxThreads = poolOptions.maxThreads ?? vitest.config.maxWorkers ?? threadsCount, minThreads = poolOptions.minThreads ?? vitest.config.minWorkers ?? Math.min(threadsCount, maxThreads), worker = resolve(vitest.distPath, "workers/vmThreads.js"), options = {
3318
3151
  filename: resolve(vitest.distPath, "worker.js"),
3319
3152
  useAtomics: poolOptions.useAtomics ?? false,
3320
3153
  maxThreads,
@@ -3332,19 +3165,13 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
3332
3165
  concurrentTasksPerWorker: 1,
3333
3166
  maxMemoryLimitBeforeRecycle: getMemoryLimit(vitest.config) || void 0
3334
3167
  };
3335
- if (poolOptions.singleThread || !vitest.config.fileParallelism) {
3336
- options.maxThreads = 1;
3337
- options.minThreads = 1;
3338
- }
3339
- const pool = new Tinypool$1(options);
3340
- const runWithFiles = (name) => {
3168
+ if (poolOptions.singleThread || !vitest.config.fileParallelism) options.maxThreads = 1, options.minThreads = 1;
3169
+ const pool = new Tinypool$1(options), runWithFiles = (name) => {
3341
3170
  let id = 0;
3342
3171
  async function runFiles(project, config, files, environment, invalidates = []) {
3343
3172
  const paths = files.map((f) => f.filepath);
3344
3173
  vitest.state.clearFiles(project, paths);
3345
- const { workerPort, onClose } = createWorkerChannel(project, name === "collect");
3346
- const workerId = ++id;
3347
- const data = {
3174
+ const { workerPort, onClose } = createWorkerChannel(project, name === "collect"), workerId = ++id, data = {
3348
3175
  pool: "vmThreads",
3349
3176
  worker,
3350
3177
  port: workerPort,
@@ -3373,17 +3200,11 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
3373
3200
  return async (specs, invalidates) => {
3374
3201
  // Cancel pending tasks from pool when possible
3375
3202
  vitest.onCancel(() => pool.cancelPendingTasks());
3376
- const configs = /* @__PURE__ */ new Map();
3377
- const getConfig = (project) => {
3203
+ const configs = /* @__PURE__ */ new Map(), getConfig = (project) => {
3378
3204
  if (configs.has(project)) return configs.get(project);
3379
3205
  const config = project.serializedConfig;
3380
- configs.set(project, config);
3381
- return config;
3382
- };
3383
- const filesByEnv = await groupFilesByEnv(specs);
3384
- const promises = Object.values(filesByEnv).flat();
3385
- const results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates)));
3386
- const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3206
+ return configs.set(project, config), config;
3207
+ }, filesByEnv = await groupFilesByEnv(specs), promises = Object.values(filesByEnv).flat(), results = await Promise.allSettled(promises.map(({ file, environment, project }) => runFiles(project, getConfig(project), [file], environment, invalidates))), errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
3387
3208
  if (errors.length > 0) throw new AggregateError(errors, "Errors occurred while running tests. For more information, see serialized error.");
3388
3209
  };
3389
3210
  };
@@ -3395,13 +3216,9 @@ function createVmThreadsPool(vitest, { execArgv, env }) {
3395
3216
  };
3396
3217
  }
3397
3218
  function getMemoryLimit(config) {
3398
- const memory = nodeos.totalmem();
3399
- const limit = getWorkerMemoryLimit(config, "vmThreads");
3400
- if (typeof memory === "number") return stringToBytes(limit, config.watch ? memory / 2 : memory);
3401
- // If totalmem is not supported we cannot resolve percentage based values like 0.5, "50%"
3402
- if (typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%") return stringToBytes(limit);
3219
+ const memory = nodeos.totalmem(), limit = getWorkerMemoryLimit(config, "vmThreads");
3403
3220
  // just ignore "memoryLimit" value because we cannot detect memory limit
3404
- return null;
3221
+ return typeof memory === "number" ? stringToBytes(limit, config.watch ? memory / 2 : memory) : typeof limit === "number" && limit > 1 || typeof limit === "string" && limit.at(-1) !== "%" ? stringToBytes(limit) : null;
3405
3222
  }
3406
3223
 
3407
3224
  const builtinPools = [
@@ -3413,8 +3230,7 @@ const builtinPools = [
3413
3230
  "typescript"
3414
3231
  ];
3415
3232
  function getDefaultPoolName(project) {
3416
- if (project.config.browser.enabled) return "browser";
3417
- return project.config.pool;
3233
+ return project.config.browser.enabled ? "browser" : project.config.pool;
3418
3234
  }
3419
3235
  function getFilePoolName(project) {
3420
3236
  return getDefaultPoolName(project);
@@ -3427,26 +3243,15 @@ function createPool(ctx) {
3427
3243
  vmThreads: null,
3428
3244
  vmForks: null,
3429
3245
  typescript: null
3430
- };
3431
- // in addition to resolve.conditions Vite also adds production/development,
3432
- // see: https://github.com/vitejs/vite/blob/af2aa09575229462635b7cbb6d248ca853057ba2/packages/vite/src/node/plugins/resolve.ts#L1056-L1080
3433
- const viteMajor = Number(version.split(".")[0]);
3434
- const potentialConditions = new Set(viteMajor >= 6 ? ctx.vite.config.ssr.resolve?.conditions ?? [] : [
3246
+ }, viteMajor = Number(version.split(".")[0]), potentialConditions = new Set(viteMajor >= 6 ? ctx.vite.config.ssr.resolve?.conditions ?? [] : [
3435
3247
  "production",
3436
3248
  "development",
3437
3249
  ...ctx.vite.config.resolve.conditions
3438
- ]);
3439
- const conditions = [...potentialConditions].filter((condition) => {
3440
- if (condition === "production") return ctx.vite.config.isProduction;
3441
- if (condition === "development") return !ctx.vite.config.isProduction;
3442
- return true;
3250
+ ]), conditions = [...potentialConditions].filter((condition) => {
3251
+ return condition === "production" ? ctx.vite.config.isProduction : condition === "development" ? !ctx.vite.config.isProduction : true;
3443
3252
  }).map((condition) => {
3444
- if (viteMajor >= 6 && condition === "development|production") return ctx.vite.config.isProduction ? "production" : "development";
3445
- return condition;
3446
- }).flatMap((c) => ["--conditions", c]);
3447
- // Instead of passing whole process.execArgv to the workers, pick allowed options.
3448
- // Some options may crash worker, e.g. --prof, --title. nodejs/node#41103
3449
- const execArgv = process.execArgv.filter((execArg) => execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"));
3253
+ return viteMajor >= 6 && condition === "development|production" ? ctx.vite.config.isProduction ? "production" : "development" : condition;
3254
+ }).flatMap((c) => ["--conditions", c]), execArgv = process.execArgv.filter((execArg) => execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir"));
3450
3255
  async function executeTests(method, files, invalidate) {
3451
3256
  const options = {
3452
3257
  execArgv: [...execArgv, ...conditions],
@@ -3462,8 +3267,7 @@ function createPool(ctx) {
3462
3267
  };
3463
3268
  // env are case-insensitive on Windows, but spawned processes don't support it
3464
3269
  if (isWindows) for (const name in options.env) options.env[name.toUpperCase()] = options.env[name];
3465
- const poolConcurrentPromises = /* @__PURE__ */ new Map();
3466
- const customPools = /* @__PURE__ */ new Map();
3270
+ const poolConcurrentPromises = /* @__PURE__ */ new Map(), customPools = /* @__PURE__ */ new Map();
3467
3271
  async function resolveCustomPool(filepath) {
3468
3272
  if (customPools.has(filepath)) return customPools.get(filepath);
3469
3273
  const pool = await ctx.runner.import(filepath);
@@ -3471,16 +3275,14 @@ function createPool(ctx) {
3471
3275
  const poolInstance = await pool.default(ctx, options);
3472
3276
  if (typeof poolInstance?.name !== "string") throw new TypeError(`Custom pool "${filepath}" should return an object with "name" property`);
3473
3277
  if (typeof poolInstance?.[method] !== "function") throw new TypeError(`Custom pool "${filepath}" should return an object with "${method}" method`);
3474
- customPools.set(filepath, poolInstance);
3475
- return poolInstance;
3278
+ return customPools.set(filepath, poolInstance), poolInstance;
3476
3279
  }
3477
3280
  function getConcurrentPool(pool, fn) {
3478
3281
  if (poolConcurrentPromises.has(pool)) return poolConcurrentPromises.get(pool);
3479
3282
  const promise = fn().finally(() => {
3480
3283
  poolConcurrentPromises.delete(pool);
3481
3284
  });
3482
- poolConcurrentPromises.set(pool, promise);
3483
- return promise;
3285
+ return poolConcurrentPromises.set(pool, promise), promise;
3484
3286
  }
3485
3287
  function getCustomPool(pool) {
3486
3288
  return getConcurrentPool(pool, () => resolveCustomPool(pool));
@@ -3491,9 +3293,7 @@ function createPool(ctx) {
3491
3293
  return createBrowserPool(ctx);
3492
3294
  });
3493
3295
  }
3494
- const groupedSpecifications = {};
3495
- const groups = /* @__PURE__ */ new Set();
3496
- const factories = {
3296
+ const groupedSpecifications = {}, groups = /* @__PURE__ */ new Set(), factories = {
3497
3297
  vmThreads: () => createVmThreadsPool(ctx, options),
3498
3298
  vmForks: () => createVmForksPool(ctx, options),
3499
3299
  threads: () => createThreadsPool(ctx, options),
@@ -3502,12 +3302,9 @@ function createPool(ctx) {
3502
3302
  };
3503
3303
  for (const spec of files) {
3504
3304
  const group = spec[0].config.sequence.groupOrder ?? 0;
3505
- groups.add(group);
3506
- groupedSpecifications[group] ??= [];
3507
- groupedSpecifications[group].push(spec);
3305
+ groups.add(group), groupedSpecifications[group] ??= [], groupedSpecifications[group].push(spec);
3508
3306
  }
3509
- const Sequencer = ctx.config.sequence.sequencer;
3510
- const sequencer = new Sequencer(ctx);
3307
+ const Sequencer = ctx.config.sequence.sequencer, sequencer = new Sequencer(ctx);
3511
3308
  async function sortSpecs(specs) {
3512
3309
  if (ctx.config.shard) {
3513
3310
  if (!ctx.config.passWithNoTests && ctx.config.shard.count > specs.length) throw new Error(`--shard <count> must be a smaller than count of test files. Resolved ${specs.length} test files for --shard=${ctx.config.shard.index}/${ctx.config.shard.count}.`);
@@ -3528,25 +3325,18 @@ function createPool(ctx) {
3528
3325
  };
3529
3326
  specifications.forEach((specification) => {
3530
3327
  const pool = specification[2].pool;
3531
- filesByPool[pool] ??= [];
3532
- filesByPool[pool].push(specification);
3533
- });
3534
- await Promise.all(Object.entries(filesByPool).map(async (entry) => {
3328
+ filesByPool[pool] ??= [], filesByPool[pool].push(specification);
3329
+ }), await Promise.all(Object.entries(filesByPool).map(async (entry) => {
3535
3330
  const [pool, files] = entry;
3536
3331
  if (!files.length) return null;
3537
3332
  const specs = await sortSpecs(files);
3538
3333
  if (pool in factories) {
3539
3334
  const factory = factories[pool];
3540
- pools[pool] ??= factory();
3541
- return pools[pool][method](specs, invalidate);
3542
- }
3543
- if (pool === "browser") {
3544
- pools.browser ??= await getBrowserPool();
3545
- return pools.browser[method](specs, invalidate);
3335
+ return pools[pool] ??= factory(), pools[pool][method](specs, invalidate);
3546
3336
  }
3337
+ if (pool === "browser") return pools.browser ??= await getBrowserPool(), pools.browser[method](specs, invalidate);
3547
3338
  const poolHandler = await getCustomPool(pool);
3548
- pools[poolHandler.name] ??= poolHandler;
3549
- return poolHandler[method](specs, invalidate);
3339
+ return pools[poolHandler.name] ??= poolHandler, poolHandler[method](specs, invalidate);
3550
3340
  }));
3551
3341
  }
3552
3342
  }
@@ -3567,12 +3357,9 @@ class BaseSequencer {
3567
3357
  }
3568
3358
  // async so it can be extended by other sequelizers
3569
3359
  async shard(files) {
3570
- const { config } = this.ctx;
3571
- const { index, count } = config.shard;
3572
- const [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count);
3360
+ const { config } = this.ctx, { index, count } = config.shard, [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count);
3573
3361
  return [...files].map((spec) => {
3574
- const fullPath = resolve$1(slash(config.root), slash(spec.moduleId));
3575
- const specPath = fullPath?.slice(config.root.length);
3362
+ const fullPath = resolve$1(slash(config.root), slash(spec.moduleId)), specPath = fullPath?.slice(config.root.length);
3576
3363
  return {
3577
3364
  spec,
3578
3365
  hash: hash("sha1", specPath, "hex")
@@ -3583,37 +3370,24 @@ class BaseSequencer {
3583
3370
  async sort(files) {
3584
3371
  const cache = this.ctx.cache;
3585
3372
  return [...files].sort((a, b) => {
3586
- const keyA = `${a.project.name}:${relative(this.ctx.config.root, a.moduleId)}`;
3587
- const keyB = `${b.project.name}:${relative(this.ctx.config.root, b.moduleId)}`;
3588
- const aState = cache.getFileTestResults(keyA);
3589
- const bState = cache.getFileTestResults(keyB);
3373
+ const keyA = `${a.project.name}:${relative(this.ctx.config.root, a.moduleId)}`, keyB = `${b.project.name}:${relative(this.ctx.config.root, b.moduleId)}`, aState = cache.getFileTestResults(keyA), bState = cache.getFileTestResults(keyB);
3590
3374
  if (!aState || !bState) {
3591
- const statsA = cache.getFileStats(keyA);
3592
- const statsB = cache.getFileStats(keyB);
3593
- // run unknown first
3594
- if (!statsA || !statsB) return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0;
3375
+ const statsA = cache.getFileStats(keyA), statsB = cache.getFileStats(keyB);
3595
3376
  // run larger files first
3596
- return statsB.size - statsA.size;
3377
+ return !statsA || !statsB ? !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0 : statsB.size - statsA.size;
3597
3378
  }
3598
- // run failed first
3599
- if (aState.failed && !bState.failed) return -1;
3600
- if (!aState.failed && bState.failed) return 1;
3601
3379
  // run longer first
3602
- return bState.duration - aState.duration;
3380
+ return aState.failed && !bState.failed ? -1 : !aState.failed && bState.failed ? 1 : bState.duration - aState.duration;
3603
3381
  });
3604
3382
  }
3605
3383
  // Calculate distributed shard range [start, end] distributed equally
3606
3384
  calculateShardRange(filesCount, index, count) {
3607
- const baseShardSize = Math.floor(filesCount / count);
3608
- const remainderTestFilesCount = filesCount % count;
3385
+ const baseShardSize = Math.floor(filesCount / count), remainderTestFilesCount = filesCount % count;
3609
3386
  if (remainderTestFilesCount >= index) {
3610
- const shardSize = baseShardSize + 1;
3611
- const shardStart = shardSize * (index - 1);
3612
- const shardEnd = shardSize * index;
3387
+ const shardSize = baseShardSize + 1, shardStart = shardSize * (index - 1), shardEnd = shardSize * index;
3613
3388
  return [shardStart, shardEnd];
3614
3389
  }
3615
- const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize;
3616
- const shardEnd = shardStart + baseShardSize;
3390
+ const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize, shardEnd = shardStart + baseShardSize;
3617
3391
  return [shardStart, shardEnd];
3618
3392
  }
3619
3393
  }
@@ -3633,11 +3407,10 @@ function parseInspector(inspect) {
3633
3407
  if (typeof inspect === "number") return { port: inspect };
3634
3408
  if (inspect.match(/https?:\//)) throw new Error(`Inspector host cannot be a URL. Use "host:port" instead of "${inspect}"`);
3635
3409
  const [host, port] = inspect.split(":");
3636
- if (!port) return { host };
3637
- return {
3410
+ return port ? {
3638
3411
  host,
3639
3412
  port: Number(port) || defaultInspectPort
3640
- };
3413
+ } : { host };
3641
3414
  }
3642
3415
  function resolveApiServerConfig(options, defaultPort) {
3643
3416
  let api;
@@ -3655,12 +3428,10 @@ function resolveApiServerConfig(options, defaultPort) {
3655
3428
  return api;
3656
3429
  }
3657
3430
  function resolveInlineWorkerOption(value) {
3658
- if (typeof value === "string" && value.trim().endsWith("%")) return getWorkersCountByPercentage(value);
3659
- else return Number(value);
3431
+ return typeof value === "string" && value.trim().endsWith("%") ? getWorkersCountByPercentage(value) : Number(value);
3660
3432
  }
3661
3433
  function resolveConfig$1(vitest, options, viteConfig) {
3662
- const mode = vitest.mode;
3663
- const logger = vitest.logger;
3434
+ const mode = vitest.mode, logger = vitest.logger;
3664
3435
  if (options.dom) {
3665
3436
  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}"`));
3666
3437
  options.environment = "happy-dom";
@@ -3671,25 +3442,17 @@ function resolveConfig$1(vitest, options, viteConfig) {
3671
3442
  root: viteConfig.root,
3672
3443
  mode
3673
3444
  };
3674
- resolved.project = toArray(resolved.project);
3675
- resolved.provide ??= {};
3676
- resolved.name = typeof options.name === "string" ? options.name : options.name?.label || "";
3677
- resolved.color = typeof options.name !== "string" ? options.name?.color : void 0;
3678
- if (resolved.environment === "browser") throw new Error(`Looks like you set "test.environment" to "browser". To enabled Browser Mode, use "test.browser.enabled" instead.`);
3445
+ if (resolved.project = toArray(resolved.project), resolved.provide ??= {}, resolved.name = typeof options.name === "string" ? options.name : options.name?.label || "", resolved.color = typeof options.name !== "string" ? options.name?.color : void 0, resolved.environment === "browser") throw new Error(`Looks like you set "test.environment" to "browser". To enabled Browser Mode, use "test.browser.enabled" instead.`);
3679
3446
  const inspector = resolved.inspect || resolved.inspectBrk;
3680
- resolved.inspector = {
3447
+ if (resolved.inspector = {
3681
3448
  ...resolved.inspector,
3682
3449
  ...parseInspector(inspector),
3683
3450
  enabled: !!inspector,
3684
3451
  waitForDebugger: options.inspector?.waitForDebugger ?? !!resolved.inspectBrk
3685
- };
3686
- if (viteConfig.base !== "/") resolved.base = viteConfig.base;
3687
- resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true;
3688
- if (options.shard) {
3452
+ }, viteConfig.base !== "/") resolved.base = viteConfig.base;
3453
+ if (resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true, options.shard) {
3689
3454
  if (resolved.watch) throw new Error("You cannot use --shard option with enabled watch");
3690
- const [indexString, countString] = options.shard.split("/");
3691
- const index = Math.abs(Number.parseInt(indexString, 10));
3692
- const count = Math.abs(Number.parseInt(countString, 10));
3455
+ const [indexString, countString] = options.shard.split("/"), index = Math.abs(Number.parseInt(indexString, 10)), count = Math.abs(Number.parseInt(countString, 10));
3693
3456
  if (Number.isNaN(count) || count <= 0) throw new Error("--shard <count> must be a positive number");
3694
3457
  if (Number.isNaN(index) || index <= 0 || index > count) throw new Error("--shard <index> must be a positive number less then <count>");
3695
3458
  resolved.shard = {
@@ -3701,20 +3464,10 @@ function resolveConfig$1(vitest, options, viteConfig) {
3701
3464
  if (resolved.mergeReports && resolved.watch) throw new Error(`Cannot merge reports with --watch enabled`);
3702
3465
  if (resolved.maxWorkers) resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers);
3703
3466
  if (resolved.minWorkers) resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers);
3704
- // run benchmark sequentially by default
3705
- resolved.fileParallelism ??= mode !== "benchmark";
3706
- if (!resolved.fileParallelism) {
3707
- // ignore user config, parallelism cannot be implemented without limiting workers
3708
- resolved.maxWorkers = 1;
3709
- resolved.minWorkers = 1;
3710
- }
3711
- if (resolved.maxConcurrency === 0) {
3712
- logger.console.warn(c.yellow(`The option "maxConcurrency" cannot be set to 0. Using default value ${configDefaults.maxConcurrency} instead.`));
3713
- resolved.maxConcurrency = configDefaults.maxConcurrency;
3714
- }
3467
+ if (resolved.fileParallelism ??= mode !== "benchmark", !resolved.fileParallelism) resolved.maxWorkers = 1, resolved.minWorkers = 1;
3468
+ if (resolved.maxConcurrency === 0) logger.console.warn(c.yellow(`The option "maxConcurrency" cannot be set to 0. Using default value ${configDefaults.maxConcurrency} instead.`)), resolved.maxConcurrency = configDefaults.maxConcurrency;
3715
3469
  if (resolved.inspect || resolved.inspectBrk) {
3716
- const isSingleThread = resolved.pool === "threads" && resolved.poolOptions?.threads?.singleThread;
3717
- const isSingleFork = resolved.pool === "forks" && resolved.poolOptions?.forks?.singleFork;
3470
+ const isSingleThread = resolved.pool === "threads" && resolved.poolOptions?.threads?.singleThread, isSingleFork = resolved.pool === "forks" && resolved.poolOptions?.forks?.singleFork;
3718
3471
  if (resolved.fileParallelism && !isSingleThread && !isSingleFork) {
3719
3472
  const inspectOption = `--inspect${resolved.inspectBrk ? "-brk" : ""}`;
3720
3473
  throw new Error(`You cannot use ${inspectOption} without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"`);
@@ -3752,37 +3505,20 @@ function resolveConfig$1(vitest, options, viteConfig) {
3752
3505
  } }, null, 2)}\n\n...or disable ${inspectOption}\n`);
3753
3506
  }
3754
3507
  }
3755
- resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter);
3756
- if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
3508
+ if (resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter), resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
3757
3509
  const reportsDirectory = resolve$1(resolved.root, resolved.coverage.reportsDirectory);
3758
3510
  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`);
3759
3511
  }
3760
3512
  if (resolved.coverage.enabled && resolved.coverage.provider === "custom" && resolved.coverage.customProviderModule) resolved.coverage.customProviderModule = resolvePath(resolved.coverage.customProviderModule, resolved.root);
3761
- resolved.expect ??= {};
3762
- resolved.deps ??= {};
3763
- resolved.deps.moduleDirectories ??= [];
3513
+ resolved.expect ??= {}, resolved.deps ??= {}, resolved.deps.moduleDirectories ??= [];
3764
3514
  const envModuleDirectories = process.env.VITEST_MODULE_DIRECTORIES || process.env.npm_config_VITEST_MODULE_DIRECTORIES;
3765
3515
  if (envModuleDirectories) resolved.deps.moduleDirectories.push(...envModuleDirectories.split(","));
3766
- resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
3516
+ if (resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
3767
3517
  if (!dir.startsWith("/")) dir = `/${dir}`;
3768
3518
  if (!dir.endsWith("/")) dir += "/";
3769
3519
  return normalize(dir);
3770
- });
3771
- if (!resolved.deps.moduleDirectories.includes("/node_modules/")) resolved.deps.moduleDirectories.push("/node_modules/");
3772
- resolved.deps.optimizer ??= {};
3773
- resolved.deps.optimizer.ssr ??= {};
3774
- resolved.deps.optimizer.ssr.enabled ??= false;
3775
- resolved.deps.optimizer.client ??= {};
3776
- resolved.deps.optimizer.client.enabled ??= false;
3777
- resolved.deps.web ??= {};
3778
- resolved.deps.web.transformAssets ??= true;
3779
- resolved.deps.web.transformCss ??= true;
3780
- resolved.deps.web.transformGlobPattern ??= [];
3781
- resolved.setupFiles = toArray(resolved.setupFiles || []).map((file) => resolvePath(file, resolved.root));
3782
- resolved.globalSetup = toArray(resolved.globalSetup || []).map((file) => resolvePath(file, resolved.root));
3783
- // Add hard-coded default coverage exclusions. These cannot be overidden by user config.
3784
- // Override original exclude array for cases where user re-uses same object in test.exclude.
3785
- resolved.coverage.exclude = [
3520
+ }), !resolved.deps.moduleDirectories.includes("/node_modules/")) resolved.deps.moduleDirectories.push("/node_modules/");
3521
+ if (resolved.deps.optimizer ??= {}, resolved.deps.optimizer.ssr ??= {}, resolved.deps.optimizer.ssr.enabled ??= false, resolved.deps.optimizer.client ??= {}, resolved.deps.optimizer.client.enabled ??= false, resolved.deps.web ??= {}, resolved.deps.web.transformAssets ??= true, resolved.deps.web.transformCss ??= true, resolved.deps.web.transformGlobPattern ??= [], resolved.setupFiles = toArray(resolved.setupFiles || []).map((file) => resolvePath(file, resolved.root)), resolved.globalSetup = toArray(resolved.globalSetup || []).map((file) => resolvePath(file, resolved.root)), resolved.coverage.exclude = [
3786
3522
  ...resolved.coverage.exclude,
3787
3523
  ...resolved.setupFiles.map((file) => `${resolved.coverage.allowExternal ? "**/" : ""}${relative(resolved.root, file)}`),
3788
3524
  ...resolved.include,
@@ -3791,32 +3527,22 @@ function resolveConfig$1(vitest, options, viteConfig) {
3791
3527
  "**/virtual:*",
3792
3528
  "**/__x00__*",
3793
3529
  "**/node_modules/**"
3794
- ].filter((pattern) => pattern != null);
3795
- resolved.forceRerunTriggers = [...resolved.forceRerunTriggers, ...resolved.setupFiles];
3796
- if (resolved.cliExclude) resolved.exclude.push(...resolved.cliExclude);
3530
+ ].filter((pattern) => pattern != null), resolved.forceRerunTriggers = [...resolved.forceRerunTriggers, ...resolved.setupFiles], resolved.cliExclude) resolved.exclude.push(...resolved.cliExclude);
3797
3531
  if (resolved.runner) resolved.runner = resolvePath(resolved.runner, resolved.root);
3798
- resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments");
3799
- if (resolved.snapshotEnvironment) resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
3800
- resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
3801
- if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
3802
- resolved.snapshotFormat.plugins = [];
3532
+ if (resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments"), resolved.snapshotEnvironment) resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
3533
+ if (resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0, resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
3803
3534
  // TODO: support it via separate config (like DiffOptions) or via `Function.toString()`
3804
- if (typeof resolved.snapshotFormat.compareKeys === "function") throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`);
3535
+ if (resolved.snapshotFormat.plugins = [], typeof resolved.snapshotFormat.compareKeys === "function") throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`);
3805
3536
  }
3806
3537
  const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
3807
- resolved.snapshotOptions = {
3538
+ if (resolved.snapshotOptions = {
3808
3539
  expand: resolved.expandSnapshotDiff ?? false,
3809
3540
  snapshotFormat: resolved.snapshotFormat || {},
3810
3541
  updateSnapshot: isCI && !UPDATE_SNAPSHOT ? "none" : UPDATE_SNAPSHOT ? "all" : "new",
3811
3542
  resolveSnapshotPath: options.resolveSnapshotPath,
3812
3543
  snapshotEnvironment: null
3813
- };
3814
- resolved.snapshotSerializers ??= [];
3815
- resolved.snapshotSerializers = resolved.snapshotSerializers.map((file) => resolvePath(file, resolved.root));
3816
- resolved.forceRerunTriggers.push(...resolved.snapshotSerializers);
3817
- if (options.resolveSnapshotPath) delete resolved.resolveSnapshotPath;
3818
- resolved.pool ??= "threads";
3819
- if (process.env.VITEST_MAX_THREADS) resolved.poolOptions = {
3544
+ }, resolved.snapshotSerializers ??= [], resolved.snapshotSerializers = resolved.snapshotSerializers.map((file) => resolvePath(file, resolved.root)), resolved.forceRerunTriggers.push(...resolved.snapshotSerializers), options.resolveSnapshotPath) delete resolved.resolveSnapshotPath;
3545
+ if (resolved.pool ??= "threads", process.env.VITEST_MAX_THREADS) resolved.poolOptions = {
3820
3546
  ...resolved.poolOptions,
3821
3547
  threads: {
3822
3548
  ...resolved.poolOptions?.threads,
@@ -3879,13 +3605,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
3879
3605
  resolved.benchmark = {
3880
3606
  ...benchmarkConfigDefaults,
3881
3607
  ...resolved.benchmark
3882
- };
3883
- // override test config
3884
- resolved.coverage.enabled = false;
3885
- resolved.typecheck.enabled = false;
3886
- resolved.include = resolved.benchmark.include;
3887
- resolved.exclude = resolved.benchmark.exclude;
3888
- resolved.includeSource = resolved.benchmark.includeSource;
3608
+ }, resolved.coverage.enabled = false, resolved.typecheck.enabled = false, resolved.include = resolved.benchmark.include, resolved.exclude = resolved.benchmark.exclude, resolved.includeSource = resolved.benchmark.includeSource;
3889
3609
  const reporters = Array.from(new Set([...toArray(resolved.benchmark.reporters), ...toArray(options.reporter)])).filter(Boolean);
3890
3610
  if (reporters.length) resolved.benchmark.reporters = reporters;
3891
3611
  else resolved.benchmark.reporters = ["default"];
@@ -3894,17 +3614,13 @@ function resolveConfig$1(vitest, options, viteConfig) {
3894
3614
  if (options.compare) resolved.benchmark.compare = options.compare;
3895
3615
  if (options.outputJson) resolved.benchmark.outputJson = options.outputJson;
3896
3616
  }
3897
- if (typeof resolved.diff === "string") {
3898
- resolved.diff = resolvePath(resolved.diff, resolved.root);
3899
- resolved.forceRerunTriggers.push(resolved.diff);
3900
- }
3617
+ if (typeof resolved.diff === "string") resolved.diff = resolvePath(resolved.diff, resolved.root), resolved.forceRerunTriggers.push(resolved.diff);
3901
3618
  // the server has been created, we don't need to override vite.server options
3902
3619
  const api = resolveApiServerConfig(options, defaultPort);
3903
- resolved.api = {
3620
+ if (resolved.api = {
3904
3621
  ...api,
3905
3622
  token: crypto.randomUUID()
3906
- };
3907
- if (options.related) resolved.related = toArray(options.related).map((file) => resolve$1(resolved.root, file));
3623
+ }, options.related) resolved.related = toArray(options.related).map((file) => resolve$1(resolved.root, file));
3908
3624
  /*
3909
3625
  * Reporters can be defined in many different ways:
3910
3626
  * { reporter: 'json' }
@@ -3933,85 +3649,51 @@ function resolveConfig$1(vitest, options, viteConfig) {
3933
3649
  if (mode !== "benchmark") {
3934
3650
  // @ts-expect-error "reporter" is from CLI, should be absolute to the running directory
3935
3651
  // it is passed down as "vitest --reporter ../reporter.js"
3936
- const reportersFromCLI = resolved.reporter;
3937
- const cliReporters = toArray(reportersFromCLI || []).map((reporter) => {
3938
- // ./reporter.js || ../reporter.js, but not .reporters/reporter.js
3939
- if (/^\.\.?\//.test(reporter)) return resolve$1(process.cwd(), reporter);
3940
- return reporter;
3652
+ const reportersFromCLI = resolved.reporter, cliReporters = toArray(reportersFromCLI || []).map((reporter) => {
3653
+ return /^\.\.?\//.test(reporter) ? resolve$1(process.cwd(), reporter) : reporter;
3941
3654
  });
3942
3655
  if (cliReporters.length) resolved.reporters = Array.from(new Set(toArray(cliReporters))).filter(Boolean).map((reporter) => [reporter, {}]);
3943
3656
  }
3944
3657
  if (!resolved.reporters.length) {
3945
- resolved.reporters.push(["default", {}]);
3946
3658
  // also enable github-actions reporter as a default
3947
- if (process.env.GITHUB_ACTIONS === "true") resolved.reporters.push(["github-actions", {}]);
3659
+ if (resolved.reporters.push(["default", {}]), process.env.GITHUB_ACTIONS === "true") resolved.reporters.push(["github-actions", {}]);
3948
3660
  }
3949
3661
  if (resolved.changed) resolved.passWithNoTests ??= true;
3950
- resolved.css ??= {};
3951
- if (typeof resolved.css === "object") {
3952
- resolved.css.modules ??= {};
3953
- resolved.css.modules.classNameStrategy ??= "stable";
3954
- }
3662
+ if (resolved.css ??= {}, typeof resolved.css === "object") resolved.css.modules ??= {}, resolved.css.modules.classNameStrategy ??= "stable";
3955
3663
  if (resolved.cache !== false) {
3956
3664
  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"`);
3957
3665
  resolved.cache = { dir: viteConfig.cacheDir };
3958
3666
  }
3959
- resolved.sequence ??= {};
3960
- if (resolved.sequence.shuffle && typeof resolved.sequence.shuffle === "object") {
3667
+ if (resolved.sequence ??= {}, resolved.sequence.shuffle && typeof resolved.sequence.shuffle === "object") {
3961
3668
  const { files, tests } = resolved.sequence.shuffle;
3962
- resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer;
3963
- resolved.sequence.shuffle = tests;
3669
+ resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer, resolved.sequence.shuffle = tests;
3964
3670
  }
3965
3671
  if (!resolved.sequence?.sequencer)
3966
3672
  // CLI flag has higher priority
3967
3673
  resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
3968
- resolved.sequence.groupOrder ??= 0;
3969
- resolved.sequence.hooks ??= "stack";
3970
- if (resolved.sequence.sequencer === RandomSequencer) resolved.sequence.seed ??= Date.now();
3971
- resolved.typecheck = {
3674
+ if (resolved.sequence.groupOrder ??= 0, resolved.sequence.hooks ??= "stack", resolved.sequence.sequencer === RandomSequencer) resolved.sequence.seed ??= Date.now();
3675
+ if (resolved.typecheck = {
3972
3676
  ...configDefaults.typecheck,
3973
3677
  ...resolved.typecheck
3974
- };
3975
- resolved.typecheck ??= {};
3976
- resolved.typecheck.enabled ??= false;
3977
- 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."));
3978
- resolved.browser.enabled ??= false;
3979
- resolved.browser.headless ??= isCI;
3980
- resolved.browser.isolate ??= true;
3981
- resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark";
3982
- // disable in headless mode by default, and if CI is detected
3983
- resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI;
3984
- if (resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve$1(resolved.root, resolved.browser.screenshotDirectory);
3678
+ }, resolved.typecheck ??= {}, resolved.typecheck.enabled ??= false, 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."));
3679
+ if (resolved.browser.enabled ??= false, resolved.browser.headless ??= isCI, resolved.browser.isolate ??= true, resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark", resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI, resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve$1(resolved.root, resolved.browser.screenshotDirectory);
3985
3680
  const isPreview = resolved.browser.provider === "preview";
3986
- if (isPreview && resolved.browser.screenshotFailures === true) {
3987
- console.warn(c.yellow([
3988
- `Browser provider "preview" doesn't support screenshots, `,
3989
- `so "browser.screenshotFailures" option is forcefully disabled. `,
3990
- `Set "browser.screenshotFailures" to false or remove it from the config to suppress this warning.`
3991
- ].join("")));
3992
- resolved.browser.screenshotFailures = false;
3993
- } else resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
3994
- resolved.browser.viewport ??= {};
3995
- resolved.browser.viewport.width ??= 414;
3996
- resolved.browser.viewport.height ??= 896;
3997
- resolved.browser.locators ??= {};
3998
- resolved.browser.locators.testIdAttribute ??= "data-testid";
3999
- if (resolved.browser.enabled && provider === "stackblitz") resolved.browser.provider = "preview";
4000
- resolved.browser.api = resolveApiServerConfig(resolved.browser, defaultBrowserPort) || { port: defaultBrowserPort };
3681
+ if (isPreview && resolved.browser.screenshotFailures === true) console.warn(c.yellow([
3682
+ `Browser provider "preview" doesn't support screenshots, `,
3683
+ `so "browser.screenshotFailures" option is forcefully disabled. `,
3684
+ `Set "browser.screenshotFailures" to false or remove it from the config to suppress this warning.`
3685
+ ].join(""))), resolved.browser.screenshotFailures = false;
3686
+ else resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui;
3687
+ if (resolved.browser.viewport ??= {}, resolved.browser.viewport.width ??= 414, resolved.browser.viewport.height ??= 896, resolved.browser.locators ??= {}, resolved.browser.locators.testIdAttribute ??= "data-testid", resolved.browser.enabled && provider === "stackblitz") resolved.browser.provider = "preview";
4001
3688
  // enable includeTaskLocation by default in UI mode
4002
- if (resolved.browser.enabled) {
3689
+ if (resolved.browser.api = resolveApiServerConfig(resolved.browser, defaultBrowserPort) || { port: defaultBrowserPort }, resolved.browser.enabled) {
4003
3690
  if (resolved.browser.ui) resolved.includeTaskLocation ??= true;
4004
3691
  } else if (resolved.ui) resolved.includeTaskLocation ??= true;
4005
3692
  const htmlReporter = toArray(resolved.reporters).some((reporter) => {
4006
- if (Array.isArray(reporter)) return reporter[0] === "html";
4007
- return false;
3693
+ return Array.isArray(reporter) ? reporter[0] === "html" : false;
4008
3694
  });
4009
3695
  if (htmlReporter) resolved.includeTaskLocation ??= true;
4010
- resolved.server ??= {};
4011
- resolved.server.deps ??= {};
4012
- resolved.testTimeout ??= resolved.browser.enabled ? 15e3 : 5e3;
4013
- resolved.hookTimeout ??= resolved.browser.enabled ? 3e4 : 1e4;
4014
- return resolved;
3696
+ return resolved.server ??= {}, resolved.server.deps ??= {}, resolved.testTimeout ??= resolved.browser.enabled ? 15e3 : 5e3, resolved.hookTimeout ??= resolved.browser.enabled ? 3e4 : 1e4, resolved;
4015
3697
  }
4016
3698
  function isBrowserEnabled(config) {
4017
3699
  return Boolean(config.browser?.enabled);
@@ -4047,14 +3729,11 @@ const THRESHOLD_KEYS = [
4047
3729
  "functions",
4048
3730
  "statements",
4049
3731
  "branches"
4050
- ];
4051
- const GLOBAL_THRESHOLDS_KEY = "global";
4052
- const DEFAULT_PROJECT = Symbol.for("default-project");
3732
+ ], GLOBAL_THRESHOLDS_KEY = "global", DEFAULT_PROJECT = Symbol.for("default-project");
4053
3733
  let uniqueId = 0;
4054
3734
  async function getCoverageProvider(options, loader) {
4055
3735
  const coverageModule = await resolveCoverageProviderModule(options, loader);
4056
- if (coverageModule) return coverageModule.getProvider();
4057
- return null;
3736
+ return coverageModule ? coverageModule.getProvider() : null;
4058
3737
  }
4059
3738
  class BaseCoverageProvider {
4060
3739
  ctx;
@@ -4067,8 +3746,7 @@ class BaseCoverageProvider {
4067
3746
  coverageFilesDirectory;
4068
3747
  roots = [];
4069
3748
  _initialize(ctx) {
4070
- this.ctx = ctx;
4071
- 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} `))}.
3749
+ if (this.ctx = ctx, 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} `))}.
4072
3750
  Running mixed versions is not supported and may lead into bugs
4073
3751
  Update your dependencies and make sure the versions match.`));
4074
3752
  const config = ctx.config.coverage;
@@ -4086,25 +3764,18 @@ Update your dependencies and make sure the versions match.`));
4086
3764
  statements: config.thresholds["100"] ? 100 : config.thresholds.statements
4087
3765
  }
4088
3766
  };
4089
- const shard = this.ctx.config.shard;
4090
- const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
4091
- this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory);
3767
+ const shard = this.ctx.config.shard, tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
4092
3768
  // If --project filter is set pick only roots of resolved projects
4093
- this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
3769
+ this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory), this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
4094
3770
  }
4095
3771
  /**
4096
3772
  * Check if file matches `coverage.include` but not `coverage.exclude`
4097
3773
  */
4098
3774
  isIncluded(_filename, root) {
4099
- const roots = root ? [root] : this.roots;
4100
- const filename = slash(_filename);
4101
- const cacheHit = this.globCache.get(filename);
3775
+ const roots = root ? [root] : this.roots, filename = slash(_filename), cacheHit = this.globCache.get(filename);
4102
3776
  if (cacheHit !== void 0) return cacheHit;
4103
3777
  // File outside project root with default allowExternal
4104
- if (this.options.allowExternal === false && roots.every((root) => !filename.startsWith(root))) {
4105
- this.globCache.set(filename, false);
4106
- return false;
4107
- }
3778
+ if (this.options.allowExternal === false && roots.every((root) => !filename.startsWith(root))) return this.globCache.set(filename, false), false;
4108
3779
  // By default `coverage.include` matches all files, except "coverage.exclude"
4109
3780
  const glob = this.options.include || "**";
4110
3781
  let included = roots.some((root) => {
@@ -4116,9 +3787,7 @@ Update your dependencies and make sure the versions match.`));
4116
3787
  };
4117
3788
  return pm.isMatch(filename, glob, options);
4118
3789
  });
4119
- included &&= existsSync(cleanUrl(filename));
4120
- this.globCache.set(filename, included);
4121
- return included;
3790
+ return included &&= existsSync(cleanUrl(filename)), this.globCache.set(filename, included), included;
4122
3791
  }
4123
3792
  async getUntestedFilesByRoot(testedFiles, include, root) {
4124
3793
  let includedFiles = await glob(include, {
@@ -4128,15 +3797,12 @@ Update your dependencies and make sure the versions match.`));
4128
3797
  dot: true,
4129
3798
  onlyFiles: true
4130
3799
  });
4131
- // Run again through picomatch as tinyglobby's exclude pattern is different ({ "exclude": ["math"] } should ignore "src/math.ts")
4132
- includedFiles = includedFiles.filter((file) => this.isIncluded(file, root));
4133
- if (this.ctx.config.changed) includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
3800
+ if (includedFiles = includedFiles.filter((file) => this.isIncluded(file, root)), this.ctx.config.changed) includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
4134
3801
  return includedFiles.map((file) => slash(path.resolve(root, file)));
4135
3802
  }
4136
3803
  async getUntestedFiles(testedFiles) {
4137
3804
  if (this.options.include == null) return [];
4138
- const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include);
4139
- const matrix = await Promise.all(this.roots.map(rootMapper));
3805
+ const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include), matrix = await Promise.all(this.roots.map(rootMapper));
4140
3806
  return matrix.flatMap((files) => files);
4141
3807
  }
4142
3808
  createCoverageMap() {
@@ -4162,41 +3828,28 @@ Update your dependencies and make sure the versions match.`));
4162
3828
  force: true,
4163
3829
  maxRetries: 10
4164
3830
  });
4165
- await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true });
4166
- this.coverageFiles = /* @__PURE__ */ new Map();
4167
- this.pendingPromises = [];
3831
+ await promises$1.mkdir(this.coverageFilesDirectory, { recursive: true }), this.coverageFiles = /* @__PURE__ */ new Map(), this.pendingPromises = [];
4168
3832
  }
4169
3833
  onAfterSuiteRun({ coverage, environment, projectName, testFiles }) {
4170
3834
  if (!coverage) return;
4171
3835
  let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
4172
- if (!entry) {
4173
- entry = {};
4174
- this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
4175
- }
4176
- const testFilenames = testFiles.join();
4177
- const filename = resolve$1(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
4178
- entry[environment] ??= {};
3836
+ if (!entry) entry = {}, this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
3837
+ const testFilenames = testFiles.join(), filename = resolve$1(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
4179
3838
  // If there's a result from previous run, overwrite it
4180
- entry[environment][testFilenames] = filename;
3839
+ entry[environment] ??= {}, entry[environment][testFilenames] = filename;
4181
3840
  const promise = promises$1.writeFile(filename, JSON.stringify(coverage), "utf-8");
4182
3841
  this.pendingPromises.push(promise);
4183
3842
  }
4184
3843
  async readCoverageFiles({ onFileRead, onFinished, onDebug }) {
4185
3844
  let index = 0;
4186
3845
  const total = this.pendingPromises.length;
4187
- await Promise.all(this.pendingPromises);
4188
- this.pendingPromises = [];
3846
+ await Promise.all(this.pendingPromises), this.pendingPromises = [];
4189
3847
  for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) for (const [environment, coverageByTestfiles] of Object.entries(coveragePerProject)) {
4190
- const filenames = Object.values(coverageByTestfiles);
4191
- const project = this.ctx.getProjectByName(projectName);
3848
+ const filenames = Object.values(coverageByTestfiles), project = this.ctx.getProjectByName(projectName);
4192
3849
  for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
4193
- if (onDebug.enabled) {
4194
- index += chunk.length;
4195
- onDebug(`Reading coverage results ${index}/${total}`);
4196
- }
3850
+ if (onDebug.enabled) index += chunk.length, onDebug(`Reading coverage results ${index}/${total}`);
4197
3851
  await Promise.all(chunk.map(async (filename) => {
4198
- const contents = await promises$1.readFile(filename, "utf-8");
4199
- const coverage = JSON.parse(contents);
3852
+ const contents = await promises$1.readFile(filename, "utf-8"), coverage = JSON.parse(contents);
4200
3853
  onFileRead(coverage);
4201
3854
  }));
4202
3855
  }
@@ -4204,10 +3857,8 @@ Update your dependencies and make sure the versions match.`));
4204
3857
  }
4205
3858
  }
4206
3859
  async cleanAfterRun() {
4207
- this.coverageFiles = /* @__PURE__ */ new Map();
4208
- await promises$1.rm(this.coverageFilesDirectory, { recursive: true });
4209
3860
  // Remove empty reports directory, e.g. when only text-reporter is used
4210
- if (readdirSync(this.options.reportsDirectory).length === 0) await promises$1.rm(this.options.reportsDirectory, { recursive: true });
3861
+ if (this.coverageFiles = /* @__PURE__ */ new Map(), await promises$1.rm(this.coverageFilesDirectory, { recursive: true }), readdirSync(this.options.reportsDirectory).length === 0) await promises$1.rm(this.options.reportsDirectory, { recursive: true });
4211
3862
  }
4212
3863
  async onTestFailure() {
4213
3864
  if (!this.options.reportOnFailure) await this.cleanAfterRun();
@@ -4220,11 +3871,9 @@ Update your dependencies and make sure the versions match.`));
4220
3871
  }
4221
3872
  async reportThresholds(coverageMap, allTestsRun) {
4222
3873
  const resolvedThresholds = this.resolveThresholds(coverageMap);
4223
- this.checkThresholds(resolvedThresholds);
4224
- if (this.options.thresholds?.autoUpdate && allTestsRun) {
3874
+ if (this.checkThresholds(resolvedThresholds), this.options.thresholds?.autoUpdate && allTestsRun) {
4225
3875
  if (!this.ctx.server.config.configFile) throw new Error("Missing configurationFile. The \"coverage.thresholds.autoUpdate\" can only be enabled when configuration file is used.");
4226
- const configFilePath = this.ctx.server.config.configFile;
4227
- const configModule = await this.parseConfigModule(configFilePath);
3876
+ const configFilePath = this.ctx.server.config.configFile, configModule = await this.parseConfigModule(configFilePath);
4228
3877
  await this.updateThresholds({
4229
3878
  thresholds: resolvedThresholds,
4230
3879
  configurationFile: configModule,
@@ -4238,16 +3887,10 @@ Update your dependencies and make sure the versions match.`));
4238
3887
  * for specific files defined by glob pattern or global for all other files.
4239
3888
  */
4240
3889
  resolveThresholds(coverageMap) {
4241
- const resolvedThresholds = [];
4242
- const files = coverageMap.files();
4243
- const globalCoverageMap = this.createCoverageMap();
3890
+ const resolvedThresholds = [], files = coverageMap.files(), globalCoverageMap = this.createCoverageMap();
4244
3891
  for (const key of Object.keys(this.options.thresholds)) {
4245
3892
  if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) continue;
4246
- const glob = key;
4247
- const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]);
4248
- const globCoverageMap = this.createCoverageMap();
4249
- const matcher = pm(glob);
4250
- const matchingFiles = files.filter((file) => matcher(relative(this.ctx.config.root, file)));
3893
+ const glob = key, globThresholds = resolveGlobThresholds(this.options.thresholds[glob]), globCoverageMap = this.createCoverageMap(), matcher = pm(glob), matchingFiles = files.filter((file) => matcher(relative(this.ctx.config.root, file)));
4251
3894
  for (const file of matchingFiles) {
4252
3895
  const fileCoverage = coverageMap.fileCoverageFor(file);
4253
3896
  globCoverageMap.addFileCoverage(fileCoverage);
@@ -4263,7 +3906,7 @@ Update your dependencies and make sure the versions match.`));
4263
3906
  const fileCoverage = coverageMap.fileCoverageFor(file);
4264
3907
  globalCoverageMap.addFileCoverage(fileCoverage);
4265
3908
  }
4266
- resolvedThresholds.unshift({
3909
+ return resolvedThresholds.unshift({
4267
3910
  name: GLOBAL_THRESHOLDS_KEY,
4268
3911
  coverageMap: globalCoverageMap,
4269
3912
  thresholds: {
@@ -4272,8 +3915,7 @@ Update your dependencies and make sure the versions match.`));
4272
3915
  lines: this.options.thresholds?.lines,
4273
3916
  statements: this.options.thresholds?.statements
4274
3917
  }
4275
- });
4276
- return resolvedThresholds;
3918
+ }), resolvedThresholds;
4277
3919
  }
4278
3920
  /**
4279
3921
  * Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
@@ -4311,8 +3953,7 @@ Update your dependencies and make sure the versions match.`));
4311
3953
  this.ctx.logger.error(errorMessage);
4312
3954
  }
4313
3955
  } else {
4314
- const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered;
4315
- const absoluteThreshold = threshold * -1;
3956
+ const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered, absoluteThreshold = threshold * -1;
4316
3957
  if (uncovered > absoluteThreshold) {
4317
3958
  process.exitCode = 1;
4318
3959
  /**
@@ -4336,8 +3977,7 @@ Update your dependencies and make sure the versions match.`));
4336
3977
  const config = resolveConfig(configurationFile);
4337
3978
  assertConfigurationModule(config);
4338
3979
  for (const { coverageMap, thresholds, name } of allThresholds) {
4339
- const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => coverageMap.fileCoverageFor(file).toSummary()) : [coverageMap.getCoverageSummary()];
4340
- const thresholdsToUpdate = [];
3980
+ const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => coverageMap.fileCoverageFor(file).toSummary()) : [coverageMap.getCoverageSummary()], thresholdsToUpdate = [];
4341
3981
  for (const key of THRESHOLD_KEYS) {
4342
3982
  const threshold = thresholds[key] ?? 100;
4343
3983
  /**
@@ -4348,8 +3988,7 @@ Update your dependencies and make sure the versions match.`));
4348
3988
  const actual = Math.min(...summaries.map((summary) => summary[key].pct));
4349
3989
  if (actual > threshold) thresholdsToUpdate.push([key, actual]);
4350
3990
  } else {
4351
- const absoluteThreshold = threshold * -1;
4352
- const actual = Math.max(...summaries.map((summary) => summary[key].total - summary[key].covered));
3991
+ const absoluteThreshold = threshold * -1, actual = Math.max(...summaries.map((summary) => summary[key].total - summary[key].covered));
4353
3992
  if (actual < absoluteThreshold) {
4354
3993
  // If everything was covered, set new threshold to 100% (since a threshold of 0 would be considered as 0%)
4355
3994
  const updatedThreshold = actual === 0 ? 100 : actual * -1;
@@ -4365,10 +4004,7 @@ Update your dependencies and make sure the versions match.`));
4365
4004
  glob[threshold] = newValue;
4366
4005
  }
4367
4006
  }
4368
- if (updatedThresholds) {
4369
- this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds.");
4370
- onUpdate();
4371
- }
4007
+ if (updatedThresholds) this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds."), onUpdate();
4372
4008
  }
4373
4009
  async mergeReports(coverageMaps) {
4374
4010
  const coverageMap = this.createCoverageMap();
@@ -4380,10 +4016,8 @@ Update your dependencies and make sure the versions match.`));
4380
4016
  }
4381
4017
  toSlices(array, size) {
4382
4018
  return array.reduce((chunks, item) => {
4383
- const index = Math.max(0, chunks.length - 1);
4384
- const lastChunk = chunks[index] || [];
4385
- chunks[index] = lastChunk;
4386
- if (lastChunk.length >= size) chunks.push([item]);
4019
+ const index = Math.max(0, chunks.length - 1), lastChunk = chunks[index] || [];
4020
+ if (chunks[index] = lastChunk, lastChunk.length >= size) chunks.push([item]);
4387
4021
  else lastChunk.push(item);
4388
4022
  return chunks;
4389
4023
  }, []);
@@ -4393,13 +4027,13 @@ Update your dependencies and make sure the versions match.`));
4393
4027
  root: project.config.root,
4394
4028
  isBrowserEnabled: project.isBrowserEnabled(),
4395
4029
  vite: project.vite
4396
- })),
4030
+ })), (
4397
4031
  // Check core last as it will match all files anyway
4398
- {
4032
+ {
4399
4033
  root: ctx.config.root,
4400
4034
  vite: ctx.vite,
4401
4035
  isBrowserEnabled: ctx.getRootProject().isBrowserEnabled()
4402
- }];
4036
+ })];
4403
4037
  return async function transformFile(filename) {
4404
4038
  let lastError;
4405
4039
  for (const { root, vite, isBrowserEnabled } of servers) {
@@ -4424,14 +4058,12 @@ Update your dependencies and make sure the versions match.`));
4424
4058
  * Narrow down `unknown` glob thresholds to resolved ones
4425
4059
  */
4426
4060
  function resolveGlobThresholds(thresholds) {
4427
- if (!thresholds || typeof thresholds !== "object") return {};
4428
- if (100 in thresholds && thresholds[100] === true) return {
4061
+ return !thresholds || typeof thresholds !== "object" ? {} : 100 in thresholds && thresholds[100] === true ? {
4429
4062
  lines: 100,
4430
4063
  branches: 100,
4431
4064
  functions: 100,
4432
4065
  statements: 100
4433
- };
4434
- return {
4066
+ } : {
4435
4067
  lines: "lines" in thresholds && typeof thresholds.lines === "number" ? thresholds.lines : void 0,
4436
4068
  branches: "branches" in thresholds && typeof thresholds.branches === "number" ? thresholds.branches : void 0,
4437
4069
  functions: "functions" in thresholds && typeof thresholds.functions === "number" ? thresholds.functions : void 0,
@@ -4457,8 +4089,7 @@ function resolveConfig(configModule) {
4457
4089
  if (config) return config;
4458
4090
  // "export default mergeConfig(..., defineConfig(...))"
4459
4091
  if (mod.$type === "function-call" && mod.$callee === "mergeConfig") {
4460
- config = resolveMergeConfig(mod);
4461
- if (config) return config;
4092
+ if (config = resolveMergeConfig(mod), config) return config;
4462
4093
  }
4463
4094
  } catch (error) {
4464
4095
  // Reduce magicast's verbose errors to readable ones