vitest 3.1.0-beta.1 → 3.1.0

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 (88) hide show
  1. package/LICENSE.md +29 -0
  2. package/dist/browser.js +4 -4
  3. package/dist/chunks/base.bV8rwssx.js +41 -0
  4. package/dist/chunks/benchmark.BKUatJGy.js +39 -0
  5. package/dist/chunks/cac.1WcTh-zl.js +1529 -0
  6. package/dist/chunks/{cli-api.BwkkJsRe.js → cli-api.2yb7XCwB.js} +4640 -5072
  7. package/dist/chunks/console.D6t261w0.js +173 -0
  8. package/dist/chunks/constants.BZZyIeIE.js +43 -0
  9. package/dist/chunks/coverage.0iPg4Wrz.js +33 -0
  10. package/dist/chunks/{coverage.gV8doR2Y.js → coverage.SfnlalVs.js} +2424 -2482
  11. package/dist/chunks/creator.CuL7xDWI.js +705 -0
  12. package/dist/chunks/date.CDOsz-HY.js +53 -0
  13. package/dist/chunks/defaults.DmfNPoe5.js +114 -0
  14. package/dist/chunks/{env.D4Lgay0q.js → env.Dq0hM4Xv.js} +1 -1
  15. package/dist/chunks/execute.CwmnH2oH.js +791 -0
  16. package/dist/chunks/git.DXfdBEfR.js +74 -0
  17. package/dist/chunks/{globals.BEpDe-k3.js → globals.DCbUWjip.js} +10 -10
  18. package/dist/chunks/{index.D7Ny8f_s.js → index.BDobFbcz.js} +6 -7
  19. package/dist/chunks/index.CwHmn5H5.js +2422 -0
  20. package/dist/chunks/index.DFXFpH3w.js +607 -0
  21. package/dist/chunks/index.VfYQ6MXY.js +104 -0
  22. package/dist/chunks/inspector.DbDkSkFn.js +54 -0
  23. package/dist/chunks/node.IqGoMrm4.js +15 -0
  24. package/dist/chunks/{reporters.d.r7poTZjA.d.ts → reporters.d.CfRkRKN2.d.ts} +52 -20
  25. package/dist/chunks/rpc.DGgL5dw7.js +92 -0
  26. package/dist/chunks/run-once.I7PpBOk1.js +47 -0
  27. package/dist/chunks/runBaseTests.CqmKSG99.js +134 -0
  28. package/dist/chunks/setup-common.DEGDGBiA.js +88 -0
  29. package/dist/chunks/{typechecker.BlF3eHsb.js → typechecker.CG0zmr19.js} +620 -622
  30. package/dist/chunks/utils.BfxieIyZ.js +66 -0
  31. package/dist/chunks/utils.CtocqOoE.js +72 -0
  32. package/dist/chunks/utils.Lot3J_8U.js +194 -0
  33. package/dist/chunks/{vi.nSCvwQ7l.js → vi.B-PuvDzu.js} +878 -1019
  34. package/dist/chunks/vite.d.4pkSbgmp.d.ts +23 -0
  35. package/dist/chunks/vm.Lp7mPCVW.js +796 -0
  36. package/dist/cli.js +2 -2
  37. package/dist/config.cjs +97 -103
  38. package/dist/config.d.ts +6 -4
  39. package/dist/config.js +6 -6
  40. package/dist/coverage.d.ts +2 -1
  41. package/dist/coverage.js +7 -7
  42. package/dist/environments.js +1 -1
  43. package/dist/execute.d.ts +0 -2
  44. package/dist/execute.js +1 -1
  45. package/dist/index.d.ts +6 -5
  46. package/dist/index.js +6 -6
  47. package/dist/node.d.ts +17 -6
  48. package/dist/node.js +36 -45
  49. package/dist/path.js +1 -4
  50. package/dist/reporters.d.ts +2 -1
  51. package/dist/reporters.js +4 -4
  52. package/dist/runners.js +231 -267
  53. package/dist/snapshot.js +2 -2
  54. package/dist/suite.js +2 -2
  55. package/dist/worker.js +98 -114
  56. package/dist/workers/forks.js +22 -22
  57. package/dist/workers/runVmTests.js +61 -66
  58. package/dist/workers/threads.js +13 -13
  59. package/dist/workers/vmForks.js +24 -24
  60. package/dist/workers/vmThreads.js +15 -15
  61. package/dist/workers.d.ts +2 -1
  62. package/dist/workers.js +10 -10
  63. package/package.json +17 -17
  64. package/dist/chunks/base.DV59CbtV.js +0 -45
  65. package/dist/chunks/benchmark.DL72EVN-.js +0 -40
  66. package/dist/chunks/cac.BjmXy7OV.js +0 -1664
  67. package/dist/chunks/console.CN7AiMGV.js +0 -179
  68. package/dist/chunks/constants.DTYd6dNH.js +0 -46
  69. package/dist/chunks/coverage.A3sS5-Wm.js +0 -40
  70. package/dist/chunks/creator.BsBnpTzI.js +0 -670
  71. package/dist/chunks/date.W2xKR2qe.js +0 -53
  72. package/dist/chunks/defaults.C2Ndd9wx.js +0 -119
  73. package/dist/chunks/execute.eDH0aFFd.js +0 -839
  74. package/dist/chunks/git.B5SDxu-n.js +0 -69
  75. package/dist/chunks/index.DOyx6FYJ.js +0 -2551
  76. package/dist/chunks/index.K90BXFOx.js +0 -658
  77. package/dist/chunks/index.uXkkC4xl.js +0 -111
  78. package/dist/chunks/inspector.DKLceBVD.js +0 -54
  79. package/dist/chunks/node.AKq966Jp.js +0 -15
  80. package/dist/chunks/rpc.TVf73xOu.js +0 -102
  81. package/dist/chunks/run-once.2ogXb3JV.js +0 -28
  82. package/dist/chunks/runBaseTests.BVrL_ow3.js +0 -142
  83. package/dist/chunks/setup-common.CPvtqi8q.js +0 -96
  84. package/dist/chunks/utils.C8RiOc4B.js +0 -77
  85. package/dist/chunks/utils.Cn0zI1t3.js +0 -68
  86. package/dist/chunks/utils.bLM2atbD.js +0 -198
  87. package/dist/chunks/vite.d.Fvq-NZoa.d.ts +0 -11
  88. package/dist/chunks/vm.jEFQDlX_.js +0 -852
@@ -14,60 +14,75 @@ import ve from 'node:module';
14
14
  import require$$0 from 'fs';
15
15
 
16
16
  function hasFailedSnapshot(suite) {
17
- return getTests(suite).some((s) => {
18
- return s.result?.errors?.some(
19
- (e) => typeof e?.message === "string" && e.message.match(/Snapshot .* mismatched/)
20
- );
21
- });
17
+ return getTests(suite).some((s) => {
18
+ return s.result?.errors?.some((e) => typeof e?.message === "string" && e.message.match(/Snapshot .* mismatched/));
19
+ });
22
20
  }
23
21
  function convertTasksToEvents(file, onTask) {
24
- const packs = [];
25
- const events = [];
26
- function visit(suite) {
27
- onTask?.(suite);
28
- packs.push([suite.id, suite.result, suite.meta]);
29
- events.push([suite.id, "suite-prepare"]);
30
- suite.tasks.forEach((task) => {
31
- if (task.type === "suite") {
32
- visit(task);
33
- } else {
34
- onTask?.(task);
35
- packs.push([task.id, task.result, task.meta]);
36
- if (task.mode !== "skip" && task.mode !== "todo") {
37
- events.push([task.id, "test-prepare"], [task.id, "test-finished"]);
38
- }
39
- }
40
- });
41
- events.push([suite.id, "suite-finished"]);
42
- }
43
- visit(file);
44
- return { packs, events };
22
+ const packs = [];
23
+ const events = [];
24
+ function visit(suite) {
25
+ onTask?.(suite);
26
+ packs.push([
27
+ suite.id,
28
+ suite.result,
29
+ suite.meta
30
+ ]);
31
+ events.push([suite.id, "suite-prepare"]);
32
+ suite.tasks.forEach((task) => {
33
+ if (task.type === "suite") {
34
+ visit(task);
35
+ } else {
36
+ onTask?.(task);
37
+ if (suite.mode !== "skip" && suite.mode !== "todo") {
38
+ packs.push([
39
+ task.id,
40
+ task.result,
41
+ task.meta
42
+ ]);
43
+ events.push([task.id, "test-prepare"], [task.id, "test-finished"]);
44
+ }
45
+ }
46
+ });
47
+ events.push([suite.id, "suite-finished"]);
48
+ }
49
+ visit(file);
50
+ return {
51
+ packs,
52
+ events
53
+ };
45
54
  }
46
55
 
47
56
  const REGEXP_WRAP_PREFIX = "$$vitest:";
48
57
  function getOutputFile(config, reporter) {
49
- if (!config?.outputFile) {
50
- return;
51
- }
52
- if (typeof config.outputFile === "string") {
53
- return config.outputFile;
54
- }
55
- return config.outputFile[reporter];
58
+ if (!config?.outputFile) {
59
+ return;
60
+ }
61
+ if (typeof config.outputFile === "string") {
62
+ return config.outputFile;
63
+ }
64
+ return config.outputFile[reporter];
56
65
  }
66
+ /**
67
+ * Prepares `SerializedConfig` for serialization, e.g. `node:v8.serialize`
68
+ */
57
69
  function wrapSerializableConfig(config) {
58
- let testNamePattern = config.testNamePattern;
59
- let defines = config.defines;
60
- if (testNamePattern && typeof testNamePattern !== "string") {
61
- testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
62
- }
63
- if (defines) {
64
- defines = { keys: Object.keys(defines), original: defines };
65
- }
66
- return {
67
- ...config,
68
- testNamePattern,
69
- defines
70
- };
70
+ let testNamePattern = config.testNamePattern;
71
+ let defines = config.defines;
72
+ if (testNamePattern && typeof testNamePattern !== "string") {
73
+ testNamePattern = `${REGEXP_WRAP_PREFIX}${testNamePattern.toString()}`;
74
+ }
75
+ if (defines) {
76
+ defines = {
77
+ keys: Object.keys(defines),
78
+ original: defines
79
+ };
80
+ }
81
+ return {
82
+ ...config,
83
+ testNamePattern,
84
+ defines
85
+ };
71
86
  }
72
87
 
73
88
  // AST walker module for ESTree compatible trees
@@ -347,170 +362,169 @@ base.MethodDefinition = base.PropertyDefinition = base.Property = function (node
347
362
  };
348
363
 
349
364
  async function collectTests(ctx, filepath) {
350
- const request = await ctx.vitenode.transformRequest(filepath, filepath);
351
- if (!request) {
352
- return null;
353
- }
354
- const ast = await parseAstAsync(request.code);
355
- const testFilepath = relative(ctx.config.root, filepath);
356
- const projectName = ctx.name;
357
- const typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__";
358
- const file = {
359
- filepath,
360
- type: "suite",
361
- id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
362
- name: testFilepath,
363
- mode: "run",
364
- tasks: [],
365
- start: ast.start,
366
- end: ast.end,
367
- projectName,
368
- meta: { typecheck: true },
369
- file: null
370
- };
371
- file.file = file;
372
- const definitions = [];
373
- const getName = (callee) => {
374
- if (!callee) {
375
- return null;
376
- }
377
- if (callee.type === "Identifier") {
378
- return callee.name;
379
- }
380
- if (callee.type === "CallExpression") {
381
- return getName(callee.callee);
382
- }
383
- if (callee.type === "TaggedTemplateExpression") {
384
- return getName(callee.tag);
385
- }
386
- if (callee.type === "MemberExpression") {
387
- if (callee.object?.type === "Identifier" && ["it", "test", "describe", "suite"].includes(callee.object.name)) {
388
- return callee.object?.name;
389
- }
390
- if (callee.object?.name?.startsWith("__vite_ssr_")) {
391
- return getName(callee.property);
392
- }
393
- return getName(callee.object?.property);
394
- }
395
- if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
396
- const [e0, e1] = callee.expressions;
397
- if (e0.type === "Literal" && e0.value === 0) {
398
- return getName(e1);
399
- }
400
- }
401
- return null;
402
- };
403
- ancestor(ast, {
404
- CallExpression(node) {
405
- const { callee } = node;
406
- const name = getName(callee);
407
- if (!name) {
408
- return;
409
- }
410
- if (!["it", "test", "describe", "suite"].includes(name)) {
411
- return;
412
- }
413
- const property = callee?.property?.name;
414
- let mode = !property || property === name ? "run" : property;
415
- if (["each", "for", "skipIf", "runIf"].includes(mode)) {
416
- return;
417
- }
418
- let start;
419
- const end = node.end;
420
- if (callee.type === "CallExpression") {
421
- start = callee.end;
422
- } else if (callee.type === "TaggedTemplateExpression") {
423
- start = callee.end + 1;
424
- } else {
425
- start = node.start;
426
- }
427
- const {
428
- arguments: [messageNode]
429
- } = node;
430
- const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
431
- const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
432
- if (mode === "skipIf" || mode === "runIf") {
433
- mode = "skip";
434
- }
435
- definitions.push({
436
- start,
437
- end,
438
- name: message,
439
- type: name === "it" || name === "test" ? "test" : "suite",
440
- mode,
441
- task: null
442
- });
443
- }
444
- });
445
- let lastSuite = file;
446
- const updateLatestSuite = (index) => {
447
- while (lastSuite.suite && lastSuite.end < index) {
448
- lastSuite = lastSuite.suite;
449
- }
450
- return lastSuite;
451
- };
452
- definitions.sort((a, b) => a.start - b.start).forEach((definition) => {
453
- const latestSuite = updateLatestSuite(definition.start);
454
- let mode = definition.mode;
455
- if (latestSuite.mode !== "run") {
456
- mode = latestSuite.mode;
457
- }
458
- if (definition.type === "suite") {
459
- const task2 = {
460
- type: definition.type,
461
- id: "",
462
- suite: latestSuite,
463
- file,
464
- tasks: [],
465
- mode,
466
- name: definition.name,
467
- end: definition.end,
468
- start: definition.start,
469
- meta: {
470
- typecheck: true
471
- }
472
- };
473
- definition.task = task2;
474
- latestSuite.tasks.push(task2);
475
- lastSuite = task2;
476
- return;
477
- }
478
- const task = {
479
- type: definition.type,
480
- id: "",
481
- suite: latestSuite,
482
- file,
483
- mode,
484
- timeout: 0,
485
- context: {},
486
- // not used in typecheck
487
- name: definition.name,
488
- end: definition.end,
489
- start: definition.start,
490
- meta: {
491
- typecheck: true
492
- }
493
- };
494
- definition.task = task;
495
- latestSuite.tasks.push(task);
496
- });
497
- calculateSuiteHash(file);
498
- const hasOnly = someTasksAreOnly(file);
499
- interpretTaskModes(
500
- file,
501
- ctx.config.testNamePattern,
502
- void 0,
503
- hasOnly,
504
- false,
505
- ctx.config.allowOnly
506
- );
507
- return {
508
- file,
509
- parsed: request.code,
510
- filepath,
511
- map: request.map,
512
- definitions
513
- };
365
+ const request = await ctx.vitenode.transformRequest(filepath, filepath);
366
+ if (!request) {
367
+ return null;
368
+ }
369
+ const ast = await parseAstAsync(request.code);
370
+ const testFilepath = relative(ctx.config.root, filepath);
371
+ const projectName = ctx.name;
372
+ const typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__";
373
+ const file = {
374
+ filepath,
375
+ type: "suite",
376
+ id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
377
+ name: testFilepath,
378
+ mode: "run",
379
+ tasks: [],
380
+ start: ast.start,
381
+ end: ast.end,
382
+ projectName,
383
+ meta: { typecheck: true },
384
+ file: null
385
+ };
386
+ file.file = file;
387
+ const definitions = [];
388
+ const getName = (callee) => {
389
+ if (!callee) {
390
+ return null;
391
+ }
392
+ if (callee.type === "Identifier") {
393
+ return callee.name;
394
+ }
395
+ if (callee.type === "CallExpression") {
396
+ return getName(callee.callee);
397
+ }
398
+ if (callee.type === "TaggedTemplateExpression") {
399
+ return getName(callee.tag);
400
+ }
401
+ if (callee.type === "MemberExpression") {
402
+ if (callee.object?.type === "Identifier" && [
403
+ "it",
404
+ "test",
405
+ "describe",
406
+ "suite"
407
+ ].includes(callee.object.name)) {
408
+ return callee.object?.name;
409
+ }
410
+ if (callee.object?.name?.startsWith("__vite_ssr_")) {
411
+ return getName(callee.property);
412
+ }
413
+ return getName(callee.object?.property);
414
+ }
415
+ if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
416
+ const [e0, e1] = callee.expressions;
417
+ if (e0.type === "Literal" && e0.value === 0) {
418
+ return getName(e1);
419
+ }
420
+ }
421
+ return null;
422
+ };
423
+ ancestor(ast, { CallExpression(node) {
424
+ const { callee } = node;
425
+ const name = getName(callee);
426
+ if (!name) {
427
+ return;
428
+ }
429
+ if (![
430
+ "it",
431
+ "test",
432
+ "describe",
433
+ "suite"
434
+ ].includes(name)) {
435
+ return;
436
+ }
437
+ const property = callee?.property?.name;
438
+ let mode = !property || property === name ? "run" : property;
439
+ if ([
440
+ "each",
441
+ "for",
442
+ "skipIf",
443
+ "runIf"
444
+ ].includes(mode)) {
445
+ return;
446
+ }
447
+ let start;
448
+ const end = node.end;
449
+ if (callee.type === "CallExpression") {
450
+ start = callee.end;
451
+ } else if (callee.type === "TaggedTemplateExpression") {
452
+ start = callee.end + 1;
453
+ } else {
454
+ start = node.start;
455
+ }
456
+ const { arguments: [messageNode] } = node;
457
+ const isQuoted = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral";
458
+ const message = isQuoted ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
459
+ if (mode === "skipIf" || mode === "runIf") {
460
+ mode = "skip";
461
+ }
462
+ definitions.push({
463
+ start,
464
+ end,
465
+ name: message,
466
+ type: name === "it" || name === "test" ? "test" : "suite",
467
+ mode,
468
+ task: null
469
+ });
470
+ } });
471
+ let lastSuite = file;
472
+ const updateLatestSuite = (index) => {
473
+ while (lastSuite.suite && lastSuite.end < index) {
474
+ lastSuite = lastSuite.suite;
475
+ }
476
+ return lastSuite;
477
+ };
478
+ definitions.sort((a, b) => a.start - b.start).forEach((definition) => {
479
+ const latestSuite = updateLatestSuite(definition.start);
480
+ let mode = definition.mode;
481
+ if (latestSuite.mode !== "run") {
482
+ mode = latestSuite.mode;
483
+ }
484
+ if (definition.type === "suite") {
485
+ const task = {
486
+ type: definition.type,
487
+ id: "",
488
+ suite: latestSuite,
489
+ file,
490
+ tasks: [],
491
+ mode,
492
+ name: definition.name,
493
+ end: definition.end,
494
+ start: definition.start,
495
+ meta: { typecheck: true }
496
+ };
497
+ definition.task = task;
498
+ latestSuite.tasks.push(task);
499
+ lastSuite = task;
500
+ return;
501
+ }
502
+ const task = {
503
+ type: definition.type,
504
+ id: "",
505
+ suite: latestSuite,
506
+ file,
507
+ mode,
508
+ timeout: 0,
509
+ context: {},
510
+ name: definition.name,
511
+ end: definition.end,
512
+ start: definition.start,
513
+ meta: { typecheck: true }
514
+ };
515
+ definition.task = task;
516
+ latestSuite.tasks.push(task);
517
+ });
518
+ calculateSuiteHash(file);
519
+ const hasOnly = someTasksAreOnly(file);
520
+ interpretTaskModes(file, ctx.config.testNamePattern, undefined, hasOnly, false, ctx.config.allowOnly);
521
+ return {
522
+ file,
523
+ parsed: request.code,
524
+ filepath,
525
+ map: request.map,
526
+ definitions
527
+ };
514
528
  }
515
529
 
516
530
  const A=r=>r!==null&&typeof r=="object",a=(r,t)=>Object.assign(new Error(`[${r}]: ${t}`),{code:r}),_="ERR_INVALID_PACKAGE_CONFIG",E$1="ERR_INVALID_PACKAGE_TARGET",I="ERR_PACKAGE_PATH_NOT_EXPORTED",R=/^\d+$/,O$1=/^(\.{1,2}|node_modules)$/i,w=/\/|\\/;var h$1=(r=>(r.Export="exports",r.Import="imports",r))(h$1||{});const f=(r,t,e,o,c)=>{if(t==null)return [];if(typeof t=="string"){const[n,...i]=t.split(w);if(n===".."||i.some(l=>O$1.test(l)))throw a(E$1,`Invalid "${r}" target "${t}" defined in the package config`);return [c?t.replace(/\*/g,c):t]}if(Array.isArray(t))return t.flatMap(n=>f(r,n,e,o,c));if(A(t)){for(const n of Object.keys(t)){if(R.test(n))throw a(_,"Cannot contain numeric property keys");if(n==="default"||o.includes(n))return f(r,t[n],e,o,c)}return []}throw a(E$1,`Invalid "${r}" target "${t}"`)},s="*",m=(r,t)=>{const e=r.indexOf(s),o=t.indexOf(s);return e===o?t.length>r.length:o>e};function d(r,t){if(!t.includes(s)&&r.hasOwnProperty(t))return [t];let e,o;for(const c of Object.keys(r))if(c.includes(s)){const[n,i,l]=c.split(s);if(l===void 0&&t.startsWith(n)&&t.endsWith(i)){const g=t.slice(n.length,-i.length||void 0);g&&(!e||m(e,c))&&(e=c,o=g);}}return [e,o]}const p=r=>Object.keys(r).reduce((t,e)=>{const o=e===""||e[0]!==".";if(t===void 0||t===o)return o;throw a(_,'"exports" cannot contain some keys starting with "." and some not')},void 0),u=/^\w+:/,v=(r,t,e)=>{if(!r)throw new Error('"exports" is required');t=t===""?".":`./${t}`,(typeof r=="string"||Array.isArray(r)||A(r)&&p(r))&&(r={".":r});const[o,c]=d(r,t),n=f(h$1.Export,r[o],t,e,c);if(n.length===0)throw a(I,t==="."?'No "exports" main defined':`Package subpath '${t}' is not defined by "exports"`);for(const i of n)if(!i.startsWith("./")&&!u.test(i))throw a(E$1,`Invalid "exports" target "${i}" defined in the package config`);return n};
@@ -527,432 +541,416 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
527
541
  const newLineRegExp = /\r?\n/;
528
542
  const errCodeRegExp = /error TS(?<errCode>\d+)/;
529
543
  async function makeTscErrorInfo(errInfo) {
530
- const [errFilePathPos = "", ...errMsgRawArr] = errInfo.split(":");
531
- if (!errFilePathPos || errMsgRawArr.length === 0 || errMsgRawArr.join("").length === 0) {
532
- return ["unknown filepath", null];
533
- }
534
- const errMsgRaw = errMsgRawArr.join("").trim();
535
- const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
536
- if (!errFilePath || !errPos) {
537
- return ["unknown filepath", null];
538
- }
539
- const [errLine, errCol] = errPos.split(",");
540
- if (!errLine || !errCol) {
541
- return [errFilePath, null];
542
- }
543
- const execArr = errCodeRegExp.exec(errMsgRaw);
544
- if (!execArr) {
545
- return [errFilePath, null];
546
- }
547
- const errCodeStr = execArr.groups?.errCode ?? "";
548
- if (!errCodeStr) {
549
- return [errFilePath, null];
550
- }
551
- const line = Number(errLine);
552
- const col = Number(errCol);
553
- const errCode = Number(errCodeStr);
554
- return [
555
- errFilePath,
556
- {
557
- filePath: errFilePath,
558
- errCode,
559
- line,
560
- column: col,
561
- errMsg: errMsgRaw.slice(`error TS${errCode} `.length)
562
- }
563
- ];
544
+ const [errFilePathPos = "", ...errMsgRawArr] = errInfo.split(":");
545
+ if (!errFilePathPos || errMsgRawArr.length === 0 || errMsgRawArr.join("").length === 0) {
546
+ return ["unknown filepath", null];
547
+ }
548
+ const errMsgRaw = errMsgRawArr.join("").trim();
549
+ const [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
550
+ if (!errFilePath || !errPos) {
551
+ return ["unknown filepath", null];
552
+ }
553
+ const [errLine, errCol] = errPos.split(",");
554
+ if (!errLine || !errCol) {
555
+ return [errFilePath, null];
556
+ }
557
+ const execArr = errCodeRegExp.exec(errMsgRaw);
558
+ if (!execArr) {
559
+ return [errFilePath, null];
560
+ }
561
+ const errCodeStr = execArr.groups?.errCode ?? "";
562
+ if (!errCodeStr) {
563
+ return [errFilePath, null];
564
+ }
565
+ const line = Number(errLine);
566
+ const col = Number(errCol);
567
+ const errCode = Number(errCodeStr);
568
+ return [errFilePath, {
569
+ filePath: errFilePath,
570
+ errCode,
571
+ line,
572
+ column: col,
573
+ errMsg: errMsgRaw.slice(`error TS${errCode} `.length)
574
+ }];
564
575
  }
565
576
  async function getTsconfig(root, config) {
566
- const configName = config.tsconfig ? basename(config.tsconfig) : void 0;
567
- const configSearchPath = config.tsconfig ? dirname(resolve(root, config.tsconfig)) : root;
568
- const tsconfig = he(configSearchPath, configName);
569
- if (!tsconfig) {
570
- throw new Error("no tsconfig.json found");
571
- }
572
- const tsconfigName = basename(tsconfig.path, ".json");
573
- const tempTsConfigName = `${tsconfigName}.vitest-temp.json`;
574
- const tempTsbuildinfoName = `${tsconfigName}.tmp.tsbuildinfo`;
575
- const tempConfigPath = join(
576
- dirname(tsconfig.path),
577
- tempTsConfigName
578
- );
579
- try {
580
- const tmpTsConfig = { ...tsconfig.config };
581
- tmpTsConfig.compilerOptions = tmpTsConfig.compilerOptions || {};
582
- tmpTsConfig.compilerOptions.emitDeclarationOnly = false;
583
- tmpTsConfig.compilerOptions.incremental = true;
584
- tmpTsConfig.compilerOptions.tsBuildInfoFile = join(
585
- process.versions.pnp ? join(nodeos__default.tmpdir(), "vitest") : __dirname,
586
- tempTsbuildinfoName
587
- );
588
- const tsconfigFinalContent = JSON.stringify(tmpTsConfig, null, 2);
589
- await writeFile(tempConfigPath, tsconfigFinalContent);
590
- return { path: tempConfigPath, config: tmpTsConfig };
591
- } catch (err) {
592
- throw new Error(`failed to write ${tempTsConfigName}`, { cause: err });
593
- }
577
+ const configName = config.tsconfig ? basename(config.tsconfig) : undefined;
578
+ const configSearchPath = config.tsconfig ? dirname(resolve(root, config.tsconfig)) : root;
579
+ const tsconfig = he(configSearchPath, configName);
580
+ if (!tsconfig) {
581
+ throw new Error("no tsconfig.json found");
582
+ }
583
+ const tsconfigName = basename(tsconfig.path, ".json");
584
+ const tempTsConfigName = `${tsconfigName}.vitest-temp.json`;
585
+ const tempTsbuildinfoName = `${tsconfigName}.tmp.tsbuildinfo`;
586
+ const tempConfigPath = join(dirname(tsconfig.path), tempTsConfigName);
587
+ try {
588
+ const tmpTsConfig = { ...tsconfig.config };
589
+ tmpTsConfig.compilerOptions = tmpTsConfig.compilerOptions || {};
590
+ tmpTsConfig.compilerOptions.emitDeclarationOnly = false;
591
+ tmpTsConfig.compilerOptions.incremental = true;
592
+ tmpTsConfig.compilerOptions.tsBuildInfoFile = join(process.versions.pnp ? join(nodeos__default.tmpdir(), "vitest") : __dirname, tempTsbuildinfoName);
593
+ const tsconfigFinalContent = JSON.stringify(tmpTsConfig, null, 2);
594
+ await writeFile(tempConfigPath, tsconfigFinalContent);
595
+ return {
596
+ path: tempConfigPath,
597
+ config: tmpTsConfig
598
+ };
599
+ } catch (err) {
600
+ throw new Error(`failed to write ${tempTsConfigName}`, { cause: err });
601
+ }
594
602
  }
595
603
  async function getRawErrsMapFromTsCompile(tscErrorStdout) {
596
- const rawErrsMap = /* @__PURE__ */ new Map();
597
- const infos = await Promise.all(
598
- tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
599
- if (!next) {
600
- return prev;
601
- } else if (!next.startsWith(" ")) {
602
- prev.push(next);
603
- } else {
604
- prev[prev.length - 1] += `
605
- ${next}`;
606
- }
607
- return prev;
608
- }, []).map((errInfoLine) => makeTscErrorInfo(errInfoLine))
609
- );
610
- infos.forEach(([errFilePath, errInfo]) => {
611
- if (!errInfo) {
612
- return;
613
- }
614
- if (!rawErrsMap.has(errFilePath)) {
615
- rawErrsMap.set(errFilePath, [errInfo]);
616
- } else {
617
- rawErrsMap.get(errFilePath)?.push(errInfo);
618
- }
619
- });
620
- return rawErrsMap;
604
+ const rawErrsMap = new Map();
605
+ const infos = await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
606
+ if (!next) {
607
+ return prev;
608
+ } else if (!next.startsWith(" ")) {
609
+ prev.push(next);
610
+ } else {
611
+ prev[prev.length - 1] += `\n${next}`;
612
+ }
613
+ return prev;
614
+ }, []).map((errInfoLine) => makeTscErrorInfo(errInfoLine)));
615
+ infos.forEach(([errFilePath, errInfo]) => {
616
+ if (!errInfo) {
617
+ return;
618
+ }
619
+ if (!rawErrsMap.has(errFilePath)) {
620
+ rawErrsMap.set(errFilePath, [errInfo]);
621
+ } else {
622
+ rawErrsMap.get(errFilePath)?.push(errInfo);
623
+ }
624
+ });
625
+ return rawErrsMap;
621
626
  }
622
627
 
623
628
  function createIndexMap(source) {
624
- const map = /* @__PURE__ */ new Map();
625
- let index = 0;
626
- let line = 1;
627
- let column = 1;
628
- for (const char of source) {
629
- map.set(`${line}:${column}`, index++);
630
- if (char === "\n" || char === "\r\n") {
631
- line++;
632
- column = 0;
633
- } else {
634
- column++;
635
- }
636
- }
637
- return map;
629
+ const map = new Map();
630
+ let index = 0;
631
+ let line = 1;
632
+ let column = 1;
633
+ for (const char of source) {
634
+ map.set(`${line}:${column}`, index++);
635
+ if (char === "\n" || char === "\r\n") {
636
+ line++;
637
+ column = 0;
638
+ } else {
639
+ column++;
640
+ }
641
+ }
642
+ return map;
638
643
  }
639
644
 
640
645
  class TypeCheckError extends Error {
641
- constructor(message, stacks) {
642
- super(message);
643
- this.message = message;
644
- this.stacks = stacks;
645
- }
646
- name = "TypeCheckError";
646
+ name = "TypeCheckError";
647
+ constructor(message, stacks) {
648
+ super(message);
649
+ this.message = message;
650
+ this.stacks = stacks;
651
+ }
647
652
  }
648
653
  class Typechecker {
649
- constructor(ctx) {
650
- this.ctx = ctx;
651
- }
652
- _onParseStart;
653
- _onParseEnd;
654
- _onWatcherRerun;
655
- _result = {
656
- files: [],
657
- sourceErrors: [],
658
- time: 0
659
- };
660
- _startTime = 0;
661
- _output = "";
662
- _tests = {};
663
- tempConfigPath;
664
- allowJs;
665
- process;
666
- files = [];
667
- setFiles(files) {
668
- this.files = files;
669
- }
670
- onParseStart(fn) {
671
- this._onParseStart = fn;
672
- }
673
- onParseEnd(fn) {
674
- this._onParseEnd = fn;
675
- }
676
- onWatcherRerun(fn) {
677
- this._onWatcherRerun = fn;
678
- }
679
- async collectFileTests(filepath) {
680
- return collectTests(this.ctx, filepath);
681
- }
682
- getFiles() {
683
- return this.files.filter((filename) => {
684
- const extension = extname(filename);
685
- return extension !== ".js" || this.allowJs;
686
- });
687
- }
688
- async collectTests() {
689
- const tests = (await Promise.all(
690
- this.getFiles().map((filepath) => this.collectFileTests(filepath))
691
- )).reduce((acc, data) => {
692
- if (!data) {
693
- return acc;
694
- }
695
- acc[data.filepath] = data;
696
- return acc;
697
- }, {});
698
- this._tests = tests;
699
- return tests;
700
- }
701
- markPassed(file) {
702
- if (!file.result?.state) {
703
- file.result = {
704
- state: "pass"
705
- };
706
- }
707
- const markTasks = (tasks) => {
708
- for (const task of tasks) {
709
- if ("tasks" in task) {
710
- markTasks(task.tasks);
711
- }
712
- if (!task.result?.state && (task.mode === "run" || task.mode === "queued")) {
713
- task.result = {
714
- state: "pass"
715
- };
716
- }
717
- }
718
- };
719
- markTasks(file.tasks);
720
- }
721
- async prepareResults(output) {
722
- const typeErrors = await this.parseTscLikeOutput(output);
723
- const testFiles = new Set(this.getFiles());
724
- if (!this._tests) {
725
- this._tests = await this.collectTests();
726
- }
727
- const sourceErrors = [];
728
- const files = [];
729
- testFiles.forEach((path) => {
730
- const { file, definitions, map, parsed } = this._tests[path];
731
- const errors = typeErrors.get(path);
732
- files.push(file);
733
- if (!errors) {
734
- this.markPassed(file);
735
- return;
736
- }
737
- const sortedDefinitions = [
738
- ...definitions.sort((a, b) => b.start - a.start)
739
- ];
740
- const traceMap = map && new TraceMap(map);
741
- const indexMap = createIndexMap(parsed);
742
- const markState = (task, state) => {
743
- task.result = {
744
- state: task.mode === "run" || task.mode === "only" ? state : task.mode
745
- };
746
- if (task.suite) {
747
- markState(task.suite, state);
748
- } else if (task.file && task !== task.file) {
749
- markState(task.file, state);
750
- }
751
- };
752
- errors.forEach(({ error, originalError }) => {
753
- const processedPos = traceMap ? findGeneratedPosition(traceMap, {
754
- line: originalError.line,
755
- column: originalError.column,
756
- source: basename(path)
757
- }) : originalError;
758
- const line = processedPos.line ?? originalError.line;
759
- const column = processedPos.column ?? originalError.column;
760
- const index = indexMap.get(`${line}:${column}`);
761
- const definition = index != null && sortedDefinitions.find(
762
- (def) => def.start <= index && def.end >= index
763
- );
764
- const suite = definition ? definition.task : file;
765
- const state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode;
766
- const errors2 = suite.result?.errors || [];
767
- suite.result = {
768
- state,
769
- errors: errors2
770
- };
771
- errors2.push(error);
772
- if (state === "fail") {
773
- if (suite.suite) {
774
- markState(suite.suite, "fail");
775
- } else if (suite.file && suite !== suite.file) {
776
- markState(suite.file, "fail");
777
- }
778
- }
779
- });
780
- this.markPassed(file);
781
- });
782
- typeErrors.forEach((errors, path) => {
783
- if (!testFiles.has(path)) {
784
- sourceErrors.push(...errors.map(({ error }) => error));
785
- }
786
- });
787
- return {
788
- files,
789
- sourceErrors,
790
- time: performance.now() - this._startTime
791
- };
792
- }
793
- async parseTscLikeOutput(output) {
794
- const errorsMap = await getRawErrsMapFromTsCompile(output);
795
- const typesErrors = /* @__PURE__ */ new Map();
796
- errorsMap.forEach((errors, path) => {
797
- const filepath = resolve(this.ctx.config.root, path);
798
- const suiteErrors = errors.map((info) => {
799
- const limit = Error.stackTraceLimit;
800
- Error.stackTraceLimit = 0;
801
- const errMsg = info.errMsg.replace(
802
- /\r?\n\s*(Type .* has no call signatures)/g,
803
- " $1"
804
- );
805
- const error = new TypeCheckError(errMsg, [
806
- {
807
- file: filepath,
808
- line: info.line,
809
- column: info.column,
810
- method: ""
811
- }
812
- ]);
813
- Error.stackTraceLimit = limit;
814
- return {
815
- originalError: info,
816
- error: {
817
- name: error.name,
818
- nameStr: String(error.name),
819
- message: errMsg,
820
- stacks: error.stacks,
821
- stack: "",
822
- stackStr: ""
823
- }
824
- };
825
- });
826
- typesErrors.set(filepath, suiteErrors);
827
- });
828
- return typesErrors;
829
- }
830
- async clear() {
831
- if (this.tempConfigPath) {
832
- await rm(this.tempConfigPath, { force: true });
833
- }
834
- }
835
- async stop() {
836
- await this.clear();
837
- this.process?.kill();
838
- this.process = void 0;
839
- }
840
- async ensurePackageInstalled(ctx, checker) {
841
- if (checker !== "tsc" && checker !== "vue-tsc") {
842
- return;
843
- }
844
- const packageName = checker === "tsc" ? "typescript" : "vue-tsc";
845
- await ctx.packageInstaller.ensureInstalled(packageName, ctx.config.root);
846
- }
847
- async prepare() {
848
- const { root, typecheck } = this.ctx.config;
849
- const { config, path } = await getTsconfig(root, typecheck);
850
- this.tempConfigPath = path;
851
- this.allowJs = typecheck.allowJs || config.allowJs || false;
852
- }
853
- getExitCode() {
854
- return this.process?.exitCode != null && this.process.exitCode;
855
- }
856
- getOutput() {
857
- return this._output;
858
- }
859
- async start() {
860
- if (this.process) {
861
- return;
862
- }
863
- if (!this.tempConfigPath) {
864
- throw new Error("tsconfig was not initialized");
865
- }
866
- const { root, watch, typecheck } = this.ctx.config;
867
- const args = ["--noEmit", "--pretty", "false", "-p", this.tempConfigPath];
868
- if (watch) {
869
- args.push("--watch");
870
- }
871
- if (typecheck.allowJs) {
872
- args.push("--allowJs", "--checkJs");
873
- }
874
- this._output = "";
875
- this._startTime = performance.now();
876
- const child = x$1(typecheck.checker, args, {
877
- nodeOptions: {
878
- cwd: root,
879
- stdio: "pipe"
880
- },
881
- throwOnError: false
882
- });
883
- this.process = child.process;
884
- await this._onParseStart?.();
885
- let rerunTriggered = false;
886
- child.process?.stdout?.on("data", (chunk) => {
887
- this._output += chunk;
888
- if (!watch) {
889
- return;
890
- }
891
- if (this._output.includes("File change detected") && !rerunTriggered) {
892
- this._onWatcherRerun?.();
893
- this._startTime = performance.now();
894
- this._result.sourceErrors = [];
895
- this._result.files = [];
896
- this._tests = null;
897
- rerunTriggered = true;
898
- }
899
- if (/Found \w+ errors*. Watching for/.test(this._output)) {
900
- rerunTriggered = false;
901
- this.prepareResults(this._output).then((result) => {
902
- this._result = result;
903
- this._onParseEnd?.(result);
904
- });
905
- this._output = "";
906
- }
907
- });
908
- if (!watch) {
909
- await child;
910
- this._result = await this.prepareResults(this._output);
911
- await this._onParseEnd?.(this._result);
912
- }
913
- }
914
- getResult() {
915
- return this._result;
916
- }
917
- getTestFiles() {
918
- return Object.values(this._tests || {}).map((i) => i.file);
919
- }
920
- getTestPacksAndEvents() {
921
- const packs = [];
922
- const events = [];
923
- for (const { file } of Object.values(this._tests || {})) {
924
- const result = convertTasksToEvents(file);
925
- packs.push(...result.packs);
926
- events.push(...result.events);
927
- }
928
- return { packs, events };
929
- }
654
+ _onParseStart;
655
+ _onParseEnd;
656
+ _onWatcherRerun;
657
+ _result = {
658
+ files: [],
659
+ sourceErrors: [],
660
+ time: 0
661
+ };
662
+ _startTime = 0;
663
+ _output = "";
664
+ _tests = {};
665
+ tempConfigPath;
666
+ allowJs;
667
+ process;
668
+ files = [];
669
+ constructor(ctx) {
670
+ this.ctx = ctx;
671
+ }
672
+ setFiles(files) {
673
+ this.files = files;
674
+ }
675
+ onParseStart(fn) {
676
+ this._onParseStart = fn;
677
+ }
678
+ onParseEnd(fn) {
679
+ this._onParseEnd = fn;
680
+ }
681
+ onWatcherRerun(fn) {
682
+ this._onWatcherRerun = fn;
683
+ }
684
+ async collectFileTests(filepath) {
685
+ return collectTests(this.ctx, filepath);
686
+ }
687
+ getFiles() {
688
+ return this.files.filter((filename) => {
689
+ const extension = extname(filename);
690
+ return extension !== ".js" || this.allowJs;
691
+ });
692
+ }
693
+ async collectTests() {
694
+ const tests = (await Promise.all(this.getFiles().map((filepath) => this.collectFileTests(filepath)))).reduce((acc, data) => {
695
+ if (!data) {
696
+ return acc;
697
+ }
698
+ acc[data.filepath] = data;
699
+ return acc;
700
+ }, {});
701
+ this._tests = tests;
702
+ return tests;
703
+ }
704
+ markPassed(file) {
705
+ if (!file.result?.state) {
706
+ file.result = { state: "pass" };
707
+ }
708
+ const markTasks = (tasks) => {
709
+ for (const task of tasks) {
710
+ if ("tasks" in task) {
711
+ markTasks(task.tasks);
712
+ }
713
+ if (!task.result?.state && (task.mode === "run" || task.mode === "queued")) {
714
+ task.result = { state: "pass" };
715
+ }
716
+ }
717
+ };
718
+ markTasks(file.tasks);
719
+ }
720
+ async prepareResults(output) {
721
+ const typeErrors = await this.parseTscLikeOutput(output);
722
+ const testFiles = new Set(this.getFiles());
723
+ if (!this._tests) {
724
+ this._tests = await this.collectTests();
725
+ }
726
+ const sourceErrors = [];
727
+ const files = [];
728
+ testFiles.forEach((path) => {
729
+ const { file, definitions, map, parsed } = this._tests[path];
730
+ const errors = typeErrors.get(path);
731
+ files.push(file);
732
+ if (!errors) {
733
+ this.markPassed(file);
734
+ return;
735
+ }
736
+ const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)];
737
+ const traceMap = map && new TraceMap(map);
738
+ const indexMap = createIndexMap(parsed);
739
+ const markState = (task, state) => {
740
+ task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode };
741
+ if (task.suite) {
742
+ markState(task.suite, state);
743
+ } else if (task.file && task !== task.file) {
744
+ markState(task.file, state);
745
+ }
746
+ };
747
+ errors.forEach(({ error, originalError }) => {
748
+ const processedPos = traceMap ? findGeneratedPosition(traceMap, {
749
+ line: originalError.line,
750
+ column: originalError.column,
751
+ source: basename(path)
752
+ }) : originalError;
753
+ const line = processedPos.line ?? originalError.line;
754
+ const column = processedPos.column ?? originalError.column;
755
+ const index = indexMap.get(`${line}:${column}`);
756
+ const definition = index != null && sortedDefinitions.find((def) => def.start <= index && def.end >= index);
757
+ const suite = definition ? definition.task : file;
758
+ const state = suite.mode === "run" || suite.mode === "only" ? "fail" : suite.mode;
759
+ const errors = suite.result?.errors || [];
760
+ suite.result = {
761
+ state,
762
+ errors
763
+ };
764
+ errors.push(error);
765
+ if (state === "fail") {
766
+ if (suite.suite) {
767
+ markState(suite.suite, "fail");
768
+ } else if (suite.file && suite !== suite.file) {
769
+ markState(suite.file, "fail");
770
+ }
771
+ }
772
+ });
773
+ this.markPassed(file);
774
+ });
775
+ typeErrors.forEach((errors, path) => {
776
+ if (!testFiles.has(path)) {
777
+ sourceErrors.push(...errors.map(({ error }) => error));
778
+ }
779
+ });
780
+ return {
781
+ files,
782
+ sourceErrors,
783
+ time: performance.now() - this._startTime
784
+ };
785
+ }
786
+ async parseTscLikeOutput(output) {
787
+ const errorsMap = await getRawErrsMapFromTsCompile(output);
788
+ const typesErrors = new Map();
789
+ errorsMap.forEach((errors, path) => {
790
+ const filepath = resolve(this.ctx.config.root, path);
791
+ const suiteErrors = errors.map((info) => {
792
+ const limit = Error.stackTraceLimit;
793
+ Error.stackTraceLimit = 0;
794
+ const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1");
795
+ const error = new TypeCheckError(errMsg, [{
796
+ file: filepath,
797
+ line: info.line,
798
+ column: info.column,
799
+ method: ""
800
+ }]);
801
+ Error.stackTraceLimit = limit;
802
+ return {
803
+ originalError: info,
804
+ error: {
805
+ name: error.name,
806
+ nameStr: String(error.name),
807
+ message: errMsg,
808
+ stacks: error.stacks,
809
+ stack: "",
810
+ stackStr: ""
811
+ }
812
+ };
813
+ });
814
+ typesErrors.set(filepath, suiteErrors);
815
+ });
816
+ return typesErrors;
817
+ }
818
+ async clear() {
819
+ if (this.tempConfigPath) {
820
+ await rm(this.tempConfigPath, { force: true });
821
+ }
822
+ }
823
+ async stop() {
824
+ await this.clear();
825
+ this.process?.kill();
826
+ this.process = undefined;
827
+ }
828
+ async ensurePackageInstalled(ctx, checker) {
829
+ if (checker !== "tsc" && checker !== "vue-tsc") {
830
+ return;
831
+ }
832
+ const packageName = checker === "tsc" ? "typescript" : "vue-tsc";
833
+ await ctx.packageInstaller.ensureInstalled(packageName, ctx.config.root);
834
+ }
835
+ async prepare() {
836
+ const { root, typecheck } = this.ctx.config;
837
+ const { config, path } = await getTsconfig(root, typecheck);
838
+ this.tempConfigPath = path;
839
+ this.allowJs = typecheck.allowJs || config.allowJs || false;
840
+ }
841
+ getExitCode() {
842
+ return this.process?.exitCode != null && this.process.exitCode;
843
+ }
844
+ getOutput() {
845
+ return this._output;
846
+ }
847
+ async start() {
848
+ if (this.process) {
849
+ return;
850
+ }
851
+ if (!this.tempConfigPath) {
852
+ throw new Error("tsconfig was not initialized");
853
+ }
854
+ const { root, watch, typecheck } = this.ctx.config;
855
+ const args = [
856
+ "--noEmit",
857
+ "--pretty",
858
+ "false",
859
+ "-p",
860
+ this.tempConfigPath
861
+ ];
862
+ if (watch) {
863
+ args.push("--watch");
864
+ }
865
+ if (typecheck.allowJs) {
866
+ args.push("--allowJs", "--checkJs");
867
+ }
868
+ this._output = "";
869
+ this._startTime = performance.now();
870
+ const child = x$1(typecheck.checker, args, {
871
+ nodeOptions: {
872
+ cwd: root,
873
+ stdio: "pipe"
874
+ },
875
+ throwOnError: false
876
+ });
877
+ this.process = child.process;
878
+ await this._onParseStart?.();
879
+ let rerunTriggered = false;
880
+ child.process?.stdout?.on("data", (chunk) => {
881
+ this._output += chunk;
882
+ if (!watch) {
883
+ return;
884
+ }
885
+ if (this._output.includes("File change detected") && !rerunTriggered) {
886
+ this._onWatcherRerun?.();
887
+ this._startTime = performance.now();
888
+ this._result.sourceErrors = [];
889
+ this._result.files = [];
890
+ this._tests = null;
891
+ rerunTriggered = true;
892
+ }
893
+ if (/Found \w+ errors*. Watching for/.test(this._output)) {
894
+ rerunTriggered = false;
895
+ this.prepareResults(this._output).then((result) => {
896
+ this._result = result;
897
+ this._onParseEnd?.(result);
898
+ });
899
+ this._output = "";
900
+ }
901
+ });
902
+ if (!watch) {
903
+ await child;
904
+ this._result = await this.prepareResults(this._output);
905
+ await this._onParseEnd?.(this._result);
906
+ }
907
+ }
908
+ getResult() {
909
+ return this._result;
910
+ }
911
+ getTestFiles() {
912
+ return Object.values(this._tests || {}).map((i) => i.file);
913
+ }
914
+ getTestPacksAndEvents() {
915
+ const packs = [];
916
+ const events = [];
917
+ for (const { file } of Object.values(this._tests || {})) {
918
+ const result = convertTasksToEvents(file);
919
+ packs.push(...result.packs);
920
+ events.push(...result.events);
921
+ }
922
+ return {
923
+ packs,
924
+ events
925
+ };
926
+ }
930
927
  }
931
928
  function findGeneratedPosition(traceMap, { line, column, source }) {
932
- const found = generatedPositionFor(traceMap, {
933
- line,
934
- column,
935
- source
936
- });
937
- if (found.line !== null) {
938
- return found;
939
- }
940
- const mappings = [];
941
- eachMapping(traceMap, (m) => {
942
- if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) {
943
- mappings.push(m);
944
- }
945
- });
946
- const next = mappings.sort(
947
- (a, b) => a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine
948
- ).at(0);
949
- if (next) {
950
- return {
951
- line: next.generatedLine,
952
- column: next.generatedColumn
953
- };
954
- }
955
- return { line: null, column: null };
929
+ const found = generatedPositionFor(traceMap, {
930
+ line,
931
+ column,
932
+ source
933
+ });
934
+ if (found.line !== null) {
935
+ return found;
936
+ }
937
+ const mappings = [];
938
+ eachMapping(traceMap, (m) => {
939
+ if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) {
940
+ mappings.push(m);
941
+ }
942
+ });
943
+ const next = mappings.sort((a, b) => a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine).at(0);
944
+ if (next) {
945
+ return {
946
+ line: next.generatedLine,
947
+ column: next.generatedColumn
948
+ };
949
+ }
950
+ return {
951
+ line: null,
952
+ column: null
953
+ };
956
954
  }
957
955
 
958
956
  export { TypeCheckError as T, Typechecker as a, convertTasksToEvents as c, getOutputFile as g, hasFailedSnapshot as h, wrapSerializableConfig as w };