vitest 4.0.0-beta.9 → 4.0.1
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.
- package/LICENSE.md +86 -102
- package/browser/context.d.ts +7 -0
- package/browser/context.js +20 -0
- package/dist/browser.d.ts +24 -7
- package/dist/browser.js +15 -5
- package/dist/chunks/{base.CA5N8Af0.js → base.BYPMk0VN.js} +36 -36
- package/dist/chunks/{benchmark.CJUa-Hsa.js → benchmark.DHKMYAts.js} +2 -2
- package/dist/chunks/{browser.d.DtfyY9yS.d.ts → browser.d.B9iJzZyn.d.ts} +3 -3
- package/dist/chunks/{cac.Dt7e1TIu.js → cac.DrF4Gm0S.js} +47 -73
- package/dist/chunks/{cli-api.eAzsLIxz.js → cli-api.W2Q-JQoO.js} +1524 -296
- package/dist/chunks/{config.d.DacWrqWe.d.ts → config.d.u2CUDWwS.d.ts} +5 -19
- package/dist/chunks/{console.7h5kHUIf.js → console.CTJL2nuH.js} +4 -6
- package/dist/chunks/{coverage.CDRAMTt7.js → coverage.FU3w4IrQ.js} +125 -1108
- package/dist/chunks/{creator.KEg6n5IC.js → creator.DucAaYBz.js} +10 -37
- package/dist/chunks/{defaults.CXFFjsi8.js → defaults.BOqNVLsY.js} +0 -1
- package/dist/chunks/environment.d.CrsxCzP1.d.ts +29 -0
- package/dist/chunks/evaluatedModules.Dg1zASAC.js +17 -0
- package/dist/chunks/{global.d.K6uBQHzY.d.ts → global.d.BgJSTpgQ.d.ts} +2 -17
- package/dist/chunks/{globals.CJrTTbxC.js → globals.BGT_RUsD.js} +11 -7
- package/dist/chunks/{index.BjKEiSn0.js → index.BdSLhLDZ.js} +3 -3
- package/dist/chunks/{index.DfviD7lX.js → index.CbWINfS7.js} +49 -21
- package/dist/chunks/{index.BIP7prJq.js → index.CcRZ6fUh.js} +1493 -114
- package/dist/chunks/{index.X0nbfr6-.js → index.Dc3xnDvT.js} +48 -289
- package/dist/chunks/{index.C832ioot.js → index.RwjEGCQ0.js} +4 -4
- package/dist/chunks/init-forks.WglB-sfY.js +54 -0
- package/dist/chunks/init-threads.Czek6eA5.js +17 -0
- package/dist/chunks/init.94FWN9pW.js +213 -0
- package/dist/chunks/{inspector.CvQD-Nie.js → inspector.DLZxSeU3.js} +2 -6
- package/dist/chunks/{moduleRunner.d.DxTLreRD.d.ts → moduleRunner.d.YtNsMIoJ.d.ts} +9 -14
- package/dist/chunks/{node.CyipiPvJ.js → node.BwAWWjHZ.js} +3 -4
- package/dist/chunks/{plugin.d.CIk0YiKb.d.ts → plugin.d.DQU1R5px.d.ts} +1 -1
- package/dist/chunks/{reporters.d.DmP-iHLr.d.ts → reporters.d.BMKt7f6I.d.ts} +1064 -1021
- package/dist/chunks/{resolveSnapshotEnvironment.Bvv2zr69.js → resolveSnapshotEnvironment.DJJKMKxb.js} +7 -8
- package/dist/chunks/{rpc.BKr6mtxz.js → rpc.cD77ENhU.js} +13 -14
- package/dist/chunks/{setup-common.B7I37Tji.js → setup-common.DR1sucx6.js} +6 -6
- package/dist/chunks/{startModuleRunner.BDRvKSdz.js → startModuleRunner.iF1E9Bt4.js} +126 -110
- package/dist/chunks/{test.BAlBebnP.js → test.C3RPt8JR.js} +7 -7
- package/dist/chunks/{utils.D2R2NiOH.js → utils.CG9h5ccR.js} +2 -5
- package/dist/chunks/{vi.BB37KeLx.js → vi.BZvkKVkM.js} +61 -164
- package/dist/chunks/{vm.CjLTDaST.js → vm.CuMWYx_F.js} +20 -29
- package/dist/chunks/{worker.d.B2r4Ln6p.d.ts → worker.d.BFk-vvBU.d.ts} +42 -6
- package/dist/cli.js +12 -11
- package/dist/config.cjs +0 -1
- package/dist/config.d.ts +11 -13
- package/dist/config.js +1 -1
- package/dist/coverage.d.ts +7 -6
- package/dist/coverage.js +3 -14
- package/dist/environments.d.ts +3 -6
- package/dist/environments.js +1 -1
- package/dist/index.d.ts +20 -25
- package/dist/index.js +11 -7
- package/dist/module-evaluator.d.ts +5 -4
- package/dist/module-evaluator.js +11 -13
- package/dist/module-runner.js +5 -5
- package/dist/node.d.ts +82 -25
- package/dist/node.js +23 -20
- package/dist/reporters.d.ts +10 -9
- package/dist/reporters.js +12 -11
- package/dist/runners.d.ts +1 -1
- package/dist/runners.js +9 -7
- package/dist/snapshot.js +3 -3
- package/dist/suite.js +4 -3
- package/dist/worker.d.ts +26 -0
- package/dist/worker.js +45 -165
- package/dist/workers/forks.js +26 -43
- package/dist/workers/runVmTests.js +16 -12
- package/dist/workers/threads.js +26 -31
- package/dist/workers/vmForks.js +26 -39
- package/dist/workers/vmThreads.js +26 -29
- package/package.json +48 -32
- package/worker.d.ts +1 -0
- package/browser.d.ts +0 -1
- package/dist/chunks/environment.d.2fYMoz3o.d.ts +0 -66
- package/dist/chunks/moduleTransport.I-bgQy0S.js +0 -19
- package/dist/chunks/resolver.Bx6lE0iq.js +0 -119
- package/dist/chunks/typechecker.DB-fIMaH.js +0 -805
- package/dist/chunks/utils.C2YI6McM.js +0 -52
- package/dist/chunks/worker.d.DJ6qxO2w.d.ts +0 -8
- package/dist/workers.d.ts +0 -38
- package/dist/workers.js +0 -49
- package/execute.d.ts +0 -1
- package/utils.d.ts +0 -1
- package/workers.d.ts +0 -1
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { existsSync, readFileSync, promises } from 'node:fs';
|
|
2
2
|
import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
|
|
3
|
-
import { resolve, dirname, isAbsolute, relative, basename, normalize } from 'pathe';
|
|
4
|
-
import { g as getOutputFile, h as hasFailedSnapshot, T as TypeCheckError } from './typechecker.DB-fIMaH.js';
|
|
3
|
+
import { resolve as resolve$1, dirname, isAbsolute, relative, basename, join, normalize } from 'pathe';
|
|
5
4
|
import { performance as performance$1 } from 'node:perf_hooks';
|
|
6
|
-
import {
|
|
7
|
-
import { slash, toArray, isPrimitive
|
|
5
|
+
import { getTests, getTestName, hasFailed, getSuites, generateHash, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, getTasks, getFullName } from '@vitest/runner/utils';
|
|
6
|
+
import { slash, toArray, isPrimitive } from '@vitest/utils/helpers';
|
|
8
7
|
import { parseStacktrace, parseErrorStacktrace, defaultStackIgnorePatterns } from '@vitest/utils/source-map';
|
|
9
8
|
import c from 'tinyrainbow';
|
|
10
9
|
import { i as isTTY } from './env.D4Lgay0q.js';
|
|
11
10
|
import { stripVTControlCharacters } from 'node:util';
|
|
12
11
|
import { Console } from 'node:console';
|
|
13
12
|
import { Writable } from 'node:stream';
|
|
13
|
+
import { inspect } from '@vitest/utils/display';
|
|
14
|
+
import nodeos__default, { hostname } from 'node:os';
|
|
15
|
+
import { x } from 'tinyexec';
|
|
16
|
+
import { distDir } from '../path.js';
|
|
17
|
+
import { parseAstAsync } from 'vite';
|
|
18
|
+
import { positionToOffset, lineSplitRE } from '@vitest/utils/offset';
|
|
14
19
|
import { createRequire } from 'node:module';
|
|
15
|
-
import { hostname } from 'node:os';
|
|
16
20
|
|
|
17
21
|
/// <reference types="../types/index.d.ts" />
|
|
18
22
|
|
|
@@ -24,7 +28,7 @@ const {keys} = Object;
|
|
|
24
28
|
const Primitive = String; // it could be Number
|
|
25
29
|
const primitive = 'string'; // it could be 'number'
|
|
26
30
|
|
|
27
|
-
const ignore = {};
|
|
31
|
+
const ignore$1 = {};
|
|
28
32
|
const object = 'object';
|
|
29
33
|
|
|
30
34
|
const noop = (_, value) => value;
|
|
@@ -46,13 +50,13 @@ const revive = (input, parsed, output, $) => {
|
|
|
46
50
|
const tmp = input[value];
|
|
47
51
|
if (typeof tmp === object && !parsed.has(tmp)) {
|
|
48
52
|
parsed.add(tmp);
|
|
49
|
-
output[k] = ignore;
|
|
53
|
+
output[k] = ignore$1;
|
|
50
54
|
lazy.push({k, a: [input, parsed, tmp, $]});
|
|
51
55
|
}
|
|
52
56
|
else
|
|
53
57
|
output[k] = $.call(output, k, tmp);
|
|
54
58
|
}
|
|
55
|
-
else if (output[k] !== ignore)
|
|
59
|
+
else if (output[k] !== ignore$1)
|
|
56
60
|
output[k] = $.call(output, k, value);
|
|
57
61
|
}
|
|
58
62
|
for (let {length} = lazy, i = 0; i < length; i++) {
|
|
@@ -74,7 +78,7 @@ const set = (known, input, value) => {
|
|
|
74
78
|
* @param {(this: any, key: string, value: any) => any} [reviver]
|
|
75
79
|
* @returns {any}
|
|
76
80
|
*/
|
|
77
|
-
const parse = (text, reviver) => {
|
|
81
|
+
const parse$1 = (text, reviver) => {
|
|
78
82
|
const input = $parse(text, Primitives).map(primitives);
|
|
79
83
|
const value = input[0];
|
|
80
84
|
const $ = reviver || noop;
|
|
@@ -121,6 +125,51 @@ const stringify = (value, replacer, space) => {
|
|
|
121
125
|
}
|
|
122
126
|
};
|
|
123
127
|
|
|
128
|
+
function getOutputFile(config, reporter) {
|
|
129
|
+
if (config?.outputFile) return typeof config.outputFile === "string" ? config.outputFile : config.outputFile[reporter];
|
|
130
|
+
}
|
|
131
|
+
function createDefinesScript(define) {
|
|
132
|
+
return !define || serializeDefine(define) === "{}" ? "" : `
|
|
133
|
+
const defines = ${serializeDefine(define)}
|
|
134
|
+
Object.keys(defines).forEach((key) => {
|
|
135
|
+
const segments = key.split('.')
|
|
136
|
+
let target = globalThis
|
|
137
|
+
for (let i = 0; i < segments.length; i++) {
|
|
138
|
+
const segment = segments[i]
|
|
139
|
+
if (i === segments.length - 1) {
|
|
140
|
+
target[segment] = defines[key]
|
|
141
|
+
} else {
|
|
142
|
+
target = target[segment] || (target[segment] = {})
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Like `JSON.stringify` but keeps raw string values as a literal
|
|
150
|
+
* in the generated code. For example: `"window"` would refer to
|
|
151
|
+
* the global `window` object directly.
|
|
152
|
+
*/
|
|
153
|
+
function serializeDefine(define) {
|
|
154
|
+
const userDefine = {};
|
|
155
|
+
for (const key in define) {
|
|
156
|
+
// vitest sets this to avoid vite:client-inject plugin
|
|
157
|
+
if (key === "process.env.NODE_ENV" && define[key] === "process.env.NODE_ENV") continue;
|
|
158
|
+
// import.meta.env.* is handled in `importAnalysis` plugin
|
|
159
|
+
if (!key.startsWith("import.meta.env.")) userDefine[key] = define[key];
|
|
160
|
+
}
|
|
161
|
+
let res = `{`;
|
|
162
|
+
const keys = Object.keys(userDefine).sort();
|
|
163
|
+
for (let i = 0; i < keys.length; i++) {
|
|
164
|
+
const key = keys[i], val = userDefine[key];
|
|
165
|
+
if (res += `${JSON.stringify(key)}: ${handleDefineValue(val)}`, i !== keys.length - 1) res += `, `;
|
|
166
|
+
}
|
|
167
|
+
return `${res}}`;
|
|
168
|
+
}
|
|
169
|
+
function handleDefineValue(value) {
|
|
170
|
+
return typeof value === "undefined" ? "undefined" : typeof value === "string" ? value : JSON.stringify(value);
|
|
171
|
+
}
|
|
172
|
+
|
|
124
173
|
class BlobReporter {
|
|
125
174
|
start = 0;
|
|
126
175
|
ctx;
|
|
@@ -158,7 +207,7 @@ class BlobReporter {
|
|
|
158
207
|
modules,
|
|
159
208
|
coverage,
|
|
160
209
|
executionTime
|
|
161
|
-
], reportFile = resolve(this.ctx.config.root, outputFile);
|
|
210
|
+
], reportFile = resolve$1(this.ctx.config.root, outputFile);
|
|
162
211
|
await writeBlob(report, reportFile), this.ctx.logger.log("blob report written to", reportFile);
|
|
163
212
|
}
|
|
164
213
|
}
|
|
@@ -169,10 +218,10 @@ async function writeBlob(content, filename) {
|
|
|
169
218
|
}
|
|
170
219
|
async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
171
220
|
// using process.cwd() because --merge-reports can only be used in CLI
|
|
172
|
-
const resolvedDir = resolve(process.cwd(), blobsDirectory),
|
|
173
|
-
const fullPath = resolve(resolvedDir, filename)
|
|
174
|
-
if (!
|
|
175
|
-
const content = await readFile(fullPath, "utf-8"), [version, files, errors, moduleKeys, coverage, executionTime] = parse(content);
|
|
221
|
+
const resolvedDir = resolve$1(process.cwd(), blobsDirectory), promises = (await readdir(resolvedDir)).map(async (filename) => {
|
|
222
|
+
const fullPath = resolve$1(resolvedDir, filename);
|
|
223
|
+
if (!(await stat(fullPath)).isFile()) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
|
|
224
|
+
const content = await readFile(fullPath, "utf-8"), [version, files, errors, moduleKeys, coverage, executionTime] = parse$1(content);
|
|
176
225
|
if (!version) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
|
|
177
226
|
return {
|
|
178
227
|
version,
|
|
@@ -214,6 +263,55 @@ async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
|
|
|
214
263
|
};
|
|
215
264
|
}
|
|
216
265
|
|
|
266
|
+
function hasFailedSnapshot(suite) {
|
|
267
|
+
return getTests(suite).some((s) => {
|
|
268
|
+
return s.result?.errors?.some((e) => typeof e?.message === "string" && e.message.match(/Snapshot .* mismatched/));
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
function convertTasksToEvents(file, onTask) {
|
|
272
|
+
const packs = [], events = [];
|
|
273
|
+
function visit(suite) {
|
|
274
|
+
onTask?.(suite), packs.push([
|
|
275
|
+
suite.id,
|
|
276
|
+
suite.result,
|
|
277
|
+
suite.meta
|
|
278
|
+
]), events.push([
|
|
279
|
+
suite.id,
|
|
280
|
+
"suite-prepare",
|
|
281
|
+
void 0
|
|
282
|
+
]), suite.tasks.forEach((task) => {
|
|
283
|
+
if (task.type === "suite") visit(task);
|
|
284
|
+
else if (onTask?.(task), suite.mode !== "skip" && suite.mode !== "todo") packs.push([
|
|
285
|
+
task.id,
|
|
286
|
+
task.result,
|
|
287
|
+
task.meta
|
|
288
|
+
]), events.push([
|
|
289
|
+
task.id,
|
|
290
|
+
"test-prepare",
|
|
291
|
+
void 0
|
|
292
|
+
]), task.annotations.forEach((annotation) => {
|
|
293
|
+
events.push([
|
|
294
|
+
task.id,
|
|
295
|
+
"test-annotation",
|
|
296
|
+
{ annotation }
|
|
297
|
+
]);
|
|
298
|
+
}), events.push([
|
|
299
|
+
task.id,
|
|
300
|
+
"test-finished",
|
|
301
|
+
void 0
|
|
302
|
+
]);
|
|
303
|
+
}), events.push([
|
|
304
|
+
suite.id,
|
|
305
|
+
"suite-finished",
|
|
306
|
+
void 0
|
|
307
|
+
]);
|
|
308
|
+
}
|
|
309
|
+
return visit(file), {
|
|
310
|
+
packs,
|
|
311
|
+
events
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
217
315
|
const F_RIGHT = "→";
|
|
218
316
|
const F_DOWN = "↓";
|
|
219
317
|
const F_DOWN_RIGHT = "↳";
|
|
@@ -232,6 +330,7 @@ const testPass = c.green(F_CHECK);
|
|
|
232
330
|
const taskFail = c.red(F_CROSS);
|
|
233
331
|
const suiteFail = c.red(F_POINTER);
|
|
234
332
|
const pending$1 = c.gray("·");
|
|
333
|
+
const separator = c.dim(" > ");
|
|
235
334
|
const labelDefaultColors = [
|
|
236
335
|
c.bgYellow,
|
|
237
336
|
c.bgCyan,
|
|
@@ -351,6 +450,7 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
351
450
|
pending: pending$1,
|
|
352
451
|
pointer: pointer,
|
|
353
452
|
renderSnapshotSummary: renderSnapshotSummary,
|
|
453
|
+
separator: separator,
|
|
354
454
|
skipped: skipped,
|
|
355
455
|
suiteFail: suiteFail,
|
|
356
456
|
taskFail: taskFail,
|
|
@@ -440,19 +540,10 @@ class BaseReporter {
|
|
|
440
540
|
})), logs.forEach((log) => this.log(log));
|
|
441
541
|
}
|
|
442
542
|
printTestCase(moduleState, test) {
|
|
443
|
-
const testResult = test.result(), { duration
|
|
444
|
-
|
|
445
|
-
if (
|
|
446
|
-
if (
|
|
447
|
-
if (testResult.state === "failed")
|
|
448
|
-
// print short errors, full errors will be at the end in summary
|
|
449
|
-
this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(" > "))}`) + suffix), testResult.errors.forEach((error) => {
|
|
450
|
-
const message = this.formatShortError(error);
|
|
451
|
-
if (message) this.log(c.red(` ${padding}${message}`));
|
|
452
|
-
});
|
|
453
|
-
else if (duration && duration > this.ctx.config.slowTestThreshold) this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(" > "))} ${suffix}`);
|
|
454
|
-
else if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") ; else if (testResult.state === "skipped" && testResult.note) this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${c.dim(c.gray(` [${testResult.note}]`))}`);
|
|
455
|
-
else if (this.renderSucceed || moduleState === "failed") this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${suffix}`);
|
|
543
|
+
const testResult = test.result(), { duration = 0 } = test.diagnostic() || {}, padding = this.getTestIndentation(test.task), suffix = this.getTestCaseSuffix(test);
|
|
544
|
+
if (testResult.state === "failed") this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, separator)}`) + suffix);
|
|
545
|
+
else if (duration > this.ctx.config.slowTestThreshold) this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, separator)} ${suffix}`);
|
|
546
|
+
else if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") ; else if (this.renderSucceed || moduleState === "failed") this.log(` ${padding}${this.getStateSymbol(test)} ${this.getTestName(test.task, separator)}${suffix}`);
|
|
456
547
|
}
|
|
457
548
|
getModuleLog(testModule, counts) {
|
|
458
549
|
let state = c.dim(`${counts.tests} test${counts.tests > 1 ? "s" : ""}`);
|
|
@@ -461,46 +552,65 @@ class BaseReporter {
|
|
|
461
552
|
let suffix = c.dim("(") + state + c.dim(")") + this.getDurationPrefix(testModule.task);
|
|
462
553
|
const diagnostic = testModule.diagnostic();
|
|
463
554
|
if (diagnostic.heap != null) suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
|
|
464
|
-
|
|
465
|
-
if (testModule.meta().typecheck) title += ` ${c.bgBlue(c.bold(" TS "))}`;
|
|
466
|
-
if (testModule.project.name) title += ` ${formatProjectName(testModule.project, "")}`;
|
|
467
|
-
return ` ${title} ${testModule.task.name} ${suffix}`;
|
|
555
|
+
return ` ${this.getEntityPrefix(testModule)} ${testModule.task.name} ${suffix}`;
|
|
468
556
|
}
|
|
469
|
-
printTestSuite(
|
|
470
|
-
|
|
557
|
+
printTestSuite(testSuite) {
|
|
558
|
+
if (!this.renderSucceed) return;
|
|
559
|
+
const indentation = " ".repeat(getIndentation(testSuite.task)), tests = Array.from(testSuite.children.allTests()), state = this.getStateSymbol(testSuite);
|
|
560
|
+
this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`);
|
|
471
561
|
}
|
|
472
|
-
getTestName(test,
|
|
473
|
-
return
|
|
562
|
+
getTestName(test, _separator) {
|
|
563
|
+
return test.name;
|
|
474
564
|
}
|
|
475
565
|
getFullName(test, separator) {
|
|
476
|
-
|
|
566
|
+
if (test === test.file) return test.name;
|
|
567
|
+
let name = test.file.name;
|
|
568
|
+
if (test.location) name += c.dim(`:${test.location.line}:${test.location.column}`);
|
|
569
|
+
return name += separator, name += getTestName(test, separator), name;
|
|
477
570
|
}
|
|
478
|
-
|
|
479
|
-
return
|
|
480
|
-
}
|
|
481
|
-
getTestIndentation(_test) {
|
|
482
|
-
return " ";
|
|
571
|
+
getTestIndentation(test) {
|
|
572
|
+
return " ".repeat(getIndentation(test));
|
|
483
573
|
}
|
|
484
574
|
printAnnotations(test, console, padding = 0) {
|
|
485
575
|
const annotations = test.annotations();
|
|
486
576
|
if (!annotations.length) return;
|
|
487
|
-
const PADDING = " ".repeat(padding);
|
|
488
|
-
annotations.forEach((
|
|
577
|
+
const PADDING = " ".repeat(padding), groupedAnnotations = {};
|
|
578
|
+
for (const group in annotations.forEach((annotation) => {
|
|
579
|
+
const { location, type } = annotation;
|
|
580
|
+
let group;
|
|
489
581
|
if (location) {
|
|
490
582
|
const file = relative(test.project.config.root, location.file);
|
|
491
|
-
|
|
492
|
-
} else
|
|
583
|
+
group = `${c.gray(`${file}:${location.line}:${location.column}`)} ${c.bold(type)}`;
|
|
584
|
+
} else group = c.bold(type);
|
|
585
|
+
groupedAnnotations[group] ??= [], groupedAnnotations[group].push(annotation);
|
|
586
|
+
}), groupedAnnotations) this[console](`${PADDING}${c.blue(F_POINTER)} ${group}`), groupedAnnotations[group].forEach(({ message }) => {
|
|
493
587
|
this[console](`${PADDING} ${c.blue(F_DOWN_RIGHT)} ${message}`);
|
|
494
588
|
});
|
|
495
589
|
}
|
|
590
|
+
getEntityPrefix(entity) {
|
|
591
|
+
let title = this.getStateSymbol(entity);
|
|
592
|
+
if (entity.project.name) title += ` ${formatProjectName(entity.project, "")}`;
|
|
593
|
+
if (entity.meta().typecheck) title += ` ${c.bgBlue(c.bold(" TS "))}`;
|
|
594
|
+
return title;
|
|
595
|
+
}
|
|
596
|
+
getTestCaseSuffix(testCase) {
|
|
597
|
+
const { heap, retryCount, repeatCount } = testCase.diagnostic() || {}, testResult = testCase.result();
|
|
598
|
+
let suffix = this.getDurationPrefix(testCase.task);
|
|
599
|
+
if (retryCount != null && retryCount > 0) suffix += c.yellow(` (retry x${retryCount})`);
|
|
600
|
+
if (repeatCount != null && repeatCount > 0) suffix += c.yellow(` (repeat x${repeatCount})`);
|
|
601
|
+
if (heap != null) suffix += c.magenta(` ${Math.floor(heap / 1024 / 1024)} MB heap used`);
|
|
602
|
+
if (testResult.state === "skipped" && testResult.note) suffix += c.dim(c.gray(` [${testResult.note}]`));
|
|
603
|
+
return suffix;
|
|
604
|
+
}
|
|
605
|
+
getStateSymbol(test) {
|
|
606
|
+
return getStateSymbol(test.task);
|
|
607
|
+
}
|
|
496
608
|
getDurationPrefix(task) {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
return color(` ${Math.round(task.result.duration)}${c.dim("ms")}`);
|
|
609
|
+
const duration = task.result?.duration && Math.round(task.result?.duration);
|
|
610
|
+
return duration == null ? "" : (duration > this.ctx.config.slowTestThreshold ? c.yellow : c.green)(` ${duration}${c.dim("ms")}`);
|
|
500
611
|
}
|
|
501
612
|
onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
|
|
502
|
-
|
|
503
|
-
if (failed) this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
|
|
613
|
+
if (errors.length > 0 || hasFailed(files)) this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
|
|
504
614
|
else if (this.ctx.isCancelling) this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
|
|
505
615
|
else this.log(withLabel("green", "PASS", "Waiting for file changes..."));
|
|
506
616
|
const hints = [c.dim("press ") + c.bold("h") + c.dim(" to show help")];
|
|
@@ -531,7 +641,7 @@ class BaseReporter {
|
|
|
531
641
|
const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream, write = (msg) => output.write(msg);
|
|
532
642
|
let headerText = "unknown test";
|
|
533
643
|
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
|
|
534
|
-
if (task) headerText = this.getFullName(task,
|
|
644
|
+
if (task) headerText = this.getFullName(task, separator);
|
|
535
645
|
else if (log.taskId && log.taskId !== "__vitest__unknown_test__") headerText = log.taskId;
|
|
536
646
|
if (write(c.gray(log.type + c.dim(` | ${headerText}\n`)) + log.content), log.origin) {
|
|
537
647
|
// browser logs don't have an extra end of line at the end like Node.js does
|
|
@@ -550,8 +660,8 @@ class BaseReporter {
|
|
|
550
660
|
shouldLog(log, taskState) {
|
|
551
661
|
if (this.ctx.config.silent === true || this.ctx.config.silent === "passed-only" && taskState !== "failed") return false;
|
|
552
662
|
if (this.ctx.config.onConsoleLog) {
|
|
553
|
-
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0, entity = task && this.ctx.state.getReportedEntity(task)
|
|
554
|
-
if (
|
|
663
|
+
const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0, entity = task && this.ctx.state.getReportedEntity(task);
|
|
664
|
+
if (this.ctx.config.onConsoleLog(log.content, log.type, entity) === false) return false;
|
|
555
665
|
}
|
|
556
666
|
return true;
|
|
557
667
|
}
|
|
@@ -601,12 +711,12 @@ class BaseReporter {
|
|
|
601
711
|
if (errors.length) this.ctx.logger.printUnhandledErrors(errors), this.error();
|
|
602
712
|
}
|
|
603
713
|
reportBenchmarkSummary(files) {
|
|
604
|
-
const
|
|
714
|
+
const topBenches = getTests(files).filter((i) => i.result?.benchmark?.rank === 1);
|
|
605
715
|
this.log(`\n${withLabel("cyan", "BENCH", "Summary\n")}`);
|
|
606
716
|
for (const bench of topBenches) {
|
|
607
717
|
const group = bench.suite || bench.file;
|
|
608
718
|
if (!group) continue;
|
|
609
|
-
const groupName = this.getFullName(group,
|
|
719
|
+
const groupName = this.getFullName(group, separator), project = this.ctx.projects.find((p) => p.name === bench.file.projectName);
|
|
610
720
|
this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`);
|
|
611
721
|
const siblings = group.tasks.filter((i) => i.meta.benchmark && i.result?.benchmark && i !== bench).sort((a, b) => a.result.benchmark.rank - b.result.benchmark.rank);
|
|
612
722
|
for (const sibling of siblings) {
|
|
@@ -633,7 +743,7 @@ class BaseReporter {
|
|
|
633
743
|
for (const [error, tasks] of errorsQueue) {
|
|
634
744
|
for (const task of tasks) {
|
|
635
745
|
const filepath = task?.filepath || "", projectName = task?.projectName || task.file?.projectName || "", project = this.ctx.projects.find((p) => p.name === projectName);
|
|
636
|
-
let name = this.getFullName(task,
|
|
746
|
+
let name = this.getFullName(task, separator);
|
|
637
747
|
if (filepath) name += c.dim(` [ ${this.relative(filepath)} ]`);
|
|
638
748
|
this.ctx.logger.error(`${c.bgRed(c.bold(" FAIL "))} ${formatProjectName(project)}${name}`);
|
|
639
749
|
}
|
|
@@ -664,6 +774,9 @@ function sum(items, cb) {
|
|
|
664
774
|
return total + Math.max(cb(next) || 0, 0);
|
|
665
775
|
}, 0);
|
|
666
776
|
}
|
|
777
|
+
function getIndentation(suite, level = 1) {
|
|
778
|
+
return suite.suite && !("filepath" in suite.suite) ? getIndentation(suite.suite, level + 1) : level;
|
|
779
|
+
}
|
|
667
780
|
|
|
668
781
|
const DEFAULT_RENDER_INTERVAL_MS = 1e3, ESC = "\x1B[", CLEAR_LINE = `${ESC}K`, MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`, SYNC_START = `${ESC}?2026h`, SYNC_END = `${ESC}?2026l`;
|
|
669
782
|
/**
|
|
@@ -876,11 +989,10 @@ class SummaryReporter {
|
|
|
876
989
|
else if (state === "failed") this.modules.failed++;
|
|
877
990
|
else if (module.task.mode === "todo" && state === "skipped") this.modules.todo++;
|
|
878
991
|
else if (state === "skipped") this.modules.skipped++;
|
|
879
|
-
const left = this.modules.total - this.modules.completed;
|
|
880
992
|
// Keep finished tests visible in summary for a while if there are more tests left.
|
|
881
993
|
// When a new test starts in onTestModuleQueued it will take this ones place.
|
|
882
994
|
// This reduces flickering by making summary more stable.
|
|
883
|
-
if (
|
|
995
|
+
if (this.modules.total - this.modules.completed > this.maxParallelTests) this.finishedModules.set(module.id, setTimeout(() => {
|
|
884
996
|
this.removeTestModule(module.id);
|
|
885
997
|
}, FINISHED_TEST_CLEANUP_TIME_MS).unref());
|
|
886
998
|
else
|
|
@@ -1097,6 +1209,1298 @@ function formatTests(states) {
|
|
|
1097
1209
|
return output += currentIcon.color(currentIcon.char.repeat(count)), output;
|
|
1098
1210
|
}
|
|
1099
1211
|
|
|
1212
|
+
// src/vlq.ts
|
|
1213
|
+
var comma = ",".charCodeAt(0);
|
|
1214
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1215
|
+
var intToChar = new Uint8Array(64);
|
|
1216
|
+
var charToInt = new Uint8Array(128);
|
|
1217
|
+
for (let i = 0; i < chars.length; i++) {
|
|
1218
|
+
const c = chars.charCodeAt(i);
|
|
1219
|
+
intToChar[i] = c;
|
|
1220
|
+
charToInt[c] = i;
|
|
1221
|
+
}
|
|
1222
|
+
function decodeInteger(reader, relative) {
|
|
1223
|
+
let value = 0;
|
|
1224
|
+
let shift = 0;
|
|
1225
|
+
let integer = 0;
|
|
1226
|
+
do {
|
|
1227
|
+
const c = reader.next();
|
|
1228
|
+
integer = charToInt[c];
|
|
1229
|
+
value |= (integer & 31) << shift;
|
|
1230
|
+
shift += 5;
|
|
1231
|
+
} while (integer & 32);
|
|
1232
|
+
const shouldNegate = value & 1;
|
|
1233
|
+
value >>>= 1;
|
|
1234
|
+
if (shouldNegate) {
|
|
1235
|
+
value = -2147483648 | -value;
|
|
1236
|
+
}
|
|
1237
|
+
return relative + value;
|
|
1238
|
+
}
|
|
1239
|
+
function hasMoreVlq(reader, max) {
|
|
1240
|
+
if (reader.pos >= max) return false;
|
|
1241
|
+
return reader.peek() !== comma;
|
|
1242
|
+
}
|
|
1243
|
+
var StringReader = class {
|
|
1244
|
+
constructor(buffer) {
|
|
1245
|
+
this.pos = 0;
|
|
1246
|
+
this.buffer = buffer;
|
|
1247
|
+
}
|
|
1248
|
+
next() {
|
|
1249
|
+
return this.buffer.charCodeAt(this.pos++);
|
|
1250
|
+
}
|
|
1251
|
+
peek() {
|
|
1252
|
+
return this.buffer.charCodeAt(this.pos);
|
|
1253
|
+
}
|
|
1254
|
+
indexOf(char) {
|
|
1255
|
+
const { buffer, pos } = this;
|
|
1256
|
+
const idx = buffer.indexOf(char, pos);
|
|
1257
|
+
return idx === -1 ? buffer.length : idx;
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
// src/sourcemap-codec.ts
|
|
1262
|
+
function decode(mappings) {
|
|
1263
|
+
const { length } = mappings;
|
|
1264
|
+
const reader = new StringReader(mappings);
|
|
1265
|
+
const decoded = [];
|
|
1266
|
+
let genColumn = 0;
|
|
1267
|
+
let sourcesIndex = 0;
|
|
1268
|
+
let sourceLine = 0;
|
|
1269
|
+
let sourceColumn = 0;
|
|
1270
|
+
let namesIndex = 0;
|
|
1271
|
+
do {
|
|
1272
|
+
const semi = reader.indexOf(";");
|
|
1273
|
+
const line = [];
|
|
1274
|
+
let sorted = true;
|
|
1275
|
+
let lastCol = 0;
|
|
1276
|
+
genColumn = 0;
|
|
1277
|
+
while (reader.pos < semi) {
|
|
1278
|
+
let seg;
|
|
1279
|
+
genColumn = decodeInteger(reader, genColumn);
|
|
1280
|
+
if (genColumn < lastCol) sorted = false;
|
|
1281
|
+
lastCol = genColumn;
|
|
1282
|
+
if (hasMoreVlq(reader, semi)) {
|
|
1283
|
+
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
|
1284
|
+
sourceLine = decodeInteger(reader, sourceLine);
|
|
1285
|
+
sourceColumn = decodeInteger(reader, sourceColumn);
|
|
1286
|
+
if (hasMoreVlq(reader, semi)) {
|
|
1287
|
+
namesIndex = decodeInteger(reader, namesIndex);
|
|
1288
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
|
|
1289
|
+
} else {
|
|
1290
|
+
seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
|
|
1291
|
+
}
|
|
1292
|
+
} else {
|
|
1293
|
+
seg = [genColumn];
|
|
1294
|
+
}
|
|
1295
|
+
line.push(seg);
|
|
1296
|
+
reader.pos++;
|
|
1297
|
+
}
|
|
1298
|
+
if (!sorted) sort(line);
|
|
1299
|
+
decoded.push(line);
|
|
1300
|
+
reader.pos = semi + 1;
|
|
1301
|
+
} while (reader.pos <= length);
|
|
1302
|
+
return decoded;
|
|
1303
|
+
}
|
|
1304
|
+
function sort(line) {
|
|
1305
|
+
line.sort(sortComparator$1);
|
|
1306
|
+
}
|
|
1307
|
+
function sortComparator$1(a, b) {
|
|
1308
|
+
return a[0] - b[0];
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// Matches the scheme of a URL, eg "http://"
|
|
1312
|
+
const schemeRegex = /^[\w+.-]+:\/\//;
|
|
1313
|
+
/**
|
|
1314
|
+
* Matches the parts of a URL:
|
|
1315
|
+
* 1. Scheme, including ":", guaranteed.
|
|
1316
|
+
* 2. User/password, including "@", optional.
|
|
1317
|
+
* 3. Host, guaranteed.
|
|
1318
|
+
* 4. Port, including ":", optional.
|
|
1319
|
+
* 5. Path, including "/", optional.
|
|
1320
|
+
* 6. Query, including "?", optional.
|
|
1321
|
+
* 7. Hash, including "#", optional.
|
|
1322
|
+
*/
|
|
1323
|
+
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
|
|
1324
|
+
/**
|
|
1325
|
+
* File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
|
|
1326
|
+
* with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
|
|
1327
|
+
*
|
|
1328
|
+
* 1. Host, optional.
|
|
1329
|
+
* 2. Path, which may include "/", guaranteed.
|
|
1330
|
+
* 3. Query, including "?", optional.
|
|
1331
|
+
* 4. Hash, including "#", optional.
|
|
1332
|
+
*/
|
|
1333
|
+
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
|
|
1334
|
+
function isAbsoluteUrl(input) {
|
|
1335
|
+
return schemeRegex.test(input);
|
|
1336
|
+
}
|
|
1337
|
+
function isSchemeRelativeUrl(input) {
|
|
1338
|
+
return input.startsWith('//');
|
|
1339
|
+
}
|
|
1340
|
+
function isAbsolutePath(input) {
|
|
1341
|
+
return input.startsWith('/');
|
|
1342
|
+
}
|
|
1343
|
+
function isFileUrl(input) {
|
|
1344
|
+
return input.startsWith('file:');
|
|
1345
|
+
}
|
|
1346
|
+
function isRelative(input) {
|
|
1347
|
+
return /^[.?#]/.test(input);
|
|
1348
|
+
}
|
|
1349
|
+
function parseAbsoluteUrl(input) {
|
|
1350
|
+
const match = urlRegex.exec(input);
|
|
1351
|
+
return makeUrl(match[1], match[2] || '', match[3], match[4] || '', match[5] || '/', match[6] || '', match[7] || '');
|
|
1352
|
+
}
|
|
1353
|
+
function parseFileUrl(input) {
|
|
1354
|
+
const match = fileRegex.exec(input);
|
|
1355
|
+
const path = match[2];
|
|
1356
|
+
return makeUrl('file:', '', match[1] || '', '', isAbsolutePath(path) ? path : '/' + path, match[3] || '', match[4] || '');
|
|
1357
|
+
}
|
|
1358
|
+
function makeUrl(scheme, user, host, port, path, query, hash) {
|
|
1359
|
+
return {
|
|
1360
|
+
scheme,
|
|
1361
|
+
user,
|
|
1362
|
+
host,
|
|
1363
|
+
port,
|
|
1364
|
+
path,
|
|
1365
|
+
query,
|
|
1366
|
+
hash,
|
|
1367
|
+
type: 7 /* Absolute */,
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
function parseUrl(input) {
|
|
1371
|
+
if (isSchemeRelativeUrl(input)) {
|
|
1372
|
+
const url = parseAbsoluteUrl('http:' + input);
|
|
1373
|
+
url.scheme = '';
|
|
1374
|
+
url.type = 6 /* SchemeRelative */;
|
|
1375
|
+
return url;
|
|
1376
|
+
}
|
|
1377
|
+
if (isAbsolutePath(input)) {
|
|
1378
|
+
const url = parseAbsoluteUrl('http://foo.com' + input);
|
|
1379
|
+
url.scheme = '';
|
|
1380
|
+
url.host = '';
|
|
1381
|
+
url.type = 5 /* AbsolutePath */;
|
|
1382
|
+
return url;
|
|
1383
|
+
}
|
|
1384
|
+
if (isFileUrl(input))
|
|
1385
|
+
return parseFileUrl(input);
|
|
1386
|
+
if (isAbsoluteUrl(input))
|
|
1387
|
+
return parseAbsoluteUrl(input);
|
|
1388
|
+
const url = parseAbsoluteUrl('http://foo.com/' + input);
|
|
1389
|
+
url.scheme = '';
|
|
1390
|
+
url.host = '';
|
|
1391
|
+
url.type = input
|
|
1392
|
+
? input.startsWith('?')
|
|
1393
|
+
? 3 /* Query */
|
|
1394
|
+
: input.startsWith('#')
|
|
1395
|
+
? 2 /* Hash */
|
|
1396
|
+
: 4 /* RelativePath */
|
|
1397
|
+
: 1 /* Empty */;
|
|
1398
|
+
return url;
|
|
1399
|
+
}
|
|
1400
|
+
function stripPathFilename(path) {
|
|
1401
|
+
// If a path ends with a parent directory "..", then it's a relative path with excess parent
|
|
1402
|
+
// paths. It's not a file, so we can't strip it.
|
|
1403
|
+
if (path.endsWith('/..'))
|
|
1404
|
+
return path;
|
|
1405
|
+
const index = path.lastIndexOf('/');
|
|
1406
|
+
return path.slice(0, index + 1);
|
|
1407
|
+
}
|
|
1408
|
+
function mergePaths(url, base) {
|
|
1409
|
+
normalizePath(base, base.type);
|
|
1410
|
+
// If the path is just a "/", then it was an empty path to begin with (remember, we're a relative
|
|
1411
|
+
// path).
|
|
1412
|
+
if (url.path === '/') {
|
|
1413
|
+
url.path = base.path;
|
|
1414
|
+
}
|
|
1415
|
+
else {
|
|
1416
|
+
// Resolution happens relative to the base path's directory, not the file.
|
|
1417
|
+
url.path = stripPathFilename(base.path) + url.path;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* The path can have empty directories "//", unneeded parents "foo/..", or current directory
|
|
1422
|
+
* "foo/.". We need to normalize to a standard representation.
|
|
1423
|
+
*/
|
|
1424
|
+
function normalizePath(url, type) {
|
|
1425
|
+
const rel = type <= 4 /* RelativePath */;
|
|
1426
|
+
const pieces = url.path.split('/');
|
|
1427
|
+
// We need to preserve the first piece always, so that we output a leading slash. The item at
|
|
1428
|
+
// pieces[0] is an empty string.
|
|
1429
|
+
let pointer = 1;
|
|
1430
|
+
// Positive is the number of real directories we've output, used for popping a parent directory.
|
|
1431
|
+
// Eg, "foo/bar/.." will have a positive 2, and we can decrement to be left with just "foo".
|
|
1432
|
+
let positive = 0;
|
|
1433
|
+
// We need to keep a trailing slash if we encounter an empty directory (eg, splitting "foo/" will
|
|
1434
|
+
// generate `["foo", ""]` pieces). And, if we pop a parent directory. But once we encounter a
|
|
1435
|
+
// real directory, we won't need to append, unless the other conditions happen again.
|
|
1436
|
+
let addTrailingSlash = false;
|
|
1437
|
+
for (let i = 1; i < pieces.length; i++) {
|
|
1438
|
+
const piece = pieces[i];
|
|
1439
|
+
// An empty directory, could be a trailing slash, or just a double "//" in the path.
|
|
1440
|
+
if (!piece) {
|
|
1441
|
+
addTrailingSlash = true;
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
// If we encounter a real directory, then we don't need to append anymore.
|
|
1445
|
+
addTrailingSlash = false;
|
|
1446
|
+
// A current directory, which we can always drop.
|
|
1447
|
+
if (piece === '.')
|
|
1448
|
+
continue;
|
|
1449
|
+
// A parent directory, we need to see if there are any real directories we can pop. Else, we
|
|
1450
|
+
// have an excess of parents, and we'll need to keep the "..".
|
|
1451
|
+
if (piece === '..') {
|
|
1452
|
+
if (positive) {
|
|
1453
|
+
addTrailingSlash = true;
|
|
1454
|
+
positive--;
|
|
1455
|
+
pointer--;
|
|
1456
|
+
}
|
|
1457
|
+
else if (rel) {
|
|
1458
|
+
// If we're in a relativePath, then we need to keep the excess parents. Else, in an absolute
|
|
1459
|
+
// URL, protocol relative URL, or an absolute path, we don't need to keep excess.
|
|
1460
|
+
pieces[pointer++] = piece;
|
|
1461
|
+
}
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
// We've encountered a real directory. Move it to the next insertion pointer, which accounts for
|
|
1465
|
+
// any popped or dropped directories.
|
|
1466
|
+
pieces[pointer++] = piece;
|
|
1467
|
+
positive++;
|
|
1468
|
+
}
|
|
1469
|
+
let path = '';
|
|
1470
|
+
for (let i = 1; i < pointer; i++) {
|
|
1471
|
+
path += '/' + pieces[i];
|
|
1472
|
+
}
|
|
1473
|
+
if (!path || (addTrailingSlash && !path.endsWith('/..'))) {
|
|
1474
|
+
path += '/';
|
|
1475
|
+
}
|
|
1476
|
+
url.path = path;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Attempts to resolve `input` URL/path relative to `base`.
|
|
1480
|
+
*/
|
|
1481
|
+
function resolve(input, base) {
|
|
1482
|
+
if (!input && !base)
|
|
1483
|
+
return '';
|
|
1484
|
+
const url = parseUrl(input);
|
|
1485
|
+
let inputType = url.type;
|
|
1486
|
+
if (base && inputType !== 7 /* Absolute */) {
|
|
1487
|
+
const baseUrl = parseUrl(base);
|
|
1488
|
+
const baseType = baseUrl.type;
|
|
1489
|
+
switch (inputType) {
|
|
1490
|
+
case 1 /* Empty */:
|
|
1491
|
+
url.hash = baseUrl.hash;
|
|
1492
|
+
// fall through
|
|
1493
|
+
case 2 /* Hash */:
|
|
1494
|
+
url.query = baseUrl.query;
|
|
1495
|
+
// fall through
|
|
1496
|
+
case 3 /* Query */:
|
|
1497
|
+
case 4 /* RelativePath */:
|
|
1498
|
+
mergePaths(url, baseUrl);
|
|
1499
|
+
// fall through
|
|
1500
|
+
case 5 /* AbsolutePath */:
|
|
1501
|
+
// The host, user, and port are joined, you can't copy one without the others.
|
|
1502
|
+
url.user = baseUrl.user;
|
|
1503
|
+
url.host = baseUrl.host;
|
|
1504
|
+
url.port = baseUrl.port;
|
|
1505
|
+
// fall through
|
|
1506
|
+
case 6 /* SchemeRelative */:
|
|
1507
|
+
// The input doesn't have a schema at least, so we need to copy at least that over.
|
|
1508
|
+
url.scheme = baseUrl.scheme;
|
|
1509
|
+
}
|
|
1510
|
+
if (baseType > inputType)
|
|
1511
|
+
inputType = baseType;
|
|
1512
|
+
}
|
|
1513
|
+
normalizePath(url, inputType);
|
|
1514
|
+
const queryHash = url.query + url.hash;
|
|
1515
|
+
switch (inputType) {
|
|
1516
|
+
// This is impossible, because of the empty checks at the start of the function.
|
|
1517
|
+
// case UrlType.Empty:
|
|
1518
|
+
case 2 /* Hash */:
|
|
1519
|
+
case 3 /* Query */:
|
|
1520
|
+
return queryHash;
|
|
1521
|
+
case 4 /* RelativePath */: {
|
|
1522
|
+
// The first char is always a "/", and we need it to be relative.
|
|
1523
|
+
const path = url.path.slice(1);
|
|
1524
|
+
if (!path)
|
|
1525
|
+
return queryHash || '.';
|
|
1526
|
+
if (isRelative(base || input) && !isRelative(path)) {
|
|
1527
|
+
// If base started with a leading ".", or there is no base and input started with a ".",
|
|
1528
|
+
// then we need to ensure that the relative path starts with a ".". We don't know if
|
|
1529
|
+
// relative starts with a "..", though, so check before prepending.
|
|
1530
|
+
return './' + path + queryHash;
|
|
1531
|
+
}
|
|
1532
|
+
return path + queryHash;
|
|
1533
|
+
}
|
|
1534
|
+
case 5 /* AbsolutePath */:
|
|
1535
|
+
return url.path + queryHash;
|
|
1536
|
+
default:
|
|
1537
|
+
return url.scheme + '//' + url.user + url.host + url.port + url.path + queryHash;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// src/trace-mapping.ts
|
|
1542
|
+
|
|
1543
|
+
// src/strip-filename.ts
|
|
1544
|
+
function stripFilename(path) {
|
|
1545
|
+
if (!path) return "";
|
|
1546
|
+
const index = path.lastIndexOf("/");
|
|
1547
|
+
return path.slice(0, index + 1);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
// src/resolve.ts
|
|
1551
|
+
function resolver(mapUrl, sourceRoot) {
|
|
1552
|
+
const from = stripFilename(mapUrl);
|
|
1553
|
+
const prefix = sourceRoot ? sourceRoot + "/" : "";
|
|
1554
|
+
return (source) => resolve(prefix + (source || ""), from);
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
// src/sourcemap-segment.ts
|
|
1558
|
+
var COLUMN = 0;
|
|
1559
|
+
var SOURCES_INDEX = 1;
|
|
1560
|
+
var SOURCE_LINE = 2;
|
|
1561
|
+
var SOURCE_COLUMN = 3;
|
|
1562
|
+
var NAMES_INDEX = 4;
|
|
1563
|
+
var REV_GENERATED_LINE = 1;
|
|
1564
|
+
var REV_GENERATED_COLUMN = 2;
|
|
1565
|
+
|
|
1566
|
+
// src/sort.ts
|
|
1567
|
+
function maybeSort(mappings, owned) {
|
|
1568
|
+
const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
|
|
1569
|
+
if (unsortedIndex === mappings.length) return mappings;
|
|
1570
|
+
if (!owned) mappings = mappings.slice();
|
|
1571
|
+
for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) {
|
|
1572
|
+
mappings[i] = sortSegments(mappings[i], owned);
|
|
1573
|
+
}
|
|
1574
|
+
return mappings;
|
|
1575
|
+
}
|
|
1576
|
+
function nextUnsortedSegmentLine(mappings, start) {
|
|
1577
|
+
for (let i = start; i < mappings.length; i++) {
|
|
1578
|
+
if (!isSorted(mappings[i])) return i;
|
|
1579
|
+
}
|
|
1580
|
+
return mappings.length;
|
|
1581
|
+
}
|
|
1582
|
+
function isSorted(line) {
|
|
1583
|
+
for (let j = 1; j < line.length; j++) {
|
|
1584
|
+
if (line[j][COLUMN] < line[j - 1][COLUMN]) {
|
|
1585
|
+
return false;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
return true;
|
|
1589
|
+
}
|
|
1590
|
+
function sortSegments(line, owned) {
|
|
1591
|
+
if (!owned) line = line.slice();
|
|
1592
|
+
return line.sort(sortComparator);
|
|
1593
|
+
}
|
|
1594
|
+
function sortComparator(a, b) {
|
|
1595
|
+
return a[COLUMN] - b[COLUMN];
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// src/by-source.ts
|
|
1599
|
+
function buildBySources(decoded, memos) {
|
|
1600
|
+
const sources = memos.map(() => []);
|
|
1601
|
+
for (let i = 0; i < decoded.length; i++) {
|
|
1602
|
+
const line = decoded[i];
|
|
1603
|
+
for (let j = 0; j < line.length; j++) {
|
|
1604
|
+
const seg = line[j];
|
|
1605
|
+
if (seg.length === 1) continue;
|
|
1606
|
+
const sourceIndex2 = seg[SOURCES_INDEX];
|
|
1607
|
+
const sourceLine = seg[SOURCE_LINE];
|
|
1608
|
+
const sourceColumn = seg[SOURCE_COLUMN];
|
|
1609
|
+
const source = sources[sourceIndex2];
|
|
1610
|
+
const segs = source[sourceLine] || (source[sourceLine] = []);
|
|
1611
|
+
segs.push([sourceColumn, i, seg[COLUMN]]);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
for (let i = 0; i < sources.length; i++) {
|
|
1615
|
+
const source = sources[i];
|
|
1616
|
+
for (let j = 0; j < source.length; j++) {
|
|
1617
|
+
const line = source[j];
|
|
1618
|
+
if (line) line.sort(sortComparator);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
return sources;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
// src/binary-search.ts
|
|
1625
|
+
var found = false;
|
|
1626
|
+
function binarySearch(haystack, needle, low, high) {
|
|
1627
|
+
while (low <= high) {
|
|
1628
|
+
const mid = low + (high - low >> 1);
|
|
1629
|
+
const cmp = haystack[mid][COLUMN] - needle;
|
|
1630
|
+
if (cmp === 0) {
|
|
1631
|
+
found = true;
|
|
1632
|
+
return mid;
|
|
1633
|
+
}
|
|
1634
|
+
if (cmp < 0) {
|
|
1635
|
+
low = mid + 1;
|
|
1636
|
+
} else {
|
|
1637
|
+
high = mid - 1;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
found = false;
|
|
1641
|
+
return low - 1;
|
|
1642
|
+
}
|
|
1643
|
+
function upperBound(haystack, needle, index) {
|
|
1644
|
+
for (let i = index + 1; i < haystack.length; index = i++) {
|
|
1645
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
1646
|
+
}
|
|
1647
|
+
return index;
|
|
1648
|
+
}
|
|
1649
|
+
function lowerBound(haystack, needle, index) {
|
|
1650
|
+
for (let i = index - 1; i >= 0; index = i--) {
|
|
1651
|
+
if (haystack[i][COLUMN] !== needle) break;
|
|
1652
|
+
}
|
|
1653
|
+
return index;
|
|
1654
|
+
}
|
|
1655
|
+
function memoizedState() {
|
|
1656
|
+
return {
|
|
1657
|
+
lastKey: -1,
|
|
1658
|
+
lastNeedle: -1,
|
|
1659
|
+
lastIndex: -1
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
function memoizedBinarySearch(haystack, needle, state, key) {
|
|
1663
|
+
const { lastKey, lastNeedle, lastIndex } = state;
|
|
1664
|
+
let low = 0;
|
|
1665
|
+
let high = haystack.length - 1;
|
|
1666
|
+
if (key === lastKey) {
|
|
1667
|
+
if (needle === lastNeedle) {
|
|
1668
|
+
found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
|
|
1669
|
+
return lastIndex;
|
|
1670
|
+
}
|
|
1671
|
+
if (needle >= lastNeedle) {
|
|
1672
|
+
low = lastIndex === -1 ? 0 : lastIndex;
|
|
1673
|
+
} else {
|
|
1674
|
+
high = lastIndex;
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
state.lastKey = key;
|
|
1678
|
+
state.lastNeedle = needle;
|
|
1679
|
+
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// src/types.ts
|
|
1683
|
+
function parse(map) {
|
|
1684
|
+
return typeof map === "string" ? JSON.parse(map) : map;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
// src/trace-mapping.ts
|
|
1688
|
+
var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
|
|
1689
|
+
var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
|
|
1690
|
+
var LEAST_UPPER_BOUND = -1;
|
|
1691
|
+
var GREATEST_LOWER_BOUND = 1;
|
|
1692
|
+
var TraceMap = class {
|
|
1693
|
+
constructor(map, mapUrl) {
|
|
1694
|
+
const isString = typeof map === "string";
|
|
1695
|
+
if (!isString && map._decodedMemo) return map;
|
|
1696
|
+
const parsed = parse(map);
|
|
1697
|
+
const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
|
|
1698
|
+
this.version = version;
|
|
1699
|
+
this.file = file;
|
|
1700
|
+
this.names = names || [];
|
|
1701
|
+
this.sourceRoot = sourceRoot;
|
|
1702
|
+
this.sources = sources;
|
|
1703
|
+
this.sourcesContent = sourcesContent;
|
|
1704
|
+
this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
|
|
1705
|
+
const resolve = resolver(mapUrl, sourceRoot);
|
|
1706
|
+
this.resolvedSources = sources.map(resolve);
|
|
1707
|
+
const { mappings } = parsed;
|
|
1708
|
+
if (typeof mappings === "string") {
|
|
1709
|
+
this._encoded = mappings;
|
|
1710
|
+
this._decoded = void 0;
|
|
1711
|
+
} else if (Array.isArray(mappings)) {
|
|
1712
|
+
this._encoded = void 0;
|
|
1713
|
+
this._decoded = maybeSort(mappings, isString);
|
|
1714
|
+
} else if (parsed.sections) {
|
|
1715
|
+
throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
|
|
1716
|
+
} else {
|
|
1717
|
+
throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
|
|
1718
|
+
}
|
|
1719
|
+
this._decodedMemo = memoizedState();
|
|
1720
|
+
this._bySources = void 0;
|
|
1721
|
+
this._bySourceMemos = void 0;
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
function cast(map) {
|
|
1725
|
+
return map;
|
|
1726
|
+
}
|
|
1727
|
+
function decodedMappings(map) {
|
|
1728
|
+
var _a;
|
|
1729
|
+
return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
|
|
1730
|
+
}
|
|
1731
|
+
function originalPositionFor(map, needle) {
|
|
1732
|
+
let { line, column, bias } = needle;
|
|
1733
|
+
line--;
|
|
1734
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
1735
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
1736
|
+
const decoded = decodedMappings(map);
|
|
1737
|
+
if (line >= decoded.length) return OMapping(null, null, null, null);
|
|
1738
|
+
const segments = decoded[line];
|
|
1739
|
+
const index = traceSegmentInternal(
|
|
1740
|
+
segments,
|
|
1741
|
+
cast(map)._decodedMemo,
|
|
1742
|
+
line,
|
|
1743
|
+
column,
|
|
1744
|
+
bias || GREATEST_LOWER_BOUND
|
|
1745
|
+
);
|
|
1746
|
+
if (index === -1) return OMapping(null, null, null, null);
|
|
1747
|
+
const segment = segments[index];
|
|
1748
|
+
if (segment.length === 1) return OMapping(null, null, null, null);
|
|
1749
|
+
const { names, resolvedSources } = map;
|
|
1750
|
+
return OMapping(
|
|
1751
|
+
resolvedSources[segment[SOURCES_INDEX]],
|
|
1752
|
+
segment[SOURCE_LINE] + 1,
|
|
1753
|
+
segment[SOURCE_COLUMN],
|
|
1754
|
+
segment.length === 5 ? names[segment[NAMES_INDEX]] : null
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1757
|
+
function generatedPositionFor(map, needle) {
|
|
1758
|
+
const { source, line, column, bias } = needle;
|
|
1759
|
+
return generatedPosition(map, source, line, column, bias || GREATEST_LOWER_BOUND, false);
|
|
1760
|
+
}
|
|
1761
|
+
function eachMapping(map, cb) {
|
|
1762
|
+
const decoded = decodedMappings(map);
|
|
1763
|
+
const { names, resolvedSources } = map;
|
|
1764
|
+
for (let i = 0; i < decoded.length; i++) {
|
|
1765
|
+
const line = decoded[i];
|
|
1766
|
+
for (let j = 0; j < line.length; j++) {
|
|
1767
|
+
const seg = line[j];
|
|
1768
|
+
const generatedLine = i + 1;
|
|
1769
|
+
const generatedColumn = seg[0];
|
|
1770
|
+
let source = null;
|
|
1771
|
+
let originalLine = null;
|
|
1772
|
+
let originalColumn = null;
|
|
1773
|
+
let name = null;
|
|
1774
|
+
if (seg.length !== 1) {
|
|
1775
|
+
source = resolvedSources[seg[1]];
|
|
1776
|
+
originalLine = seg[2] + 1;
|
|
1777
|
+
originalColumn = seg[3];
|
|
1778
|
+
}
|
|
1779
|
+
if (seg.length === 5) name = names[seg[4]];
|
|
1780
|
+
cb({
|
|
1781
|
+
generatedLine,
|
|
1782
|
+
generatedColumn,
|
|
1783
|
+
source,
|
|
1784
|
+
originalLine,
|
|
1785
|
+
originalColumn,
|
|
1786
|
+
name
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
function OMapping(source, line, column, name) {
|
|
1792
|
+
return { source, line, column, name };
|
|
1793
|
+
}
|
|
1794
|
+
function GMapping(line, column) {
|
|
1795
|
+
return { line, column };
|
|
1796
|
+
}
|
|
1797
|
+
function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
1798
|
+
let index = memoizedBinarySearch(segments, column, memo, line);
|
|
1799
|
+
if (found) {
|
|
1800
|
+
index = (bias === LEAST_UPPER_BOUND ? upperBound : lowerBound)(segments, column, index);
|
|
1801
|
+
} else if (bias === LEAST_UPPER_BOUND) index++;
|
|
1802
|
+
if (index === -1 || index === segments.length) return -1;
|
|
1803
|
+
return index;
|
|
1804
|
+
}
|
|
1805
|
+
function generatedPosition(map, source, line, column, bias, all) {
|
|
1806
|
+
var _a, _b;
|
|
1807
|
+
line--;
|
|
1808
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
1809
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
1810
|
+
const { sources, resolvedSources } = map;
|
|
1811
|
+
let sourceIndex2 = sources.indexOf(source);
|
|
1812
|
+
if (sourceIndex2 === -1) sourceIndex2 = resolvedSources.indexOf(source);
|
|
1813
|
+
if (sourceIndex2 === -1) return all ? [] : GMapping(null, null);
|
|
1814
|
+
const bySourceMemos = (_a = cast(map))._bySourceMemos || (_a._bySourceMemos = sources.map(memoizedState));
|
|
1815
|
+
const generated = (_b = cast(map))._bySources || (_b._bySources = buildBySources(decodedMappings(map), bySourceMemos));
|
|
1816
|
+
const segments = generated[sourceIndex2][line];
|
|
1817
|
+
if (segments == null) return all ? [] : GMapping(null, null);
|
|
1818
|
+
const memo = bySourceMemos[sourceIndex2];
|
|
1819
|
+
const index = traceSegmentInternal(segments, memo, line, column, bias);
|
|
1820
|
+
if (index === -1) return GMapping(null, null);
|
|
1821
|
+
const segment = segments[index];
|
|
1822
|
+
return GMapping(segment[REV_GENERATED_LINE] + 1, segment[REV_GENERATED_COLUMN]);
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
// AST walker module for ESTree compatible trees
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
// An ancestor walk keeps an array of ancestor nodes (including the
|
|
1829
|
+
// current node) and passes them to the callback as third parameter
|
|
1830
|
+
// (and also as state parameter when no other state is present).
|
|
1831
|
+
function ancestor(node, visitors, baseVisitor, state, override) {
|
|
1832
|
+
var ancestors = [];
|
|
1833
|
+
if (!baseVisitor) { baseVisitor = base
|
|
1834
|
+
; }(function c(node, st, override) {
|
|
1835
|
+
var type = override || node.type;
|
|
1836
|
+
var isNew = node !== ancestors[ancestors.length - 1];
|
|
1837
|
+
if (isNew) { ancestors.push(node); }
|
|
1838
|
+
baseVisitor[type](node, st, c);
|
|
1839
|
+
if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); }
|
|
1840
|
+
if (isNew) { ancestors.pop(); }
|
|
1841
|
+
})(node, state, override);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
function skipThrough(node, st, c) { c(node, st); }
|
|
1845
|
+
function ignore(_node, _st, _c) {}
|
|
1846
|
+
|
|
1847
|
+
// Node walkers.
|
|
1848
|
+
|
|
1849
|
+
var base = {};
|
|
1850
|
+
|
|
1851
|
+
base.Program = base.BlockStatement = base.StaticBlock = function (node, st, c) {
|
|
1852
|
+
for (var i = 0, list = node.body; i < list.length; i += 1)
|
|
1853
|
+
{
|
|
1854
|
+
var stmt = list[i];
|
|
1855
|
+
|
|
1856
|
+
c(stmt, st, "Statement");
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
base.Statement = skipThrough;
|
|
1860
|
+
base.EmptyStatement = ignore;
|
|
1861
|
+
base.ExpressionStatement = base.ParenthesizedExpression = base.ChainExpression =
|
|
1862
|
+
function (node, st, c) { return c(node.expression, st, "Expression"); };
|
|
1863
|
+
base.IfStatement = function (node, st, c) {
|
|
1864
|
+
c(node.test, st, "Expression");
|
|
1865
|
+
c(node.consequent, st, "Statement");
|
|
1866
|
+
if (node.alternate) { c(node.alternate, st, "Statement"); }
|
|
1867
|
+
};
|
|
1868
|
+
base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); };
|
|
1869
|
+
base.BreakStatement = base.ContinueStatement = ignore;
|
|
1870
|
+
base.WithStatement = function (node, st, c) {
|
|
1871
|
+
c(node.object, st, "Expression");
|
|
1872
|
+
c(node.body, st, "Statement");
|
|
1873
|
+
};
|
|
1874
|
+
base.SwitchStatement = function (node, st, c) {
|
|
1875
|
+
c(node.discriminant, st, "Expression");
|
|
1876
|
+
for (var i = 0, list = node.cases; i < list.length; i += 1) {
|
|
1877
|
+
var cs = list[i];
|
|
1878
|
+
|
|
1879
|
+
c(cs, st);
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
base.SwitchCase = function (node, st, c) {
|
|
1883
|
+
if (node.test) { c(node.test, st, "Expression"); }
|
|
1884
|
+
for (var i = 0, list = node.consequent; i < list.length; i += 1)
|
|
1885
|
+
{
|
|
1886
|
+
var cons = list[i];
|
|
1887
|
+
|
|
1888
|
+
c(cons, st, "Statement");
|
|
1889
|
+
}
|
|
1890
|
+
};
|
|
1891
|
+
base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {
|
|
1892
|
+
if (node.argument) { c(node.argument, st, "Expression"); }
|
|
1893
|
+
};
|
|
1894
|
+
base.ThrowStatement = base.SpreadElement =
|
|
1895
|
+
function (node, st, c) { return c(node.argument, st, "Expression"); };
|
|
1896
|
+
base.TryStatement = function (node, st, c) {
|
|
1897
|
+
c(node.block, st, "Statement");
|
|
1898
|
+
if (node.handler) { c(node.handler, st); }
|
|
1899
|
+
if (node.finalizer) { c(node.finalizer, st, "Statement"); }
|
|
1900
|
+
};
|
|
1901
|
+
base.CatchClause = function (node, st, c) {
|
|
1902
|
+
if (node.param) { c(node.param, st, "Pattern"); }
|
|
1903
|
+
c(node.body, st, "Statement");
|
|
1904
|
+
};
|
|
1905
|
+
base.WhileStatement = base.DoWhileStatement = function (node, st, c) {
|
|
1906
|
+
c(node.test, st, "Expression");
|
|
1907
|
+
c(node.body, st, "Statement");
|
|
1908
|
+
};
|
|
1909
|
+
base.ForStatement = function (node, st, c) {
|
|
1910
|
+
if (node.init) { c(node.init, st, "ForInit"); }
|
|
1911
|
+
if (node.test) { c(node.test, st, "Expression"); }
|
|
1912
|
+
if (node.update) { c(node.update, st, "Expression"); }
|
|
1913
|
+
c(node.body, st, "Statement");
|
|
1914
|
+
};
|
|
1915
|
+
base.ForInStatement = base.ForOfStatement = function (node, st, c) {
|
|
1916
|
+
c(node.left, st, "ForInit");
|
|
1917
|
+
c(node.right, st, "Expression");
|
|
1918
|
+
c(node.body, st, "Statement");
|
|
1919
|
+
};
|
|
1920
|
+
base.ForInit = function (node, st, c) {
|
|
1921
|
+
if (node.type === "VariableDeclaration") { c(node, st); }
|
|
1922
|
+
else { c(node, st, "Expression"); }
|
|
1923
|
+
};
|
|
1924
|
+
base.DebuggerStatement = ignore;
|
|
1925
|
+
|
|
1926
|
+
base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); };
|
|
1927
|
+
base.VariableDeclaration = function (node, st, c) {
|
|
1928
|
+
for (var i = 0, list = node.declarations; i < list.length; i += 1)
|
|
1929
|
+
{
|
|
1930
|
+
var decl = list[i];
|
|
1931
|
+
|
|
1932
|
+
c(decl, st);
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
base.VariableDeclarator = function (node, st, c) {
|
|
1936
|
+
c(node.id, st, "Pattern");
|
|
1937
|
+
if (node.init) { c(node.init, st, "Expression"); }
|
|
1938
|
+
};
|
|
1939
|
+
|
|
1940
|
+
base.Function = function (node, st, c) {
|
|
1941
|
+
if (node.id) { c(node.id, st, "Pattern"); }
|
|
1942
|
+
for (var i = 0, list = node.params; i < list.length; i += 1)
|
|
1943
|
+
{
|
|
1944
|
+
var param = list[i];
|
|
1945
|
+
|
|
1946
|
+
c(param, st, "Pattern");
|
|
1947
|
+
}
|
|
1948
|
+
c(node.body, st, node.expression ? "Expression" : "Statement");
|
|
1949
|
+
};
|
|
1950
|
+
|
|
1951
|
+
base.Pattern = function (node, st, c) {
|
|
1952
|
+
if (node.type === "Identifier")
|
|
1953
|
+
{ c(node, st, "VariablePattern"); }
|
|
1954
|
+
else if (node.type === "MemberExpression")
|
|
1955
|
+
{ c(node, st, "MemberPattern"); }
|
|
1956
|
+
else
|
|
1957
|
+
{ c(node, st); }
|
|
1958
|
+
};
|
|
1959
|
+
base.VariablePattern = ignore;
|
|
1960
|
+
base.MemberPattern = skipThrough;
|
|
1961
|
+
base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); };
|
|
1962
|
+
base.ArrayPattern = function (node, st, c) {
|
|
1963
|
+
for (var i = 0, list = node.elements; i < list.length; i += 1) {
|
|
1964
|
+
var elt = list[i];
|
|
1965
|
+
|
|
1966
|
+
if (elt) { c(elt, st, "Pattern"); }
|
|
1967
|
+
}
|
|
1968
|
+
};
|
|
1969
|
+
base.ObjectPattern = function (node, st, c) {
|
|
1970
|
+
for (var i = 0, list = node.properties; i < list.length; i += 1) {
|
|
1971
|
+
var prop = list[i];
|
|
1972
|
+
|
|
1973
|
+
if (prop.type === "Property") {
|
|
1974
|
+
if (prop.computed) { c(prop.key, st, "Expression"); }
|
|
1975
|
+
c(prop.value, st, "Pattern");
|
|
1976
|
+
} else if (prop.type === "RestElement") {
|
|
1977
|
+
c(prop.argument, st, "Pattern");
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
};
|
|
1981
|
+
|
|
1982
|
+
base.Expression = skipThrough;
|
|
1983
|
+
base.ThisExpression = base.Super = base.MetaProperty = ignore;
|
|
1984
|
+
base.ArrayExpression = function (node, st, c) {
|
|
1985
|
+
for (var i = 0, list = node.elements; i < list.length; i += 1) {
|
|
1986
|
+
var elt = list[i];
|
|
1987
|
+
|
|
1988
|
+
if (elt) { c(elt, st, "Expression"); }
|
|
1989
|
+
}
|
|
1990
|
+
};
|
|
1991
|
+
base.ObjectExpression = function (node, st, c) {
|
|
1992
|
+
for (var i = 0, list = node.properties; i < list.length; i += 1)
|
|
1993
|
+
{
|
|
1994
|
+
var prop = list[i];
|
|
1995
|
+
|
|
1996
|
+
c(prop, st);
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;
|
|
2000
|
+
base.SequenceExpression = function (node, st, c) {
|
|
2001
|
+
for (var i = 0, list = node.expressions; i < list.length; i += 1)
|
|
2002
|
+
{
|
|
2003
|
+
var expr = list[i];
|
|
2004
|
+
|
|
2005
|
+
c(expr, st, "Expression");
|
|
2006
|
+
}
|
|
2007
|
+
};
|
|
2008
|
+
base.TemplateLiteral = function (node, st, c) {
|
|
2009
|
+
for (var i = 0, list = node.quasis; i < list.length; i += 1)
|
|
2010
|
+
{
|
|
2011
|
+
var quasi = list[i];
|
|
2012
|
+
|
|
2013
|
+
c(quasi, st);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
for (var i$1 = 0, list$1 = node.expressions; i$1 < list$1.length; i$1 += 1)
|
|
2017
|
+
{
|
|
2018
|
+
var expr = list$1[i$1];
|
|
2019
|
+
|
|
2020
|
+
c(expr, st, "Expression");
|
|
2021
|
+
}
|
|
2022
|
+
};
|
|
2023
|
+
base.TemplateElement = ignore;
|
|
2024
|
+
base.UnaryExpression = base.UpdateExpression = function (node, st, c) {
|
|
2025
|
+
c(node.argument, st, "Expression");
|
|
2026
|
+
};
|
|
2027
|
+
base.BinaryExpression = base.LogicalExpression = function (node, st, c) {
|
|
2028
|
+
c(node.left, st, "Expression");
|
|
2029
|
+
c(node.right, st, "Expression");
|
|
2030
|
+
};
|
|
2031
|
+
base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {
|
|
2032
|
+
c(node.left, st, "Pattern");
|
|
2033
|
+
c(node.right, st, "Expression");
|
|
2034
|
+
};
|
|
2035
|
+
base.ConditionalExpression = function (node, st, c) {
|
|
2036
|
+
c(node.test, st, "Expression");
|
|
2037
|
+
c(node.consequent, st, "Expression");
|
|
2038
|
+
c(node.alternate, st, "Expression");
|
|
2039
|
+
};
|
|
2040
|
+
base.NewExpression = base.CallExpression = function (node, st, c) {
|
|
2041
|
+
c(node.callee, st, "Expression");
|
|
2042
|
+
if (node.arguments)
|
|
2043
|
+
{ for (var i = 0, list = node.arguments; i < list.length; i += 1)
|
|
2044
|
+
{
|
|
2045
|
+
var arg = list[i];
|
|
2046
|
+
|
|
2047
|
+
c(arg, st, "Expression");
|
|
2048
|
+
} }
|
|
2049
|
+
};
|
|
2050
|
+
base.MemberExpression = function (node, st, c) {
|
|
2051
|
+
c(node.object, st, "Expression");
|
|
2052
|
+
if (node.computed) { c(node.property, st, "Expression"); }
|
|
2053
|
+
};
|
|
2054
|
+
base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) {
|
|
2055
|
+
if (node.declaration)
|
|
2056
|
+
{ c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); }
|
|
2057
|
+
if (node.source) { c(node.source, st, "Expression"); }
|
|
2058
|
+
};
|
|
2059
|
+
base.ExportAllDeclaration = function (node, st, c) {
|
|
2060
|
+
if (node.exported)
|
|
2061
|
+
{ c(node.exported, st); }
|
|
2062
|
+
c(node.source, st, "Expression");
|
|
2063
|
+
};
|
|
2064
|
+
base.ImportDeclaration = function (node, st, c) {
|
|
2065
|
+
for (var i = 0, list = node.specifiers; i < list.length; i += 1)
|
|
2066
|
+
{
|
|
2067
|
+
var spec = list[i];
|
|
2068
|
+
|
|
2069
|
+
c(spec, st);
|
|
2070
|
+
}
|
|
2071
|
+
c(node.source, st, "Expression");
|
|
2072
|
+
};
|
|
2073
|
+
base.ImportExpression = function (node, st, c) {
|
|
2074
|
+
c(node.source, st, "Expression");
|
|
2075
|
+
};
|
|
2076
|
+
base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.PrivateIdentifier = base.Literal = ignore;
|
|
2077
|
+
|
|
2078
|
+
base.TaggedTemplateExpression = function (node, st, c) {
|
|
2079
|
+
c(node.tag, st, "Expression");
|
|
2080
|
+
c(node.quasi, st, "Expression");
|
|
2081
|
+
};
|
|
2082
|
+
base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); };
|
|
2083
|
+
base.Class = function (node, st, c) {
|
|
2084
|
+
if (node.id) { c(node.id, st, "Pattern"); }
|
|
2085
|
+
if (node.superClass) { c(node.superClass, st, "Expression"); }
|
|
2086
|
+
c(node.body, st);
|
|
2087
|
+
};
|
|
2088
|
+
base.ClassBody = function (node, st, c) {
|
|
2089
|
+
for (var i = 0, list = node.body; i < list.length; i += 1)
|
|
2090
|
+
{
|
|
2091
|
+
var elt = list[i];
|
|
2092
|
+
|
|
2093
|
+
c(elt, st);
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
base.MethodDefinition = base.PropertyDefinition = base.Property = function (node, st, c) {
|
|
2097
|
+
if (node.computed) { c(node.key, st, "Expression"); }
|
|
2098
|
+
if (node.value) { c(node.value, st, "Expression"); }
|
|
2099
|
+
};
|
|
2100
|
+
|
|
2101
|
+
async function collectTests(ctx, filepath) {
|
|
2102
|
+
const request = await ctx.vite.environments.ssr.transformRequest(filepath);
|
|
2103
|
+
if (!request) return null;
|
|
2104
|
+
const ast = await parseAstAsync(request.code), testFilepath = relative(ctx.config.root, filepath), projectName = ctx.name, typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : "__typecheck__", file = {
|
|
2105
|
+
filepath,
|
|
2106
|
+
type: "suite",
|
|
2107
|
+
id: generateHash(`${testFilepath}${typecheckSubprojectName}`),
|
|
2108
|
+
name: testFilepath,
|
|
2109
|
+
mode: "run",
|
|
2110
|
+
tasks: [],
|
|
2111
|
+
start: ast.start,
|
|
2112
|
+
end: ast.end,
|
|
2113
|
+
projectName,
|
|
2114
|
+
meta: { typecheck: true },
|
|
2115
|
+
file: null
|
|
2116
|
+
};
|
|
2117
|
+
file.file = file;
|
|
2118
|
+
const definitions = [], getName = (callee) => {
|
|
2119
|
+
if (!callee) return null;
|
|
2120
|
+
if (callee.type === "Identifier") return callee.name;
|
|
2121
|
+
if (callee.type === "CallExpression") return getName(callee.callee);
|
|
2122
|
+
if (callee.type === "TaggedTemplateExpression") return getName(callee.tag);
|
|
2123
|
+
if (callee.type === "MemberExpression")
|
|
2124
|
+
// call as `__vite_ssr__.test.skip()`
|
|
2125
|
+
return callee.object?.type === "Identifier" && [
|
|
2126
|
+
"it",
|
|
2127
|
+
"test",
|
|
2128
|
+
"describe",
|
|
2129
|
+
"suite"
|
|
2130
|
+
].includes(callee.object.name) ? callee.object?.name : callee.object?.name?.startsWith("__vite_ssr_") ? getName(callee.property) : getName(callee.object?.property);
|
|
2131
|
+
// unwrap (0, ...)
|
|
2132
|
+
if (callee.type === "SequenceExpression" && callee.expressions.length === 2) {
|
|
2133
|
+
const [e0, e1] = callee.expressions;
|
|
2134
|
+
if (e0.type === "Literal" && e0.value === 0) return getName(e1);
|
|
2135
|
+
}
|
|
2136
|
+
return null;
|
|
2137
|
+
};
|
|
2138
|
+
ancestor(ast, { CallExpression(node) {
|
|
2139
|
+
const { callee } = node, name = getName(callee);
|
|
2140
|
+
if (!name || ![
|
|
2141
|
+
"it",
|
|
2142
|
+
"test",
|
|
2143
|
+
"describe",
|
|
2144
|
+
"suite"
|
|
2145
|
+
].includes(name)) return;
|
|
2146
|
+
const property = callee?.property?.name;
|
|
2147
|
+
let mode = !property || property === name ? "run" : property;
|
|
2148
|
+
// they will be picked up in the next iteration
|
|
2149
|
+
if ([
|
|
2150
|
+
"each",
|
|
2151
|
+
"for",
|
|
2152
|
+
"skipIf",
|
|
2153
|
+
"runIf"
|
|
2154
|
+
].includes(mode)) return;
|
|
2155
|
+
let start;
|
|
2156
|
+
const end = node.end;
|
|
2157
|
+
// .each
|
|
2158
|
+
if (callee.type === "CallExpression") start = callee.end;
|
|
2159
|
+
else if (callee.type === "TaggedTemplateExpression") start = callee.end + 1;
|
|
2160
|
+
else start = node.start;
|
|
2161
|
+
const { arguments: [messageNode] } = node, message = messageNode?.type === "Literal" || messageNode?.type === "TemplateLiteral" ? request.code.slice(messageNode.start + 1, messageNode.end - 1) : request.code.slice(messageNode.start, messageNode.end);
|
|
2162
|
+
// cannot statically analyze, so we always skip it
|
|
2163
|
+
if (mode === "skipIf" || mode === "runIf") mode = "skip";
|
|
2164
|
+
definitions.push({
|
|
2165
|
+
start,
|
|
2166
|
+
end,
|
|
2167
|
+
name: message,
|
|
2168
|
+
type: name === "it" || name === "test" ? "test" : "suite",
|
|
2169
|
+
mode,
|
|
2170
|
+
task: null
|
|
2171
|
+
});
|
|
2172
|
+
} });
|
|
2173
|
+
let lastSuite = file;
|
|
2174
|
+
const updateLatestSuite = (index) => {
|
|
2175
|
+
while (lastSuite.suite && lastSuite.end < index) lastSuite = lastSuite.suite;
|
|
2176
|
+
return lastSuite;
|
|
2177
|
+
};
|
|
2178
|
+
definitions.sort((a, b) => a.start - b.start).forEach((definition) => {
|
|
2179
|
+
const latestSuite = updateLatestSuite(definition.start);
|
|
2180
|
+
let mode = definition.mode;
|
|
2181
|
+
if (latestSuite.mode !== "run")
|
|
2182
|
+
// inherit suite mode, if it's set
|
|
2183
|
+
mode = latestSuite.mode;
|
|
2184
|
+
if (definition.type === "suite") {
|
|
2185
|
+
const task = {
|
|
2186
|
+
type: definition.type,
|
|
2187
|
+
id: "",
|
|
2188
|
+
suite: latestSuite,
|
|
2189
|
+
file,
|
|
2190
|
+
tasks: [],
|
|
2191
|
+
mode,
|
|
2192
|
+
name: definition.name,
|
|
2193
|
+
end: definition.end,
|
|
2194
|
+
start: definition.start,
|
|
2195
|
+
meta: { typecheck: true }
|
|
2196
|
+
};
|
|
2197
|
+
definition.task = task, latestSuite.tasks.push(task), lastSuite = task;
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
const task = {
|
|
2201
|
+
type: definition.type,
|
|
2202
|
+
id: "",
|
|
2203
|
+
suite: latestSuite,
|
|
2204
|
+
file,
|
|
2205
|
+
mode,
|
|
2206
|
+
timeout: 0,
|
|
2207
|
+
context: {},
|
|
2208
|
+
name: definition.name,
|
|
2209
|
+
end: definition.end,
|
|
2210
|
+
start: definition.start,
|
|
2211
|
+
annotations: [],
|
|
2212
|
+
meta: { typecheck: true }
|
|
2213
|
+
};
|
|
2214
|
+
definition.task = task, latestSuite.tasks.push(task);
|
|
2215
|
+
}), calculateSuiteHash(file);
|
|
2216
|
+
const hasOnly = someTasksAreOnly(file);
|
|
2217
|
+
return interpretTaskModes(file, ctx.config.testNamePattern, void 0, hasOnly, false, ctx.config.allowOnly), {
|
|
2218
|
+
file,
|
|
2219
|
+
parsed: request.code,
|
|
2220
|
+
filepath,
|
|
2221
|
+
map: request.map,
|
|
2222
|
+
definitions
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
const newLineRegExp = /\r?\n/, errCodeRegExp = /error TS(?<errCode>\d+)/;
|
|
2227
|
+
async function makeTscErrorInfo(errInfo) {
|
|
2228
|
+
const [errFilePathPos = "", ...errMsgRawArr] = errInfo.split(":");
|
|
2229
|
+
if (!errFilePathPos || errMsgRawArr.length === 0 || errMsgRawArr.join("").length === 0) return ["unknown filepath", null];
|
|
2230
|
+
const errMsgRaw = errMsgRawArr.join("").trim(), [errFilePath, errPos] = errFilePathPos.slice(0, -1).split("(");
|
|
2231
|
+
if (!errFilePath || !errPos) return ["unknown filepath", null];
|
|
2232
|
+
const [errLine, errCol] = errPos.split(",");
|
|
2233
|
+
if (!errLine || !errCol) return [errFilePath, null];
|
|
2234
|
+
// get errCode, errMsg
|
|
2235
|
+
const execArr = errCodeRegExp.exec(errMsgRaw);
|
|
2236
|
+
if (!execArr) return [errFilePath, null];
|
|
2237
|
+
const errCodeStr = execArr.groups?.errCode ?? "";
|
|
2238
|
+
if (!errCodeStr) return [errFilePath, null];
|
|
2239
|
+
const line = Number(errLine), col = Number(errCol), errCode = Number(errCodeStr);
|
|
2240
|
+
return [errFilePath, {
|
|
2241
|
+
filePath: errFilePath,
|
|
2242
|
+
errCode,
|
|
2243
|
+
line,
|
|
2244
|
+
column: col,
|
|
2245
|
+
errMsg: errMsgRaw.slice(`error TS${errCode} `.length)
|
|
2246
|
+
}];
|
|
2247
|
+
}
|
|
2248
|
+
async function getRawErrsMapFromTsCompile(tscErrorStdout) {
|
|
2249
|
+
const rawErrsMap = /* @__PURE__ */ new Map();
|
|
2250
|
+
return (await Promise.all(tscErrorStdout.split(newLineRegExp).reduce((prev, next) => {
|
|
2251
|
+
if (!next) return prev;
|
|
2252
|
+
if (next[0] !== " ") prev.push(next);
|
|
2253
|
+
else prev[prev.length - 1] += `\n${next}`;
|
|
2254
|
+
return prev;
|
|
2255
|
+
}, []).map((errInfoLine) => makeTscErrorInfo(errInfoLine)))).forEach(([errFilePath, errInfo]) => {
|
|
2256
|
+
if (errInfo) if (!rawErrsMap.has(errFilePath)) rawErrsMap.set(errFilePath, [errInfo]);
|
|
2257
|
+
else rawErrsMap.get(errFilePath)?.push(errInfo);
|
|
2258
|
+
}), rawErrsMap;
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
function createIndexMap(source) {
|
|
2262
|
+
const map = /* @__PURE__ */ new Map();
|
|
2263
|
+
let index = 0, line = 1, column = 1;
|
|
2264
|
+
for (const char of source) if (map.set(`${line}:${column}`, index++), char === "\n" || char === "\r\n") line++, column = 0;
|
|
2265
|
+
else column++;
|
|
2266
|
+
return map;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
class TypeCheckError extends Error {
|
|
2270
|
+
name = "TypeCheckError";
|
|
2271
|
+
constructor(message, stacks) {
|
|
2272
|
+
super(message), this.message = message, this.stacks = stacks;
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
class Typechecker {
|
|
2276
|
+
_onParseStart;
|
|
2277
|
+
_onParseEnd;
|
|
2278
|
+
_onWatcherRerun;
|
|
2279
|
+
_result = {
|
|
2280
|
+
files: [],
|
|
2281
|
+
sourceErrors: [],
|
|
2282
|
+
time: 0
|
|
2283
|
+
};
|
|
2284
|
+
_startTime = 0;
|
|
2285
|
+
_output = "";
|
|
2286
|
+
_tests = {};
|
|
2287
|
+
process;
|
|
2288
|
+
files = [];
|
|
2289
|
+
constructor(project) {
|
|
2290
|
+
this.project = project;
|
|
2291
|
+
}
|
|
2292
|
+
setFiles(files) {
|
|
2293
|
+
this.files = files;
|
|
2294
|
+
}
|
|
2295
|
+
onParseStart(fn) {
|
|
2296
|
+
this._onParseStart = fn;
|
|
2297
|
+
}
|
|
2298
|
+
onParseEnd(fn) {
|
|
2299
|
+
this._onParseEnd = fn;
|
|
2300
|
+
}
|
|
2301
|
+
onWatcherRerun(fn) {
|
|
2302
|
+
this._onWatcherRerun = fn;
|
|
2303
|
+
}
|
|
2304
|
+
async collectFileTests(filepath) {
|
|
2305
|
+
return collectTests(this.project, filepath);
|
|
2306
|
+
}
|
|
2307
|
+
getFiles() {
|
|
2308
|
+
return this.files;
|
|
2309
|
+
}
|
|
2310
|
+
async collectTests() {
|
|
2311
|
+
const tests = (await Promise.all(this.getFiles().map((filepath) => this.collectFileTests(filepath)))).reduce((acc, data) => {
|
|
2312
|
+
return data && (acc[data.filepath] = data), acc;
|
|
2313
|
+
}, {});
|
|
2314
|
+
return this._tests = tests, tests;
|
|
2315
|
+
}
|
|
2316
|
+
markPassed(file) {
|
|
2317
|
+
if (!file.result?.state) file.result = { state: "pass" };
|
|
2318
|
+
const markTasks = (tasks) => {
|
|
2319
|
+
for (const task of tasks) {
|
|
2320
|
+
if ("tasks" in task) markTasks(task.tasks);
|
|
2321
|
+
if (!task.result?.state && (task.mode === "run" || task.mode === "queued")) task.result = { state: "pass" };
|
|
2322
|
+
}
|
|
2323
|
+
};
|
|
2324
|
+
markTasks(file.tasks);
|
|
2325
|
+
}
|
|
2326
|
+
async prepareResults(output) {
|
|
2327
|
+
const typeErrors = await this.parseTscLikeOutput(output), testFiles = new Set(this.getFiles());
|
|
2328
|
+
if (!this._tests) this._tests = await this.collectTests();
|
|
2329
|
+
const sourceErrors = [], files = [];
|
|
2330
|
+
return testFiles.forEach((path) => {
|
|
2331
|
+
const { file, definitions, map, parsed } = this._tests[path], errors = typeErrors.get(path);
|
|
2332
|
+
if (files.push(file), !errors) {
|
|
2333
|
+
this.markPassed(file);
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2336
|
+
const sortedDefinitions = [...definitions.sort((a, b) => b.start - a.start)], traceMap = map && new TraceMap(map), indexMap = createIndexMap(parsed), markState = (task, state) => {
|
|
2337
|
+
if (task.result = { state: task.mode === "run" || task.mode === "only" ? state : task.mode }, task.suite) markState(task.suite, state);
|
|
2338
|
+
else if (task.file && task !== task.file) markState(task.file, state);
|
|
2339
|
+
};
|
|
2340
|
+
errors.forEach(({ error, originalError }) => {
|
|
2341
|
+
const processedPos = traceMap ? findGeneratedPosition(traceMap, {
|
|
2342
|
+
line: originalError.line,
|
|
2343
|
+
column: originalError.column,
|
|
2344
|
+
source: basename(path)
|
|
2345
|
+
}) : 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 || [];
|
|
2346
|
+
if (suite.result = {
|
|
2347
|
+
state,
|
|
2348
|
+
errors
|
|
2349
|
+
}, errors.push(error), state === "fail") {
|
|
2350
|
+
if (suite.suite) markState(suite.suite, "fail");
|
|
2351
|
+
else if (suite.file && suite !== suite.file) markState(suite.file, "fail");
|
|
2352
|
+
}
|
|
2353
|
+
}), this.markPassed(file);
|
|
2354
|
+
}), typeErrors.forEach((errors, path) => {
|
|
2355
|
+
if (!testFiles.has(path)) sourceErrors.push(...errors.map(({ error }) => error));
|
|
2356
|
+
}), {
|
|
2357
|
+
files,
|
|
2358
|
+
sourceErrors,
|
|
2359
|
+
time: performance$1.now() - this._startTime
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
async parseTscLikeOutput(output) {
|
|
2363
|
+
const errorsMap = await getRawErrsMapFromTsCompile(output), typesErrors = /* @__PURE__ */ new Map();
|
|
2364
|
+
return errorsMap.forEach((errors, path) => {
|
|
2365
|
+
const filepath = resolve$1(this.project.config.root, path), suiteErrors = errors.map((info) => {
|
|
2366
|
+
const limit = Error.stackTraceLimit;
|
|
2367
|
+
Error.stackTraceLimit = 0;
|
|
2368
|
+
// 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.`
|
|
2369
|
+
const errMsg = info.errMsg.replace(/\r?\n\s*(Type .* has no call signatures)/g, " $1"), error = new TypeCheckError(errMsg, [{
|
|
2370
|
+
file: filepath,
|
|
2371
|
+
line: info.line,
|
|
2372
|
+
column: info.column,
|
|
2373
|
+
method: ""
|
|
2374
|
+
}]);
|
|
2375
|
+
return Error.stackTraceLimit = limit, {
|
|
2376
|
+
originalError: info,
|
|
2377
|
+
error: {
|
|
2378
|
+
name: error.name,
|
|
2379
|
+
message: errMsg,
|
|
2380
|
+
stacks: error.stacks,
|
|
2381
|
+
stack: ""
|
|
2382
|
+
}
|
|
2383
|
+
};
|
|
2384
|
+
});
|
|
2385
|
+
typesErrors.set(filepath, suiteErrors);
|
|
2386
|
+
}), typesErrors;
|
|
2387
|
+
}
|
|
2388
|
+
async stop() {
|
|
2389
|
+
this.process?.kill(), this.process = void 0;
|
|
2390
|
+
}
|
|
2391
|
+
async ensurePackageInstalled(ctx, checker) {
|
|
2392
|
+
if (checker !== "tsc" && checker !== "vue-tsc") return;
|
|
2393
|
+
const packageName = checker === "tsc" ? "typescript" : "vue-tsc";
|
|
2394
|
+
await ctx.packageInstaller.ensureInstalled(packageName, ctx.config.root);
|
|
2395
|
+
}
|
|
2396
|
+
getExitCode() {
|
|
2397
|
+
return this.process?.exitCode != null && this.process.exitCode;
|
|
2398
|
+
}
|
|
2399
|
+
getOutput() {
|
|
2400
|
+
return this._output;
|
|
2401
|
+
}
|
|
2402
|
+
async spawn() {
|
|
2403
|
+
const { root, watch, typecheck } = this.project.config, args = [
|
|
2404
|
+
"--noEmit",
|
|
2405
|
+
"--pretty",
|
|
2406
|
+
"false",
|
|
2407
|
+
"--incremental",
|
|
2408
|
+
"--tsBuildInfoFile",
|
|
2409
|
+
join(process.versions.pnp ? join(nodeos__default.tmpdir(), this.project.hash) : distDir, "tsconfig.tmp.tsbuildinfo")
|
|
2410
|
+
];
|
|
2411
|
+
// use builtin watcher because it's faster
|
|
2412
|
+
if (watch) args.push("--watch");
|
|
2413
|
+
if (typecheck.allowJs) args.push("--allowJs", "--checkJs");
|
|
2414
|
+
if (typecheck.tsconfig) args.push("-p", resolve$1(root, typecheck.tsconfig));
|
|
2415
|
+
this._output = "", this._startTime = performance$1.now();
|
|
2416
|
+
const child = x(typecheck.checker, args, {
|
|
2417
|
+
nodeOptions: {
|
|
2418
|
+
cwd: root,
|
|
2419
|
+
stdio: "pipe"
|
|
2420
|
+
},
|
|
2421
|
+
throwOnError: false
|
|
2422
|
+
});
|
|
2423
|
+
this.process = child.process;
|
|
2424
|
+
let rerunTriggered = false, dataReceived = false;
|
|
2425
|
+
return new Promise((resolve, reject) => {
|
|
2426
|
+
if (!child.process || !child.process.stdout) {
|
|
2427
|
+
reject(/* @__PURE__ */ new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`));
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
child.process.stdout.on("data", (chunk) => {
|
|
2431
|
+
if (dataReceived = true, this._output += chunk, watch) {
|
|
2432
|
+
if (this._output.includes("File change detected") && !rerunTriggered) this._onWatcherRerun?.(), this._startTime = performance$1.now(), this._result.sourceErrors = [], this._result.files = [], this._tests = null, rerunTriggered = true;
|
|
2433
|
+
if (/Found \w+ errors*. Watching for/.test(this._output)) rerunTriggered = false, this.prepareResults(this._output).then((result) => {
|
|
2434
|
+
this._result = result, this._onParseEnd?.(result);
|
|
2435
|
+
}), this._output = "";
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
const timeout = setTimeout(() => reject(/* @__PURE__ */ new Error(`${typecheck.checker} spawn timed out`)), this.project.config.typecheck.spawnTimeout);
|
|
2439
|
+
function onError(cause) {
|
|
2440
|
+
clearTimeout(timeout), reject(new Error("Spawning typechecker failed - is typescript installed?", { cause }));
|
|
2441
|
+
}
|
|
2442
|
+
if (child.process.once("spawn", () => {
|
|
2443
|
+
if (this._onParseStart?.(), child.process?.off("error", onError), clearTimeout(timeout), process.platform === "win32")
|
|
2444
|
+
// on Windows, the process might be spawned but fail to start
|
|
2445
|
+
// we wait for a potential error here. if "close" event didn't trigger,
|
|
2446
|
+
// we resolve the promise
|
|
2447
|
+
setTimeout(() => {
|
|
2448
|
+
resolve({ result: child });
|
|
2449
|
+
}, 200);
|
|
2450
|
+
else resolve({ result: child });
|
|
2451
|
+
}), process.platform === "win32") child.process.once("close", (code) => {
|
|
2452
|
+
if (code != null && code !== 0 && !dataReceived) onError(/* @__PURE__ */ new Error(`The ${typecheck.checker} command exited with code ${code}.`));
|
|
2453
|
+
});
|
|
2454
|
+
child.process.once("error", onError);
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
async start() {
|
|
2458
|
+
if (this.process) return;
|
|
2459
|
+
const { watch } = this.project.config, { result: child } = await this.spawn();
|
|
2460
|
+
if (!watch) await child, this._result = await this.prepareResults(this._output), await this._onParseEnd?.(this._result);
|
|
2461
|
+
}
|
|
2462
|
+
getResult() {
|
|
2463
|
+
return this._result;
|
|
2464
|
+
}
|
|
2465
|
+
getTestFiles() {
|
|
2466
|
+
return Object.values(this._tests || {}).map((i) => i.file);
|
|
2467
|
+
}
|
|
2468
|
+
getTestPacksAndEvents() {
|
|
2469
|
+
const packs = [], events = [];
|
|
2470
|
+
for (const { file } of Object.values(this._tests || {})) {
|
|
2471
|
+
const result = convertTasksToEvents(file);
|
|
2472
|
+
packs.push(...result.packs), events.push(...result.events);
|
|
2473
|
+
}
|
|
2474
|
+
return {
|
|
2475
|
+
packs,
|
|
2476
|
+
events
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
function findGeneratedPosition(traceMap, { line, column, source }) {
|
|
2481
|
+
const found = generatedPositionFor(traceMap, {
|
|
2482
|
+
line,
|
|
2483
|
+
column,
|
|
2484
|
+
source
|
|
2485
|
+
});
|
|
2486
|
+
if (found.line !== null) return found;
|
|
2487
|
+
// find the next source token position when the exact error position doesn't exist in source map.
|
|
2488
|
+
// this can happen, for example, when the type error is in the comment "// @ts-expect-error"
|
|
2489
|
+
// and comments are stripped away in the generated code.
|
|
2490
|
+
const mappings = [];
|
|
2491
|
+
eachMapping(traceMap, (m) => {
|
|
2492
|
+
if (m.source === source && m.originalLine !== null && m.originalColumn !== null && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)) mappings.push(m);
|
|
2493
|
+
});
|
|
2494
|
+
const next = mappings.sort((a, b) => a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine).at(0);
|
|
2495
|
+
return next ? {
|
|
2496
|
+
line: next.generatedLine,
|
|
2497
|
+
column: next.generatedColumn
|
|
2498
|
+
} : {
|
|
2499
|
+
line: null,
|
|
2500
|
+
column: null
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
|
|
1100
2504
|
// use Logger with custom Console to capture entire error printing
|
|
1101
2505
|
function capturePrintError(error, ctx, options) {
|
|
1102
2506
|
let output = "";
|
|
@@ -1105,12 +2509,12 @@ function capturePrintError(error, ctx, options) {
|
|
|
1105
2509
|
} }), console = new Console(writable), logger = {
|
|
1106
2510
|
error: console.error.bind(console),
|
|
1107
2511
|
highlight: ctx.logger.highlight.bind(ctx.logger)
|
|
1108
|
-
}
|
|
1109
|
-
showCodeFrame: false,
|
|
1110
|
-
...options
|
|
1111
|
-
});
|
|
2512
|
+
};
|
|
1112
2513
|
return {
|
|
1113
|
-
nearest:
|
|
2514
|
+
nearest: printError(error, ctx, logger, {
|
|
2515
|
+
showCodeFrame: false,
|
|
2516
|
+
...options
|
|
2517
|
+
})?.nearest,
|
|
1114
2518
|
output
|
|
1115
2519
|
};
|
|
1116
2520
|
}
|
|
@@ -1158,19 +2562,17 @@ function printErrorInner(error, project, options) {
|
|
|
1158
2562
|
const stacks = options.parseErrorStacktrace(e), nearest = error instanceof TypeCheckError ? error.stacks[0] : stacks.find((stack) => {
|
|
1159
2563
|
// we are checking that this module was processed by us at one point
|
|
1160
2564
|
try {
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
});
|
|
1165
|
-
return hasResult && existsSync(stack.file);
|
|
2565
|
+
return [...Object.values(project._vite?.environments || {}), ...Object.values(project.browser?.vite.environments || {})].some((environment) => {
|
|
2566
|
+
return [...environment.moduleGraph.getModulesByFile(stack.file)?.values() || []].some((module) => !!module.transformResult);
|
|
2567
|
+
}) && existsSync(stack.file);
|
|
1166
2568
|
} catch {
|
|
1167
2569
|
return false;
|
|
1168
2570
|
}
|
|
1169
2571
|
});
|
|
1170
2572
|
if (type) printErrorType(type, project.vitest);
|
|
1171
2573
|
if (printErrorMessage(e, logger), options.screenshotPaths?.length) {
|
|
1172
|
-
const
|
|
1173
|
-
if (logger.error(`\nFailure screenshot${length > 1 ? "s" : ""}:`), logger.error(
|
|
2574
|
+
const uniqueScreenshots = Array.from(new Set(options.screenshotPaths)), length = uniqueScreenshots.length;
|
|
2575
|
+
if (logger.error(`\nFailure screenshot${length > 1 ? "s" : ""}:`), logger.error(uniqueScreenshots.map((p) => ` - ${c.dim(relative(process.cwd(), p))}`).join("\n")), !e.diff) logger.error();
|
|
1174
2576
|
}
|
|
1175
2577
|
if (e.codeFrame) logger.error(`${e.codeFrame}\n`);
|
|
1176
2578
|
if ("__vitest_rollup_error__" in e) {
|
|
@@ -1252,7 +2654,7 @@ function handleImportOutsideModuleError(stack, logger) {
|
|
|
1252
2654
|
if (!esmErrors.some((e) => stack.includes(e))) return;
|
|
1253
2655
|
const path = normalize(stack.split("\n")[0].trim());
|
|
1254
2656
|
let name = path.split("/node_modules/").pop() || "";
|
|
1255
|
-
if (name
|
|
2657
|
+
if (name[0] === "@") name = name.split("/").slice(0, 2).join("/");
|
|
1256
2658
|
else name = name.split("/")[0];
|
|
1257
2659
|
if (name) printModuleWarningForPackage(logger, path, name);
|
|
1258
2660
|
else printModuleWarningForSourceCode(logger, path);
|
|
@@ -1348,7 +2750,7 @@ class GithubActionsReporter {
|
|
|
1348
2750
|
this.ctx = ctx;
|
|
1349
2751
|
}
|
|
1350
2752
|
onTestCaseAnnotate(testCase, annotation) {
|
|
1351
|
-
if (!annotation.location) return;
|
|
2753
|
+
if (!annotation.location || this.options.displayAnnotations === false) return;
|
|
1352
2754
|
const type = getTitle(annotation.type), formatted = formatMessage({
|
|
1353
2755
|
command: getType(annotation.type),
|
|
1354
2756
|
properties: {
|
|
@@ -1409,7 +2811,7 @@ const BUILT_IN_TYPES = [
|
|
|
1409
2811
|
"warning"
|
|
1410
2812
|
];
|
|
1411
2813
|
function getTitle(type) {
|
|
1412
|
-
|
|
2814
|
+
if (!BUILT_IN_TYPES.includes(type)) return type;
|
|
1413
2815
|
}
|
|
1414
2816
|
function getType(type) {
|
|
1415
2817
|
return BUILT_IN_TYPES.includes(type) ? type : "notice";
|
|
@@ -1436,8 +2838,7 @@ function escapeProperty(s) {
|
|
|
1436
2838
|
class HangingProcessReporter {
|
|
1437
2839
|
whyRunning;
|
|
1438
2840
|
onInit() {
|
|
1439
|
-
|
|
1440
|
-
this.whyRunning = _require("why-is-node-running");
|
|
2841
|
+
this.whyRunning = createRequire(import.meta.url)("why-is-node-running");
|
|
1441
2842
|
}
|
|
1442
2843
|
onProcessTimeout() {
|
|
1443
2844
|
this.whyRunning?.();
|
|
@@ -1525,7 +2926,7 @@ class JsonReporter {
|
|
|
1525
2926
|
async writeReport(report) {
|
|
1526
2927
|
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "json");
|
|
1527
2928
|
if (outputFile) {
|
|
1528
|
-
const reportFile = resolve(this.ctx.config.root, outputFile), outputDirectory = dirname(reportFile);
|
|
2929
|
+
const reportFile = resolve$1(this.ctx.config.root, outputFile), outputDirectory = dirname(reportFile);
|
|
1529
2930
|
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
1530
2931
|
await promises.writeFile(reportFile, report, "utf-8"), this.ctx.logger.log(`JSON report written to ${reportFile}`);
|
|
1531
2932
|
} else this.ctx.logger.log(report);
|
|
@@ -1594,11 +2995,10 @@ class JUnitReporter {
|
|
|
1594
2995
|
this.ctx = ctx;
|
|
1595
2996
|
const outputFile = this.options.outputFile ?? getOutputFile(this.ctx.config, "junit");
|
|
1596
2997
|
if (outputFile) {
|
|
1597
|
-
this.reportFile = resolve(this.ctx.config.root, outputFile);
|
|
2998
|
+
this.reportFile = resolve$1(this.ctx.config.root, outputFile);
|
|
1598
2999
|
const outputDirectory = dirname(this.reportFile);
|
|
1599
3000
|
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
1600
|
-
|
|
1601
|
-
this.fileFd = fileFd, this.baseLog = async (text) => {
|
|
3001
|
+
this.fileFd = await promises.open(this.reportFile, "w+"), this.baseLog = async (text) => {
|
|
1602
3002
|
if (!this.fileFd) this.fileFd = await promises.open(this.reportFile, "w+");
|
|
1603
3003
|
await promises.writeFile(this.fileFd, `${text}\n`);
|
|
1604
3004
|
};
|
|
@@ -1761,7 +3161,7 @@ class TapReporter {
|
|
|
1761
3161
|
this.logger.log(`# ${type}: ${message}`);
|
|
1762
3162
|
}), this.logger.unindent();
|
|
1763
3163
|
if (task.result?.state === "fail" && task.result.errors) this.logger.indent(), task.result.errors.forEach((error) => {
|
|
1764
|
-
const
|
|
3164
|
+
const stack = (task.file.pool === "browser" ? project.browser?.parseErrorStacktrace(error) || [] : parseErrorStacktrace(error, { frameFilter: this.ctx.config.onStackTrace }))[0];
|
|
1765
3165
|
if (this.logger.log("---"), this.logger.log("error:"), this.logger.indent(), this.logErrorDetails(error), this.logger.unindent(), stack) this.logger.log(`at: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
|
|
1766
3166
|
if (error.showDiff) this.logger.log(`actual: ${yamlString(error.actual)}`), this.logger.log(`expected: ${yamlString(error.expected)}`);
|
|
1767
3167
|
}), this.logger.log("..."), this.logger.unindent();
|
|
@@ -1792,48 +3192,26 @@ class TapFlatReporter extends TapReporter {
|
|
|
1792
3192
|
}
|
|
1793
3193
|
}
|
|
1794
3194
|
|
|
3195
|
+
class TreeReporter extends DefaultReporter {
|
|
3196
|
+
verbose = true;
|
|
3197
|
+
renderSucceed = true;
|
|
3198
|
+
}
|
|
3199
|
+
|
|
1795
3200
|
class VerboseReporter extends DefaultReporter {
|
|
1796
3201
|
verbose = true;
|
|
1797
3202
|
renderSucceed = true;
|
|
1798
|
-
printTestModule(
|
|
1799
|
-
//
|
|
1800
|
-
// but don't print it in the CLI because we
|
|
1801
|
-
// print all the tests when they finish
|
|
1802
|
-
// instead of printing them when the test file finishes
|
|
1803
|
-
if (this.isTTY) return super.printTestModule(module);
|
|
3203
|
+
printTestModule(_module) {
|
|
3204
|
+
// don't print test module, only print tests
|
|
1804
3205
|
}
|
|
1805
3206
|
onTestCaseResult(test) {
|
|
1806
|
-
|
|
1807
|
-
// in the CLI when they finish
|
|
1808
|
-
if (super.onTestCaseResult(test), this.isTTY) return;
|
|
3207
|
+
super.onTestCaseResult(test);
|
|
1809
3208
|
const testResult = test.result();
|
|
1810
3209
|
if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") return;
|
|
1811
|
-
let title = ` ${
|
|
1812
|
-
if (test.
|
|
1813
|
-
title +=
|
|
1814
|
-
const diagnostic = test.diagnostic();
|
|
1815
|
-
if (diagnostic?.heap != null) title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
|
|
1816
|
-
if (testResult.state === "skipped" && testResult.note) title += c.dim(c.gray(` [${testResult.note}]`));
|
|
1817
|
-
if (this.log(title), testResult.state === "failed") testResult.errors.forEach((error) => this.log(c.red(` ${F_RIGHT} ${error?.message}`)));
|
|
3210
|
+
let title = ` ${this.getEntityPrefix(test)} `;
|
|
3211
|
+
if (title += test.module.task.name, test.location) title += c.dim(`:${test.location.line}:${test.location.column}`);
|
|
3212
|
+
if (title += separator, title += getTestName(test.task, separator), title += this.getTestCaseSuffix(test), this.log(title), testResult.state === "failed") testResult.errors.forEach((error) => this.log(c.red(` ${F_RIGHT} ${error.message}`)));
|
|
1818
3213
|
if (test.annotations().length) this.log(), this.printAnnotations(test, "log", 3), this.log();
|
|
1819
3214
|
}
|
|
1820
|
-
printTestSuite(testSuite) {
|
|
1821
|
-
const indentation = " ".repeat(getIndentation(testSuite.task)), tests = Array.from(testSuite.children.allTests()), state = getStateSymbol(testSuite.task);
|
|
1822
|
-
this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`);
|
|
1823
|
-
}
|
|
1824
|
-
getTestName(test) {
|
|
1825
|
-
return test.name;
|
|
1826
|
-
}
|
|
1827
|
-
getTestIndentation(test) {
|
|
1828
|
-
return " ".repeat(getIndentation(test));
|
|
1829
|
-
}
|
|
1830
|
-
formatShortError() {
|
|
1831
|
-
// Short errors are not shown in tree-view
|
|
1832
|
-
return "";
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
function getIndentation(suite, level = 1) {
|
|
1836
|
-
return suite.suite && !("filepath" in suite.suite) ? getIndentation(suite.suite, level + 1) : level;
|
|
1837
3215
|
}
|
|
1838
3216
|
|
|
1839
3217
|
const ReportersMap = {
|
|
@@ -1845,8 +3223,9 @@ const ReportersMap = {
|
|
|
1845
3223
|
"tap": TapReporter,
|
|
1846
3224
|
"tap-flat": TapFlatReporter,
|
|
1847
3225
|
"junit": JUnitReporter,
|
|
3226
|
+
"tree": TreeReporter,
|
|
1848
3227
|
"hanging-process": HangingProcessReporter,
|
|
1849
3228
|
"github-actions": GithubActionsReporter
|
|
1850
3229
|
};
|
|
1851
3230
|
|
|
1852
|
-
export { BlobReporter as B, DefaultReporter as D, F_RIGHT as F, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c,
|
|
3231
|
+
export { BlobReporter as B, DefaultReporter as D, F_RIGHT as F, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, stringify as d, TraceMap as e, formatProjectName as f, getStateSymbol as g, ancestor as h, printError as i, errorBanner as j, divider as k, Typechecker as l, generateCodeFrame as m, createDefinesScript as n, originalPositionFor as o, parse$1 as p, convertTasksToEvents as q, readBlobs as r, separator as s, truncateString as t, utils as u, withLabel as w };
|