vitest 4.0.0-beta.4 → 4.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/browser.d.ts +8 -9
  3. package/dist/browser.js +3 -2
  4. package/dist/chunks/base.BXI97p6t.js +39 -0
  5. package/dist/chunks/{benchmark.CYdenmiT.js → benchmark.UW6Ezvxy.js} +6 -8
  6. package/dist/chunks/{browser.d.BRP8scJf.d.ts → browser.d.Cawq_X_N.d.ts} +1 -1
  7. package/dist/chunks/{cac.CY0IAxC4.js → cac.WE-urWw5.js} +38 -115
  8. package/dist/chunks/{cli-api.B8xRY9Zt.js → cli-api.CZz3evYC.js} +931 -1439
  9. package/dist/chunks/{config.d.DZo8c7fw.d.ts → config.d.CKNVOKm0.d.ts} +3 -8
  10. package/dist/chunks/{console.DoJHFxmj.js → console.B0quX7yH.js} +32 -68
  11. package/dist/chunks/{constants.CXzqaLmq.js → constants.D_Q9UYh-.js} +1 -6
  12. package/dist/chunks/{coverage.C84l9G-M.js → coverage.BPRS6xgn.js} +395 -665
  13. package/dist/chunks/{coverage.DVF1vEu8.js → coverage.D_JHT54q.js} +2 -2
  14. package/dist/chunks/{coverage.d.CNYjU4GF.d.ts → coverage.d.BZtK59WP.d.ts} +7 -5
  15. package/dist/chunks/{creator.yfA2ExGt.js → creator.KEg6n5IC.js} +29 -75
  16. package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
  17. package/dist/chunks/{environment.d.Bhm9oc0v.d.ts → environment.d.2fYMoz3o.d.ts} +26 -4
  18. package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
  19. package/dist/chunks/{global.d.DAhT2emn.d.ts → global.d.K6uBQHzY.d.ts} +1 -1
  20. package/dist/chunks/{globals.Dgo-vS5G.js → globals.lgsmH00r.js} +7 -6
  21. package/dist/chunks/{index.D3SKT3tv.js → index.7w0eqmYM.js} +14 -24
  22. package/dist/chunks/{index.D1_MsKEt.js → index.AR8aAkCC.js} +4 -2
  23. package/dist/chunks/{index.CmSc2RE5.js → index.BG0gqZH-.js} +43 -106
  24. package/dist/chunks/{index.CtUvr1c8.js → index.CsFXYRkW.js} +27 -46
  25. package/dist/chunks/{index.Bz6b0Ib7.js → index.VNI-1z5c.js} +276 -604
  26. package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
  27. package/dist/chunks/moduleRunner.d.8kKUsuDg.d.ts +202 -0
  28. package/dist/chunks/moduleTransport.I-bgQy0S.js +19 -0
  29. package/dist/chunks/{node.fjCdwEIl.js → node.BOqcT2jW.js} +1 -1
  30. package/dist/chunks/{plugin.d.CLhMcYdD.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
  31. package/dist/chunks/{reporters.d.DWg40D2B.d.ts → reporters.d.CqR9-CDJ.d.ts} +52 -101
  32. package/dist/chunks/resolver.Bx6lE0iq.js +119 -0
  33. package/dist/chunks/{rpc.jnQO9F8a.js → rpc.RpPylpp0.js} +7 -21
  34. package/dist/chunks/runBaseTests.D6sfuWBM.js +99 -0
  35. package/dist/chunks/{setup-common.Ebx5x0eP.js → setup-common.hLGRxhC8.js} +15 -27
  36. package/dist/chunks/startModuleRunner.C8TW8zTN.js +655 -0
  37. package/dist/chunks/{typechecker.CMNPqJOo.js → typechecker.Cd1wvxUM.js} +97 -209
  38. package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
  39. package/dist/chunks/{utils.XdZDrNZV.js → utils.C7__0Iv5.js} +7 -17
  40. package/dist/chunks/{vi.CA0EPI9Y.js → vi.BfdOiD4j.js} +116 -269
  41. package/dist/chunks/{vm.BUnLJt_P.js → vm.BHBje7cC.js} +101 -225
  42. package/dist/chunks/{worker.d.zjyR34Pb.d.ts → worker.d.D9QWnzAe.d.ts} +16 -13
  43. package/dist/chunks/{worker.d.C-1AbnVe.d.ts → worker.d.Db-UVmXc.d.ts} +1 -1
  44. package/dist/cli.js +4 -4
  45. package/dist/config.cjs +3 -9
  46. package/dist/config.d.ts +10 -12
  47. package/dist/config.js +1 -1
  48. package/dist/coverage.d.ts +10 -11
  49. package/dist/coverage.js +5 -6
  50. package/dist/environments.d.ts +2 -2
  51. package/dist/environments.js +1 -1
  52. package/dist/index.d.ts +10 -9
  53. package/dist/index.js +6 -5
  54. package/dist/module-evaluator.d.ts +12 -0
  55. package/dist/module-evaluator.js +276 -0
  56. package/dist/module-runner.js +15 -0
  57. package/dist/node.d.ts +12 -13
  58. package/dist/node.js +19 -24
  59. package/dist/reporters.d.ts +7 -8
  60. package/dist/reporters.js +3 -3
  61. package/dist/runners.d.ts +3 -3
  62. package/dist/runners.js +35 -57
  63. package/dist/snapshot.js +2 -2
  64. package/dist/suite.js +2 -2
  65. package/dist/worker.js +82 -45
  66. package/dist/workers/forks.js +11 -10
  67. package/dist/workers/runVmTests.js +27 -46
  68. package/dist/workers/threads.js +11 -10
  69. package/dist/workers/vmForks.js +11 -10
  70. package/dist/workers/vmThreads.js +11 -10
  71. package/dist/workers.d.ts +5 -4
  72. package/dist/workers.js +17 -16
  73. package/package.json +22 -17
  74. package/dist/chunks/base.BaCDDRPG.js +0 -38
  75. package/dist/chunks/execute.Dt-pCVcL.js +0 -708
  76. package/dist/chunks/runBaseTests.DBVVLMSb.js +0 -129
  77. package/dist/execute.d.ts +0 -148
  78. package/dist/execute.js +0 -13
@@ -10,16 +10,13 @@ import { parseAstAsync } from 'vite';
10
10
 
11
11
  const REGEXP_WRAP_PREFIX = "$$vitest:";
12
12
  function getOutputFile(config, reporter) {
13
- if (!config?.outputFile) return;
14
- if (typeof config.outputFile === "string") return config.outputFile;
15
- return config.outputFile[reporter];
13
+ if (config?.outputFile) return typeof config.outputFile === "string" ? config.outputFile : config.outputFile[reporter];
16
14
  }
17
15
  /**
18
16
  * Prepares `SerializedConfig` for serialization, e.g. `node:v8.serialize`
19
17
  */
20
18
  function wrapSerializableConfig(config) {
21
- let testNamePattern = config.testNamePattern;
22
- let defines = config.defines;
19
+ let testNamePattern = config.testNamePattern, defines = config.defines;
23
20
  // v8 serialize does not support regex
24
21
  if (testNamePattern && typeof testNamePattern !== "string") testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
25
22
  // v8 serialize drops properties with undefined value
@@ -40,58 +37,44 @@ function hasFailedSnapshot(suite) {
40
37
  });
41
38
  }
42
39
  function convertTasksToEvents(file, onTask) {
43
- const packs = [];
44
- const events = [];
40
+ const packs = [], events = [];
45
41
  function visit(suite) {
46
- onTask?.(suite);
47
- packs.push([
42
+ onTask?.(suite), packs.push([
48
43
  suite.id,
49
44
  suite.result,
50
45
  suite.meta
51
- ]);
52
- events.push([
46
+ ]), events.push([
53
47
  suite.id,
54
48
  "suite-prepare",
55
49
  void 0
56
- ]);
57
- suite.tasks.forEach((task) => {
50
+ ]), suite.tasks.forEach((task) => {
58
51
  if (task.type === "suite") visit(task);
59
- else {
60
- onTask?.(task);
61
- if (suite.mode !== "skip" && suite.mode !== "todo") {
62
- packs.push([
63
- task.id,
64
- task.result,
65
- task.meta
66
- ]);
67
- events.push([
68
- task.id,
69
- "test-prepare",
70
- void 0
71
- ]);
72
- task.annotations.forEach((annotation) => {
73
- events.push([
74
- task.id,
75
- "test-annotation",
76
- { annotation }
77
- ]);
78
- });
79
- events.push([
80
- task.id,
81
- "test-finished",
82
- void 0
83
- ]);
84
- }
85
- }
86
- });
87
- events.push([
52
+ else if (onTask?.(task), suite.mode !== "skip" && suite.mode !== "todo") packs.push([
53
+ task.id,
54
+ task.result,
55
+ task.meta
56
+ ]), events.push([
57
+ task.id,
58
+ "test-prepare",
59
+ void 0
60
+ ]), task.annotations.forEach((annotation) => {
61
+ events.push([
62
+ task.id,
63
+ "test-annotation",
64
+ { annotation }
65
+ ]);
66
+ }), events.push([
67
+ task.id,
68
+ "test-finished",
69
+ void 0
70
+ ]);
71
+ }), events.push([
88
72
  suite.id,
89
73
  "suite-finished",
90
74
  void 0
91
75
  ]);
92
76
  }
93
- visit(file);
94
- return {
77
+ return visit(file), {
95
78
  packs,
96
79
  events
97
80
  };
@@ -374,13 +357,9 @@ base.MethodDefinition = base.PropertyDefinition = base.Property = function (node
374
357
  };
375
358
 
376
359
  async function collectTests(ctx, filepath) {
377
- const request = await ctx.vitenode.transformRequest(filepath, filepath);
360
+ const request = await ctx.vite.environments.ssr.transformRequest(filepath);
378
361
  if (!request) return null;
379
- const ast = await parseAstAsync(request.code);
380
- const testFilepath = relative(ctx.config.root, filepath);
381
- const projectName = ctx.name;
382
- const typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__";
383
- const file = {
362
+ const ast = await parseAstAsync(request.code), testFilepath = relative(ctx.config.root, filepath), projectName = ctx.name, typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__", file = {
384
363
  filepath,
385
364
  type: "suite",
386
365
  id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
@@ -394,24 +373,19 @@ async function collectTests(ctx, filepath) {
394
373
  file: null
395
374
  };
396
375
  file.file = file;
397
- const definitions = [];
398
- const getName = (callee) => {
376
+ const definitions = [], getName = (callee) => {
399
377
  if (!callee) return null;
400
378
  if (callee.type === "Identifier") return callee.name;
401
379
  if (callee.type === "CallExpression") return getName(callee.callee);
402
380
  if (callee.type === "TaggedTemplateExpression") return getName(callee.tag);
403
- if (callee.type === "MemberExpression") {
404
- if (callee.object?.type === "Identifier" && [
405
- "it",
406
- "test",
407
- "describe",
408
- "suite"
409
- ].includes(callee.object.name)) return callee.object?.name;
410
- // direct call as `__vite_ssr_exports_0__.test()`
411
- if (callee.object?.name?.startsWith("__vite_ssr_")) return getName(callee.property);
412
- // call as `__vite_ssr__.test.skip()`
413
- return getName(callee.object?.property);
414
- }
381
+ if (callee.type === "MemberExpression")
382
+ // call as `__vite_ssr__.test.skip()`
383
+ return callee.object?.type === "Identifier" && [
384
+ "it",
385
+ "test",
386
+ "describe",
387
+ "suite"
388
+ ].includes(callee.object.name) ? callee.object?.name : callee.object?.name?.startsWith("__vite_ssr_") ? getName(callee.property) : getName(callee.object?.property);
415
389
  // unwrap (0, ...)
416
390
  if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
417
391
  const [e0, e1] = callee.expressions;
@@ -420,10 +394,8 @@ async function collectTests(ctx, filepath) {
420
394
  return null;
421
395
  };
422
396
  ancestor(ast, { CallExpression(node) {
423
- const { callee } = node;
424
- const name = getName(callee);
425
- if (!name) return;
426
- if (![
397
+ const { callee } = node, name = getName(callee);
398
+ if (!name || ![
427
399
  "it",
428
400
  "test",
429
401
  "describe",
@@ -444,9 +416,7 @@ async function collectTests(ctx, filepath) {
444
416
  if (callee.type === "CallExpression") start = callee.end;
445
417
  else if (callee.type === "TaggedTemplateExpression") start = callee.end + 1;
446
418
  else start = node.start;
447
- const { arguments: [messageNode] } = node;
448
- const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
449
- const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
419
+ const { arguments: [messageNode] } = node, isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral", message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
450
420
  // cannot statically analyze, so we always skip it
451
421
  if (mode === "skipIf" || mode === "runIf") mode = "skip";
452
422
  definitions.push({
@@ -482,9 +452,7 @@ async function collectTests(ctx, filepath) {
482
452
  start: definition.start,
483
453
  meta: { typecheck: true }
484
454
  };
485
- definition.task = task;
486
- latestSuite.tasks.push(task);
487
- lastSuite = task;
455
+ definition.task = task, latestSuite.tasks.push(task), lastSuite = task;
488
456
  return;
489
457
  }
490
458
  const task = {
@@ -501,13 +469,10 @@ async function collectTests(ctx, filepath) {
501
469
  annotations: [],
502
470
  meta: { typecheck: true }
503
471
  };
504
- definition.task = task;
505
- latestSuite.tasks.push(task);
506
- });
507
- calculateSuiteHash(file);
472
+ definition.task = task, latestSuite.tasks.push(task);
473
+ }), calculateSuiteHash(file);
508
474
  const hasOnly = someTasksAreOnly(file);
509
- interpretTaskModes(file, ctx.config.testNamePattern, void 0, hasOnly, false, ctx.config.allowOnly);
510
- return {
475
+ return interpretTaskModes(file, ctx.config.testNamePattern, void 0, hasOnly, false, ctx.config.allowOnly), {
511
476
  file,
512
477
  parsed: request.code,
513
478
  filepath,
@@ -516,14 +481,11 @@ async function collectTests(ctx, filepath) {
516
481
  };
517
482
  }
518
483
 
519
- const newLineRegExp = /\r?\n/;
520
- const errCodeRegExp = /error TS(?<errCode>\d+)/;
484
+ const newLineRegExp = /\r?\n/, errCodeRegExp = /error TS(?<errCode>\d+)/;
521
485
  async function makeTscErrorInfo(errInfo) {
522
486
  const [errFilePathPos = "", ...errMsgRawArr] = errInfo.split(":");
523
487
  if (!errFilePathPos || errMsgRawArr.length === 0 || errMsgRawArr.join("").length === 0) return ["unknown filepath", null];
524
- const errMsgRaw = errMsgRawArr.join("").trim();
525
- // get filePath, line, col
526
- const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
488
+ const errMsgRaw = errMsgRawArr.join("").trim(), [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
527
489
  if (!errFilePath || !errPos) return ["unknown filepath", null];
528
490
  const [errLine, errCol] = errPos.split(",");
529
491
  if (!errLine || !errCol) return [errFilePath, null];
@@ -532,9 +494,7 @@ async function makeTscErrorInfo(errInfo) {
532
494
  if (!execArr) return [errFilePath, null];
533
495
  const errCodeStr = execArr.groups?.errCode ?? "";
534
496
  if (!errCodeStr) return [errFilePath, null];
535
- const line = Number(errLine);
536
- const col = Number(errCol);
537
- const errCode = Number(errCodeStr);
497
+ const line = Number(errLine), col = Number(errCol), errCode = Number(errCodeStr);
538
498
  return [errFilePath, {
539
499
  filePath: errFilePath,
540
500
  errCode,
@@ -544,43 +504,30 @@ async function makeTscErrorInfo(errInfo) {
544
504
  }];
545
505
  }
546
506
  async function getRawErrsMapFromTsCompile(tscErrorStdout) {
547
- const rawErrsMap = /* @__PURE__ */ new Map();
548
- // Merge details line with main line (i.e. which contains file path)
549
- const infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
507
+ const rawErrsMap = /* @__PURE__ */ new Map(), infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
550
508
  if (!next) return prev;
551
- else if (!next.startsWith(" ")) prev.push(next);
509
+ if (!next.startsWith(" ")) prev.push(next);
552
510
  else prev[prev.length - 1] += `\n${next}`;
553
511
  return prev;
554
512
  }, []).map((errInfoLine) => makeTscErrorInfo(errInfoLine)));
555
- infos.forEach(([errFilePath, errInfo]) => {
556
- if (!errInfo) return;
557
- if (!rawErrsMap.has(errFilePath)) rawErrsMap.set(errFilePath, [errInfo]);
513
+ return infos.forEach(([errFilePath, errInfo]) => {
514
+ if (errInfo) if (!rawErrsMap.has(errFilePath)) rawErrsMap.set(errFilePath, [errInfo]);
558
515
  else rawErrsMap.get(errFilePath)?.push(errInfo);
559
- });
560
- return rawErrsMap;
516
+ }), rawErrsMap;
561
517
  }
562
518
 
563
519
  function createIndexMap(source) {
564
520
  const map = /* @__PURE__ */ new Map();
565
- let index = 0;
566
- let line = 1;
567
- let column = 1;
568
- for (const char of source) {
569
- map.set(`${line}:${column}`, index++);
570
- if (char === "\n" || char === "\r\n") {
571
- line++;
572
- column = 0;
573
- } else column++;
574
- }
521
+ let index = 0, line = 1, column = 1;
522
+ for (const char of source) if (map.set(`${line}:${column}`, index++), char === "\n" || char === "\r\n") line++, column = 0;
523
+ else column++;
575
524
  return map;
576
525
  }
577
526
 
578
527
  class TypeCheckError extends Error {
579
528
  name = "TypeCheckError";
580
529
  constructor(message, stacks) {
581
- super(message);
582
- this.message = message;
583
- this.stacks = stacks;
530
+ super(message), this.message = message, this.stacks = stacks;
584
531
  }
585
532
  }
586
533
  class Typechecker {
@@ -620,12 +567,9 @@ class Typechecker {
620
567
  }
621
568
  async collectTests() {
622
569
  const tests = (await Promise.all(this.getFiles().map((filepath) => this.collectFileTests(filepath)))).reduce((acc, data) => {
623
- if (!data) return acc;
624
- acc[data.filepath] = data;
625
- return acc;
570
+ return data && (acc[data.filepath] = data), acc;
626
571
  }, {});
627
- this._tests = tests;
628
- return tests;
572
+ return this._tests = tests, tests;
629
573
  }
630
574
  markPassed(file) {
631
575
  if (!file.result?.state) file.result = { state: "pass" };
@@ -638,26 +582,17 @@ class Typechecker {
638
582
  markTasks(file.tasks);
639
583
  }
640
584
  async prepareResults(output) {
641
- const typeErrors = await this.parseTscLikeOutput(output);
642
- const testFiles = new Set(this.getFiles());
585
+ const typeErrors = await this.parseTscLikeOutput(output), testFiles = new Set(this.getFiles());
643
586
  if (!this._tests) this._tests = await this.collectTests();
644
- const sourceErrors = [];
645
- const files = [];
646
- testFiles.forEach((path) => {
647
- const { file, definitions, map, parsed } = this._tests[path];
648
- const errors = typeErrors.get(path);
649
- files.push(file);
650
- if (!errors) {
587
+ const sourceErrors = [], files = [];
588
+ return testFiles.forEach((path) => {
589
+ const { file, definitions, map, parsed } = this._tests[path], errors = typeErrors.get(path);
590
+ if (files.push(file), !errors) {
651
591
  this.markPassed(file);
652
592
  return;
653
593
  }
654
- const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)];
655
- // has no map for ".js" files that use // @ts-check
656
- const traceMap = map && new TraceMap(map);
657
- const indexMap = createIndexMap(parsed);
658
- const markState = (task, state) => {
659
- task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode };
660
- if (task.suite) markState(task.suite, state);
594
+ const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)], traceMap = map && new TraceMap(map), indexMap = createIndexMap(parsed), markState = (task, state) => {
595
+ if (task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode }, task.suite) markState(task.suite, state);
661
596
  else if (task.file && task !== task.file) markState(task.file, state);
662
597
  };
663
598
  errors.forEach(({ error, originalError }) => {
@@ -665,53 +600,37 @@ class Typechecker {
665
600
  line: originalError.line,
666
601
  column: originalError.column,
667
602
  source: basename(path)
668
- }) : originalError;
669
- const line = processedPos.line ?? originalError.line;
670
- const column = processedPos.column ?? originalError.column;
671
- const index = indexMap.get(`${line}:${column}`);
672
- const definition = index != null && sortedDefinitions.find((def) => def.start <= index && def.end >= index);
673
- const suite = definition ? definition.task : file;
674
- const state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode;
675
- const errors = suite.result?.errors || [];
676
- suite.result = {
603
+ }) : originalError, line = processedPos.line ?? originalError.line, column = processedPos.column ?? originalError.column, index = indexMap.get(`${line}:${column}`), definition = index != null && sortedDefinitions.find((def) => def.start <= index && def.end >= index), suite = definition ? definition.task : file, state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode, errors = suite.result?.errors || [];
604
+ if (suite.result = {
677
605
  state,
678
606
  errors
679
- };
680
- errors.push(error);
681
- if (state === "fail") {
607
+ }, errors.push(error), state === "fail") {
682
608
  if (suite.suite) markState(suite.suite, "fail");
683
609
  else if (suite.file && suite !== suite.file) markState(suite.file, "fail");
684
610
  }
685
- });
686
- this.markPassed(file);
687
- });
688
- typeErrors.forEach((errors, path) => {
611
+ }), this.markPassed(file);
612
+ }), typeErrors.forEach((errors, path) => {
689
613
  if (!testFiles.has(path)) sourceErrors.push(...errors.map(({ error }) => error));
690
- });
691
- return {
614
+ }), {
692
615
  files,
693
616
  sourceErrors,
694
617
  time: performance.now() - this._startTime
695
618
  };
696
619
  }
697
620
  async parseTscLikeOutput(output) {
698
- const errorsMap = await getRawErrsMapFromTsCompile(output);
699
- const typesErrors = /* @__PURE__ */ new Map();
700
- errorsMap.forEach((errors, path) => {
701
- const filepath = resolve(this.project.config.root, path);
702
- const suiteErrors = errors.map((info) => {
621
+ const errorsMap = await getRawErrsMapFromTsCompile(output), typesErrors = /* @__PURE__ */ new Map();
622
+ return errorsMap.forEach((errors, path) => {
623
+ const filepath = resolve(this.project.config.root, path), suiteErrors = errors.map((info) => {
703
624
  const limit = Error.stackTraceLimit;
704
625
  Error.stackTraceLimit = 0;
705
626
  // 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.`
706
- const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1");
707
- const error = new TypeCheckError(errMsg, [{
627
+ const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1"), error = new TypeCheckError(errMsg, [{
708
628
  file: filepath,
709
629
  line: info.line,
710
630
  column: info.column,
711
631
  method: ""
712
632
  }]);
713
- Error.stackTraceLimit = limit;
714
- return {
633
+ return Error.stackTraceLimit = limit, {
715
634
  originalError: info,
716
635
  error: {
717
636
  name: error.name,
@@ -722,12 +641,10 @@ class Typechecker {
722
641
  };
723
642
  });
724
643
  typesErrors.set(filepath, suiteErrors);
725
- });
726
- return typesErrors;
644
+ }), typesErrors;
727
645
  }
728
646
  async stop() {
729
- this.process?.kill();
730
- this.process = void 0;
647
+ this.process?.kill(), this.process = void 0;
731
648
  }
732
649
  async ensurePackageInstalled(ctx, checker) {
733
650
  if (checker !== "tsc" && checker !== "vue-tsc") return;
@@ -741,8 +658,7 @@ class Typechecker {
741
658
  return this._output;
742
659
  }
743
660
  async spawn() {
744
- const { root, watch, typecheck } = this.project.config;
745
- const args = [
661
+ const { root, watch, typecheck } = this.project.config, args = [
746
662
  "--noEmit",
747
663
  "--pretty",
748
664
  "false",
@@ -754,8 +670,7 @@ class Typechecker {
754
670
  if (watch) args.push("--watch");
755
671
  if (typecheck.allowJs) args.push("--allowJs", "--checkJs");
756
672
  if (typecheck.tsconfig) args.push("-p", resolve(root, typecheck.tsconfig));
757
- this._output = "";
758
- this._startTime = performance.now();
673
+ this._output = "", this._startTime = performance.now();
759
674
  const child = x(typecheck.checker, args, {
760
675
  nodeOptions: {
761
676
  cwd: root,
@@ -764,44 +679,26 @@ class Typechecker {
764
679
  throwOnError: false
765
680
  });
766
681
  this.process = child.process;
767
- let rerunTriggered = false;
768
- let dataReceived = false;
682
+ let rerunTriggered = false, dataReceived = false;
769
683
  return new Promise((resolve, reject) => {
770
684
  if (!child.process || !child.process.stdout) {
771
685
  reject(/* @__PURE__ */ new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`));
772
686
  return;
773
687
  }
774
688
  child.process.stdout.on("data", (chunk) => {
775
- dataReceived = true;
776
- this._output += chunk;
777
- if (!watch) return;
778
- if (this._output.includes("File change detected") && !rerunTriggered) {
779
- this._onWatcherRerun?.();
780
- this._startTime = performance.now();
781
- this._result.sourceErrors = [];
782
- this._result.files = [];
783
- this._tests = null;
784
- rerunTriggered = true;
785
- }
786
- if (/Found \w+ errors*. Watching for/.test(this._output)) {
787
- rerunTriggered = false;
788
- this.prepareResults(this._output).then((result) => {
789
- this._result = result;
790
- this._onParseEnd?.(result);
791
- });
792
- this._output = "";
689
+ if (dataReceived = true, this._output += chunk, watch) {
690
+ if (this._output.includes("File change detected") && !rerunTriggered) this._onWatcherRerun?.(), this._startTime = performance.now(), this._result.sourceErrors = [], this._result.files = [], this._tests = null, rerunTriggered = true;
691
+ if (/Found \w+ errors*. Watching for/.test(this._output)) rerunTriggered = false, this.prepareResults(this._output).then((result) => {
692
+ this._result = result, this._onParseEnd?.(result);
693
+ }), this._output = "";
793
694
  }
794
695
  });
795
696
  const timeout = setTimeout(() => reject(/* @__PURE__ */ new Error(`${typecheck.checker} spawn timed out`)), this.project.config.typecheck.spawnTimeout);
796
697
  function onError(cause) {
797
- clearTimeout(timeout);
798
- reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
698
+ clearTimeout(timeout), reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
799
699
  }
800
- child.process.once("spawn", () => {
801
- this._onParseStart?.();
802
- child.process?.off("error", onError);
803
- clearTimeout(timeout);
804
- if (process.platform === "win32")
700
+ if (child.process.once("spawn", () => {
701
+ if (this._onParseStart?.(), child.process?.off("error", onError), clearTimeout(timeout), process.platform === "win32")
805
702
  // on Windows, the process might be spawned but fail to start
806
703
  // we wait for a potential error here. if "close" event didn't trigger,
807
704
  // we resolve the promise
@@ -809,8 +706,7 @@ class Typechecker {
809
706
  resolve({ result: child });
810
707
  }, 200);
811
708
  else resolve({ result: child });
812
- });
813
- if (process.platform === "win32") child.process.once("close", (code) => {
709
+ }), process.platform === "win32") child.process.once("close", (code) => {
814
710
  if (code != null && code !== 0 && !dataReceived) onError(/* @__PURE__ */ new Error(`The ${typecheck.checker} command exited with code ${code}.`));
815
711
  });
816
712
  child.process.once("error", onError);
@@ -818,13 +714,8 @@ class Typechecker {
818
714
  }
819
715
  async start() {
820
716
  if (this.process) return;
821
- const { watch } = this.project.config;
822
- const { result: child } = await this.spawn();
823
- if (!watch) {
824
- await child;
825
- this._result = await this.prepareResults(this._output);
826
- await this._onParseEnd?.(this._result);
827
- }
717
+ const { watch } = this.project.config, { result: child } = await this.spawn();
718
+ if (!watch) await child, this._result = await this.prepareResults(this._output), await this._onParseEnd?.(this._result);
828
719
  }
829
720
  getResult() {
830
721
  return this._result;
@@ -833,12 +724,10 @@ class Typechecker {
833
724
  return Object.values(this._tests || {}).map((i) => i.file);
834
725
  }
835
726
  getTestPacksAndEvents() {
836
- const packs = [];
837
- const events = [];
727
+ const packs = [], events = [];
838
728
  for (const { file } of Object.values(this._tests || {})) {
839
729
  const result = convertTasksToEvents(file);
840
- packs.push(...result.packs);
841
- events.push(...result.events);
730
+ packs.push(...result.packs), events.push(...result.events);
842
731
  }
843
732
  return {
844
733
  packs,
@@ -861,11 +750,10 @@ function findGeneratedPosition(traceMap, { line, column, source }) {
861
750
  if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) mappings.push(m);
862
751
  });
863
752
  const next = mappings.sort((a, b) => a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine).at(0);
864
- if (next) return {
753
+ return next ? {
865
754
  line: next.generatedLine,
866
755
  column: next.generatedColumn
867
- };
868
- return {
756
+ } : {
869
757
  line: null,
870
758
  column: null
871
759
  };
@@ -1,11 +1,6 @@
1
1
  import { parseRegexp } from '@vitest/utils';
2
2
 
3
- const REGEXP_WRAP_PREFIX = "$$vitest:";
4
- // Store global APIs in case process is overwritten by tests
5
- const processSend = process.send?.bind(process);
6
- const processOn = process.on?.bind(process);
7
- const processOff = process.off?.bind(process);
8
- const dispose = [];
3
+ const REGEXP_WRAP_PREFIX = "$$vitest:", processSend = process.send?.bind(process), processOn = process.on?.bind(process), processOff = process.off?.bind(process), dispose = [];
9
4
  function createThreadsRpcOptions({ port }) {
10
5
  return {
11
6
  post: (v) => {
@@ -31,12 +26,9 @@ function createForksRpcOptions(nodeV8) {
31
26
  },
32
27
  on(fn) {
33
28
  const handler = (message, ...extras) => {
34
- // Do not react on Tinypool's internal messaging
35
- if (message?.__tinypool_worker_message__) return;
36
- return fn(message, ...extras);
29
+ if (!message?.__tinypool_worker_message__) return fn(message, ...extras);
37
30
  };
38
- processOn("message", handler);
39
- dispose.push(() => processOff("message", handler));
31
+ processOn("message", handler), dispose.push(() => processOff("message", handler));
40
32
  }
41
33
  };
42
34
  }
@@ -49,8 +41,7 @@ function unwrapSerializableConfig(config) {
49
41
  if (testNamePattern.startsWith(REGEXP_WRAP_PREFIX)) config.testNamePattern = parseRegexp(testNamePattern.slice(9));
50
42
  }
51
43
  if (config.defines && Array.isArray(config.defines.keys) && config.defines.original) {
52
- const { keys, original } = config.defines;
53
- const defines = {};
44
+ const { keys, original } = config.defines, defines = {};
54
45
  // Apply all keys from the original. Entries which had undefined value are missing from original now
55
46
  for (const key of keys) defines[key] = original[key];
56
47
  config.defines = defines;
@@ -11,13 +11,12 @@ function getWorkerState() {
11
11
  return workerState;
12
12
  }
13
13
  function provideWorkerState(context, state) {
14
- Object.defineProperty(context, NAME_WORKER_STATE, {
14
+ return Object.defineProperty(context, NAME_WORKER_STATE, {
15
15
  value: state,
16
16
  configurable: true,
17
17
  writable: true,
18
18
  enumerable: false
19
- });
20
- return state;
19
+ }), state;
21
20
  }
22
21
  function getCurrentEnvironment() {
23
22
  const state = getWorkerState();
@@ -34,14 +33,12 @@ function setProcessTitle(title) {
34
33
  function resetModules(modules, resetMocks = false) {
35
34
  const skipPaths = [
36
35
  /\/vitest\/dist\//,
37
- /\/vite-node\/dist\//,
38
36
  /vitest-virtual-\w+\/dist/,
39
37
  /@vitest\/dist/,
40
38
  ...!resetMocks ? [/^mock:/] : []
41
39
  ];
42
- modules.forEach((mod, path) => {
43
- if (skipPaths.some((re) => re.test(path))) return;
44
- modules.invalidateModule(mod);
40
+ modules.idToModuleMap.forEach((node, path) => {
41
+ skipPaths.some((re) => re.test(path)) || (node.promise = void 0, node.exports = void 0, node.evaluated = false, node.importers.clear());
45
42
  });
46
43
  }
47
44
  function waitNextTick() {
@@ -50,16 +47,9 @@ function waitNextTick() {
50
47
  }
51
48
  async function waitForImportsToResolve() {
52
49
  await waitNextTick();
53
- const state = getWorkerState();
54
- const promises = [];
55
- let resolvingCount = 0;
56
- for (const mod of state.moduleCache.values()) {
57
- if (mod.promise && !mod.evaluated) promises.push(mod.promise);
58
- if (mod.resolving) resolvingCount++;
59
- }
60
- if (!promises.length && !resolvingCount) return;
61
- await Promise.allSettled(promises);
62
- await waitForImportsToResolve();
50
+ const state = getWorkerState(), promises = [], resolvingCount = state.resolvingModules.size;
51
+ for (const [_, mod] of state.evaluatedModules.idToModuleMap) if (mod.promise && !mod.evaluated) promises.push(mod.promise);
52
+ !promises.length && !resolvingCount || (await Promise.allSettled(promises), await waitForImportsToResolve());
63
53
  }
64
54
 
65
55
  export { getCurrentEnvironment as a, getWorkerState as g, isChildProcess as i, provideWorkerState as p, resetModules as r, setProcessTitle as s, waitForImportsToResolve as w };