vitest 3.2.0-beta.2 → 3.2.0-beta.3

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 (67) hide show
  1. package/dist/browser.d.ts +3 -3
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{base.DwtwORaC.js → base.D4119yLM.js} +4 -3
  4. package/dist/chunks/{benchmark.BoF7jW0Q.js → benchmark.Cf_PACH1.js} +1 -1
  5. package/dist/chunks/{cac.I9MLYfT-.js → cac.DWaWHIIE.js} +18 -15
  6. package/dist/chunks/{cli-api.d6IK1pnk.js → cli-api.CnmEXkxs.js} +250 -49
  7. package/dist/chunks/{config.d.UqE-KR0o.d.ts → config.d.D2ROskhv.d.ts} +2 -0
  8. package/dist/chunks/{console.K1NMVOSc.js → console.Cwr-MFPV.js} +3 -2
  9. package/dist/chunks/{constants.BZZyIeIE.js → constants.DnKduX2e.js} +1 -0
  10. package/dist/chunks/{coverage.OGU09Jbh.js → coverage.C73DaDgS.js} +116 -12
  11. package/dist/chunks/{creator.DGAdZ4Hj.js → creator.C8WKy2eW.js} +10 -7
  12. package/dist/chunks/{date.CDOsz-HY.js → date.ByMsSlOr.js} +25 -0
  13. package/dist/chunks/{defaults.DSxsTG0h.js → defaults.DpVH7vbg.js} +1 -0
  14. package/dist/chunks/{environment.d.D8YDy2v5.d.ts → environment.d.cL3nLXbE.d.ts} +1 -0
  15. package/dist/chunks/{execute.JlGHLJZT.js → execute.B3q-2LPV.js} +25 -0
  16. package/dist/chunks/{global.d.BPa1eL3O.d.ts → global.d.BNLIi6yo.d.ts} +3 -1
  17. package/dist/chunks/{globals.CpxW8ccg.js → globals.CI21aWXF.js} +7 -6
  18. package/dist/chunks/{index.DFXFpH3w.js → index.2jgTs_Q5.js} +19 -1
  19. package/dist/chunks/{index.CV36oG_L.js → index.Bter3jj9.js} +83 -16
  20. package/dist/chunks/{index.DswW_LEs.js → index.CbT4iuwc.js} +7 -4
  21. package/dist/chunks/index.D3XRDfWc.js +213 -0
  22. package/dist/chunks/{index.CfXMNXHg.js → index.DNgLEKsQ.js} +4 -2
  23. package/dist/chunks/{index.CmC5OK9L.js → index.JOzufsrU.js} +2 -1
  24. package/dist/chunks/{inspector.DbDkSkFn.js → inspector.BFsh5KO0.js} +3 -0
  25. package/dist/chunks/{node.3xsWotC9.js → node.Be-ntJnD.js} +1 -1
  26. package/dist/chunks/{reporters.d.CLC9rhKy.d.ts → reporters.d.Bt4IGtsa.d.ts} +24 -6
  27. package/dist/chunks/{rpc.D9_013TY.js → rpc.BKExFSRG.js} +2 -1
  28. package/dist/chunks/{runBaseTests.Dn2vyej_.js → runBaseTests.B_M1TTsK.js} +19 -10
  29. package/dist/chunks/{setup-common.CYo3Y0dD.js → setup-common.CF-O-dZX.js} +2 -1
  30. package/dist/chunks/{typechecker.DnTrplSJ.js → typechecker.BgzF-6iO.js} +78 -21
  31. package/dist/chunks/{utils.CgTj3MsC.js → utils.BlI4TC7Y.js} +1 -0
  32. package/dist/chunks/{utils.BfxieIyZ.js → utils.DPCq3gzW.js} +3 -0
  33. package/dist/chunks/{vi.BFR5YIgu.js → vi.pkoYCV6A.js} +25 -2
  34. package/dist/chunks/{vite.d.CBZ3M_ru.d.ts → vite.d.B-Kx3KCF.d.ts} +3 -1
  35. package/dist/chunks/{vm.C1HHjtNS.js → vm.DPYem2so.js} +72 -4
  36. package/dist/chunks/{worker.d.CoCI7hzP.d.ts → worker.d.BKbBp2ga.d.ts} +2 -2
  37. package/dist/chunks/{worker.d.D5Xdi-Zr.d.ts → worker.d.Bl1O4kuf.d.ts} +1 -1
  38. package/dist/cli.js +4 -4
  39. package/dist/config.cjs +2 -0
  40. package/dist/config.d.ts +7 -6
  41. package/dist/config.js +2 -2
  42. package/dist/coverage.d.ts +4 -4
  43. package/dist/coverage.js +5 -5
  44. package/dist/environments.d.ts +6 -2
  45. package/dist/environments.js +1 -1
  46. package/dist/execute.d.ts +9 -3
  47. package/dist/execute.js +1 -1
  48. package/dist/index.d.ts +24 -12
  49. package/dist/index.js +5 -5
  50. package/dist/node.d.ts +18 -10
  51. package/dist/node.js +14 -12
  52. package/dist/reporters.d.ts +4 -4
  53. package/dist/reporters.js +3 -3
  54. package/dist/runners.d.ts +1 -1
  55. package/dist/runners.js +13 -5
  56. package/dist/snapshot.js +2 -2
  57. package/dist/suite.js +2 -2
  58. package/dist/worker.js +9 -5
  59. package/dist/workers/forks.js +6 -4
  60. package/dist/workers/runVmTests.js +14 -9
  61. package/dist/workers/threads.js +4 -4
  62. package/dist/workers/vmForks.js +6 -6
  63. package/dist/workers/vmThreads.js +6 -6
  64. package/dist/workers.d.ts +4 -4
  65. package/dist/workers.js +10 -10
  66. package/package.json +18 -18
  67. package/dist/chunks/index.CK1YOQaa.js +0 -143
@@ -64,9 +64,11 @@ function getOutputFile(config, reporter) {
64
64
  function wrapSerializableConfig(config) {
65
65
  let testNamePattern = config.testNamePattern;
66
66
  let defines = config.defines;
67
+ // v8 serialize does not support regex
67
68
  if (testNamePattern && typeof testNamePattern !== "string") {
68
69
  testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
69
70
  }
71
+ // v8 serialize drops properties with undefined value
70
72
  if (defines) {
71
73
  defines = {
72
74
  keys: Object.keys(defines),
@@ -402,11 +404,14 @@ async function collectTests(ctx, filepath) {
402
404
  ].includes(callee.object.name)) {
403
405
  return callee.object?.name;
404
406
  }
407
+ // direct call as `__vite_ssr_exports_0__.test()`
405
408
  if (callee.object?.name?.startsWith("__vite_ssr_")) {
406
409
  return getName(callee.property);
407
410
  }
411
+ // call as `__vite_ssr__.test.skip()`
408
412
  return getName(callee.object?.property);
409
413
  }
414
+ // unwrap (0, ...)
410
415
  if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
411
416
  const [e0, e1] = callee.expressions;
412
417
  if (e0.type === "Literal" && e0.value === 0) {
@@ -431,6 +436,7 @@ async function collectTests(ctx, filepath) {
431
436
  }
432
437
  const property = callee?.property?.name;
433
438
  let mode = !property || property === name ? "run" : property;
439
+ // they will be picked up in the next iteration
434
440
  if ([
435
441
  "each",
436
442
  "for",
@@ -441,6 +447,7 @@ async function collectTests(ctx, filepath) {
441
447
  }
442
448
  let start;
443
449
  const end = node.end;
450
+ // .each
444
451
  if (callee.type === "CallExpression") {
445
452
  start = callee.end;
446
453
  } else if (callee.type === "TaggedTemplateExpression") {
@@ -451,6 +458,7 @@ async function collectTests(ctx, filepath) {
451
458
  const { arguments: [messageNode] } = node;
452
459
  const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
453
460
  const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
461
+ // cannot statically analyze, so we always skip it
454
462
  if (mode === "skipIf" || mode === "runIf") {
455
463
  mode = "skip";
456
464
  }
@@ -474,6 +482,7 @@ async function collectTests(ctx, filepath) {
474
482
  const latestSuite = updateLatestSuite(definition.start);
475
483
  let mode = definition.mode;
476
484
  if (latestSuite.mode !== "run") {
485
+ // inherit suite mode, if it's set
477
486
  mode = latestSuite.mode;
478
487
  }
479
488
  if (definition.type === "suite") {
@@ -530,6 +539,7 @@ async function makeTscErrorInfo(errInfo) {
530
539
  return ["unknown filepath", null];
531
540
  }
532
541
  const errMsgRaw = errMsgRawArr.join("").trim();
542
+ // get filePath, line, col
533
543
  const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
534
544
  if (!errFilePath || !errPos) {
535
545
  return ["unknown filepath", null];
@@ -538,6 +548,7 @@ async function makeTscErrorInfo(errInfo) {
538
548
  if (!errLine || !errCol) {
539
549
  return [errFilePath, null];
540
550
  }
551
+ // get errCode, errMsg
541
552
  const execArr = errCodeRegExp.exec(errMsgRaw);
542
553
  if (!execArr) {
543
554
  return [errFilePath, null];
@@ -559,6 +570,7 @@ async function makeTscErrorInfo(errInfo) {
559
570
  }
560
571
  async function getRawErrsMapFromTsCompile(tscErrorStdout) {
561
572
  const rawErrsMap = new Map();
573
+ // Merge details line with main line (i.e. which contains file path)
562
574
  const infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
563
575
  if (!next) {
564
576
  return prev;
@@ -686,6 +698,7 @@ class Typechecker {
686
698
  return;
687
699
  }
688
700
  const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)];
701
+ // has no map for ".js" files that use // @ts-check
689
702
  const traceMap = map && new TraceMap(map);
690
703
  const indexMap = createIndexMap(parsed);
691
704
  const markState = (task, state) => {
@@ -743,6 +756,7 @@ class Typechecker {
743
756
  const suiteErrors = errors.map((info) => {
744
757
  const limit = Error.stackTraceLimit;
745
758
  Error.stackTraceLimit = 0;
759
+ // Some expect-type errors have the most useful information on the second line e.g. `This expression is not callable.\n Type 'ExpectString<number>' has no call signatures.`
746
760
  const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1");
747
761
  const error = new TypeCheckError(errMsg, [{
748
762
  file: filepath,
@@ -784,10 +798,7 @@ class Typechecker {
784
798
  getOutput() {
785
799
  return this._output;
786
800
  }
787
- async start() {
788
- if (this.process) {
789
- return;
790
- }
801
+ async spawn() {
791
802
  const { root, watch, typecheck } = this.project.config;
792
803
  const args = [
793
804
  "--noEmit",
@@ -797,6 +808,7 @@ class Typechecker {
797
808
  "--tsBuildInfoFile",
798
809
  join(process.versions.pnp ? join(nodeos__default.tmpdir(), this.project.hash) : distDir, "tsconfig.tmp.tsbuildinfo")
799
810
  ];
811
+ // use builtin watcher because it's faster
800
812
  if (watch) {
801
813
  args.push("--watch");
802
814
  }
@@ -816,30 +828,72 @@ class Typechecker {
816
828
  throwOnError: false
817
829
  });
818
830
  this.process = child.process;
819
- await this._onParseStart?.();
820
831
  let rerunTriggered = false;
821
- child.process?.stdout?.on("data", (chunk) => {
822
- this._output += chunk;
823
- if (!watch) {
832
+ let dataReceived = false;
833
+ return new Promise((resolve, reject) => {
834
+ if (!child.process || !child.process.stdout) {
835
+ reject(new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`));
824
836
  return;
825
837
  }
826
- if (this._output.includes("File change detected") && !rerunTriggered) {
827
- this._onWatcherRerun?.();
828
- this._startTime = performance.now();
829
- this._result.sourceErrors = [];
830
- this._result.files = [];
831
- this._tests = null;
832
- rerunTriggered = true;
838
+ child.process.stdout.on("data", (chunk) => {
839
+ dataReceived = true;
840
+ this._output += chunk;
841
+ if (!watch) {
842
+ return;
843
+ }
844
+ if (this._output.includes("File change detected") && !rerunTriggered) {
845
+ this._onWatcherRerun?.();
846
+ this._startTime = performance.now();
847
+ this._result.sourceErrors = [];
848
+ this._result.files = [];
849
+ this._tests = null;
850
+ rerunTriggered = true;
851
+ }
852
+ if (/Found \w+ errors*. Watching for/.test(this._output)) {
853
+ rerunTriggered = false;
854
+ this.prepareResults(this._output).then((result) => {
855
+ this._result = result;
856
+ this._onParseEnd?.(result);
857
+ });
858
+ this._output = "";
859
+ }
860
+ });
861
+ const timeout = setTimeout(() => reject(new Error(`${typecheck.checker} spawn timed out`)), this.project.config.typecheck.spawnTimeout);
862
+ function onError(cause) {
863
+ clearTimeout(timeout);
864
+ reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
833
865
  }
834
- if (/Found \w+ errors*. Watching for/.test(this._output)) {
835
- rerunTriggered = false;
836
- this.prepareResults(this._output).then((result) => {
837
- this._result = result;
838
- this._onParseEnd?.(result);
866
+ child.process.once("spawn", () => {
867
+ this._onParseStart?.();
868
+ child.process?.off("error", onError);
869
+ clearTimeout(timeout);
870
+ if (process.platform === "win32") {
871
+ // on Windows, the process might be spawned but fail to start
872
+ // we wait for a potential error here. if "close" event didn't trigger,
873
+ // we resolve the promise
874
+ setTimeout(() => {
875
+ resolve({ result: child });
876
+ }, 200);
877
+ } else {
878
+ resolve({ result: child });
879
+ }
880
+ });
881
+ if (process.platform === "win32") {
882
+ child.process.once("close", (code) => {
883
+ if (code != null && code !== 0 && !dataReceived) {
884
+ onError(new Error(`The ${typecheck.checker} command exited with code ${code}.`));
885
+ }
839
886
  });
840
- this._output = "";
841
887
  }
888
+ child.process.once("error", onError);
842
889
  });
890
+ }
891
+ async start() {
892
+ if (this.process) {
893
+ return;
894
+ }
895
+ const { watch } = this.project.config;
896
+ const { result: child } = await this.spawn();
843
897
  if (!watch) {
844
898
  await child;
845
899
  this._result = await this.prepareResults(this._output);
@@ -875,6 +929,9 @@ function findGeneratedPosition(traceMap, { line, column, source }) {
875
929
  if (found.line !== null) {
876
930
  return found;
877
931
  }
932
+ // find the next source token position when the exact error position doesn't exist in source map.
933
+ // this can happen, for example, when the type error is in the comment "// @ts-expect-error"
934
+ // and comments are stripped away in the generated code.
878
935
  const mappings = [];
879
936
  eachMapping(traceMap, (m) => {
880
937
  if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) {
@@ -2,6 +2,7 @@ import { getSafeTimers } from '@vitest/utils';
2
2
 
3
3
  const NAME_WORKER_STATE = "__vitest_worker__";
4
4
  function getWorkerState() {
5
+ // @ts-expect-error untyped global
5
6
  const workerState = globalThis[NAME_WORKER_STATE];
6
7
  if (!workerState) {
7
8
  const errorMsg = "Vitest failed to access its internal state." + "\n\nOne of the following is possible:" + "\n- \"vitest\" is imported directly without running \"vitest\" command" + "\n- \"vitest\" is imported inside \"globalSetup\" (to fix this, use \"setupFiles\" instead, because \"globalSetup\" runs in a different context)" + "\n- \"vitest\" is imported inside Vite / Vitest config file" + "\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\n";
@@ -1,6 +1,7 @@
1
1
  import { parseRegexp } from '@vitest/utils';
2
2
 
3
3
  const REGEXP_WRAP_PREFIX = "$$vitest:";
4
+ // Store global APIs in case process is overwritten by tests
4
5
  const processSend = process.send?.bind(process);
5
6
  const processOn = process.on?.bind(process);
6
7
  const processOff = process.off?.bind(process);
@@ -32,6 +33,7 @@ function createForksRpcOptions(nodeV8) {
32
33
  },
33
34
  on(fn) {
34
35
  const handler = (message, ...extras) => {
36
+ // Do not react on Tinypool's internal messaging
35
37
  if (message?.__tinypool_worker_message__) {
36
38
  return;
37
39
  }
@@ -55,6 +57,7 @@ function unwrapSerializableConfig(config) {
55
57
  if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
56
58
  const { keys, original } = config.defines;
57
59
  const defines = {};
60
+ // Apply all keys from the original. Entries which had undefined value are missing from original now
58
61
  for (const key of keys) {
59
62
  defines[key] = original[key];
60
63
  }
@@ -2,15 +2,16 @@ import { equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, J
2
2
  import { getCurrentTest } from '@vitest/runner';
3
3
  import { getNames, getTestName } from '@vitest/runner/utils';
4
4
  import * as chai$1 from 'chai';
5
- import { g as getWorkerState, a as getCurrentEnvironment, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.CgTj3MsC.js';
5
+ import { g as getWorkerState, a as getCurrentEnvironment, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.BlI4TC7Y.js';
6
6
  import { getSafeTimers, assertTypes, createSimpleStackTrace } from '@vitest/utils';
7
7
  import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
8
8
  import { stripSnapshotIndentation, addSerializer, SnapshotClient } from '@vitest/snapshot';
9
9
  import '@vitest/utils/error';
10
10
  import { fn, spyOn, mocks, isMockFunction } from '@vitest/spy';
11
11
  import { parseSingleStack } from '@vitest/utils/source-map';
12
- import { R as RealDate, r as resetDate, m as mockDate } from './date.CDOsz-HY.js';
12
+ import { R as RealDate, r as resetDate, m as mockDate } from './date.ByMsSlOr.js';
13
13
 
14
+ // these matchers are not supported because they don't make sense with poll
14
15
  const unsupported = [
15
16
  "matchSnapshot",
16
17
  "toMatchSnapshot",
@@ -28,6 +29,7 @@ function createExpectPoll(expect) {
28
29
  const state = getWorkerState();
29
30
  const defaults = state.config.expect?.poll ?? {};
30
31
  const { interval = defaults.interval ?? 50, timeout = defaults.timeout ?? 1e3, message } = options;
32
+ // @ts-expect-error private poll access
31
33
  const assertion = expect(null, message).withContext({ poll: true });
32
34
  fn = fn.bind(assertion);
33
35
  const test = chai$1.util.flag(assertion, "vitest-test");
@@ -89,6 +91,8 @@ function createExpectPoll(expect) {
89
91
  }
90
92
  });
91
93
  let resultPromise;
94
+ // only .then is enough to check awaited, but we type this as `Promise<void>` in global types
95
+ // so let's follow it
92
96
  return {
93
97
  then(onFulfilled, onRejected) {
94
98
  awaited = true;
@@ -222,7 +226,9 @@ function createAssertionMessage(util, assertion, hasArgs) {
222
226
  }
223
227
  function recordAsyncExpect(_test, promise, assertion, error) {
224
228
  const test = _test;
229
+ // record promise for test, that resolves before test ends
225
230
  if (test && promise instanceof Promise) {
231
+ // if promise is explicitly awaited, remove it from the list
226
232
  promise = promise.finally(() => {
227
233
  if (!test.promises) {
228
234
  return;
@@ -232,6 +238,7 @@ function recordAsyncExpect(_test, promise, assertion, error) {
232
238
  test.promises.splice(index, 1);
233
239
  }
234
240
  });
241
+ // record promise
235
242
  if (!test.promises) {
236
243
  test.promises = [];
237
244
  }
@@ -281,6 +288,7 @@ function getError(expected, promise) {
281
288
  if (!promise) {
282
289
  throw new Error(`expected must be a function, received ${typeof expected}`);
283
290
  }
291
+ // when "promised", it receives thrown error
284
292
  return expected;
285
293
  }
286
294
  try {
@@ -442,6 +450,7 @@ function createExpect(test) {
442
450
  const assert = chai$1.expect(value, message);
443
451
  const _test = test || getCurrentTest();
444
452
  if (_test) {
453
+ // @ts-expect-error internal
445
454
  return assert.withTest(_test);
446
455
  } else {
447
456
  return assert;
@@ -451,6 +460,7 @@ function createExpect(test) {
451
460
  Object.assign(expect, globalThis[ASYMMETRIC_MATCHERS_OBJECT]);
452
461
  expect.getState = () => getState(expect);
453
462
  expect.setState = (state) => setState(state, expect);
463
+ // @ts-expect-error global is not typed
454
464
  const globalState = getState(globalThis[GLOBAL_EXPECT]) || {};
455
465
  setState({
456
466
  ...globalState,
@@ -465,9 +475,11 @@ function createExpect(test) {
465
475
  },
466
476
  currentTestName: test ? getTestName(test) : globalState.currentTestName
467
477
  }, expect);
478
+ // @ts-expect-error untyped
468
479
  expect.extend = (matchers) => chai$1.expect.extend(expect, matchers);
469
480
  expect.addEqualityTesters = (customTesters) => addCustomEqualityTesters(customTesters);
470
481
  expect.soft = (...args) => {
482
+ // @ts-expect-error private soft access
471
483
  return expect(...args).withContext({ soft: true });
472
484
  };
473
485
  expect.poll = createExpectPoll(expect);
@@ -3611,6 +3623,12 @@ var fakeTimersSrcExports = requireFakeTimersSrc();
3611
3623
  class FakeTimers {
3612
3624
  _global;
3613
3625
  _clock;
3626
+ // | _fakingTime | _fakingDate |
3627
+ // +-------------+-------------+
3628
+ // | false | falsy | initial
3629
+ // | false | truthy | vi.setSystemTime called first (for mocking only Date without fake timers)
3630
+ // | true | falsy | vi.useFakeTimers called first
3631
+ // | true | truthy | unreachable
3614
3632
  _fakingTime;
3615
3633
  _fakingDate;
3616
3634
  _fakeTimers;
@@ -3655,6 +3673,7 @@ class FakeTimers {
3655
3673
  if (this._checkFakeTimers()) {
3656
3674
  for (let i = steps; i > 0; i--) {
3657
3675
  this._clock.next();
3676
+ // Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
3658
3677
  this._clock.tick(0);
3659
3678
  if (this._clock.countTimers() === 0) {
3660
3679
  break;
@@ -3666,6 +3685,7 @@ class FakeTimers {
3666
3685
  if (this._checkFakeTimers()) {
3667
3686
  for (let i = steps; i > 0; i--) {
3668
3687
  await this._clock.nextAsync();
3688
+ // Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
3669
3689
  this._clock.tick(0);
3670
3690
  if (this._clock.countTimers() === 0) {
3671
3691
  break;
@@ -3690,6 +3710,7 @@ class FakeTimers {
3690
3710
  }
3691
3711
  runAllTicks() {
3692
3712
  if (this._checkFakeTimers()) {
3713
+ // @ts-expect-error method not exposed
3693
3714
  this._clock.runMicrotasks();
3694
3715
  }
3695
3716
  }
@@ -4124,6 +4145,7 @@ function createVitest() {
4124
4145
  const vitest = createVitest();
4125
4146
  const vi = vitest;
4126
4147
  function _mocker() {
4148
+ // @ts-expect-error injected by vite-nide
4127
4149
  return typeof __vitest_mocker__ !== "undefined" ? __vitest_mocker__ : new Proxy({}, { get(_, name) {
4128
4150
  throw new Error("Vitest mocker was not initialized in this environment. " + `vi.${String(name)}() is forbidden.`);
4129
4151
  } });
@@ -4131,6 +4153,7 @@ function _mocker() {
4131
4153
  function getImporter(name) {
4132
4154
  const stackTrace = createSimpleStackTrace({ stackTraceLimit: 5 });
4133
4155
  const stackArray = stackTrace.split("\n");
4156
+ // if there is no message in a stack trace, use the item - 1
4134
4157
  const importerStackIndex = stackArray.findIndex((stack) => {
4135
4158
  return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`);
4136
4159
  });
@@ -1,5 +1,5 @@
1
1
  import { HookHandler } from 'vite';
2
- import { V as Vitest, T as TestProject, b as TestProjectConfiguration, I as InlineConfig } from './reporters.d.CLC9rhKy.js';
2
+ import { V as Vitest, T as TestProject, b as TestProjectConfiguration, I as InlineConfig } from './reporters.d.Bt4IGtsa.js';
3
3
 
4
4
  interface VitestPluginContext {
5
5
  vitest: Vitest;
@@ -7,6 +7,8 @@ interface VitestPluginContext {
7
7
  injectTestProjects: (config: TestProjectConfiguration | TestProjectConfiguration[]) => Promise<TestProject[]>;
8
8
  }
9
9
 
10
+ /* eslint-disable unused-imports/no-unused-vars */
11
+
10
12
  type VitestInlineConfig = InlineConfig;
11
13
  declare module "vite" {
12
14
  interface UserConfig {
@@ -2,14 +2,14 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
2
2
  import vm, { isContext } from 'node:vm';
3
3
  import { dirname, basename, extname, normalize, join, resolve } from 'pathe';
4
4
  import { distDir } from '../path.js';
5
- import { createCustomConsole } from './console.K1NMVOSc.js';
6
- import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.JlGHLJZT.js';
5
+ import { createCustomConsole } from './console.Cwr-MFPV.js';
6
+ import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.B3q-2LPV.js';
7
7
  import fs from 'node:fs';
8
8
  import { dirname as dirname$1 } from 'node:path';
9
9
  import { isPrimitive, isNodeBuiltin, toArray, getCachedData, setCacheData, isBareImport } from 'vite-node/utils';
10
10
  import { createRequire, Module } from 'node:module';
11
11
  import { CSS_LANGS_RE, KNOWN_ASSET_RE } from 'vite-node/constants';
12
- import { p as provideWorkerState } from './utils.CgTj3MsC.js';
12
+ import { p as provideWorkerState } from './utils.BlI4TC7Y.js';
13
13
 
14
14
  function interopCommonJsModule(interopDefault, mod) {
15
15
  if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) {
@@ -58,6 +58,7 @@ class CommonjsExecutor {
58
58
  this.fs = options.fileMap;
59
59
  this.interopDefault = options.interopDefault;
60
60
  const primitives = vm.runInContext("({ Object, Array, Error })", this.context);
61
+ // eslint-disable-next-line ts/no-this-alias
61
62
  const executor = this;
62
63
  this.Module = class Module$1 {
63
64
  exports;
@@ -71,6 +72,7 @@ class CommonjsExecutor {
71
72
  paths = [];
72
73
  constructor(id = "", parent) {
73
74
  this.exports = primitives.Object.create(Object.prototype);
75
+ // in our case the path should always be resolved already
74
76
  this.path = dirname(id);
75
77
  this.id = id;
76
78
  this.filename = id;
@@ -89,12 +91,16 @@ class CommonjsExecutor {
89
91
  static register = () => {
90
92
  throw new Error(`[vitest] "register" is not available when running in Vitest.`);
91
93
  };
94
+ static registerHooks = () => {
95
+ throw new Error(`[vitest] "registerHooks" is not available when running in Vitest.`);
96
+ };
92
97
  _compile(code, filename) {
93
98
  const cjsModule = Module$1.wrap(code);
94
99
  const script = new vm.Script(cjsModule, {
95
100
  filename,
96
101
  importModuleDynamically: options.importModuleDynamically
97
102
  });
103
+ // @ts-expect-error mark script with current identifier
98
104
  script.identifier = filename;
99
105
  const fn = script.runInContext(executor.context);
100
106
  const __dirname = dirname(filename);
@@ -106,6 +112,7 @@ class CommonjsExecutor {
106
112
  this.loaded = true;
107
113
  }
108
114
  }
115
+ // exposed for external use, Node.js does the opposite
109
116
  static _load = (request, parent, _isMain) => {
110
117
  const require = Module$1.createRequire(parent?.filename ?? request);
111
118
  return require(request);
@@ -126,11 +133,17 @@ class CommonjsExecutor {
126
133
  static runMain = () => {
127
134
  throw new primitives.Error("[vitest] \"runMain\" is not implemented.");
128
135
  };
136
+ // @ts-expect-error not typed
129
137
  static _resolveFilename = Module._resolveFilename;
138
+ // @ts-expect-error not typed
130
139
  static _findPath = Module._findPath;
140
+ // @ts-expect-error not typed
131
141
  static _initPaths = Module._initPaths;
142
+ // @ts-expect-error not typed
132
143
  static _preloadModules = Module._preloadModules;
144
+ // @ts-expect-error not typed
133
145
  static _resolveLookupPaths = Module._resolveLookupPaths;
146
+ // @ts-expect-error not typed
134
147
  static globalPaths = Module.globalPaths;
135
148
  static isBuiltin = Module.isBuiltin;
136
149
  static constants = Module.constants;
@@ -189,6 +202,7 @@ class CommonjsExecutor {
189
202
  }
190
203
  });
191
204
  }
205
+ // very naive implementation for Node.js require
192
206
  loadCommonJSModule(module, filename) {
193
207
  const cached = this.requireCache.get(filename);
194
208
  if (cached) {
@@ -204,6 +218,7 @@ class CommonjsExecutor {
204
218
  let currentExtension;
205
219
  let index;
206
220
  let startIndex = 0;
221
+ // eslint-disable-next-line no-cond-assign
207
222
  while ((index = name.indexOf(".", startIndex)) !== -1) {
208
223
  startIndex = index + 1;
209
224
  if (index === 0) {
@@ -239,6 +254,7 @@ class CommonjsExecutor {
239
254
  return this.moduleCache.get(identifier);
240
255
  }
241
256
  const exports = this.require(path);
257
+ // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
242
258
  const { keys, moduleExports, defaultExport } = interopCommonJsModule(this.interopDefault, exports);
243
259
  const module = new SyntheticModule([...keys, "default"], function() {
244
260
  for (const key of keys) {
@@ -252,6 +268,42 @@ class CommonjsExecutor {
252
268
  this.moduleCache.set(identifier, module);
253
269
  return module;
254
270
  }
271
+ // TODO: use this in strict mode, when available in #2854
272
+ // private _getNamedCjsExports(path: string): Set<string> {
273
+ // const cachedNamedExports = this.cjsNamedExportsMap.get(path)
274
+ // if (cachedNamedExports) {
275
+ // return cachedNamedExports
276
+ // }
277
+ // if (extname(path) === '.node') {
278
+ // const moduleExports = this.require(path)
279
+ // const namedExports = new Set(Object.keys(moduleExports))
280
+ // this.cjsNamedExportsMap.set(path, namedExports)
281
+ // return namedExports
282
+ // }
283
+ // const code = this.fs.readFile(path)
284
+ // const { exports, reexports } = parseCjs(code, path)
285
+ // const namedExports = new Set(exports)
286
+ // this.cjsNamedExportsMap.set(path, namedExports)
287
+ // for (const reexport of reexports) {
288
+ // if (isNodeBuiltin(reexport)) {
289
+ // const exports = this.require(reexport)
290
+ // if (exports !== null && typeof exports === 'object') {
291
+ // for (const e of Object.keys(exports)) {
292
+ // namedExports.add(e)
293
+ // }
294
+ // }
295
+ // }
296
+ // else {
297
+ // const require = this.createRequire(path)
298
+ // const resolved = require.resolve(reexport)
299
+ // const exports = this._getNamedCjsExports(resolved)
300
+ // for (const e of exports) {
301
+ // namedExports.add(e)
302
+ // }
303
+ // }
304
+ // }
305
+ // return namedExports
306
+ // }
255
307
  require(identifier) {
256
308
  const ext = extname(identifier);
257
309
  if (ext === ".node" || isNodeBuiltin(identifier)) {
@@ -273,6 +325,7 @@ class CommonjsExecutor {
273
325
  return module.exports;
274
326
  }
275
327
  this.builtinCache[normalized] = _require.cache[normalized];
328
+ // TODO: should we wrap module to rethrow context errors?
276
329
  return moduleExports;
277
330
  }
278
331
  }
@@ -308,6 +361,7 @@ class EsmExecutor {
308
361
  }
309
362
  async loadEsModule(fileURL, getCode) {
310
363
  const code = await getCode();
364
+ // TODO: should not be allowed in strict mode, implement in #2854
311
365
  if (fileURL.endsWith(".json")) {
312
366
  const m = new SyntheticModule(["default"], function() {
313
367
  const result = JSON.parse(code);
@@ -345,13 +399,14 @@ class EsmExecutor {
345
399
  return m;
346
400
  }
347
401
  async createNetworkModule(fileUrl) {
402
+ // https://nodejs.org/api/esm.html#https-and-http-imports
348
403
  if (fileUrl.startsWith("http:")) {
349
404
  const url = new URL(fileUrl);
350
405
  if (url.hostname !== "localhost" && url.hostname !== "::1" && (IPnumber(url.hostname) & IPmask(8)) !== this.#httpIp) {
351
406
  throw new Error(
352
407
  // we don't know the importer, so it's undefined (the same happens in --pool=threads)
353
408
  `import of '${fileUrl}' by undefined is not supported: ` + "http can only be used to load local resources (use https instead)."
354
- );
409
+ );
355
410
  }
356
411
  }
357
412
  return this.createEsModule(fileUrl, () => fetch(fileUrl).then((r) => r.text()));
@@ -496,6 +551,7 @@ class ViteExecutor {
496
551
  return result.code;
497
552
  }
498
553
  } catch (cause) {
554
+ // rethrow vite error if it cannot load the module because it's not resolved
499
555
  if (typeof cause === "object" && cause.code === "ERR_LOAD_URL" || typeof cause?.message === "string" && cause.message.includes("Failed to load url")) {
500
556
  const error = new Error(`Cannot find module '${fileUrl}'`, { cause });
501
557
  error.code = "ERR_MODULE_NOT_FOUND";
@@ -548,7 +604,9 @@ class ViteExecutor {
548
604
  }
549
605
 
550
606
  const { existsSync, statSync } = fs;
607
+ // always defined when we use vm pool
551
608
  const nativeResolve = import.meta.resolve;
609
+ // TODO: improve Node.js strict mode support in #2854
552
610
  class ExternalModulesExecutor {
553
611
  cjs;
554
612
  esm;
@@ -587,6 +645,7 @@ class ExternalModulesExecutor {
587
645
  createRequire(identifier) {
588
646
  return this.cjs.createRequire(identifier);
589
647
  }
648
+ // dynamic import can be used in both ESM and CJS, so we have it in the executor
590
649
  importModuleDynamically = async (specifier, referencer) => {
591
650
  const module = await this.resolveModule(specifier, referencer.identifier);
592
651
  return await this.esm.evaluateModule(module);
@@ -605,6 +664,7 @@ class ExternalModulesExecutor {
605
664
  return id;
606
665
  }
607
666
  }
667
+ // import.meta.resolve can be asynchronous in older +18 Node versions
608
668
  return nativeResolve(specifier, parent);
609
669
  }
610
670
  findNearestPackageData(basedir) {
@@ -667,6 +727,8 @@ class ExternalModulesExecutor {
667
727
  } else if (extension === ".cjs") {
668
728
  type = "commonjs";
669
729
  } else if (extension === ".wasm") {
730
+ // still experimental on NodeJS --experimental-wasm-modules
731
+ // cf. ESM_FILE_FORMAT(url) in https://nodejs.org/docs/latest-v20.x/api/esm.html#resolution-algorithm
670
732
  type = "wasm";
671
733
  } else {
672
734
  const pkgData = this.findNearestPackageData(normalize(pathUrl));
@@ -680,6 +742,8 @@ class ExternalModulesExecutor {
680
742
  }
681
743
  createModule(identifier) {
682
744
  const { type, url, path } = this.getModuleInformation(identifier);
745
+ // create ERR_MODULE_NOT_FOUND on our own since latest NodeJS's import.meta.resolve doesn't throw on non-existing namespace or path
746
+ // https://github.com/nodejs/node/pull/49038
683
747
  if ((type === "module" || type === "commonjs" || type === "wasm") && !existsSync(path)) {
684
748
  const error = new Error(`Cannot find ${isBareImport(path) ? "package" : "module"} '${path}'`);
685
749
  error.code = "ERR_MODULE_NOT_FOUND";
@@ -767,9 +831,13 @@ async function runVmTests(method, state) {
767
831
  throw new TypeError(`Environment ${environment.name} doesn't provide a valid context. It should be created by "vm.createContext" method.`);
768
832
  }
769
833
  provideWorkerState(context, state);
834
+ // this is unfortunately needed for our own dependencies
835
+ // we need to find a way to not rely on this by default
836
+ // because browser doesn't provide these globals
770
837
  context.process = process;
771
838
  context.global = context;
772
839
  context.console = state.config.disableConsoleIntercept ? console : createCustomConsole(state);
840
+ // TODO: don't hardcode setImmediate in fake timers defaults
773
841
  context.setImmediate = setImmediate;
774
842
  context.clearImmediate = clearImmediate;
775
843
  const stubs = getDefaultRequestStubs(context);
@@ -1,7 +1,7 @@
1
1
  import { File, TaskResultPack, TaskEventPack, CancelReason, FileSpecification, Task } from '@vitest/runner';
2
2
  import { ViteNodeResolveId, ModuleCacheMap, ModuleExecutionInfo } from 'vite-node';
3
- import { a as SerializedConfig } from './config.d.UqE-KR0o.js';
4
- import { T as TransformMode, U as UserConsoleLog, A as AfterSuiteRunMeta, E as Environment } from './environment.d.D8YDy2v5.js';
3
+ import { a as SerializedConfig } from './config.d.D2ROskhv.js';
4
+ import { T as TransformMode, U as UserConsoleLog, A as AfterSuiteRunMeta, E as Environment } from './environment.d.cL3nLXbE.js';
5
5
  import { SnapshotResult } from '@vitest/snapshot';
6
6
 
7
7
  type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;
@@ -1,5 +1,5 @@
1
1
  import { MessagePort } from 'node:worker_threads';
2
- import { C as ContextRPC } from './worker.d.CoCI7hzP.js';
2
+ import { C as ContextRPC } from './worker.d.BKbBp2ga.js';
3
3
 
4
4
  interface WorkerContext extends ContextRPC {
5
5
  port: MessagePort;
package/dist/cli.js CHANGED
@@ -1,16 +1,16 @@
1
- import { c as createCLI } from './chunks/cac.I9MLYfT-.js';
1
+ import { c as createCLI } from './chunks/cac.DWaWHIIE.js';
2
2
  import '@vitest/utils';
3
3
  import 'events';
4
4
  import 'pathe';
5
5
  import 'tinyrainbow';
6
- import './chunks/constants.BZZyIeIE.js';
7
- import './chunks/index.CV36oG_L.js';
6
+ import './chunks/constants.DnKduX2e.js';
7
+ import './chunks/index.Bter3jj9.js';
8
8
  import 'node:perf_hooks';
9
9
  import '@vitest/runner/utils';
10
10
  import '@vitest/utils/source-map';
11
11
  import './chunks/env.Dq0hM4Xv.js';
12
12
  import 'std-env';
13
- import './chunks/typechecker.DnTrplSJ.js';
13
+ import './chunks/typechecker.BgzF-6iO.js';
14
14
  import 'node:os';
15
15
  import 'tinyexec';
16
16
  import './path.js';