vitest 5.0.0-beta.6 → 5.0.0-beta.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 (76) hide show
  1. package/LICENSE.md +165 -1
  2. package/dist/browser.d.ts +27 -14
  3. package/dist/browser.js +11 -14
  4. package/dist/chunks/{artifact.BNnEI1sJ.js → artifact.DC5WoEgy.js} +1305 -8
  5. package/dist/chunks/{base.BKfXyFN7.js → base.B0fUxpj9.js} +17 -13
  6. package/dist/chunks/{browser.d.DoM6vBOs.d.ts → browser.d.BFOby8YL.d.ts} +3 -3
  7. package/dist/chunks/{cac.DKrA6qEB.js → cac.B41kXwyU.js} +20 -22
  8. package/dist/chunks/check.Cz_-YojU.js +15 -0
  9. package/dist/chunks/cli-api.bqNN5viV.js +519 -0
  10. package/dist/chunks/{config.d.CKWK3nld.d.ts → config.d.DsC1jkby.d.ts} +871 -25
  11. package/dist/chunks/{console.DjVIMaXT.js → console.omGxyKMT.js} +5 -5
  12. package/dist/chunks/{coverage.CTzCuANN.js → coverage.BVb1JqW7.js} +7 -2
  13. package/dist/chunks/coverage.BfSEMtie.js +26 -0
  14. package/dist/chunks/coverage.d.ByaAMV4A.d.ts +88 -0
  15. package/dist/chunks/{creator.C4nK7Krt.js → creator.BzMFaPC-.js} +53 -29
  16. package/dist/chunks/{defaults.B_pFOTYy.js → defaults.BJUmAuaO.js} +2 -1
  17. package/dist/chunks/display.CYwyMF4S.js +192 -0
  18. package/dist/chunks/{env.BKKtU2WC.js → env.DzFJjrmK.js} +1 -1
  19. package/dist/chunks/{environment.d.CrsxCzP1.d.ts → environment.d.4-rzQgpt.d.ts} +1 -1
  20. package/dist/chunks/globals.sd6Qutmc.js +28 -0
  21. package/dist/chunks/{cli-api.cZcvaUFI.js → index.5krd73UD.js} +15958 -14627
  22. package/dist/chunks/{index.D6NDM5O1.js → index.CLtI1k_4.js} +135 -101
  23. package/dist/chunks/{index.DNRmy2jU.js → index.DxR-nMjO.js} +42 -4
  24. package/dist/chunks/index.DzTmMrSM.js +940 -0
  25. package/dist/chunks/{index.B4UTDegh.js → index.JaztIWgW.js} +5 -4
  26. package/dist/chunks/{init-forks.BG4bCDny.js → init-forks.CXzT841o.js} +1 -1
  27. package/dist/chunks/{init-threads.DLtIP5Qq.js → init-threads.Ch-Bw5j3.js} +1 -1
  28. package/dist/chunks/{init.DTAQFCjl.js → init.CfiYZpFg.js} +40 -24
  29. package/dist/chunks/{native.DPzPHdi5.js → native.BUCvPRKp.js} +3 -4
  30. package/dist/chunks/{nativeModuleMocker.BKtCThoO.js → nativeModuleMocker.Uot80PXb.js} +2 -3
  31. package/dist/chunks/{index.CesbTg1C.js → nativeModuleRunner.BDnwGb8g.js} +39 -3
  32. package/dist/chunks/{node.C9I1sbE9.js → node.BPMnm_Q2.js} +1 -1
  33. package/dist/chunks/offset.Dy-5Fdfn.js +24 -0
  34. package/dist/chunks/pathe.M-eThtNZ.CbK_Vbae.js +489 -0
  35. package/dist/chunks/{plugin.d.Bpge8Jye.d.ts → plugin.d.BOjbmxWW.d.ts} +1719 -1549
  36. package/dist/chunks/{plugins.DrsmdUE2.js → plugins.CsoX-42X.js} +1 -1
  37. package/dist/chunks/resolver.CERfsKE-.js +48 -0
  38. package/dist/chunks/{rpc.d.C6-dGZ2f.d.ts → rpc.d.BeasqWpO.d.ts} +14 -1
  39. package/dist/chunks/{rpc.DZEh5xnQ.js → rpc.iNjF664v.js} +2 -2
  40. package/dist/chunks/setup-common.vxjAyUtK.js +36 -0
  41. package/dist/chunks/setup.DasACXvo.js +5409 -0
  42. package/dist/chunks/source-map.DZdIqpIJ.js +1776 -0
  43. package/dist/chunks/spy.B8mHA9qu.js +422 -0
  44. package/dist/chunks/{task-utils.d.mMDXJF_I.d.ts → task-utils.d.BKHiHxSN.d.ts} +1 -2
  45. package/dist/chunks/tinyrainbow.Ht9iggcq.js +95 -0
  46. package/dist/chunks/{utils.DKODp04v.js → utils.CO-iLyCr.js} +41 -42
  47. package/dist/chunks/{vm.CeHWcIrU.js → vm.DoQh8CN9.js} +110 -11
  48. package/dist/chunks/{worker.d.JES7ffPK.d.ts → worker.d.s_RdeZtI.d.ts} +14 -11
  49. package/dist/cli.js +4 -5
  50. package/dist/config.cjs +1 -0
  51. package/dist/config.d.ts +19 -17
  52. package/dist/config.js +2 -2
  53. package/dist/index.d.ts +14 -29
  54. package/dist/index.js +11 -16
  55. package/dist/module-evaluator.d.ts +40 -8
  56. package/dist/module-evaluator.js +66 -22
  57. package/dist/node.d.ts +210 -82
  58. package/dist/node.js +29 -66
  59. package/dist/runtime.d.ts +5 -10
  60. package/dist/runtime.js +4 -5
  61. package/dist/spy.js +1 -1
  62. package/dist/task-utils.js +1 -2
  63. package/dist/worker.d.ts +5 -10
  64. package/dist/worker.js +24 -36
  65. package/dist/workers/forks.js +21 -33
  66. package/dist/workers/runVmTests.js +15 -20
  67. package/dist/workers/threads.js +21 -33
  68. package/dist/workers/vmForks.js +13 -15
  69. package/dist/workers/vmThreads.js +13 -15
  70. package/package.json +15 -15
  71. package/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -6
  72. package/dist/chunks/coverage.d.CCNrKR65.d.ts +0 -43
  73. package/dist/chunks/globals.CzUA1xn8.js +0 -33
  74. package/dist/chunks/index.Djaij2xr.js +0 -6960
  75. package/dist/chunks/nativeModuleRunner.WlMdOB52.js +0 -36
  76. package/dist/chunks/setup-common.ZNdeu5wa.js +0 -64
@@ -1,22 +1,17 @@
1
- import { T as TestSyntaxError, g as getCurrentTest, c as createTaskCollector, a as getCurrentSuite, b as createChainable, d as getHooks, e as getFn, m as matchesTags, f as afterAll, h as afterEach, i as aroundAll, j as aroundEach, k as beforeAll, l as beforeEach, n as describe, o as it, q as onTestFailed, r as onTestFinished, t as recordArtifact, u as suite, v as test } from './artifact.BNnEI1sJ.js';
1
+ import { b as printDiffOrStringify, d as diff, a as processError, T as TestSyntaxError, g as getCurrentTest, c as createTaskCollector, e as getCurrentSuite, f as createChainable, h as getHooks, i as getFn, m as matchesTags, j as afterAll, k as afterEach, l as aroundAll, n as aroundEach, o as beforeAll, q as beforeEach, r as describe, t as it, u as onTestFailed, v as onTestFinished, w as recordArtifact, x as suite, y as test } from './artifact.DC5WoEgy.js';
2
2
  import { i as isChildProcess, r as resetModules, g as getWorkerState } from './utils.DYj33du9.js';
3
- import { getSafeTimers, delay } from '@vitest/utils/timers';
4
- import { isMockFunction, fn, spyOn, restoreAllMocks, resetAllMocks, clearAllMocks } from '@vitest/spy';
5
- import { getType, isObject, noop, assertTypes, ordinal, createSimpleStackTrace, getCallLastIndex } from '@vitest/utils/helpers';
6
- import { positionToOffset, offsetToLineNumber, lineSplitRE } from '@vitest/utils/offset';
7
- import { parseSingleStack, parseErrorStacktrace } from '@vitest/utils/source-map';
8
- import { c as commonjsGlobal, g as getDefaultExportFromCjs } from './_commonjsHelpers.D26ty3Ew.js';
9
- import { R as RealDate, b as resetDate, m as mockDate, r as rpc, V as VitestEvaluatedModules } from './rpc.DZEh5xnQ.js';
10
- import { stringify, inspect } from '@vitest/utils/display';
11
- import { printDiffOrStringify, diff } from '@vitest/utils/diff';
12
- import c from 'tinyrainbow';
3
+ import { h as commonjsGlobal, a as getSafeTimers, f as parseSingleStack, i as delay, d as getDefaultExportFromCjs, j as parseErrorStacktrace } from './source-map.DZdIqpIJ.js';
4
+ import { i as isMockFunction, f as fn, a as spyOn, r as restoreAllMocks, b as resetAllMocks, c as clearAllMocks } from './spy.B8mHA9qu.js';
5
+ import { g as getType, v as isObject, p as noop, y as assertTypes, x as ordinal, D as createSimpleStackTrace, E as getCallLastIndex, i as isAbsolute, a as relative, n as normalize } from './pathe.M-eThtNZ.CbK_Vbae.js';
6
+ import { R as RealDate, b as resetDate, m as mockDate, r as rpc, V as VitestEvaluatedModules } from './rpc.iNjF664v.js';
7
+ import { s as stringify, i as inspect } from './display.CYwyMF4S.js';
8
+ import { y } from './tinyrainbow.Ht9iggcq.js';
13
9
  import * as chai from 'chai';
14
10
  import { use, util } from 'chai';
15
- import { processError } from '@vitest/utils/error';
16
11
  import { getNames, getTests, getTestName, createFileTask } from '../task-utils.js';
17
- import { g as getSerializers, a as addSerializer } from './plugins.DrsmdUE2.js';
18
- import { format } from '@vitest/pretty-format';
19
- import { isAbsolute, relative, normalize } from 'pathe';
12
+ import { g as getSerializers, a as addSerializer } from './plugins.CsoX-42X.js';
13
+ import { p as positionToOffset, o as offsetToLineNumber, l as lineSplitRE } from './offset.Dy-5Fdfn.js';
14
+ import { f as format } from './index.DzTmMrSM.js';
20
15
  import { Bench } from 'tinybench';
21
16
  import { expectTypeOf } from 'expect-type';
22
17
 
@@ -119,11 +114,11 @@ ${printReceived(actual)}`
119
114
  }
120
115
  };
121
116
 
122
- const EXPECTED_COLOR = c.green;
123
- const RECEIVED_COLOR = c.red;
124
- const INVERTED_COLOR = c.inverse;
125
- const BOLD_WEIGHT = c.bold;
126
- const DIM_COLOR = c.dim;
117
+ const EXPECTED_COLOR = y.green;
118
+ const RECEIVED_COLOR = y.red;
119
+ const INVERTED_COLOR = y.inverse;
120
+ const BOLD_WEIGHT = y.bold;
121
+ const DIM_COLOR = y.dim;
127
122
  function matcherHint(matcherName, received = "received", expected = "expected", options = {}) {
128
123
  const { comment = "", isDirectExpectCall = false, isNot = false, promise = "", secondArgument = "", expectedColor = EXPECTED_COLOR, receivedColor = RECEIVED_COLOR, secondArgumentColor = EXPECTED_COLOR } = options;
129
124
  let hint = "";
@@ -1449,25 +1444,25 @@ const JestChaiExpect = (chai, utils) => {
1449
1444
  });
1450
1445
  };
1451
1446
  function formatCalls(spy, msg, showActualCall) {
1452
- if (spy.mock.calls.length) msg += c.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
1453
- let methodCall = c.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call:\n\n`);
1447
+ if (spy.mock.calls.length) msg += y.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
1448
+ let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call:\n\n`);
1454
1449
  if (showActualCall) methodCall += diff(showActualCall, callArg, { omitAnnotationLines: true });
1455
1450
  else methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
1456
1451
  methodCall += "\n";
1457
1452
  return methodCall;
1458
1453
  }).join("\n")}`);
1459
- msg += c.gray(`\n\nNumber of calls: ${c.bold(spy.mock.calls.length)}\n`);
1454
+ msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
1460
1455
  return msg;
1461
1456
  }
1462
1457
  function formatReturns(spy, results, msg, showActualReturn) {
1463
- if (results.length) msg += c.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
1464
- let methodCall = c.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call return:\n\n`);
1458
+ if (results.length) msg += y.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
1459
+ let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call return:\n\n`);
1465
1460
  if (showActualReturn) methodCall += diff(showActualReturn, callReturn.value, { omitAnnotationLines: true });
1466
1461
  else methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
1467
1462
  methodCall += "\n";
1468
1463
  return methodCall;
1469
1464
  }).join("\n")}`);
1470
- msg += c.gray(`\n\nNumber of calls: ${c.bold(spy.mock.calls.length)}\n`);
1465
+ msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
1471
1466
  return msg;
1472
1467
  }
1473
1468
 
@@ -6346,8 +6341,8 @@ function createVitest() {
6346
6341
  stubEnv(name, value) {
6347
6342
  const env = state().metaEnv;
6348
6343
  if (!_stubsEnv.has(name)) _stubsEnv.set(name, env[name]);
6349
- if (_envBooleans.includes(name)) env[name] = value ? "1" : "";
6350
- else if (value === void 0) delete env[name];
6344
+ if (value === void 0) delete env[name];
6345
+ else if (_envBooleans.includes(name)) env[name] = value ? "1" : "";
6351
6346
  else env[name] = String(value);
6352
6347
  return utils;
6353
6348
  },
@@ -7942,30 +7937,74 @@ function inject(key) {
7942
7937
  }
7943
7938
 
7944
7939
  const now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
7940
+ /**
7941
+ * The built-in benchmark provider, backed by tinybench. Selected when
7942
+ * `benchmark.provider` is not configured.
7943
+ */
7944
+ function createDefaultBenchmarkProvider(config) {
7945
+ let benchIdx = 0;
7946
+ return { async run({ test, options, registrations }) {
7947
+ const currentIndex = ++benchIdx;
7948
+ const tinybench = new Bench({
7949
+ signal: test.context.signal,
7950
+ name: `${test.fullTestName} ${currentIndex}`,
7951
+ retainSamples: config.benchmark.retainSamples,
7952
+ ...options,
7953
+ now
7954
+ });
7955
+ for (const { name, fn, fnOpts } of registrations) tinybench.add(name, fn, fnOpts);
7956
+ await tinybench.run();
7957
+ const errors = tinybench.tasks.filter((task) => task.result.state === "errored").map((task) => task.result.error);
7958
+ if (errors.length === 1) throw errors[0];
7959
+ if (errors.length > 1) throw new AggregateError(errors, "Some benchmarks failed");
7960
+ return tinybench.tasks.map(toBenchResult);
7961
+ } };
7962
+ }
7963
+ function toBenchResult(task) {
7964
+ const result = task.result;
7965
+ if (result.state !== "completed") throw new Error(`task "${task.name}" did not complete: received "${result.state}"`);
7966
+ return {
7967
+ ...result,
7968
+ name: task.name
7969
+ };
7970
+ }
7971
+
7945
7972
  const kRegistration = Symbol("registration");
7946
7973
  const kFromSource = Symbol("fromSource");
7947
7974
  const kPerProject = Symbol("perProject");
7948
7975
  const kWriteResult = Symbol("writeResult");
7949
7976
  const kFinalize = Symbol("finalize");
7977
+ let cachedProvider;
7978
+ async function loadProviderModule(provider, moduleRunner) {
7979
+ let mod;
7980
+ try {
7981
+ mod = await moduleRunner.import(provider);
7982
+ } catch (error) {
7983
+ throw new Error(`Failed to load benchmark provider from "${provider}".`, { cause: error });
7984
+ }
7985
+ if (mod.default == null) throw new Error(`Benchmark provider loaded from "${provider}" did not have a default export.`);
7986
+ return mod.default;
7987
+ }
7988
+ /**
7989
+ * Resolves the benchmark provider for the current worker, importing a custom
7990
+ * provider module on first use. The result is cached for the lifetime of the
7991
+ * worker so a custom provider is imported at most once.
7992
+ */
7993
+ function resolveBenchmarkProvider(config, moduleRunner) {
7994
+ if (!cachedProvider) {
7995
+ const provider = config.benchmark.provider;
7996
+ cachedProvider = !provider ? Promise.resolve(createDefaultBenchmarkProvider(config)) : loadProviderModule(provider, moduleRunner);
7997
+ }
7998
+ return cachedProvider;
7999
+ }
7950
8000
  function isFromRegistration(reg) {
7951
8001
  return kFromSource in reg;
7952
8002
  }
7953
8003
  function substitutePath(template, projectName) {
7954
8004
  return template.replace(/\$\{projectName\}/g, projectName ?? "");
7955
8005
  }
7956
- function createBench(test, config) {
7957
- let benchIdx = 0;
8006
+ function createBench(test, config, moduleRunner) {
7958
8007
  const pending = /* @__PURE__ */ new Set();
7959
- const createTinybench = (options) => {
7960
- const currentIndex = ++benchIdx;
7961
- return new Bench({
7962
- signal: test.context.signal,
7963
- name: `${test.fullTestName} ${currentIndex}`,
7964
- retainSamples: config.benchmark.retainSamples,
7965
- ...options,
7966
- now
7967
- });
7968
- };
7969
8008
  const resolveTemplate = (template) => substitutePath(template, config.benchmark.projectName);
7970
8009
  const resolveFromSource = async (source) => {
7971
8010
  if (typeof source === "function") return source();
@@ -7983,42 +8022,37 @@ function createBench(test, config) {
7983
8022
  rank: 0,
7984
8023
  fromStore: true
7985
8024
  });
7986
- const createCompareStorage = (bench, fromResults) => {
8025
+ const createCompareStorage = (results, fromResults) => {
7987
8026
  return { get(name) {
7988
8027
  const stored = fromResults?.get(name);
7989
8028
  if (stored) return stored;
7990
- const task = bench.getTask(name);
7991
- if (!task) throw new Error(`task "${name}" was not defined`);
7992
- return task.result;
8029
+ const result = results.get(name);
8030
+ if (!result) throw new Error(`task "${name}" was not defined`);
8031
+ return result;
7993
8032
  } };
7994
8033
  };
7995
- const serializeBenchmark = (tinybenchTasks, name, taskMeta, fromTasks) => {
7996
- const tasks = tinybenchTasks.map((t) => {
7997
- const result = t.result;
7998
- if (result.state === "errored") throw result.error;
7999
- if (result.state !== "completed") throw new Error(`task "${t.name}" did not complete: received "${result.state}"`);
8000
- return {
8001
- name: t.name,
8002
- latency: result.latency,
8003
- throughput: result.throughput,
8004
- period: result.period,
8005
- totalTime: result.totalTime,
8006
- rank: 0,
8007
- ...taskMeta?.get(t.name)
8008
- };
8009
- });
8034
+ const serializeBenchmark = (results, name, taskMeta, fromTasks) => {
8035
+ const tasks = results.map((result) => ({
8036
+ name: result.name,
8037
+ latency: result.latency,
8038
+ throughput: result.throughput,
8039
+ period: result.period,
8040
+ totalTime: result.totalTime,
8041
+ rank: 0,
8042
+ ...taskMeta?.get(result.name)
8043
+ }));
8010
8044
  if (fromTasks) tasks.push(...fromTasks);
8011
8045
  tasks.sort((a, b) => a.latency.mean - b.latency.mean);
8012
8046
  tasks.forEach((task, idx) => {
8013
8047
  task.rank = idx + 1;
8014
8048
  });
8015
8049
  return {
8016
- name: name || test.fullTestName,
8050
+ name,
8017
8051
  tasks
8018
8052
  };
8019
8053
  };
8020
- const recordBenchmark = async (tinybenchTasks, name, taskMeta, fromTasks) => {
8021
- const serializedBenchmark = serializeBenchmark(tinybenchTasks, name, taskMeta, fromTasks);
8054
+ const recordBenchmark = async (results, name, taskMeta, fromTasks) => {
8055
+ const serializedBenchmark = serializeBenchmark(results, name, taskMeta, fromTasks);
8022
8056
  test.benchmarks.push(serializedBenchmark);
8023
8057
  await rpc().onTestBenchmark(test.id, serializedBenchmark);
8024
8058
  };
@@ -8032,19 +8066,28 @@ function createBench(test, config) {
8032
8066
  };
8033
8067
  await rpc().writeBenchmarkResult(resolved, data);
8034
8068
  };
8035
- const runBenchmarks = async (tinybench) => {
8069
+ const groupName = (options) => options?.name ?? test.fullTestName;
8070
+ const runGroup = async (registrations, options) => {
8036
8071
  const workerState = getWorkerState();
8037
8072
  const getterTracker = workerState.getterTracker;
8038
8073
  getterTracker?.resetInvocations();
8039
8074
  try {
8040
- return await TestRunner.runBenchmarks(tinybench);
8075
+ const results = await (await resolveBenchmarkProvider(config, moduleRunner)).run({
8076
+ test,
8077
+ config: config.benchmark,
8078
+ registrations,
8079
+ options
8080
+ });
8081
+ const byName = /* @__PURE__ */ new Map();
8082
+ for (const result of results) byName.set(result.name, result);
8083
+ return byName;
8041
8084
  } finally {
8042
8085
  const excessiveInvocations = config.benchmark.suppressExportGetterWarnings ? void 0 : getterTracker?.getExcessiveInvocations();
8043
8086
  if (excessiveInvocations?.length) {
8044
8087
  const entries = excessiveInvocations.map(({ moduleId, exportName }) => ` - ${formatModuleId(moduleId, workerState.config.root)} > ${exportName}`).join("\n");
8045
8088
  console.warn([
8046
- c.yellow(c.bold("Benchmark Warning")),
8047
- `Benchmark ${c.bold(`"${tinybench.name}"`)} accessed module export getters too many times.`,
8089
+ y.yellow(y.bold("Benchmark Warning")),
8090
+ `Benchmark ${y.bold(`"${groupName(options)}"`)} accessed module export getters too many times.`,
8048
8091
  "",
8049
8092
  "This can make results unreliable because export getters add overhead.",
8050
8093
  "See https://vitest.dev/guide/benchmarking#module-runner-overhead",
@@ -8056,13 +8099,15 @@ function createBench(test, config) {
8056
8099
  }
8057
8100
  };
8058
8101
  const runSingle = async (name, fn, fnOpts, options, meta, writeResult) => {
8059
- const tinybench = createTinybench(options).add(name, fn, fnOpts);
8060
- const tasks = await runBenchmarks(tinybench);
8061
- const task = tinybench.getTask(name);
8062
- if (task.result.state === "errored") throw task.result.error;
8063
- await recordBenchmark(tasks, tinybench.name, meta ? new Map([[name, meta]]) : void 0);
8064
- if (writeResult) await writeResultArtifact(writeResult, task.result);
8065
- return task.result;
8102
+ const result = (await runGroup([{
8103
+ name,
8104
+ fn,
8105
+ fnOpts
8106
+ }], options)).get(name);
8107
+ if (!result) throw new Error(`benchmark provider did not return a result for "${name}"`);
8108
+ await recordBenchmark([result], groupName(options), meta ? new Map([[name, meta]]) : void 0);
8109
+ if (writeResult) await writeResultArtifact(writeResult, result);
8110
+ return result;
8066
8111
  };
8067
8112
  const runFrom = async (name, source) => {
8068
8113
  const data = await resolveFromSource(source);
@@ -8116,7 +8161,7 @@ function createBench(test, config) {
8116
8161
  };
8117
8162
  bench.compare = async (...args) => {
8118
8163
  validateBenchmarkProject(config);
8119
- // extract optional trailing BenchCompareOptions argument
8164
+ // extract optional trailing BenchRunOptions argument
8120
8165
  const lastArg = args.at(-1);
8121
8166
  const benchOptions = lastArg != null && typeof lastArg === "object" && !(kRegistration in lastArg) ? args.pop() : void 0;
8122
8167
  const registrations = args;
@@ -8146,33 +8191,29 @@ function createBench(test, config) {
8146
8191
  fromTasks.push(taskFromBaseline(reg.name, data));
8147
8192
  }
8148
8193
  }
8149
- const tinybench = createTinybench(benchOptions);
8150
- runnable.forEach((reg) => {
8151
- tinybench.add(reg.name, reg.fn, reg.fnOpts);
8152
- });
8153
- let tasks = [];
8154
- if (runnable.length > 0) {
8155
- tasks = await runBenchmarks(tinybench);
8156
- const errors = tinybench.tasks.filter((task) => task.result.state === "errored").map((task) => task.result.error);
8157
- if (errors.length > 0) throw new AggregateError(errors, "Some benchmarks failed");
8158
- }
8159
- await recordBenchmark(tasks, tinybench.name, taskMeta, fromTasks);
8194
+ let results = /* @__PURE__ */ new Map();
8195
+ if (runnable.length > 0) results = await runGroup(runnable.map((reg) => ({
8196
+ name: reg.name,
8197
+ fn: reg.fn,
8198
+ fnOpts: reg.fnOpts
8199
+ })), benchOptions);
8200
+ await recordBenchmark(Array.from(results.values()), groupName(benchOptions), taskMeta, fromTasks);
8160
8201
  // write artifacts for every runnable registration that requested it. We
8161
8202
  // do this after recording so a write failure can't be confused with a
8162
8203
  // benchmark failure in the reporter output.
8163
8204
  await Promise.all(runnable.filter((reg) => reg[kWriteResult] != null).map((reg) => {
8164
- const task = tinybench.getTask(reg.name);
8165
- return writeResultArtifact(reg[kWriteResult], task.result);
8205
+ const result = results.get(reg.name);
8206
+ return writeResultArtifact(reg[kWriteResult], result);
8166
8207
  }));
8167
- return createCompareStorage(tinybench, fromResults);
8208
+ return createCompareStorage(results, fromResults);
8168
8209
  };
8169
8210
  bench[kFinalize] = () => {
8170
8211
  if (pending.size === 0) return;
8171
8212
  const names = Array.from(pending, (reg) => `"${reg.name}"`).join(", ");
8172
8213
  pending.clear();
8173
8214
  console.warn([
8174
- c.yellow(c.bold("Benchmark Warning")),
8175
- `Test ${c.bold(`"${test.fullTestName}"`)} registered benchmarks that never ran: ${names}.`,
8215
+ y.yellow(y.bold("Benchmark Warning")),
8216
+ `Test ${y.bold(`"${test.fullTestName}"`)} registered benchmarks that never ran: ${names}.`,
8176
8217
  "",
8177
8218
  "Call `.run()` on the registration, or pass it to `bench.compare()`.",
8178
8219
  "See https://vitest.dev/guide/benchmarking#defining-a-benchmark"
@@ -8197,8 +8238,8 @@ function normalizeBenchArgs(a, b) {
8197
8238
  if (typeof b !== "function") throw new TypeError("`bench()` expects a benchmark function. Call `bench(name, fn)` or `bench(name, options, fn)`.");
8198
8239
  // Strip vitest-specific fields only when present so we don't allocate a new
8199
8240
  // object — preserving referential identity matters: users inspect
8200
- // `registration.fnOpts` and tinybench's `add` sees the same object the
8201
- // caller passed in.
8241
+ // `registration.fnOpts` and the provider sees the same object the caller
8242
+ // passed in.
8202
8243
  if (a.writeResult === void 0 && a.perProject === void 0) return {
8203
8244
  fn: b,
8204
8245
  fnOpts: a,
@@ -8334,9 +8375,10 @@ class TestRunner {
8334
8375
  let _bench;
8335
8376
  const runnerConfig = this.config;
8336
8377
  const benchInstances = this.benchInstances;
8378
+ const moduleRunner = this.moduleRunner;
8337
8379
  Object.defineProperty(context, "bench", { get() {
8338
8380
  if (!_bench) {
8339
- _bench = createBench(context.task, runnerConfig);
8381
+ _bench = createBench(context.task, runnerConfig, moduleRunner);
8340
8382
  benchInstances.set(context.task, _bench);
8341
8383
  }
8342
8384
  return _bench;
@@ -8375,14 +8417,6 @@ class TestRunner {
8375
8417
  static setTestFn = getFn;
8376
8418
  static matchesTags = matchesTags;
8377
8419
  static createFileTask = createFileTask;
8378
- /**
8379
- * @experimental
8380
- * A function that runs tinybench tasks.
8381
- * Can be overriden to run tasks in a special environment.
8382
- */
8383
- static async runBenchmarks(tinybench) {
8384
- return await tinybench.run();
8385
- }
8386
8420
  }
8387
8421
  function clearModuleMocks(config) {
8388
8422
  const { clearMocks, mockReset, restoreMocks, unstubEnvs, unstubGlobals } = config;
@@ -1,9 +1,8 @@
1
1
  import fs__default from 'node:fs';
2
- import { splitFileAndPostfix as splitFileAndPostfix$1, isBareImport } from '@vitest/utils/helpers';
2
+ import { n as normalize, k as splitFileAndPostfix$1, j as join, l as isBareImport } from './pathe.M-eThtNZ.CbK_Vbae.js';
3
3
  import { i as isBuiltin, a as isBrowserExternal, t as toBuiltin } from './modules.BJuCwlRJ.js';
4
4
  import { E as EnvironmentTeardownError, a as getSafeWorkerState } from './utils.DYj33du9.js';
5
5
  import { pathToFileURL, URL as URL$1 } from 'node:url';
6
- import { normalize, join } from 'pathe';
7
6
  import { distDir } from '../path.js';
8
7
  import { VitestModuleEvaluator, unwrapId } from '../module-evaluator.js';
9
8
  import { isAbsolute, resolve } from 'node:path';
@@ -460,12 +459,12 @@ const createNodeImportMeta = (modulePath) => {
460
459
  if (!viteModuleRunner.createDefaultImportMeta) throw new Error(`createNodeImportMeta is not supported in this version of Vite.`);
461
460
  const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath);
462
461
  const href = defaultMeta.url;
463
- const importMetaResolver = createImportMetaResolver();
462
+ const importMetaResolver = createImportMetaResolver() ?? defaultMeta.resolve;
464
463
  return {
465
464
  ...defaultMeta,
466
465
  main: false,
467
466
  resolve(id, parent) {
468
- return (importMetaResolver ?? defaultMeta.resolve)(id, parent ?? href);
467
+ return importMetaResolver(id, parent ?? href);
469
468
  }
470
469
  };
471
470
  };
@@ -648,8 +647,27 @@ function startVitestModuleRunner(options) {
648
647
  context: options.context,
649
648
  externalModulesExecutor: options.externalModulesExecutor
650
649
  } : void 0;
650
+ // A fresh worker pays one strictly sequential `fetch` round-trip per module
651
+ // in its test files' import graphs, even when the server processed all of
652
+ // them already. Ask the server ONCE per run request for everything it has on
653
+ // disk and answer those fetches locally. A file change invalidates the module
654
+ // server-side, dropping it from the snapshot of every subsequent run request,
655
+ // which keeps reused (isolate: false) workers in sync; an edit DURING a run
656
+ // was racy before this fast path existed and stays racy with it — the
657
+ // scheduled rerun always sees the fresh transform.
658
+ let warmModules;
659
+ let warmModulesContext;
660
+ function fetchWarmModules() {
661
+ const workerState = state();
662
+ if (warmModulesContext !== workerState.ctx) {
663
+ warmModulesContext = workerState.ctx;
664
+ warmModules = rpc().fetchWarmModules(environment(), workerState.ctx.files.map((file) => file.filepath)).catch(() => null);
665
+ }
666
+ return warmModules;
667
+ }
651
668
  const evaluator = options.evaluator || new VitestModuleEvaluator(vm, {
652
669
  traces,
670
+ metaEnv: state().metaEnv,
653
671
  evaluatedModules: options.evaluatedModules,
654
672
  get moduleExecutionInfo() {
655
673
  return state().moduleExecutionInfo;
@@ -657,6 +675,9 @@ function startVitestModuleRunner(options) {
657
675
  get interopDefault() {
658
676
  return state().config.deps.interopDefault;
659
677
  },
678
+ get injectCjsGlobals() {
679
+ return state().config.injectCjsGlobals;
680
+ },
660
681
  getCurrentTestFilepath: () => state().filepath,
661
682
  getterTracker: state().getterTracker
662
683
  });
@@ -709,6 +730,23 @@ function startVitestModuleRunner(options) {
709
730
  // if module is invalidated, the worker will be recreated,
710
731
  // so cached is always true in a single worker
711
732
  if (!isImportActual && options?.cached) return { cache: true };
733
+ // only dependency fetches consult the snapshot: by the time the
734
+ // first dependency is requested, the entry file is transformed and
735
+ // its import graph is connected on the server, so the snapshot
736
+ // actually covers the file's transitive dependencies
737
+ if (importer != null) {
738
+ const warm = await fetchWarmModules();
739
+ // the null prototype is not preserved by the IPC serialization, so
740
+ // ids like "constructor" must not fall through to Object.prototype
741
+ const warmResult = warm && (Object.hasOwn(warm, id) ? warm[id] : Object.hasOwn(warm, rawId) ? warm[rawId] : void 0);
742
+ if (warmResult) if ("tmp" in warmResult) try {
743
+ return {
744
+ code: readFileSync(warmResult.tmp, "utf-8"),
745
+ ...warmResult
746
+ };
747
+ } catch {}
748
+ else return warmResult;
749
+ }
712
750
  const otelCarrier = traces?.getContextCarrier();
713
751
  const result = await rpc().fetch(id, importer, environment(), options, otelCarrier);
714
752
  if ("cached" in result) return {