vitest 4.0.6 → 4.0.7

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 (43) hide show
  1. package/dist/browser.d.ts +2 -2
  2. package/dist/chunks/{base.BAf_bYeI.js → base.D3GxgUMI.js} +43 -50
  3. package/dist/chunks/{browser.d.ScGeWTou.d.ts → browser.d.-LKfRopd.d.ts} +1 -1
  4. package/dist/chunks/{cac.BBqWH4nd.js → cac.G9DAn-c7.js} +8 -7
  5. package/dist/chunks/{cli-api.UL3SwFUb.js → cli-api.Csks4as1.js} +29 -24
  6. package/dist/chunks/{coverage.DuCn_Tmx.js → coverage.C2LA1DSL.js} +9 -1
  7. package/dist/chunks/{global.d.DdOkMiVb.d.ts → global.d.DxtanrNO.d.ts} +1 -1
  8. package/dist/chunks/{index.BL8Hg4Uk.js → index.CVpyv-Zg.js} +7 -9
  9. package/dist/chunks/{index.DV0mQLEO.js → index.CWIFvlX5.js} +50 -24
  10. package/dist/chunks/{resolveSnapshotEnvironment.BZzLjzkh.js → index.DEPqWSIZ.js} +12 -12
  11. package/dist/chunks/{index.CpdwpN7L.js → index.jMQYiEWE.js} +1 -1
  12. package/dist/chunks/{init-forks.CSGFj9zN.js → init-forks.IU-xQ2_X.js} +3 -2
  13. package/dist/chunks/{init-threads.CIJLeFO8.js → init-threads.C_NWvZkU.js} +3 -2
  14. package/dist/chunks/{init.DUeOfNO9.js → init.fmH9J833.js} +85 -38
  15. package/dist/chunks/{moduleRunner.d.TP-w6tIQ.d.ts → moduleRunner.d.DEkTotCv.d.ts} +1 -1
  16. package/dist/chunks/{plugin.d.lctzD3Wk.d.ts → plugin.d.Cpes8Bt6.d.ts} +1 -1
  17. package/dist/chunks/{reporters.d.PEs0tXod.d.ts → reporters.d.CSNcMDxF.d.ts} +15 -6
  18. package/dist/chunks/{rpc.Dv1Jt3i2.js → rpc.D38ahn14.js} +8 -11
  19. package/dist/chunks/{startModuleRunner.Di-EZqh0.js → startModuleRunner.Cn7hCL7D.js} +26 -26
  20. package/dist/chunks/{test.CnspO-X4.js → test.B6aJd6T3.js} +1 -1
  21. package/dist/chunks/{vm.Co_lR2NL.js → vm.BL7_zzOr.js} +6 -5
  22. package/dist/chunks/{worker.d.B4Hthdvt.d.ts → worker.d.D25zYZ7N.d.ts} +22 -4
  23. package/dist/cli.js +2 -2
  24. package/dist/config.d.ts +5 -5
  25. package/dist/coverage.d.ts +3 -3
  26. package/dist/coverage.js +1 -1
  27. package/dist/environments.js +2 -1
  28. package/dist/index.d.ts +5 -5
  29. package/dist/module-evaluator.d.ts +2 -2
  30. package/dist/module-runner.js +1 -1
  31. package/dist/node.d.ts +7 -7
  32. package/dist/node.js +7 -7
  33. package/dist/reporters.d.ts +3 -3
  34. package/dist/reporters.js +2 -2
  35. package/dist/runners.js +2 -2
  36. package/dist/worker.d.ts +2 -1
  37. package/dist/worker.js +21 -21
  38. package/dist/workers/forks.js +27 -24
  39. package/dist/workers/runVmTests.js +4 -4
  40. package/dist/workers/threads.js +27 -24
  41. package/dist/workers/vmForks.js +10 -10
  42. package/dist/workers/vmThreads.js +10 -10
  43. package/package.json +12 -12
package/dist/browser.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as SerializedCoverageConfig, S as SerializedConfig } from './chunks/config.d.BTfZNUu9.js';
2
2
  import { R as RuntimeCoverageModuleLoader } from './chunks/coverage.d.BZtK59WP.js';
3
3
  import { SerializedDiffOptions } from '@vitest/utils/diff';
4
- import { V as VitestModuleRunner } from './chunks/moduleRunner.d.TP-w6tIQ.js';
4
+ import { V as VitestModuleRunner } from './chunks/moduleRunner.d.DEkTotCv.js';
5
5
  export { collectTests, startTests } from '@vitest/runner';
6
6
  import * as _vitest_spy from '@vitest/spy';
7
7
  export { _vitest_spy as SpyModule };
@@ -15,7 +15,7 @@ import '@vitest/pretty-format';
15
15
  import '@vitest/snapshot';
16
16
  import 'node:vm';
17
17
  import 'vite/module-runner';
18
- import './chunks/worker.d.B4Hthdvt.js';
18
+ import './chunks/worker.d.D25zYZ7N.js';
19
19
  import './chunks/environment.d.CrsxCzP1.js';
20
20
  import '@vitest/mocker';
21
21
  import './chunks/mocker.d.BE_2ls6u.js';
@@ -1,10 +1,11 @@
1
1
  import { runInThisContext } from 'node:vm';
2
2
  import * as spyModule from '@vitest/spy';
3
+ import { r as resolveTestRunner, a as resolveSnapshotEnvironment, s as setupChaiConfig } from './index.DEPqWSIZ.js';
4
+ import { l as loadEnvironment } from './init.fmH9J833.js';
3
5
  import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
4
- import { s as startVitestModuleRunner, c as createNodeImportMeta } from './startModuleRunner.Di-EZqh0.js';
5
- import { performance } from 'node:perf_hooks';
6
+ import { s as startVitestModuleRunner, c as createNodeImportMeta } from './startModuleRunner.Cn7hCL7D.js';
7
+ import { performance as performance$1 } from 'node:perf_hooks';
6
8
  import { startTests, collectTests } from '@vitest/runner';
7
- import { a as resolveSnapshotEnvironment, s as setupChaiConfig, r as resolveTestRunner } from './resolveSnapshotEnvironment.BZzLjzkh.js';
8
9
  import { c as setupCommonEnv, s as startCoverageInsideWorker, a as stopCoverageInsideWorker } from './setup-common.DR1sucx6.js';
9
10
  import { g as globalExpect, v as vi } from './vi.BZvkKVkM.js';
10
11
  import { c as closeInspector } from './inspector.DLZxSeU3.js';
@@ -13,20 +14,16 @@ import timers from 'node:timers';
13
14
  import timersPromises from 'node:timers/promises';
14
15
  import util from 'node:util';
15
16
  import { KNOWN_ASSET_TYPES } from '@vitest/utils/constants';
16
- import { getSafeTimers } from '@vitest/utils/timers';
17
17
  import { i as index } from './index.RwjEGCQ0.js';
18
18
  import { g as getWorkerState, r as resetModules, p as provideWorkerState } from './utils.CG9h5ccR.js';
19
19
 
20
20
  // this should only be used in Node
21
21
  let globalSetup = false;
22
- async function setupGlobalEnv(config, { environment }, moduleRunner) {
23
- await setupCommonEnv(config), Object.defineProperty(globalThis, "__vitest_index__", {
22
+ async function setupGlobalEnv(config, environment) {
23
+ if (await setupCommonEnv(config), Object.defineProperty(globalThis, "__vitest_index__", {
24
24
  value: index,
25
25
  enumerable: false
26
- });
27
- const state = getWorkerState();
28
- if (!state.config.snapshotOptions.snapshotEnvironment) state.config.snapshotOptions.snapshotEnvironment = await resolveSnapshotEnvironment(config, moduleRunner);
29
- if (!globalSetup) {
26
+ }), globalExpect.setState({ environment: environment.name }), !globalSetup) {
30
27
  if (globalSetup = true, (environment.viteEnvironment || environment.name) === "client") {
31
28
  const _require = createRequire(import.meta.url);
32
29
  _require.extensions[".css"] = resolveCss, _require.extensions[".scss"] = resolveCss, _require.extensions[".sass"] = resolveCss, _require.extensions[".less"] = resolveCss, KNOWN_ASSET_TYPES.forEach((type) => {
@@ -50,36 +47,28 @@ async function setupConsoleLogSpy() {
50
47
  const { createCustomConsole } = await import('./console.CTJL2nuH.js');
51
48
  globalThis.console = createCustomConsole();
52
49
  }
53
- async function withEnv({ environment }, options, fn) {
54
- globalThis.__vitest_environment__ = environment.name, globalExpect.setState({ environment: environment.name });
55
- const env = await environment.setup(globalThis, options);
56
- try {
57
- await fn();
58
- } finally {
59
- // Run possible setTimeouts, e.g. the onces used by ConsoleLogSpy
60
- const { setTimeout } = getSafeTimers();
61
- await new Promise((resolve) => setTimeout(resolve)), await env.teardown(globalThis);
62
- }
63
- }
64
50
 
65
51
  // browser shouldn't call this!
66
- async function run(method, files, config, environment, moduleRunner) {
67
- const workerState = getWorkerState();
68
- if (await setupGlobalEnv(config, environment, moduleRunner), await startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate }), config.chaiConfig) setupChaiConfig(config.chaiConfig);
69
- const runner = await resolveTestRunner(config, moduleRunner);
70
- workerState.onCancel.then((reason) => {
71
- closeInspector(config), runner.cancel?.(reason);
72
- }), workerState.durations.prepare = performance.now() - workerState.durations.prepare, workerState.durations.environment = performance.now(), await withEnv(environment, environment.options || config.environmentOptions || {}, async () => {
73
- workerState.durations.environment = performance.now() - workerState.durations.environment;
74
- for (const file of files) {
75
- if (config.isolate) moduleRunner.mocker.reset(), resetModules(workerState.evaluatedModules, true);
76
- if (workerState.filepath = file.filepath, method === "run") await startTests([file], runner);
77
- else await collectTests([file], runner);
78
- // mocks should not affect different files
79
- vi.resetConfig(), vi.restoreAllMocks();
80
- }
81
- await stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate });
82
- }), workerState.environmentTeardownRun = true;
52
+ async function run(method, files, config, moduleRunner, environment) {
53
+ const workerState = getWorkerState(), [testRunner] = await Promise.all([
54
+ resolveTestRunner(config, moduleRunner),
55
+ setupGlobalEnv(config, environment),
56
+ startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate }),
57
+ (async () => {
58
+ if (!workerState.config.snapshotOptions.snapshotEnvironment) workerState.config.snapshotOptions.snapshotEnvironment = await resolveSnapshotEnvironment(config, moduleRunner);
59
+ })()
60
+ ]);
61
+ workerState.onCancel((reason) => {
62
+ closeInspector(config), testRunner.cancel?.(reason);
63
+ }), workerState.durations.prepare = performance$1.now() - workerState.durations.prepare;
64
+ for (const file of files) {
65
+ if (config.isolate) moduleRunner.mocker.reset(), resetModules(workerState.evaluatedModules, true);
66
+ if (workerState.filepath = file.filepath, method === "run") await startTests([file], testRunner);
67
+ else await collectTests([file], testRunner);
68
+ // mocks should not affect different files
69
+ vi.resetConfig(), vi.restoreAllMocks();
70
+ }
71
+ await stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate });
83
72
  }
84
73
 
85
74
  let _moduleRunner;
@@ -87,29 +76,36 @@ const evaluatedModules = new VitestEvaluatedModules(), moduleExecutionInfo = /*
87
76
  function startModuleRunner(options) {
88
77
  return _moduleRunner || (_moduleRunner = startVitestModuleRunner(options), _moduleRunner);
89
78
  }
79
+ let _currentEnvironment, _environmentTime;
80
+ async function setupEnvironment(context) {
81
+ const startTime = performance.now(), { environment: { name: environmentName, options: environmentOptions }, rpc, config } = context, { environment, loader } = await loadEnvironment(environmentName, config.root, rpc);
82
+ _currentEnvironment = environment;
83
+ const env = await environment.setup(globalThis, environmentOptions || config.environmentOptions || {});
84
+ if (_environmentTime = performance.now() - startTime, config.chaiConfig) setupChaiConfig(config.chaiConfig);
85
+ return async () => {
86
+ await env.teardown(globalThis), await loader?.close();
87
+ };
88
+ }
90
89
  /** @experimental */
91
90
  async function runBaseTests(method, state) {
92
91
  const { ctx } = state;
93
- if (state.evaluatedModules = evaluatedModules, state.moduleExecutionInfo = moduleExecutionInfo, provideWorkerState(globalThis, state), ctx.invalidates) ctx.invalidates.forEach((filepath) => {
92
+ if (state.environment = _currentEnvironment, state.durations.environment = _environmentTime, state.evaluatedModules = evaluatedModules, state.moduleExecutionInfo = moduleExecutionInfo, provideWorkerState(globalThis, state), ctx.invalidates) ctx.invalidates.forEach((filepath) => {
94
93
  (state.evaluatedModules.fileToModulesMap.get(filepath) || []).forEach((module) => {
95
94
  state.evaluatedModules.invalidateModule(module);
96
95
  });
97
96
  });
98
97
  ctx.files.forEach((i) => {
99
- const filepath = typeof i === "string" ? i : i.filepath;
98
+ const filepath = i.filepath;
100
99
  (state.evaluatedModules.fileToModulesMap.get(filepath) || []).forEach((module) => {
101
100
  state.evaluatedModules.invalidateModule(module);
102
101
  });
103
102
  });
104
- const executor = startModuleRunner({
103
+ const moduleRunner = startModuleRunner({
105
104
  state,
106
105
  evaluatedModules: state.evaluatedModules,
107
106
  spyModule,
108
107
  createImportMeta: createNodeImportMeta
109
- }), fileSpecs = ctx.files.map((f) => typeof f === "string" ? {
110
- filepath: f,
111
- testLocations: void 0
112
- } : f);
108
+ });
113
109
  // we could load @vite/env, but it would take ~8ms, while this takes ~0,02ms
114
110
  if (ctx.config.serializedDefines) try {
115
111
  runInThisContext(`(() =>{\n${ctx.config.serializedDefines}})()`, {
@@ -119,10 +115,7 @@ async function runBaseTests(method, state) {
119
115
  } catch (error) {
120
116
  throw new Error(`Failed to load custom "defines": ${error.message}`);
121
117
  }
122
- await run(method, fileSpecs, ctx.config, {
123
- environment: state.environment,
124
- options: ctx.environment.options
125
- }, executor);
118
+ await run(method, ctx.files, ctx.config, moduleRunner, _currentEnvironment);
126
119
  }
127
120
 
128
- export { runBaseTests as r };
121
+ export { runBaseTests as r, setupEnvironment as s };
@@ -1,5 +1,5 @@
1
1
  import { FileSpecification } from '@vitest/runner';
2
- import { T as TestExecutionMethod } from './worker.d.B4Hthdvt.js';
2
+ import { T as TestExecutionMethod } from './worker.d.D25zYZ7N.js';
3
3
 
4
4
  type SerializedTestSpecification = [project: {
5
5
  name: string | undefined;
@@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
3
3
  import { normalize } from 'pathe';
4
4
  import c from 'tinyrainbow';
5
5
  import { a as defaultPort, d as defaultBrowserPort } from './constants.D_Q9UYh-.js';
6
- import { R as ReportersMap } from './index.BL8Hg4Uk.js';
6
+ import { R as ReportersMap } from './index.CVpyv-Zg.js';
7
7
 
8
8
  function toArr(any) {
9
9
  return any == null ? [] : Array.isArray(any) ? any : [any];
@@ -619,7 +619,7 @@ class CAC extends EventEmitter {
619
619
 
620
620
  const cac = (name = "") => new CAC(name);
621
621
 
622
- var version = "4.0.6";
622
+ var version = "4.0.7";
623
623
 
624
624
  const apiConfig = (port) => ({
625
625
  port: {
@@ -886,7 +886,8 @@ const cliOptionsConfig = {
886
886
  },
887
887
  execArgv: {
888
888
  description: "Pass additional arguments to `node` process when spawning `worker_threads` or `child_process`.",
889
- argument: "<option>"
889
+ argument: "<option>",
890
+ array: true
890
891
  },
891
892
  vmMemoryLimit: {
892
893
  description: "Memory limit for VM pools. If you see memory leaks, try to tinker this value.",
@@ -1294,10 +1295,10 @@ function normalizeCliOptions(cliFilters, argv) {
1294
1295
  }
1295
1296
  async function start(mode, cliFilters, options) {
1296
1297
  try {
1297
- const { startVitest } = await import('./cli-api.UL3SwFUb.js').then(function (n) { return n.p; }), ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options));
1298
+ const { startVitest } = await import('./cli-api.Csks4as1.js').then(function (n) { return n.p; }), ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options));
1298
1299
  if (!ctx.shouldKeepServer()) await ctx.exit();
1299
1300
  } catch (e) {
1300
- const { errorBanner } = await import('./index.BL8Hg4Uk.js').then(function (n) { return n.u; });
1301
+ const { errorBanner } = await import('./index.CVpyv-Zg.js').then(function (n) { return n.u; });
1301
1302
  if (console.error(`\n${errorBanner("Startup Error")}`), console.error(e), console.error("\n\n"), process.exitCode == null) process.exitCode = 1;
1302
1303
  process.exit();
1303
1304
  }
@@ -1309,7 +1310,7 @@ async function init(project) {
1309
1310
  }
1310
1311
  async function collect(mode, cliFilters, options) {
1311
1312
  try {
1312
- const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.UL3SwFUb.js').then(function (n) { return n.p; }), ctx = await prepareVitest(mode, {
1313
+ const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.Csks4as1.js').then(function (n) { return n.p; }), ctx = await prepareVitest(mode, {
1313
1314
  ...normalizeCliOptions(cliFilters, options),
1314
1315
  watch: false,
1315
1316
  run: true
@@ -1327,7 +1328,7 @@ async function collect(mode, cliFilters, options) {
1327
1328
  }
1328
1329
  await ctx.close();
1329
1330
  } catch (e) {
1330
- const { errorBanner } = await import('./index.BL8Hg4Uk.js').then(function (n) { return n.u; });
1331
+ const { errorBanner } = await import('./index.CVpyv-Zg.js').then(function (n) { return n.u; });
1331
1332
  if (console.error(`\n${errorBanner("Collect Error")}`), console.error(e), console.error("\n\n"), process.exitCode == null) process.exitCode = 1;
1332
1333
  process.exit();
1333
1334
  }
@@ -4,7 +4,7 @@ import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
4
4
  import path, { resolve as resolve$1 } from 'node:path';
5
5
  import { noop, createDefer, slash, isExternalUrl, unwrapId, nanoid, withTrailingSlash, cleanUrl, wrapId, toArray, deepMerge, deepClone, isPrimitive, notNullish } from '@vitest/utils/helpers';
6
6
  import { a as any, p as prompt } from './index.Dc3xnDvT.js';
7
- import { h as hash, R as RandomSequencer, i as isPackageExists, c as isBrowserEnabled, r as resolveConfig, g as getCoverageProvider, a as resolveApiServerConfig, d as resolveModule } from './coverage.DuCn_Tmx.js';
7
+ import { h as hash, R as RandomSequencer, i as isPackageExists, c as isBrowserEnabled, r as resolveConfig, g as getCoverageProvider, a as resolveApiServerConfig, d as resolveModule } from './coverage.C2LA1DSL.js';
8
8
  import * as vite from 'vite';
9
9
  import { parseAst, fetchModule, version, searchForWorkspaceRoot, mergeConfig, createServer } from 'vite';
10
10
  import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
@@ -12,9 +12,9 @@ import * as nodeos from 'node:os';
12
12
  import nodeos__default, { tmpdir } from 'node:os';
13
13
  import { generateHash as generateHash$1, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, hasFailed, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, getTasks, isTestCase } from '@vitest/runner/utils';
14
14
  import { SnapshotManager } from '@vitest/snapshot/manager';
15
- import { v as version$1 } from './cac.BBqWH4nd.js';
15
+ import { v as version$1 } from './cac.G9DAn-c7.js';
16
16
  import { c as createBirpc } from './index.Bgo3tNWt.js';
17
- import { p as parse, d as stringify, e as TraceMap, o as originalPositionFor, h as ancestor, i as printError, f as formatProjectName, w as withLabel, j as errorBanner, k as divider, l as Typechecker, m as generateCodeFrame, n as createDefinesScript, R as ReportersMap, B as BlobReporter, r as readBlobs, q as convertTasksToEvents, H as HangingProcessReporter } from './index.BL8Hg4Uk.js';
17
+ import { p as parse, d as stringify, e as TraceMap, o as originalPositionFor, h as ancestor, i as printError, f as formatProjectName, w as withLabel, j as errorBanner, k as divider, l as Typechecker, m as generateCodeFrame, n as createDefinesScript, R as ReportersMap, B as BlobReporter, r as readBlobs, q as convertTasksToEvents, H as HangingProcessReporter } from './index.CVpyv-Zg.js';
18
18
  import require$$0$3 from 'events';
19
19
  import require$$1$1 from 'https';
20
20
  import require$$2 from 'http';
@@ -51,7 +51,7 @@ import { c as configDefaults } from './defaults.BOqNVLsY.js';
51
51
  import { KNOWN_ASSET_RE } from '@vitest/utils/constants';
52
52
  import { findNearestPackageData } from '@vitest/utils/resolver';
53
53
  import * as esModuleLexer from 'es-module-lexer';
54
- import { a as BenchmarkReportsMap } from './index.CpdwpN7L.js';
54
+ import { a as BenchmarkReportsMap } from './index.jMQYiEWE.js';
55
55
  import assert$1 from 'node:assert';
56
56
  import { serializeValue } from '@vitest/utils/serialize';
57
57
  import { parseErrorStacktrace } from '@vitest/utils/source-map';
@@ -6449,7 +6449,15 @@ class PoolRunner {
6449
6449
  this.postMessage({
6450
6450
  type: "start",
6451
6451
  __vitest_worker_request__: true,
6452
- options: { reportMemory: this.worker.reportMemory ?? false }
6452
+ options: { reportMemory: this.worker.reportMemory ?? false },
6453
+ context: {
6454
+ environment: {
6455
+ name: this.environment.name,
6456
+ options: this.environment.options
6457
+ },
6458
+ config: this.project.serializedConfig,
6459
+ pool: this.worker.name
6460
+ }
6453
6461
  }), await startPromise, this._state = RunnerState.STARTED;
6454
6462
  } catch (error) {
6455
6463
  throw this._state = RunnerState.IDLE, error;
@@ -6512,9 +6520,10 @@ class PoolRunner {
6512
6520
  this._eventEmitter.emit("error", error);
6513
6521
  };
6514
6522
  waitForStart() {
6515
- return new Promise((resolve) => {
6523
+ return new Promise((resolve, reject) => {
6516
6524
  const onStart = (message) => {
6517
- if (message.type === "started") this.off("message", onStart), resolve();
6525
+ if (message.type === "started") if (this.off("message", onStart), message.error) reject(message.error);
6526
+ else resolve();
6518
6527
  };
6519
6528
  this.on("message", onStart);
6520
6529
  });
@@ -6555,13 +6564,7 @@ class ForksPoolWorker {
6555
6564
  this.fork.off(event, callback);
6556
6565
  }
6557
6566
  send(message) {
6558
- if ("context" in message) message = {
6559
- ...message,
6560
- context: {
6561
- ...message.context,
6562
- config: wrapSerializableConfig(message.context.config)
6563
- }
6564
- };
6567
+ if ("context" in message && "config" in message.context) message.context.config = wrapSerializableConfig(message.context.config);
6565
6568
  this.fork.send(v8.serialize(message));
6566
6569
  }
6567
6570
  async start() {
@@ -6712,7 +6715,7 @@ async function onMessage(message, project) {
6712
6715
  error: await runPromise,
6713
6716
  __vitest_worker_response__
6714
6717
  };
6715
- case "stop": return await runPromise, await project.typechecker?.stop(), {
6718
+ case "stop": return await runPromise, {
6716
6719
  type: "stopped",
6717
6720
  __vitest_worker_response__
6718
6721
  };
@@ -6770,6 +6773,8 @@ function createRunner(vitest) {
6770
6773
  resolve(false), clearInterval(_i);
6771
6774
  }, 500).unref();
6772
6775
  });
6776
+ // Re-run but wasn't triggered by tsc
6777
+ if (promisesMap.has(project) && !triggered) return promisesMap.get(project);
6773
6778
  if (project.typechecker && !triggered) {
6774
6779
  const testFiles = project.typechecker.getTestFiles();
6775
6780
  for (const file of testFiles) await vitest._testRun.enqueued(project, file);
@@ -6917,7 +6922,7 @@ catch (error) {
6917
6922
  distPath: this.options.distPath,
6918
6923
  project: task.project,
6919
6924
  method,
6920
- environment: task.context.environment.name,
6925
+ environment: task.environment,
6921
6926
  env: task.env,
6922
6927
  execArgv: task.execArgv
6923
6928
  };
@@ -6958,7 +6963,7 @@ function formatFiles(task) {
6958
6963
  }
6959
6964
  function isEqualRunner(runner, task) {
6960
6965
  if (task.isolate) throw new Error("Isolated tasks should not share runners");
6961
- return runner.worker.name === task.worker && runner.project === task.project && runner.environment === task.context.environment.name && (!runner.worker.canReuse || runner.worker.canReuse(task));
6966
+ return runner.worker.name === task.worker && runner.project === task.project && runner.environment.name === task.environment.name && (!runner.worker.canReuse || runner.worker.canReuse(task));
6962
6967
  }
6963
6968
 
6964
6969
  const suppressWarningsPath = resolve(rootDir, "./suppress-warnings.cjs");
@@ -7011,18 +7016,15 @@ function createPool(ctx) {
7011
7016
  if (!execArgv) execArgv = [...options.execArgv, ...project.config.execArgv], projectExecArgvs.set(project, execArgv);
7012
7017
  taskGroup.push({
7013
7018
  context: {
7014
- pool,
7015
- config: project.serializedConfig,
7016
7019
  files: specs.map((spec) => ({
7017
7020
  filepath: spec.moduleId,
7018
7021
  testLocations: spec.testLines
7019
7022
  })),
7020
7023
  invalidates,
7021
- environment,
7022
- projectName: project.name,
7023
7024
  providedContext: project.getProvidedContext(),
7024
7025
  workerId: workerId++
7025
7026
  },
7027
+ environment,
7026
7028
  project,
7027
7029
  env,
7028
7030
  execArgv,
@@ -7058,7 +7060,11 @@ function createPool(ctx) {
7058
7060
  runTests: (files, invalidates) => executeTests("run", files, invalidates),
7059
7061
  collectTests: (files, invalidates) => executeTests("collect", files, invalidates),
7060
7062
  async close() {
7061
- await Promise.all([pool.close(), browserPool?.close?.()]);
7063
+ await Promise.all([
7064
+ pool.close(),
7065
+ browserPool?.close?.(),
7066
+ ...ctx.projects.map((project) => project.typechecker?.stop())
7067
+ ]);
7062
7068
  }
7063
7069
  };
7064
7070
  }
@@ -7079,8 +7085,7 @@ function resolveOptions(ctx) {
7079
7085
  ...process.execArgv.filter((execArg) => execArg.startsWith("--cpu-prof") || execArg.startsWith("--heap-prof") || execArg.startsWith("--diagnostic-dir")),
7080
7086
  ...conditions,
7081
7087
  "--experimental-import-meta-resolve",
7082
- "--require",
7083
- suppressWarningsPath
7088
+ ...globalThis.Deno ? [] : ["--require", suppressWarningsPath]
7084
7089
  ],
7085
7090
  env: {
7086
7091
  TEST: "true",
@@ -2374,6 +2374,14 @@ class BaseSequencer {
2374
2374
  async sort(files) {
2375
2375
  const cache = this.ctx.cache;
2376
2376
  return [...files].sort((a, b) => {
2377
+ // "sequence.groupOrder" is higher priority
2378
+ const groupOrderDiff = a.project.config.sequence.groupOrder - b.project.config.sequence.groupOrder;
2379
+ if (groupOrderDiff !== 0) return groupOrderDiff;
2380
+ // Projects run sequential
2381
+ if (a.project.name !== b.project.name) return a.project.name < b.project.name ? -1 : 1;
2382
+ // Isolated run first
2383
+ if (a.project.config.isolate && !b.project.config.isolate) return -1;
2384
+ if (!a.project.config.isolate && b.project.config.isolate) return 1;
2377
2385
  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);
2378
2386
  if (!aState || !bState) {
2379
2387
  const statsA = cache.getFileStats(keyA), statsB = cache.getFileStats(keyB);
@@ -2647,7 +2655,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
2647
2655
  ...configDefaults.typecheck,
2648
2656
  ...resolved.typecheck
2649
2657
  }, 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."));
2650
- 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.commands ??= {}, resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve(resolved.root, resolved.browser.screenshotDirectory);
2658
+ if (resolved.browser.enabled ??= false, resolved.browser.headless ??= isCI, resolved.browser.isolate ??= resolved.isolate ?? true, resolved.browser.fileParallelism ??= options.fileParallelism ?? mode !== "benchmark", resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI, resolved.browser.commands ??= {}, resolved.browser.screenshotDirectory) resolved.browser.screenshotDirectory = resolve(resolved.root, resolved.browser.screenshotDirectory);
2651
2659
  if (resolved.inspector.enabled) resolved.browser.trackUnhandledErrors ??= false;
2652
2660
  if (resolved.browser.viewport ??= {}, resolved.browser.viewport.width ??= 414, resolved.browser.viewport.height ??= 896, resolved.browser.locators ??= {}, resolved.browser.locators.testIdAttribute ??= "data-testid", typeof resolved.browser.provider === "string") {
2653
2661
  const source = `@vitest/browser-${resolved.browser.provider}`;
@@ -2,7 +2,7 @@ import { PromisifyAssertion, Tester, ExpectStatic } from '@vitest/expect';
2
2
  import { Plugin } from '@vitest/pretty-format';
3
3
  import { SnapshotState } from '@vitest/snapshot';
4
4
  import { B as BenchmarkResult } from './benchmark.d.DAaHLpsq.js';
5
- import { U as UserConsoleLog } from './worker.d.B4Hthdvt.js';
5
+ import { U as UserConsoleLog } from './worker.d.D25zYZ7N.js';
6
6
 
7
7
  interface SnapshotMatcher<T> {
8
8
  <U extends { [P in keyof T] : any }>(snapshot: Partial<U>, hint?: string): void;
@@ -387,12 +387,12 @@ function countTestErrors(tasks) {
387
387
  }
388
388
  function getStateString$1(tasks, name = "tests", showTotal = true) {
389
389
  if (tasks.length === 0) return c.dim(`no ${name}`);
390
- const passed = tasks.filter((i) => i.result?.state === "pass"), failed = tasks.filter((i) => i.result?.state === "fail"), skipped = tasks.filter((i) => i.mode === "skip"), todo = tasks.filter((i) => i.mode === "todo");
390
+ const passed = tasks.reduce((acc, i) => i.result?.state === "pass" ? acc + 1 : acc, 0), failed = tasks.reduce((acc, i) => i.result?.state === "fail" ? acc + 1 : acc, 0), skipped = tasks.reduce((acc, i) => i.mode === "skip" ? acc + 1 : acc, 0), todo = tasks.reduce((acc, i) => i.mode === "todo" ? acc + 1 : acc, 0);
391
391
  return [
392
- failed.length ? c.bold(c.red(`${failed.length} failed`)) : null,
393
- passed.length ? c.bold(c.green(`${passed.length} passed`)) : null,
394
- skipped.length ? c.yellow(`${skipped.length} skipped`) : null,
395
- todo.length ? c.gray(`${todo.length} todo`) : null
392
+ failed ? c.bold(c.red(`${failed} failed`)) : null,
393
+ passed ? c.bold(c.green(`${passed} passed`)) : null,
394
+ skipped ? c.yellow(`${skipped} skipped`) : null,
395
+ todo ? c.gray(`${todo} todo`) : null
396
396
  ].filter(Boolean).join(c.dim(" | ")) + (showTotal ? c.gray(` (${tasks.length})`) : "");
397
397
  }
398
398
  function getStateSymbol(task) {
@@ -1016,7 +1016,7 @@ class SummaryReporter {
1016
1016
  name: testFile.projectName,
1017
1017
  color: testFile.projectColor
1018
1018
  }) + typecheck + testFile.filename + c.dim(!testFile.completed && !testFile.total ? " [queued]" : ` ${testFile.completed}/${testFile.total}`));
1019
- const slowTasks = [testFile.hook, ...Array.from(testFile.tests.values())].filter((t) => t != null && t.visible);
1019
+ const slowTasks = [testFile.hook, ...testFile.tests.values()].filter((t) => t != null && t.visible);
1020
1020
  for (const [index, task] of slowTasks.entries()) {
1021
1021
  const elapsed = this.currentTime - task.startTime, icon = index === slowTasks.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE;
1022
1022
  if (summary.push(c.bold(c.yellow(` ${icon} `)) + task.name + c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`))), task.hook?.visible) summary.push(c.bold(c.yellow(` ${F_TREE_NODE_END} `)) + task.hook.name);
@@ -2598,13 +2598,12 @@ function printErrorInner(error, project, options) {
2598
2598
  }
2599
2599
  });
2600
2600
  }
2601
- const testPath = e.VITEST_TEST_PATH, testName = e.VITEST_TEST_NAME, afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
2601
+ const testPath = e.VITEST_TEST_PATH, testName = e.VITEST_TEST_NAME;
2602
2602
  // testName has testPath inside
2603
2603
  if (testPath) logger.error(c.red(`This error originated in "${c.bold(relative(project.config.root, testPath))}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
2604
2604
  if (testName) logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:
2605
2605
  - The error was thrown, while Vitest was running this test.
2606
2606
  - If the error occurred after the test had been completed, this was the last documented test before it was thrown.`));
2607
- if (afterEnvTeardown) logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:\n- cancel timeouts using clearTimeout and clearInterval\n- wait for promises to resolve using the await keyword"));
2608
2607
  if (typeof e.cause === "object" && e.cause && "name" in e.cause) e.cause.name = `Caused by: ${e.cause.name}`, printErrorInner(e.cause, project, {
2609
2608
  showCodeFrame: false,
2610
2609
  logger: options.logger,
@@ -2636,7 +2635,6 @@ const skipErrorProperties = new Set([
2636
2635
  "columnNumber",
2637
2636
  "VITEST_TEST_NAME",
2638
2637
  "VITEST_TEST_PATH",
2639
- "VITEST_AFTER_ENV_TEARDOWN",
2640
2638
  "__vitest_rollup_error__",
2641
2639
  ...Object.getOwnPropertyNames(Error.prototype),
2642
2640
  ...Object.getOwnPropertyNames(Object.prototype)
@@ -1,3 +1,4 @@
1
+ import { URL } from 'node:url';
1
2
  import { Console } from 'node:console';
2
3
 
3
4
  // SEE https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/interfaces.js
@@ -136,6 +137,7 @@ const LIVING_KEYS = [
136
137
  "Plugin",
137
138
  "MimeType",
138
139
  "FileReader",
140
+ "FormData",
139
141
  "Blob",
140
142
  "File",
141
143
  "FileList",
@@ -366,7 +368,7 @@ var happy = {
366
368
  function catchWindowErrors(window) {
367
369
  let userErrorListenerCount = 0;
368
370
  function throwUnhandlerError(e) {
369
- if (userErrorListenerCount === 0 && e.error != null) process.emit("uncaughtException", e.error);
371
+ if (userErrorListenerCount === 0 && e.error != null) e.preventDefault(), process.emit("uncaughtException", e.error);
370
372
  }
371
373
  const addEventListener = window.addEventListener.bind(window), removeEventListener = window.removeEventListener.bind(window);
372
374
  return window.addEventListener("error", throwUnhandlerError), window.addEventListener = function(...args) {
@@ -379,13 +381,12 @@ function catchWindowErrors(window) {
379
381
  window.removeEventListener("error", throwUnhandlerError);
380
382
  };
381
383
  }
382
- let _FormData;
384
+ let NodeFormData_, NodeBlob_, NodeRequest_;
383
385
  var jsdom = {
384
386
  name: "jsdom",
385
387
  viteEnvironment: "client",
386
388
  async setupVM({ jsdom = {} }) {
387
- // delay initialization because it takes ~1s
388
- _FormData = globalThis.FormData;
389
+ NodeFormData_ = globalThis.FormData, NodeBlob_ = globalThis.Blob, NodeRequest_ = globalThis.Request;
389
390
  const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import('jsdom'), { html = "<!DOCTYPE html>", userAgent, url = "http://localhost:3000", contentType = "text/html", pretendToBeVisual = true, includeNodeLocations = false, runScripts = "dangerously", resources, console = false, cookieJar = false,...restOptions } = jsdom;
390
391
  let dom = new JSDOM(html, {
391
392
  pretendToBeVisual,
@@ -399,8 +400,8 @@ var jsdom = {
399
400
  userAgent,
400
401
  ...restOptions
401
402
  });
402
- const clearAddEventListenerPatch = patchAddEventListener(dom.window), clearWindowErrors = catchWindowErrors(dom.window);
403
- dom.window.Buffer = Buffer, dom.window.jsdom = dom, dom.window.FormData = createFormData(dom.window);
403
+ const clearAddEventListenerPatch = patchAddEventListener(dom.window), clearWindowErrors = catchWindowErrors(dom.window), utils = createCompatUtils(dom.window);
404
+ dom.window.Buffer = Buffer, dom.window.jsdom = dom, dom.window.Request = createCompatRequest(utils), dom.window.URL = createJSDOMCompatURL(utils);
404
405
  for (const name of [
405
406
  "structuredClone",
406
407
  "BroadcastChannel",
@@ -414,12 +415,10 @@ var jsdom = {
414
415
  }
415
416
  for (const name of [
416
417
  "fetch",
417
- "Request",
418
418
  "Response",
419
419
  "Headers",
420
420
  "AbortController",
421
421
  "AbortSignal",
422
- "URL",
423
422
  "URLSearchParams"
424
423
  ]) {
425
424
  const value = globalThis[name];
@@ -435,8 +434,7 @@ var jsdom = {
435
434
  };
436
435
  },
437
436
  async setup(global, { jsdom = {} }) {
438
- // delay initialization because it takes ~1s
439
- _FormData = globalThis.FormData;
437
+ NodeFormData_ = globalThis.FormData, NodeBlob_ = globalThis.Blob, NodeRequest_ = globalThis.Request;
440
438
  const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import('jsdom'), { html = "<!DOCTYPE html>", userAgent, url = "http://localhost:3000", contentType = "text/html", pretendToBeVisual = true, includeNodeLocations = false, runScripts = "dangerously", resources, console = false, cookieJar = false,...restOptions } = jsdom, dom = new JSDOM(html, {
441
439
  pretendToBeVisual,
442
440
  resources: resources ?? (userAgent ? new ResourceLoader({ userAgent }) : void 0),
@@ -448,26 +446,54 @@ var jsdom = {
448
446
  contentType,
449
447
  userAgent,
450
448
  ...restOptions
451
- }), clearAddEventListenerPatch = patchAddEventListener(dom.window), { keys, originals } = populateGlobal(global, dom.window, { bindFunctions: true }), clearWindowErrors = catchWindowErrors(global);
452
- return global.jsdom = dom, global.FormData = createFormData(dom.window), { teardown(global) {
449
+ }), clearAddEventListenerPatch = patchAddEventListener(dom.window), { keys, originals } = populateGlobal(global, dom.window, { bindFunctions: true }), clearWindowErrors = catchWindowErrors(global), utils = createCompatUtils(dom.window);
450
+ return global.jsdom = dom, global.Request = createCompatRequest(utils), global.URL = createJSDOMCompatURL(utils), { teardown(global) {
453
451
  clearAddEventListenerPatch(), clearWindowErrors(), dom.window.close(), delete global.jsdom, keys.forEach((key) => delete global[key]), originals.forEach((v, k) => global[k] = v);
454
452
  } };
455
453
  }
456
454
  };
457
- // Node.js 24 has a global FormData that Request accepts
458
- // FormData is not used anywhere else in JSDOM, so we can safely
459
- // override it with Node.js implementation, but keep the DOM behaviour
460
- // this is required because Request (and other fetch API)
461
- // are not implemented by JSDOM
462
- function createFormData(window) {
463
- const JSDOMFormData = window.FormData;
464
- return _FormData ? class FormData extends _FormData {
455
+ function createCompatRequest(utils) {
456
+ return class Request extends NodeRequest_ {
465
457
  constructor(...args) {
466
- super(), new JSDOMFormData(...args).forEach((value, key) => {
467
- this.append(key, value);
468
- });
458
+ const [input, init] = args;
459
+ if (init?.body != null) {
460
+ const compatInit = { ...init };
461
+ if (init.body instanceof utils.window.Blob) compatInit.body = utils.makeCompatBlob(init.body);
462
+ if (init.body instanceof utils.window.FormData) compatInit.body = utils.makeCompatFormData(init.body);
463
+ super(input, compatInit);
464
+ } else super(...args);
469
465
  }
470
- } : JSDOMFormData;
466
+ };
467
+ }
468
+ function createJSDOMCompatURL(utils) {
469
+ return class URL$1 extends URL {
470
+ static createObjectURL(blob) {
471
+ if (blob instanceof utils.window.Blob) {
472
+ const compatBlob = utils.makeCompatBlob(blob);
473
+ return URL.createObjectURL(compatBlob);
474
+ }
475
+ return URL.createObjectURL(blob);
476
+ }
477
+ };
478
+ }
479
+ function createCompatUtils(window) {
480
+ // this returns a hidden Symbol(impl)
481
+ // this is cursed, and jsdom should just implement fetch API itself
482
+ const implSymbol = Object.getOwnPropertySymbols(Object.getOwnPropertyDescriptors(new window.Blob()))[0], utils = {
483
+ window,
484
+ makeCompatFormData(formData) {
485
+ const nodeFormData = new NodeFormData_();
486
+ return formData.forEach((value, key) => {
487
+ if (value instanceof window.Blob) nodeFormData.append(key, utils.makeCompatBlob(value));
488
+ else nodeFormData.append(key, value);
489
+ }), nodeFormData;
490
+ },
491
+ makeCompatBlob(blob) {
492
+ const buffer = blob[implSymbol]._buffer;
493
+ return new NodeBlob_([buffer], { type: blob.type });
494
+ }
495
+ };
496
+ return utils;
471
497
  }
472
498
  function patchAddEventListener(window) {
473
499
  const JSDOMAbortSignal = window.AbortSignal, JSDOMAbortController = window.AbortController, originalAddEventListener = window.EventTarget.prototype.addEventListener;