vitest 0.17.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/LICENSE.md +6 -6
  2. package/dist/browser.d.ts +1850 -0
  3. package/dist/browser.mjs +20 -0
  4. package/dist/{chunk-api-setup.c728e251.mjs → chunk-api-setup.0cf2c96a.mjs} +37 -11
  5. package/dist/{chunk-constants.27550afb.mjs → chunk-constants.38b43a44.mjs} +3 -3
  6. package/dist/{chunk-env-node.aa51c4cc.mjs → chunk-defaults.408a0cfe.mjs} +457 -455
  7. package/dist/{chunk-install-pkg.6f5930c3.mjs → chunk-install-pkg.6c6dc0c2.mjs} +11 -10
  8. package/dist/chunk-integrations-globals.803277be.mjs +24 -0
  9. package/dist/chunk-node-git.9058b82a.mjs +1139 -0
  10. package/dist/chunk-runtime-chain.1e1aabb3.mjs +2025 -0
  11. package/dist/{vendor-entry.1ad8a08d.mjs → chunk-runtime-error.d82dd2cf.mjs} +167 -183
  12. package/dist/{chunk-runtime-chain.6d23d202.mjs → chunk-runtime-hooks.db398170.mjs} +33 -2012
  13. package/dist/{chunk-runtime-mocker.34b9d585.mjs → chunk-runtime-mocker.dfdfd57b.mjs} +70 -22
  14. package/dist/{chunk-runtime-rpc.d986adb9.mjs → chunk-runtime-rpc.45d8ee19.mjs} +1 -1
  15. package/dist/{chunk-utils-global.4828c2e2.mjs → chunk-utils-global.2aa95025.mjs} +14 -9
  16. package/dist/{chunk-utils-source-map.a9047343.mjs → chunk-utils-source-map.8b066ce2.mjs} +2 -2
  17. package/dist/{chunk-vite-node-externalize.0fc8ed68.mjs → chunk-vite-node-externalize.a2813ad7.mjs} +1202 -2178
  18. package/dist/chunk-vite-node-utils.ad73f2ab.mjs +1433 -0
  19. package/dist/cli.mjs +11 -13
  20. package/dist/config.cjs +4 -1
  21. package/dist/config.d.ts +1 -0
  22. package/dist/config.mjs +4 -1
  23. package/dist/entry.mjs +54 -10
  24. package/dist/index.d.ts +126 -58
  25. package/dist/index.mjs +12 -9
  26. package/dist/node.d.ts +109 -58
  27. package/dist/node.mjs +12 -14
  28. package/dist/spy.mjs +102 -2
  29. package/dist/suite.mjs +13 -0
  30. package/dist/vendor-index.61438b77.mjs +335 -0
  31. package/dist/{vendor-index.a2a385d8.mjs → vendor-index.62ce5c33.mjs} +6 -338
  32. package/dist/{vendor-index.98e769c1.mjs → vendor-index.de788b6a.mjs} +7 -7
  33. package/dist/worker.mjs +6 -6
  34. package/package.json +20 -12
  35. package/dist/chunk-integrations-globals.3df36e26.mjs +0 -26
  36. package/dist/chunk-integrations-spy.674b628e.mjs +0 -102
  37. package/dist/chunk-vite-node-utils.0f776286.mjs +0 -9195
@@ -1,32 +1,30 @@
1
- import { p as pLimit, c as configDefaults, r as resolveC8Options, a as cleanCoverage, b as reportCoverage, e as envPackageNames } from './chunk-env-node.aa51c4cc.mjs';
2
- import { j as join, o as basename, d as dirname, q as resolve, A as AggregateErrorPonyfill, p as picocolors, s as slash$2, t as isAbsolute, u as relative, v as isNode, x as getTests, e as getFullName, y as hasFailed, z as hasFailedSnapshot, B as getSuites, C as safeSetInterval, D as safeClearInterval, f as safeSetTimeout, E as shuffle, F as toArray$1, G as normalize, n as noop$1, h as safeClearTimeout, H as deepMerge, I as toNamespacedPath, g as getCallLastIndex, l as notNullish, J as ensurePackageInstalled, K as stdout } from './chunk-utils-global.4828c2e2.mjs';
1
+ import { j as join, D as basename, d as dirname, C as resolve, E as AggregateErrorPonyfill, p as picocolors, F as isAbsolute, G as relative, c as slash$2, t as isNode, v as relativePath, H as getTests, h as getFullName, B as hasFailed, I as hasFailedSnapshot, J as safeSetInterval, K as safeClearInterval, L as getSuites, s as safeSetTimeout, z as shuffle, u as toArray$1, M as normalize, n as noop$1, k as safeClearTimeout, N as deepMerge, O as toNamespacedPath, b as getCallLastIndex, l as notNullish, P as ensurePackageInstalled, Q as stdout } from './chunk-utils-global.2aa95025.mjs';
2
+ import { p as pLimit, c as configDefaults, r as resolveC8Options, a as cleanCoverage, b as reportCoverage, d as envPackageNames } from './chunk-defaults.408a0cfe.mjs';
3
3
  import { loadConfigFromFile, createServer, mergeConfig } from 'vite';
4
4
  import path$a from 'path';
5
- import url, { fileURLToPath, pathToFileURL } from 'url';
5
+ import _url, { fileURLToPath } from 'url';
6
6
  import process$1 from 'process';
7
7
  import fs$8, { promises, existsSync, readFileSync } from 'fs';
8
- import { d as distDir, c as configFiles, a as defaultPort } from './chunk-constants.27550afb.mjs';
9
- import readline from 'readline';
10
- import require$$0, { cpus, hostname, constants as constants$5 } from 'os';
11
- import require$$0$1 from 'util';
12
- import require$$0$2 from 'stream';
8
+ import { d as distDir, c as configFiles, a as defaultPort } from './chunk-constants.38b43a44.mjs';
9
+ import require$$0, { cpus, hostname } from 'os';
10
+ import util$2 from 'util';
11
+ import require$$0$1 from 'stream';
13
12
  import require$$2 from 'events';
14
13
  import { c as commonjsGlobal } from './vendor-_commonjsHelpers.4da45ef5.mjs';
15
- import { i as isNodeBuiltin, a as isValidNodeImport, s as slash$1, t as toArray, b as toFilePath, w as withInlineSourcemap, c as createBirpc, V as ViteNodeRunner } from './chunk-vite-node-utils.0f776286.mjs';
14
+ import { i as isNodeBuiltin, a as isValidNodeImport, s as slash$1, t as toArray, b as toFilePath, w as withInlineSourcemap, c as createBirpc, V as ViteNodeRunner } from './chunk-vite-node-utils.ad73f2ab.mjs';
16
15
  import createDebug from 'debug';
17
16
  import { MessageChannel } from 'worker_threads';
18
17
  import { Tinypool } from 'tinypool';
19
18
  import { performance } from 'perf_hooks';
20
- import { c as stripAnsi, d as stringWidth, e as ansiStyles, h as sliceAnsi, i as cliTruncate, b as parseStacktrace, j as interpretSourcePos, s as stringify$5, u as unifiedDiff, a as posToNumber, l as lineSplitRE } from './chunk-utils-source-map.a9047343.mjs';
21
- import { o as onetime$1, s as signalExit, m as mergeStream, g as getStream, c as crossSpawn } from './vendor-index.a2a385d8.mjs';
19
+ import { c as stripAnsi, d as cliTruncate, p as parseStacktrace, e as stringWidth, h as ansiStyles, i as sliceAnsi, j as interpretSourcePos, s as stringify$5, u as unifiedDiff, b as posToNumber, l as lineSplitRE } from './chunk-utils-source-map.8b066ce2.mjs';
22
20
  import { resolveModule } from 'local-pkg';
23
21
  import { createHash } from 'crypto';
24
- import { Buffer } from 'buffer';
25
- import childProcess from 'child_process';
22
+ import { o as onetime, s as signalExit } from './vendor-index.61438b77.mjs';
26
23
  import MagicString from './chunk-magic-string.efe26975.mjs';
27
- import { p as prompts } from './vendor-index.98e769c1.mjs';
24
+ import require$$0$2 from 'readline';
25
+ import { p as prompts } from './vendor-index.de788b6a.mjs';
28
26
 
29
- var version = "0.17.1";
27
+ var version$1 = "0.19.0";
30
28
 
31
29
  class EndError extends Error {
32
30
  constructor(value) {
@@ -935,7 +933,7 @@ var toRegexRange_1 = toRegexRange$1;
935
933
  * Licensed under the MIT License.
936
934
  */
937
935
 
938
- const util$1 = require$$0$1;
936
+ const util$1 = util$2;
939
937
  const toRegexRange = toRegexRange_1;
940
938
 
941
939
  const isObject$1 = val => val !== null && typeof val === 'object' && !Array.isArray(val);
@@ -3972,7 +3970,7 @@ var picomatch_1 = picomatch$1;
3972
3970
  module.exports = picomatch_1;
3973
3971
  } (picomatch$2));
3974
3972
 
3975
- const util = require$$0$1;
3973
+ const util = util$2;
3976
3974
  const braces = braces_1;
3977
3975
  const picomatch = picomatch$2.exports;
3978
3976
  const utils$b = utils$f;
@@ -4616,7 +4614,7 @@ var stream$4 = {};
4616
4614
  * Copyright (c) 2014-2020 Teambition
4617
4615
  * Licensed under the MIT license.
4618
4616
  */
4619
- const Stream = require$$0$2;
4617
+ const Stream = require$$0$1;
4620
4618
  const PassThrough = Stream.PassThrough;
4621
4619
  const slice = Array.prototype.slice;
4622
4620
 
@@ -5900,7 +5898,7 @@ function callSuccessCallback(callback, entries) {
5900
5898
  var stream$1 = {};
5901
5899
 
5902
5900
  Object.defineProperty(stream$1, "__esModule", { value: true });
5903
- const stream_1$5 = require$$0$2;
5901
+ const stream_1$5 = require$$0$1;
5904
5902
  const async_1$2 = async$2;
5905
5903
  class StreamProvider {
5906
5904
  constructor(_root, _settings) {
@@ -6108,7 +6106,7 @@ class Reader {
6108
6106
  reader.default = Reader;
6109
6107
 
6110
6108
  Object.defineProperty(stream$2, "__esModule", { value: true });
6111
- const stream_1$3 = require$$0$2;
6109
+ const stream_1$3 = require$$0$1;
6112
6110
  const fsStat$1 = out$3;
6113
6111
  const fsWalk$1 = out$2;
6114
6112
  const reader_1$1 = reader;
@@ -6506,7 +6504,7 @@ async$6.default = ProviderAsync;
6506
6504
  var stream = {};
6507
6505
 
6508
6506
  Object.defineProperty(stream, "__esModule", { value: true });
6509
- const stream_1$1 = require$$0$2;
6507
+ const stream_1$1 = require$$0$1;
6510
6508
  const stream_2 = stream$2;
6511
6509
  const provider_1$1 = provider;
6512
6510
  class ProviderStream extends provider_1$1.default {
@@ -6736,10 +6734,10 @@ function assertPatternsInput(input) {
6736
6734
  var out = FastGlob;
6737
6735
 
6738
6736
  const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/;
6739
- const ESM_FOLDER_RE = /\/esm\/(.*\.js)$/;
6737
+ const ESM_FOLDER_RE = /\/(es|esm)\/(.*\.js)$/;
6740
6738
  const defaultInline = [
6741
6739
  /virtual:/,
6742
- /\.ts$/
6740
+ /\.[mc]?ts$/
6743
6741
  ];
6744
6742
  const depsExternal = [
6745
6743
  /\.cjs\.js$/,
@@ -6761,6 +6759,7 @@ function guessCJSversion(id) {
6761
6759
  for (const i of [
6762
6760
  id.replace(ESM_FOLDER_RE, "/umd/$1"),
6763
6761
  id.replace(ESM_FOLDER_RE, "/cjs/$1"),
6762
+ id.replace(ESM_FOLDER_RE, "/lib/$1"),
6764
6763
  id.replace(ESM_FOLDER_RE, "/$1")
6765
6764
  ]) {
6766
6765
  if (existsSync(i))
@@ -6979,7 +6978,7 @@ function addSnapshotResult(summary, result) {
6979
6978
  summary.total += result.added + result.matched + result.unmatched + result.updated;
6980
6979
  }
6981
6980
 
6982
- const workerPath = pathToFileURL(resolve(distDir, "./worker.mjs")).href;
6981
+ const workerPath = _url.pathToFileURL(resolve(distDir, "./worker.mjs")).href;
6983
6982
  function createPool(ctx) {
6984
6983
  var _a;
6985
6984
  const threadsCount = ctx.config.watch ? Math.max(Math.floor(cpus().length / 2), 1) : Math.max(cpus().length - 1, 1);
@@ -7014,6 +7013,7 @@ function createPool(ctx) {
7014
7013
  const runWithFiles = (name) => {
7015
7014
  let id = 0;
7016
7015
  async function runFiles(config, files, invalidates = []) {
7016
+ ctx.state.clearFiles(files);
7017
7017
  const { workerPort, port } = createChannel(ctx);
7018
7018
  const workerId = ++id;
7019
7019
  const data = {
@@ -7082,6 +7082,10 @@ function createChannel(ctx) {
7082
7082
  resolveId(id, importer) {
7083
7083
  return ctx.vitenode.resolveId(id, importer);
7084
7084
  },
7085
+ onPathsCollected(paths) {
7086
+ ctx.state.collectPaths(paths);
7087
+ ctx.report("onPathsCollected", paths);
7088
+ },
7085
7089
  onCollected(files) {
7086
7090
  ctx.state.collectFiles(files);
7087
7091
  ctx.report("onCollected", files);
@@ -7267,51 +7271,39 @@ ${picocolors.exports.bold(picocolors.exports.inverse(picocolors.exports.green("
7267
7271
  const WAIT_FOR_CHANGE_FAIL = `
7268
7272
  ${picocolors.exports.bold(picocolors.exports.inverse(picocolors.exports.red(" FAIL ")))}${picocolors.exports.red(" Tests failed. Watching for file changes...")}`;
7269
7273
  const DURATION_LONG$1 = 300;
7274
+ const LAST_RUN_LOG_TIMEOUT = 1500;
7270
7275
  class BaseReporter {
7271
7276
  constructor() {
7272
7277
  this.start = 0;
7273
7278
  this.end = 0;
7274
7279
  this.isTTY = isNode && ((_a = process.stdout) == null ? void 0 : _a.isTTY) && !process.env.CI;
7275
7280
  this.ctx = void 0;
7281
+ this._filesInWatchMode = /* @__PURE__ */ new Map();
7282
+ this._lastRunTimeout = 0;
7283
+ this._lastRunCount = 0;
7276
7284
  this.registerUnhandledRejection();
7277
7285
  }
7278
7286
  onInit(ctx) {
7279
- var _a2, _b;
7280
7287
  this.ctx = ctx;
7281
- this.ctx.log();
7282
- const versionTest = this.ctx.config.watch ? picocolors.exports.blue(`v${version}`) : picocolors.exports.cyan(`v${version}`);
7283
- const mode = this.ctx.config.watch ? picocolors.exports.blue(" DEV ") : picocolors.exports.cyan(" RUN ");
7284
- this.ctx.log(`${picocolors.exports.inverse(picocolors.exports.bold(mode))} ${versionTest} ${picocolors.exports.gray(this.ctx.config.root)}`);
7285
- if (this.ctx.config.ui)
7286
- this.ctx.log(picocolors.exports.dim(picocolors.exports.green(` UI started at http://${((_a2 = this.ctx.config.api) == null ? void 0 : _a2.host) || "localhost"}:${picocolors.exports.bold(`${this.ctx.server.config.server.port}`)}${this.ctx.config.uiBase}`)));
7287
- else if (this.ctx.config.api)
7288
- this.ctx.log(picocolors.exports.dim(picocolors.exports.green(` API started at http://${((_b = this.ctx.config.api) == null ? void 0 : _b.host) || "localhost"}:${picocolors.exports.bold(`${this.ctx.config.api.port}`)}`)));
7289
- this.ctx.log();
7288
+ ctx.logger.printBanner();
7290
7289
  this.start = performance.now();
7291
7290
  }
7292
7291
  relative(path) {
7293
- return relative(this.ctx.config.root, path);
7292
+ return relativePath(this.ctx.config.root, path);
7294
7293
  }
7295
7294
  async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
7296
7295
  this.end = performance.now();
7297
7296
  await this.reportSummary(files);
7298
7297
  if (errors.length) {
7299
7298
  process.exitCode = 1;
7300
- const errorMessage = picocolors.exports.red(picocolors.exports.bold(`
7301
- Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run. This might cause false positive tests.
7302
- Please, resolve all the errors to make sure your tests are not affected.`));
7303
- this.ctx.log(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Errors ")))));
7304
- this.ctx.log(errorMessage);
7305
- await Promise.all(errors.map(async (err) => {
7306
- await this.ctx.printError(err, true, err.type || "Unhandled Error");
7307
- }));
7308
- this.ctx.log(picocolors.exports.red(divider()));
7299
+ this.ctx.logger.printUnhandledErrors(errors);
7309
7300
  }
7310
7301
  }
7311
7302
  onTaskUpdate(packs) {
7312
7303
  var _a2, _b, _c;
7313
7304
  if (this.isTTY)
7314
7305
  return;
7306
+ const logger = this.ctx.logger;
7315
7307
  for (const pack of packs) {
7316
7308
  const task = this.ctx.state.idMap.get(pack[0]);
7317
7309
  if (task && "filepath" in task && ((_a2 = task.result) == null ? void 0 : _a2.state) && ((_b = task.result) == null ? void 0 : _b.state) !== "run") {
@@ -7333,43 +7325,81 @@ Please, resolve all the errors to make sure your tests are not affected.`));
7333
7325
  }
7334
7326
  if (this.ctx.config.logHeapUsage && task.result.heap != null)
7335
7327
  suffix += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
7336
- this.ctx.log(` ${getStateSymbol(task)} ${task.name} ${suffix}`);
7328
+ logger.log(` ${getStateSymbol(task)} ${task.name} ${suffix}`);
7337
7329
  for (const test of failed) {
7338
- this.ctx.log(picocolors.exports.red(` ${pointer} ${getFullName(test)}`));
7339
- this.ctx.log(picocolors.exports.red(` ${F_RIGHT} ${(_c = test.result.error) == null ? void 0 : _c.message}`));
7330
+ logger.log(picocolors.exports.red(` ${pointer} ${getFullName(test)}`));
7331
+ logger.log(picocolors.exports.red(` ${F_RIGHT} ${(_c = test.result.error) == null ? void 0 : _c.message}`));
7340
7332
  }
7341
7333
  }
7342
7334
  }
7343
7335
  }
7344
7336
  async onWatcherStart() {
7337
+ this.resetLastRunLog();
7345
7338
  const files = this.ctx.state.getFiles();
7346
7339
  const errors = this.ctx.state.getUnhandledErrors();
7347
7340
  const failed = errors.length > 0 || hasFailed(files);
7348
7341
  const failedSnap = hasFailedSnapshot(files);
7349
7342
  if (failed)
7350
- this.ctx.log(WAIT_FOR_CHANGE_FAIL);
7343
+ this.ctx.logger.log(WAIT_FOR_CHANGE_FAIL);
7351
7344
  else
7352
- this.ctx.log(WAIT_FOR_CHANGE_PASS);
7345
+ this.ctx.logger.log(WAIT_FOR_CHANGE_PASS);
7353
7346
  const hints = [HELP_HINT];
7354
7347
  if (failedSnap)
7355
7348
  hints.unshift(HELP_UPDATE_SNAP);
7356
7349
  else
7357
7350
  hints.push(HELP_QUITE);
7358
- this.ctx.log(BADGE_PADDING + hints.join(picocolors.exports.dim(", ")));
7351
+ this.ctx.logger.log(BADGE_PADDING + hints.join(picocolors.exports.dim(", ")));
7352
+ if (this._lastRunCount) {
7353
+ const LAST_RUN_TEXT = `rerun x${this._lastRunCount}`;
7354
+ const LAST_RUN_TEXTS = [
7355
+ picocolors.exports.blue(LAST_RUN_TEXT),
7356
+ picocolors.exports.gray(LAST_RUN_TEXT),
7357
+ picocolors.exports.dim(picocolors.exports.gray(LAST_RUN_TEXT))
7358
+ ];
7359
+ this.ctx.logger.logUpdate(BADGE_PADDING + LAST_RUN_TEXTS[0]);
7360
+ this._lastRunTimeout = 0;
7361
+ this._lastRunTimer = safeSetInterval(() => {
7362
+ this._lastRunTimeout += 1;
7363
+ if (this._lastRunTimeout >= LAST_RUN_TEXTS.length)
7364
+ this.resetLastRunLog();
7365
+ else
7366
+ this.ctx.logger.logUpdate(BADGE_PADDING + LAST_RUN_TEXTS[this._lastRunTimeout]);
7367
+ }, LAST_RUN_LOG_TIMEOUT / LAST_RUN_TEXTS.length);
7368
+ }
7369
+ }
7370
+ resetLastRunLog() {
7371
+ safeClearInterval(this._lastRunTimer);
7372
+ this._lastRunTimer = void 0;
7373
+ this.ctx.logger.logUpdate.clear();
7359
7374
  }
7360
7375
  async onWatcherRerun(files, trigger) {
7376
+ this.resetLastRunLog();
7361
7377
  this.watchFilters = files;
7362
- this.ctx.clearScreen();
7363
- this.ctx.log(`
7364
- ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" RERUN ")))}${trigger ? picocolors.exports.dim(` ${this.relative(trigger)}
7365
- `) : ""}`);
7378
+ files.forEach((filepath) => {
7379
+ let reruns = this._filesInWatchMode.get(filepath) ?? 0;
7380
+ this._filesInWatchMode.set(filepath, ++reruns);
7381
+ });
7382
+ const BADGE = picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" RERUN ")));
7383
+ const TRIGGER = trigger ? picocolors.exports.dim(` ${this.relative(trigger)}`) : "";
7384
+ if (files.length > 1) {
7385
+ this.ctx.logger.clearScreen(`
7386
+ ${BADGE}${TRIGGER}
7387
+ `, true);
7388
+ this._lastRunCount = 0;
7389
+ } else if (files.length === 1) {
7390
+ const rerun = this._filesInWatchMode.get(files[0]) ?? 1;
7391
+ this._lastRunCount = rerun;
7392
+ this.ctx.logger.clearScreen(`
7393
+ ${BADGE}${TRIGGER} ${picocolors.exports.blue(`x${rerun}`)}
7394
+ `);
7395
+ }
7366
7396
  this.start = performance.now();
7367
7397
  }
7368
7398
  onUserConsoleLog(log) {
7369
7399
  if (!this.shouldLog(log))
7370
7400
  return;
7371
7401
  const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
7372
- this.ctx.log(picocolors.exports.gray(log.type + picocolors.exports.dim(` | ${task ? getFullName(task) : "unknown test"}`)));
7402
+ this.ctx.logger.log(picocolors.exports.gray(log.type + picocolors.exports.dim(` | ${task ? getFullName(task) : "unknown test"}`)));
7373
7403
  process[log.type].write(`${log.content}
7374
7404
  `);
7375
7405
  }
@@ -7383,9 +7413,10 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
7383
7413
  return true;
7384
7414
  }
7385
7415
  onServerRestart() {
7386
- this.ctx.log(picocolors.exports.cyan("Restarted due to config changes..."));
7416
+ this.ctx.logger.log(picocolors.exports.cyan("Restarted due to config changes..."));
7387
7417
  }
7388
7418
  async reportSummary(files) {
7419
+ const logger = this.ctx.logger;
7389
7420
  const suites = getSuites(files);
7390
7421
  const tests = getTests(files);
7391
7422
  const failedSuites = suites.filter((i) => {
@@ -7398,16 +7429,16 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
7398
7429
  });
7399
7430
  const failedTotal = failedSuites.length + failedTests.length;
7400
7431
  let current = 1;
7401
- const errorDivider = () => this.ctx.error(`${picocolors.exports.red(picocolors.exports.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
7432
+ const errorDivider = () => logger.error(`${picocolors.exports.red(picocolors.exports.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
7402
7433
  `);
7403
7434
  if (failedSuites.length) {
7404
- this.ctx.error(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` Failed Suites ${failedSuites.length} `)))));
7405
- this.ctx.error();
7435
+ logger.error(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` Failed Suites ${failedSuites.length} `)))));
7436
+ logger.error();
7406
7437
  await this.printTaskErrors(failedSuites, errorDivider);
7407
7438
  }
7408
7439
  if (failedTests.length) {
7409
- this.ctx.error(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` Failed Tests ${failedTests.length} `)))));
7410
- this.ctx.error();
7440
+ logger.error(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` Failed Tests ${failedTests.length} `)))));
7441
+ logger.error();
7411
7442
  await this.printTaskErrors(failedTests, errorDivider);
7412
7443
  }
7413
7444
  const executionTime = this.end - this.start;
@@ -7423,17 +7454,17 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
7423
7454
  };
7424
7455
  const snapshotOutput = renderSnapshotSummary(this.ctx.config.root, this.ctx.snapshot.summary);
7425
7456
  if (snapshotOutput.length) {
7426
- this.ctx.log(snapshotOutput.map((t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`).join("\n"));
7457
+ logger.log(snapshotOutput.map((t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`).join("\n"));
7427
7458
  if (snapshotOutput.length > 1)
7428
- this.ctx.log();
7459
+ logger.log();
7429
7460
  }
7430
- this.ctx.log(padTitle("Test Files"), getStateString(files));
7431
- this.ctx.log(padTitle("Tests"), getStateString(tests));
7461
+ logger.log(padTitle("Test Files"), getStateString(files));
7462
+ logger.log(padTitle("Tests"), getStateString(tests));
7432
7463
  if (this.watchFilters)
7433
- this.ctx.log(padTitle("Time"), time(threadTime));
7464
+ logger.log(padTitle("Time"), time(threadTime));
7434
7465
  else
7435
- this.ctx.log(padTitle("Time"), time(executionTime) + picocolors.exports.gray(` (in thread ${time(threadTime)}, ${(executionTime / threadTime * 100).toFixed(2)}%)`));
7436
- this.ctx.log();
7466
+ logger.log(padTitle("Time"), time(executionTime) + picocolors.exports.gray(` (in thread ${time(threadTime)}, ${(executionTime / threadTime * 100).toFixed(2)}%)`));
7467
+ logger.log();
7437
7468
  }
7438
7469
  async printTaskErrors(tasks, errorDivider) {
7439
7470
  var _a2;
@@ -7455,9 +7486,9 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
7455
7486
  let name = getFullName(task);
7456
7487
  if (filepath)
7457
7488
  name = `${name} ${picocolors.exports.dim(`[ ${this.relative(filepath)} ]`)}`;
7458
- this.ctx.error(`${picocolors.exports.red(picocolors.exports.bold(picocolors.exports.inverse(" FAIL ")))} ${name}`);
7489
+ this.ctx.logger.error(`${picocolors.exports.red(picocolors.exports.bold(picocolors.exports.inverse(" FAIL ")))} ${name}`);
7459
7490
  }
7460
- await this.ctx.printError(error);
7491
+ await this.ctx.logger.printError(error);
7461
7492
  errorDivider();
7462
7493
  await Promise.resolve();
7463
7494
  }
@@ -7465,746 +7496,257 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
7465
7496
  registerUnhandledRejection() {
7466
7497
  process.on("unhandledRejection", async (err) => {
7467
7498
  process.exitCode = 1;
7468
- await this.ctx.printError(err, true, "Unhandled Rejection");
7469
- this.ctx.error("\n\n");
7499
+ await this.ctx.logger.printError(err, true, "Unhandled Rejection");
7500
+ this.ctx.logger.error("\n\n");
7470
7501
  process.exit(1);
7471
7502
  });
7472
7503
  }
7473
7504
  }
7474
7505
 
7475
- const ESC = '\u001B[';
7476
- const OSC = '\u001B]';
7477
- const BEL = '\u0007';
7478
- const SEP = ';';
7479
- const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
7506
+ const DURATION_LONG = 300;
7507
+ const outputMap = /* @__PURE__ */ new WeakMap();
7508
+ function formatFilepath(path) {
7509
+ const lastSlash = Math.max(path.lastIndexOf("/") + 1, 0);
7510
+ const basename = path.slice(lastSlash);
7511
+ let firstDot = basename.indexOf(".");
7512
+ if (firstDot < 0)
7513
+ firstDot = basename.length;
7514
+ firstDot += lastSlash;
7515
+ return picocolors.exports.dim(path.slice(0, lastSlash)) + path.slice(lastSlash, firstDot) + picocolors.exports.dim(path.slice(firstDot));
7516
+ }
7517
+ function renderHookState(task, hookName, level = 0) {
7518
+ var _a, _b;
7519
+ const state = (_b = (_a = task.result) == null ? void 0 : _a.hooks) == null ? void 0 : _b[hookName];
7520
+ if (state && state === "run")
7521
+ return `${" ".repeat(level)} ${getHookStateSymbol(task, hookName)} ${picocolors.exports.dim(`[ ${hookName} ]`)}`;
7522
+ return "";
7523
+ }
7524
+ function renderTree(tasks, options, level = 0) {
7525
+ var _a, _b, _c, _d, _e;
7526
+ let output = [];
7527
+ for (const task of tasks) {
7528
+ let suffix = "";
7529
+ const prefix = ` ${getStateSymbol(task)} `;
7530
+ if (task.type === "suite")
7531
+ suffix += picocolors.exports.dim(` (${getTests(task).length})`);
7532
+ if (task.mode === "skip" || task.mode === "todo")
7533
+ suffix += ` ${picocolors.exports.dim(picocolors.exports.gray("[skipped]"))}`;
7534
+ if (((_a = task.result) == null ? void 0 : _a.duration) != null) {
7535
+ if (task.result.duration > DURATION_LONG)
7536
+ suffix += picocolors.exports.yellow(` ${Math.round(task.result.duration)}${picocolors.exports.dim("ms")}`);
7537
+ }
7538
+ if (options.showHeap && ((_b = task.result) == null ? void 0 : _b.heap) != null)
7539
+ suffix += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
7540
+ let name = task.name;
7541
+ if (level === 0)
7542
+ name = formatFilepath(name);
7543
+ output.push(" ".repeat(level) + prefix + name + suffix);
7544
+ if (((_c = task.result) == null ? void 0 : _c.state) !== "pass" && outputMap.get(task) != null) {
7545
+ let data = outputMap.get(task);
7546
+ if (typeof data === "string") {
7547
+ data = stripAnsi(data.trim().split("\n").filter(Boolean).pop());
7548
+ if (data === "")
7549
+ data = void 0;
7550
+ }
7551
+ if (data != null) {
7552
+ const out = `${" ".repeat(level)}${F_RIGHT} ${data}`;
7553
+ output.push(` ${picocolors.exports.gray(cliTruncate(out, getCols(-3)))}`);
7554
+ }
7555
+ }
7556
+ output = output.concat(renderHookState(task, "beforeAll", level + 1));
7557
+ output = output.concat(renderHookState(task, "beforeEach", level + 1));
7558
+ if (task.type === "suite" && task.tasks.length > 0) {
7559
+ if (((_d = task.result) == null ? void 0 : _d.state) === "fail" || ((_e = task.result) == null ? void 0 : _e.state) === "run" || options.renderSucceed)
7560
+ output = output.concat(renderTree(task.tasks, options, level + 1));
7561
+ }
7562
+ output = output.concat(renderHookState(task, "afterAll", level + 1));
7563
+ output = output.concat(renderHookState(task, "afterEach", level + 1));
7564
+ }
7565
+ return output.filter(Boolean).join("\n");
7566
+ }
7567
+ const createListRenderer = (_tasks, options) => {
7568
+ let tasks = _tasks;
7569
+ let timer;
7570
+ const log = options.logger.logUpdate;
7571
+ function update() {
7572
+ log(renderTree(tasks, options));
7573
+ }
7574
+ return {
7575
+ start() {
7576
+ if (timer)
7577
+ return this;
7578
+ timer = safeSetInterval(update, 200);
7579
+ return this;
7580
+ },
7581
+ update(_tasks2) {
7582
+ tasks = _tasks2;
7583
+ update();
7584
+ return this;
7585
+ },
7586
+ async stop() {
7587
+ if (timer) {
7588
+ safeClearInterval(timer);
7589
+ timer = void 0;
7590
+ }
7591
+ log.clear();
7592
+ options.logger.log(renderTree(tasks, options));
7593
+ return this;
7594
+ },
7595
+ clear() {
7596
+ log.clear();
7597
+ }
7598
+ };
7599
+ };
7480
7600
 
7481
- const ansiEscapes = {};
7601
+ class DefaultReporter extends BaseReporter {
7602
+ constructor() {
7603
+ super(...arguments);
7604
+ this.rendererOptions = {};
7605
+ }
7606
+ async onTestRemoved(trigger) {
7607
+ await this.stopListRender();
7608
+ this.ctx.logger.clearScreen(picocolors.exports.yellow("Test removed...") + (trigger ? picocolors.exports.dim(` [ ${this.relative(trigger)} ]
7609
+ `) : ""), true);
7610
+ const files = this.ctx.state.getFiles(this.watchFilters);
7611
+ createListRenderer(files, this.rendererOptions).stop();
7612
+ this.ctx.logger.log();
7613
+ await super.reportSummary(files);
7614
+ super.onWatcherStart();
7615
+ }
7616
+ onCollected() {
7617
+ if (this.isTTY) {
7618
+ this.rendererOptions.logger = this.ctx.logger;
7619
+ this.rendererOptions.showHeap = this.ctx.config.logHeapUsage;
7620
+ const files = this.ctx.state.getFiles(this.watchFilters);
7621
+ if (!this.renderer)
7622
+ this.renderer = createListRenderer(files, this.rendererOptions).start();
7623
+ else
7624
+ this.renderer.update(files);
7625
+ }
7626
+ }
7627
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
7628
+ await this.stopListRender();
7629
+ this.ctx.logger.log();
7630
+ await super.onFinished(files, errors);
7631
+ }
7632
+ async onWatcherStart() {
7633
+ await this.stopListRender();
7634
+ await super.onWatcherStart();
7635
+ }
7636
+ async stopListRender() {
7637
+ var _a;
7638
+ await ((_a = this.renderer) == null ? void 0 : _a.stop());
7639
+ this.renderer = void 0;
7640
+ }
7641
+ async onWatcherRerun(files, trigger) {
7642
+ await this.stopListRender();
7643
+ await super.onWatcherRerun(files, trigger);
7644
+ }
7645
+ onUserConsoleLog(log) {
7646
+ var _a;
7647
+ if (!this.shouldLog(log))
7648
+ return;
7649
+ (_a = this.renderer) == null ? void 0 : _a.clear();
7650
+ super.onUserConsoleLog(log);
7651
+ }
7652
+ }
7482
7653
 
7483
- ansiEscapes.cursorTo = (x, y) => {
7484
- if (typeof x !== 'number') {
7485
- throw new TypeError('The `x` argument is required');
7486
- }
7654
+ const check = picocolors.exports.green("\xB7");
7655
+ const cross = picocolors.exports.red("x");
7656
+ const pending = picocolors.exports.yellow("*");
7657
+ const skip = picocolors.exports.dim(picocolors.exports.gray("-"));
7658
+ function render(tasks) {
7659
+ const all = getTests(tasks);
7660
+ return all.map((i) => {
7661
+ var _a;
7662
+ if (i.mode === "skip" || i.mode === "todo")
7663
+ return skip;
7664
+ switch ((_a = i.result) == null ? void 0 : _a.state) {
7665
+ case "pass":
7666
+ return check;
7667
+ case "fail":
7668
+ return cross;
7669
+ default:
7670
+ return pending;
7671
+ }
7672
+ }).join("");
7673
+ }
7674
+ const createDotRenderer = (_tasks, options) => {
7675
+ let tasks = _tasks;
7676
+ let timer;
7677
+ const log = options.logger.logUpdate;
7678
+ function update() {
7679
+ log(render(tasks));
7680
+ }
7681
+ return {
7682
+ start() {
7683
+ if (timer)
7684
+ return this;
7685
+ timer = safeSetInterval(update, 200);
7686
+ return this;
7687
+ },
7688
+ update(_tasks2) {
7689
+ tasks = _tasks2;
7690
+ update();
7691
+ return this;
7692
+ },
7693
+ async stop() {
7694
+ if (timer) {
7695
+ safeClearInterval(timer);
7696
+ timer = void 0;
7697
+ }
7698
+ log.clear();
7699
+ options.logger.log(render(tasks));
7700
+ return this;
7701
+ },
7702
+ clear() {
7703
+ log.clear();
7704
+ }
7705
+ };
7706
+ };
7487
7707
 
7488
- if (typeof y !== 'number') {
7489
- return ESC + (x + 1) + 'G';
7490
- }
7708
+ class DotReporter extends BaseReporter {
7709
+ onCollected() {
7710
+ if (this.isTTY) {
7711
+ const files = this.ctx.state.getFiles(this.watchFilters);
7712
+ if (!this.renderer)
7713
+ this.renderer = createDotRenderer(files, { logger: this.ctx.logger }).start();
7714
+ else
7715
+ this.renderer.update(files);
7716
+ }
7717
+ }
7718
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
7719
+ await this.stopListRender();
7720
+ this.ctx.logger.log();
7721
+ await super.onFinished(files, errors);
7722
+ }
7723
+ async onWatcherStart() {
7724
+ await this.stopListRender();
7725
+ super.onWatcherStart();
7726
+ }
7727
+ async stopListRender() {
7728
+ var _a;
7729
+ (_a = this.renderer) == null ? void 0 : _a.stop();
7730
+ this.renderer = void 0;
7731
+ await new Promise((resolve) => safeSetTimeout(resolve, 10));
7732
+ }
7733
+ async onWatcherRerun(files, trigger) {
7734
+ await this.stopListRender();
7735
+ await super.onWatcherRerun(files, trigger);
7736
+ }
7737
+ onUserConsoleLog(log) {
7738
+ var _a;
7739
+ (_a = this.renderer) == null ? void 0 : _a.clear();
7740
+ super.onUserConsoleLog(log);
7741
+ }
7742
+ }
7491
7743
 
7492
- return ESC + (y + 1) + ';' + (x + 1) + 'H';
7493
- };
7494
-
7495
- ansiEscapes.cursorMove = (x, y) => {
7496
- if (typeof x !== 'number') {
7497
- throw new TypeError('The `x` argument is required');
7498
- }
7499
-
7500
- let returnValue = '';
7501
-
7502
- if (x < 0) {
7503
- returnValue += ESC + (-x) + 'D';
7504
- } else if (x > 0) {
7505
- returnValue += ESC + x + 'C';
7506
- }
7507
-
7508
- if (y < 0) {
7509
- returnValue += ESC + (-y) + 'A';
7510
- } else if (y > 0) {
7511
- returnValue += ESC + y + 'B';
7512
- }
7513
-
7514
- return returnValue;
7515
- };
7516
-
7517
- ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
7518
- ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
7519
- ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
7520
- ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
7521
-
7522
- ansiEscapes.cursorLeft = ESC + 'G';
7523
- ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
7524
- ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
7525
- ansiEscapes.cursorGetPosition = ESC + '6n';
7526
- ansiEscapes.cursorNextLine = ESC + 'E';
7527
- ansiEscapes.cursorPrevLine = ESC + 'F';
7528
- ansiEscapes.cursorHide = ESC + '?25l';
7529
- ansiEscapes.cursorShow = ESC + '?25h';
7530
-
7531
- ansiEscapes.eraseLines = count => {
7532
- let clear = '';
7533
-
7534
- for (let i = 0; i < count; i++) {
7535
- clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
7536
- }
7537
-
7538
- if (count) {
7539
- clear += ansiEscapes.cursorLeft;
7540
- }
7541
-
7542
- return clear;
7543
- };
7544
-
7545
- ansiEscapes.eraseEndLine = ESC + 'K';
7546
- ansiEscapes.eraseStartLine = ESC + '1K';
7547
- ansiEscapes.eraseLine = ESC + '2K';
7548
- ansiEscapes.eraseDown = ESC + 'J';
7549
- ansiEscapes.eraseUp = ESC + '1J';
7550
- ansiEscapes.eraseScreen = ESC + '2J';
7551
- ansiEscapes.scrollUp = ESC + 'S';
7552
- ansiEscapes.scrollDown = ESC + 'T';
7553
-
7554
- ansiEscapes.clearScreen = '\u001Bc';
7555
-
7556
- ansiEscapes.clearTerminal = process.platform === 'win32' ?
7557
- `${ansiEscapes.eraseScreen}${ESC}0f` :
7558
- // 1. Erases the screen (Only done in case `2` is not supported)
7559
- // 2. Erases the whole screen including scrollback buffer
7560
- // 3. Moves cursor to the top-left position
7561
- // More info: https://www.real-world-systems.com/docs/ANSIcode.html
7562
- `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
7563
-
7564
- ansiEscapes.beep = BEL;
7565
-
7566
- ansiEscapes.link = (text, url) => {
7567
- return [
7568
- OSC,
7569
- '8',
7570
- SEP,
7571
- SEP,
7572
- url,
7573
- BEL,
7574
- text,
7575
- OSC,
7576
- '8',
7577
- SEP,
7578
- SEP,
7579
- BEL
7580
- ].join('');
7581
- };
7582
-
7583
- ansiEscapes.image = (buffer, options = {}) => {
7584
- let returnValue = `${OSC}1337;File=inline=1`;
7585
-
7586
- if (options.width) {
7587
- returnValue += `;width=${options.width}`;
7588
- }
7589
-
7590
- if (options.height) {
7591
- returnValue += `;height=${options.height}`;
7592
- }
7593
-
7594
- if (options.preserveAspectRatio === false) {
7595
- returnValue += ';preserveAspectRatio=0';
7596
- }
7597
-
7598
- return returnValue + ':' + buffer.toString('base64') + BEL;
7599
- };
7600
-
7601
- ansiEscapes.iTerm = {
7602
- setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
7603
-
7604
- annotation: (message, options = {}) => {
7605
- let returnValue = `${OSC}1337;`;
7606
-
7607
- const hasX = typeof options.x !== 'undefined';
7608
- const hasY = typeof options.y !== 'undefined';
7609
- if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
7610
- throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
7611
- }
7612
-
7613
- message = message.replace(/\|/g, '');
7614
-
7615
- returnValue += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
7616
-
7617
- if (options.length > 0) {
7618
- returnValue +=
7619
- (hasX ?
7620
- [message, options.length, options.x, options.y] :
7621
- [options.length, message]).join('|');
7622
- } else {
7623
- returnValue += message;
7624
- }
7625
-
7626
- return returnValue + BEL;
7627
- }
7628
- };
7629
-
7630
- const restoreCursor = onetime$1.exports(() => {
7631
- signalExit.exports(() => {
7632
- process$1.stderr.write('\u001B[?25h');
7633
- }, {alwaysLast: true});
7634
- });
7635
-
7636
- let isHidden = false;
7637
-
7638
- const cliCursor = {};
7639
-
7640
- cliCursor.show = (writableStream = process$1.stderr) => {
7641
- if (!writableStream.isTTY) {
7642
- return;
7643
- }
7644
-
7645
- isHidden = false;
7646
- writableStream.write('\u001B[?25h');
7647
- };
7648
-
7649
- cliCursor.hide = (writableStream = process$1.stderr) => {
7650
- if (!writableStream.isTTY) {
7651
- return;
7652
- }
7653
-
7654
- restoreCursor();
7655
- isHidden = true;
7656
- writableStream.write('\u001B[?25l');
7657
- };
7658
-
7659
- cliCursor.toggle = (force, writableStream) => {
7660
- if (force !== undefined) {
7661
- isHidden = force;
7662
- }
7663
-
7664
- if (isHidden) {
7665
- cliCursor.show(writableStream);
7666
- } else {
7667
- cliCursor.hide(writableStream);
7668
- }
7669
- };
7670
-
7671
- const ESCAPES = new Set([
7672
- '\u001B',
7673
- '\u009B',
7674
- ]);
7675
-
7676
- const END_CODE = 39;
7677
- const ANSI_ESCAPE_BELL = '\u0007';
7678
- const ANSI_CSI = '[';
7679
- const ANSI_OSC = ']';
7680
- const ANSI_SGR_TERMINATOR = 'm';
7681
- const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
7682
-
7683
- const wrapAnsiCode = code => `${ESCAPES.values().next().value}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
7684
- const wrapAnsiHyperlink = uri => `${ESCAPES.values().next().value}${ANSI_ESCAPE_LINK}${uri}${ANSI_ESCAPE_BELL}`;
7685
-
7686
- // Calculate the length of words split on ' ', ignoring
7687
- // the extra characters added by ansi escape codes
7688
- const wordLengths = string => string.split(' ').map(character => stringWidth(character));
7689
-
7690
- // Wrap a long word across multiple rows
7691
- // Ansi escape codes do not count towards length
7692
- const wrapWord = (rows, word, columns) => {
7693
- const characters = [...word];
7694
-
7695
- let isInsideEscape = false;
7696
- let isInsideLinkEscape = false;
7697
- let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
7698
-
7699
- for (const [index, character] of characters.entries()) {
7700
- const characterLength = stringWidth(character);
7701
-
7702
- if (visible + characterLength <= columns) {
7703
- rows[rows.length - 1] += character;
7704
- } else {
7705
- rows.push(character);
7706
- visible = 0;
7707
- }
7708
-
7709
- if (ESCAPES.has(character)) {
7710
- isInsideEscape = true;
7711
- isInsideLinkEscape = characters.slice(index + 1).join('').startsWith(ANSI_ESCAPE_LINK);
7712
- }
7713
-
7714
- if (isInsideEscape) {
7715
- if (isInsideLinkEscape) {
7716
- if (character === ANSI_ESCAPE_BELL) {
7717
- isInsideEscape = false;
7718
- isInsideLinkEscape = false;
7719
- }
7720
- } else if (character === ANSI_SGR_TERMINATOR) {
7721
- isInsideEscape = false;
7722
- }
7723
-
7724
- continue;
7725
- }
7726
-
7727
- visible += characterLength;
7728
-
7729
- if (visible === columns && index < characters.length - 1) {
7730
- rows.push('');
7731
- visible = 0;
7732
- }
7733
- }
7734
-
7735
- // It's possible that the last row we copy over is only
7736
- // ansi escape characters, handle this edge-case
7737
- if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) {
7738
- rows[rows.length - 2] += rows.pop();
7739
- }
7740
- };
7741
-
7742
- // Trims spaces from a string ignoring invisible sequences
7743
- const stringVisibleTrimSpacesRight = string => {
7744
- const words = string.split(' ');
7745
- let last = words.length;
7746
-
7747
- while (last > 0) {
7748
- if (stringWidth(words[last - 1]) > 0) {
7749
- break;
7750
- }
7751
-
7752
- last--;
7753
- }
7754
-
7755
- if (last === words.length) {
7756
- return string;
7757
- }
7758
-
7759
- return words.slice(0, last).join(' ') + words.slice(last).join('');
7760
- };
7761
-
7762
- // The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
7763
- //
7764
- // 'hard' will never allow a string to take up more than columns characters
7765
- //
7766
- // 'soft' allows long words to expand past the column length
7767
- const exec = (string, columns, options = {}) => {
7768
- if (options.trim !== false && string.trim() === '') {
7769
- return '';
7770
- }
7771
-
7772
- let returnValue = '';
7773
- let escapeCode;
7774
- let escapeUrl;
7775
-
7776
- const lengths = wordLengths(string);
7777
- let rows = [''];
7778
-
7779
- for (const [index, word] of string.split(' ').entries()) {
7780
- if (options.trim !== false) {
7781
- rows[rows.length - 1] = rows[rows.length - 1].trimStart();
7782
- }
7783
-
7784
- let rowLength = stringWidth(rows[rows.length - 1]);
7785
-
7786
- if (index !== 0) {
7787
- if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
7788
- // If we start with a new word but the current row length equals the length of the columns, add a new row
7789
- rows.push('');
7790
- rowLength = 0;
7791
- }
7792
-
7793
- if (rowLength > 0 || options.trim === false) {
7794
- rows[rows.length - 1] += ' ';
7795
- rowLength++;
7796
- }
7797
- }
7798
-
7799
- // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
7800
- if (options.hard && lengths[index] > columns) {
7801
- const remainingColumns = (columns - rowLength);
7802
- const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
7803
- const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns);
7804
- if (breaksStartingNextLine < breaksStartingThisLine) {
7805
- rows.push('');
7806
- }
7807
-
7808
- wrapWord(rows, word, columns);
7809
- continue;
7810
- }
7811
-
7812
- if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
7813
- if (options.wordWrap === false && rowLength < columns) {
7814
- wrapWord(rows, word, columns);
7815
- continue;
7816
- }
7817
-
7818
- rows.push('');
7819
- }
7820
-
7821
- if (rowLength + lengths[index] > columns && options.wordWrap === false) {
7822
- wrapWord(rows, word, columns);
7823
- continue;
7824
- }
7825
-
7826
- rows[rows.length - 1] += word;
7827
- }
7828
-
7829
- if (options.trim !== false) {
7830
- rows = rows.map(row => stringVisibleTrimSpacesRight(row));
7831
- }
7832
-
7833
- const pre = [...rows.join('\n')];
7834
-
7835
- for (const [index, character] of pre.entries()) {
7836
- returnValue += character;
7837
-
7838
- if (ESCAPES.has(character)) {
7839
- const {groups} = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`).exec(pre.slice(index).join('')) || {groups: {}};
7840
- if (groups.code !== undefined) {
7841
- const code = Number.parseFloat(groups.code);
7842
- escapeCode = code === END_CODE ? undefined : code;
7843
- } else if (groups.uri !== undefined) {
7844
- escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
7845
- }
7846
- }
7847
-
7848
- const code = ansiStyles.codes.get(Number(escapeCode));
7849
-
7850
- if (pre[index + 1] === '\n') {
7851
- if (escapeUrl) {
7852
- returnValue += wrapAnsiHyperlink('');
7853
- }
7854
-
7855
- if (escapeCode && code) {
7856
- returnValue += wrapAnsiCode(code);
7857
- }
7858
- } else if (character === '\n') {
7859
- if (escapeCode && code) {
7860
- returnValue += wrapAnsiCode(escapeCode);
7861
- }
7862
-
7863
- if (escapeUrl) {
7864
- returnValue += wrapAnsiHyperlink(escapeUrl);
7865
- }
7866
- }
7867
- }
7868
-
7869
- return returnValue;
7870
- };
7871
-
7872
- // For each newline, invoke the method separately
7873
- function wrapAnsi(string, columns, options) {
7874
- return String(string)
7875
- .normalize()
7876
- .replace(/\r\n/g, '\n')
7877
- .split('\n')
7878
- .map(line => exec(line, columns, options))
7879
- .join('\n');
7880
- }
7881
-
7882
- const defaultTerminalHeight = 24;
7883
-
7884
- const getWidth = stream => {
7885
- const {columns} = stream;
7886
-
7887
- if (!columns) {
7888
- return 80;
7889
- }
7890
-
7891
- return columns;
7892
- };
7893
-
7894
- const fitToTerminalHeight = (stream, text) => {
7895
- const terminalHeight = stream.rows || defaultTerminalHeight;
7896
- const lines = text.split('\n');
7897
-
7898
- const toRemove = lines.length - terminalHeight;
7899
- if (toRemove <= 0) {
7900
- return text;
7901
- }
7902
-
7903
- return sliceAnsi(
7904
- text,
7905
- stripAnsi(lines.slice(0, toRemove).join('\n')).length + 1,
7906
- );
7907
- };
7908
-
7909
- function createLogUpdate(stream, {showCursor = false} = {}) {
7910
- let previousLineCount = 0;
7911
- let previousWidth = getWidth(stream);
7912
- let previousOutput = '';
7913
-
7914
- const render = (...arguments_) => {
7915
- if (!showCursor) {
7916
- cliCursor.hide();
7917
- }
7918
-
7919
- let output = arguments_.join(' ') + '\n';
7920
- output = fitToTerminalHeight(stream, output);
7921
- const width = getWidth(stream);
7922
- if (output === previousOutput && previousWidth === width) {
7923
- return;
7924
- }
7925
-
7926
- previousOutput = output;
7927
- previousWidth = width;
7928
- output = wrapAnsi(output, width, {
7929
- trim: false,
7930
- hard: true,
7931
- wordWrap: false,
7932
- });
7933
- stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
7934
- previousLineCount = output.split('\n').length;
7935
- };
7936
-
7937
- render.clear = () => {
7938
- stream.write(ansiEscapes.eraseLines(previousLineCount));
7939
- previousOutput = '';
7940
- previousWidth = getWidth(stream);
7941
- previousLineCount = 0;
7942
- };
7943
-
7944
- render.done = () => {
7945
- previousOutput = '';
7946
- previousWidth = getWidth(stream);
7947
- previousLineCount = 0;
7948
-
7949
- if (!showCursor) {
7950
- cliCursor.show();
7951
- }
7952
- };
7953
-
7954
- return render;
7955
- }
7956
-
7957
- createLogUpdate(process$1.stdout);
7958
-
7959
- createLogUpdate(process$1.stderr);
7960
-
7961
- const DURATION_LONG = 300;
7962
- const outputMap = /* @__PURE__ */ new WeakMap();
7963
- function formatFilepath(path) {
7964
- const lastSlash = Math.max(path.lastIndexOf("/") + 1, 0);
7965
- const basename = path.slice(lastSlash);
7966
- let firstDot = basename.indexOf(".");
7967
- if (firstDot < 0)
7968
- firstDot = basename.length;
7969
- firstDot += lastSlash;
7970
- return picocolors.exports.dim(path.slice(0, lastSlash)) + path.slice(lastSlash, firstDot) + picocolors.exports.dim(path.slice(firstDot));
7971
- }
7972
- function renderHookState(task, hookName, level = 0) {
7973
- var _a, _b;
7974
- const state = (_b = (_a = task.result) == null ? void 0 : _a.hooks) == null ? void 0 : _b[hookName];
7975
- if (state && state === "run")
7976
- return `${" ".repeat(level)} ${getHookStateSymbol(task, hookName)} ${picocolors.exports.dim(`[ ${hookName} ]`)}`;
7977
- return "";
7978
- }
7979
- function renderTree(tasks, options, level = 0) {
7980
- var _a, _b, _c, _d, _e;
7981
- let output = [];
7982
- for (const task of tasks) {
7983
- let suffix = "";
7984
- const prefix = ` ${getStateSymbol(task)} `;
7985
- if (task.type === "suite")
7986
- suffix += picocolors.exports.dim(` (${getTests(task).length})`);
7987
- if (task.mode === "skip" || task.mode === "todo")
7988
- suffix += ` ${picocolors.exports.dim(picocolors.exports.gray("[skipped]"))}`;
7989
- if (((_a = task.result) == null ? void 0 : _a.duration) != null) {
7990
- if (task.result.duration > DURATION_LONG)
7991
- suffix += picocolors.exports.yellow(` ${Math.round(task.result.duration)}${picocolors.exports.dim("ms")}`);
7992
- }
7993
- if (options.showHeap && ((_b = task.result) == null ? void 0 : _b.heap) != null)
7994
- suffix += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
7995
- let name = task.name;
7996
- if (level === 0)
7997
- name = formatFilepath(name);
7998
- output.push(" ".repeat(level) + prefix + name + suffix);
7999
- if (((_c = task.result) == null ? void 0 : _c.state) !== "pass" && outputMap.get(task) != null) {
8000
- let data = outputMap.get(task);
8001
- if (typeof data === "string") {
8002
- data = stripAnsi(data.trim().split("\n").filter(Boolean).pop());
8003
- if (data === "")
8004
- data = void 0;
8005
- }
8006
- if (data != null) {
8007
- const out = `${" ".repeat(level)}${F_RIGHT} ${data}`;
8008
- output.push(` ${picocolors.exports.gray(cliTruncate(out, getCols(-3)))}`);
8009
- }
8010
- }
8011
- output = output.concat(renderHookState(task, "beforeAll", level + 1));
8012
- output = output.concat(renderHookState(task, "beforeEach", level + 1));
8013
- if (task.type === "suite" && task.tasks.length > 0) {
8014
- if (((_d = task.result) == null ? void 0 : _d.state) === "fail" || ((_e = task.result) == null ? void 0 : _e.state) === "run" || options.renderSucceed)
8015
- output = output.concat(renderTree(task.tasks, options, level + 1));
8016
- }
8017
- output = output.concat(renderHookState(task, "afterAll", level + 1));
8018
- output = output.concat(renderHookState(task, "afterEach", level + 1));
8019
- }
8020
- return output.filter(Boolean).join("\n");
8021
- }
8022
- const createListRenderer = (_tasks, options) => {
8023
- let tasks = _tasks;
8024
- let timer;
8025
- const log = createLogUpdate(options.outputStream);
8026
- function update() {
8027
- log(renderTree(tasks, options));
8028
- }
8029
- return {
8030
- start() {
8031
- if (timer)
8032
- return this;
8033
- timer = safeSetInterval(update, 200);
8034
- return this;
8035
- },
8036
- update(_tasks2) {
8037
- tasks = _tasks2;
8038
- update();
8039
- return this;
8040
- },
8041
- async stop() {
8042
- if (timer) {
8043
- safeClearInterval(timer);
8044
- timer = void 0;
8045
- }
8046
- log.clear();
8047
- options.outputStream.write(`${renderTree(tasks, options)}
8048
- `);
8049
- return this;
8050
- },
8051
- clear() {
8052
- log.clear();
8053
- }
8054
- };
8055
- };
8056
-
8057
- class DefaultReporter extends BaseReporter {
8058
- constructor() {
8059
- super(...arguments);
8060
- this.rendererOptions = {};
8061
- }
8062
- async onTestRemoved(trigger) {
8063
- await this.stopListRender();
8064
- this.ctx.clearScreen();
8065
- this.ctx.log(picocolors.exports.yellow("Test removed...") + (trigger ? picocolors.exports.dim(` [ ${this.relative(trigger)} ]
8066
- `) : ""));
8067
- const files = this.ctx.state.getFiles(this.watchFilters);
8068
- createListRenderer(files, this.rendererOptions).stop();
8069
- this.ctx.log();
8070
- await super.reportSummary(files);
8071
- super.onWatcherStart();
8072
- }
8073
- onCollected() {
8074
- if (this.isTTY) {
8075
- this.rendererOptions.outputStream = this.ctx.outputStream;
8076
- this.rendererOptions.showHeap = this.ctx.config.logHeapUsage;
8077
- const files = this.ctx.state.getFiles(this.watchFilters);
8078
- if (!this.renderer)
8079
- this.renderer = createListRenderer(files, this.rendererOptions).start();
8080
- else
8081
- this.renderer.update(files);
8082
- }
8083
- }
8084
- async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
8085
- await this.stopListRender();
8086
- this.ctx.log();
8087
- await super.onFinished(files, errors);
8088
- }
8089
- async onWatcherStart() {
8090
- await this.stopListRender();
8091
- super.onWatcherStart();
8092
- }
8093
- async stopListRender() {
8094
- var _a;
8095
- await ((_a = this.renderer) == null ? void 0 : _a.stop());
8096
- this.renderer = void 0;
8097
- }
8098
- async onWatcherRerun(files, trigger) {
8099
- await this.stopListRender();
8100
- await super.onWatcherRerun(files, trigger);
8101
- }
8102
- onUserConsoleLog(log) {
8103
- var _a;
8104
- if (!this.shouldLog(log))
8105
- return;
8106
- (_a = this.renderer) == null ? void 0 : _a.clear();
8107
- super.onUserConsoleLog(log);
8108
- }
8109
- }
8110
-
8111
- const check = picocolors.exports.green("\xB7");
8112
- const cross = picocolors.exports.red("x");
8113
- const pending = picocolors.exports.yellow("*");
8114
- const skip = picocolors.exports.dim(picocolors.exports.gray("-"));
8115
- function render(tasks) {
8116
- const all = getTests(tasks);
8117
- return all.map((i) => {
8118
- var _a;
8119
- if (i.mode === "skip" || i.mode === "todo")
8120
- return skip;
8121
- switch ((_a = i.result) == null ? void 0 : _a.state) {
8122
- case "pass":
8123
- return check;
8124
- case "fail":
8125
- return cross;
8126
- default:
8127
- return pending;
8128
- }
8129
- }).join("");
8130
- }
8131
- const createDotRenderer = (_tasks, options) => {
8132
- let tasks = _tasks;
8133
- let timer;
8134
- const log = createLogUpdate(options.outputStream);
8135
- function update() {
8136
- log(render(tasks));
8137
- }
8138
- return {
8139
- start() {
8140
- if (timer)
8141
- return this;
8142
- timer = safeSetInterval(update, 200);
8143
- return this;
8144
- },
8145
- update(_tasks2) {
8146
- tasks = _tasks2;
8147
- update();
8148
- return this;
8149
- },
8150
- async stop() {
8151
- if (timer) {
8152
- safeClearInterval(timer);
8153
- timer = void 0;
8154
- }
8155
- log.clear();
8156
- options.outputStream.write(`${render(tasks)}
8157
- `);
8158
- return this;
8159
- },
8160
- clear() {
8161
- log.clear();
8162
- }
8163
- };
8164
- };
8165
-
8166
- class DotReporter extends BaseReporter {
8167
- onCollected() {
8168
- if (this.isTTY) {
8169
- const files = this.ctx.state.getFiles(this.watchFilters);
8170
- if (!this.renderer)
8171
- this.renderer = createDotRenderer(files, { outputStream: this.ctx.outputStream }).start();
8172
- else
8173
- this.renderer.update(files);
8174
- }
8175
- }
8176
- async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
8177
- await this.stopListRender();
8178
- this.ctx.log();
8179
- await super.onFinished(files, errors);
8180
- }
8181
- async onWatcherStart() {
8182
- await this.stopListRender();
8183
- super.onWatcherStart();
8184
- }
8185
- async stopListRender() {
8186
- var _a;
8187
- (_a = this.renderer) == null ? void 0 : _a.stop();
8188
- this.renderer = void 0;
8189
- await new Promise((resolve) => safeSetTimeout(resolve, 10));
8190
- }
8191
- async onWatcherRerun(files, trigger) {
8192
- await this.stopListRender();
8193
- await super.onWatcherRerun(files, trigger);
8194
- }
8195
- onUserConsoleLog(log) {
8196
- var _a;
8197
- (_a = this.renderer) == null ? void 0 : _a.clear();
8198
- super.onUserConsoleLog(log);
8199
- }
8200
- }
8201
-
8202
- const getOutputFile = ({ config }, reporter) => {
8203
- if (!config.outputFile)
8204
- return;
8205
- if (typeof config.outputFile === "string")
8206
- return config.outputFile;
8207
- return config.outputFile[reporter];
7744
+ const getOutputFile = ({ config }, reporter) => {
7745
+ if (!config.outputFile)
7746
+ return;
7747
+ if (typeof config.outputFile === "string")
7748
+ return config.outputFile;
7749
+ return config.outputFile[reporter];
8208
7750
  };
8209
7751
 
8210
7752
  const StatusMap = {
@@ -8277,14 +7819,15 @@ class JsonReporter {
8277
7819
  status: StatusMap[((_a2 = t.result) == null ? void 0 : _a2.state) || t.mode] || "skipped",
8278
7820
  title: t.name,
8279
7821
  duration: (_b2 = t.result) == null ? void 0 : _b2.duration,
8280
- failureMessages: ((_d = (_c = t.result) == null ? void 0 : _c.error) == null ? void 0 : _d.message) == null ? [] : [t.result.error.message]
7822
+ failureMessages: ((_d = (_c = t.result) == null ? void 0 : _c.error) == null ? void 0 : _d.message) == null ? [] : [t.result.error.message],
7823
+ location: this.getFailureLocation(t)
8281
7824
  };
8282
7825
  });
8283
7826
  if (tests2.some((t) => {
8284
7827
  var _a2;
8285
7828
  return ((_a2 = t.result) == null ? void 0 : _a2.state) === "run";
8286
7829
  })) {
8287
- this.ctx.console.warn("WARNING: Some tests are still running when generating the JSON report.This is likely an internal bug in Vitest.Please report it to https://github.com/vitest-dev/vitest/issues");
7830
+ this.ctx.logger.warn("WARNING: Some tests are still running when generating the JSON report.This is likely an internal bug in Vitest.Please report it to https://github.com/vitest-dev/vitest/issues");
8288
7831
  }
8289
7832
  testResults.push({
8290
7833
  assertionResults,
@@ -8325,11 +7868,23 @@ class JsonReporter {
8325
7868
  if (!existsSync(outputDirectory))
8326
7869
  await promises.mkdir(outputDirectory, { recursive: true });
8327
7870
  await promises.writeFile(reportFile, report, "utf-8");
8328
- this.ctx.log(`JSON report written to ${reportFile}`);
7871
+ this.ctx.logger.log(`JSON report written to ${reportFile}`);
8329
7872
  } else {
8330
- this.ctx.log(report);
7873
+ this.ctx.logger.log(report);
8331
7874
  }
8332
7875
  }
7876
+ getFailureLocation(test) {
7877
+ var _a;
7878
+ const error = (_a = test.result) == null ? void 0 : _a.error;
7879
+ if (!error)
7880
+ return;
7881
+ const stack = parseStacktrace(error);
7882
+ const frame = stack[stack.length - 1];
7883
+ if (!frame)
7884
+ return;
7885
+ const pos = frame.sourcePos || frame;
7886
+ return { line: pos.line, column: pos.column };
7887
+ }
8333
7888
  }
8334
7889
 
8335
7890
  class VerboseReporter extends DefaultReporter {
@@ -8347,9 +7902,9 @@ class VerboseReporter extends DefaultReporter {
8347
7902
  let title = ` ${getStateSymbol(task)} ${getFullName(task)}`;
8348
7903
  if (this.ctx.config.logHeapUsage && task.result.heap != null)
8349
7904
  title += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
8350
- this.ctx.log(title);
7905
+ this.ctx.logger.log(title);
8351
7906
  if (task.result.state === "fail")
8352
- this.ctx.log(picocolors.exports.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
7907
+ this.ctx.logger.log(picocolors.exports.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
8353
7908
  }
8354
7909
  }
8355
7910
  }
@@ -8380,7 +7935,7 @@ function tapString(str) {
8380
7935
  class TapReporter {
8381
7936
  onInit(ctx) {
8382
7937
  this.ctx = ctx;
8383
- this.logger = new IndentedLogger(this.ctx.log.bind(this.ctx));
7938
+ this.logger = new IndentedLogger(this.ctx.logger.log.bind(this.ctx));
8384
7939
  }
8385
7940
  static getComment(task) {
8386
7941
  var _a;
@@ -8483,7 +8038,7 @@ class JUnitReporter {
8483
8038
  this.baseLog = async (text) => await promises.writeFile(fileFd, `${text}
8484
8039
  `);
8485
8040
  } else {
8486
- this.baseLog = async (text) => this.ctx.log(text);
8041
+ this.baseLog = async (text) => this.ctx.logger.log(text);
8487
8042
  }
8488
8043
  this.logger = new IndentedLogger(this.baseLog);
8489
8044
  }
@@ -8590,7 +8145,7 @@ class JUnitReporter {
8590
8145
  }
8591
8146
  });
8592
8147
  if (this.reportFile)
8593
- this.ctx.log(`JUNIT report written to ${this.reportFile}`);
8148
+ this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
8594
8149
  }
8595
8150
  }
8596
8151
 
@@ -8610,7 +8165,7 @@ class TapFlatReporter extends TapReporter {
8610
8165
  super.onInit(ctx);
8611
8166
  }
8612
8167
  async onFinished(files = this.ctx.state.getFiles()) {
8613
- this.ctx.log("TAP version 13");
8168
+ this.ctx.logger.log("TAP version 13");
8614
8169
  const flatTasks = files.flatMap((task) => flattenTasks(task));
8615
8170
  this.logTasks(flatTasks);
8616
8171
  }
@@ -8653,95 +8208,13 @@ function createReporters(reporterReferences, runner) {
8653
8208
  return Promise.all(promisedReporters);
8654
8209
  }
8655
8210
 
8656
- class FilesStatsCache {
8657
- constructor() {
8658
- this.cache = /* @__PURE__ */ new Map();
8659
- }
8660
- getStats(fsPath) {
8661
- return this.cache.get(fsPath);
8662
- }
8663
- async updateStats(fsPath) {
8664
- if (!fs$8.existsSync(fsPath))
8665
- return;
8666
- const stats = await fs$8.promises.stat(fsPath);
8667
- this.cache.set(fsPath, { size: stats.size });
8668
- }
8669
- removeStats(fsPath) {
8670
- this.cache.delete(fsPath);
8671
- }
8672
- }
8673
-
8674
- class ResultsCache {
8675
- constructor() {
8676
- this.cache = /* @__PURE__ */ new Map();
8677
- this.cachePath = null;
8678
- this.version = version;
8679
- this.root = "/";
8680
- }
8681
- setConfig(root, config) {
8682
- this.root = root;
8683
- if (config)
8684
- this.cachePath = resolve(config.dir, "results.json");
8685
- }
8686
- getResults(fsPath) {
8687
- return this.cache.get(fsPath == null ? void 0 : fsPath.slice(this.root.length));
8688
- }
8689
- async readFromCache() {
8690
- if (!this.cachePath)
8691
- return;
8692
- if (fs$8.existsSync(this.cachePath)) {
8693
- const resultsCache = await fs$8.promises.readFile(this.cachePath, "utf8");
8694
- const { results, version: version2 } = JSON.parse(resultsCache);
8695
- this.cache = new Map(results);
8696
- this.version = version2;
8697
- }
8698
- }
8699
- updateResults(files) {
8700
- files.forEach((file) => {
8701
- var _a;
8702
- const result = file.result;
8703
- if (!result)
8704
- return;
8705
- const duration = result.duration || 0;
8706
- const relativePath = (_a = file.filepath) == null ? void 0 : _a.slice(this.root.length);
8707
- this.cache.set(relativePath, {
8708
- duration: duration >= 0 ? duration : 0,
8709
- failed: result.state === "fail"
8710
- });
8711
- });
8712
- }
8713
- removeFromCache(filepath) {
8714
- this.cache.delete(filepath);
8715
- }
8716
- async writeToCache() {
8717
- if (!this.cachePath)
8718
- return;
8719
- const results = Array.from(this.cache.entries());
8720
- const cacheDirname = dirname(this.cachePath);
8721
- if (!fs$8.existsSync(cacheDirname))
8722
- await fs$8.promises.mkdir(cacheDirname, { recursive: true });
8723
- const cache = JSON.stringify({
8724
- version: this.version,
8725
- results
8726
- });
8727
- await fs$8.promises.writeFile(this.cachePath, cache);
8728
- }
8729
- }
8730
-
8731
8211
  class StateManager {
8732
8212
  constructor() {
8733
8213
  this.filesMap = /* @__PURE__ */ new Map();
8214
+ this.pathsSet = /* @__PURE__ */ new Set();
8734
8215
  this.idMap = /* @__PURE__ */ new Map();
8735
8216
  this.taskFileMap = /* @__PURE__ */ new WeakMap();
8736
8217
  this.errorsSet = /* @__PURE__ */ new Set();
8737
- this.results = new ResultsCache();
8738
- this.stats = new FilesStatsCache();
8739
- }
8740
- getFileTestResults(id) {
8741
- return this.results.getResults(id);
8742
- }
8743
- getFileStats(id) {
8744
- return this.stats.getStats(id);
8745
8218
  }
8746
8219
  catchError(err, type) {
8747
8220
  err.type = type;
@@ -8753,6 +8226,9 @@ class StateManager {
8753
8226
  getUnhandledErrors() {
8754
8227
  return Array.from(this.errorsSet.values());
8755
8228
  }
8229
+ getPaths() {
8230
+ return Array.from(this.pathsSet);
8231
+ }
8756
8232
  getFiles(keys) {
8757
8233
  if (keys)
8758
8234
  return keys.map((key) => this.filesMap.get(key)).filter(Boolean);
@@ -8767,12 +8243,22 @@ class StateManager {
8767
8243
  return ((_a = i.result) == null ? void 0 : _a.state) === "fail";
8768
8244
  }).map((i) => i.filepath);
8769
8245
  }
8246
+ collectPaths(paths = []) {
8247
+ paths.forEach((path) => {
8248
+ this.pathsSet.add(path);
8249
+ });
8250
+ }
8770
8251
  collectFiles(files = []) {
8771
8252
  files.forEach((file) => {
8772
8253
  this.filesMap.set(file.filepath, file);
8773
8254
  this.updateId(file);
8774
8255
  });
8775
8256
  }
8257
+ clearFiles(paths = []) {
8258
+ paths.forEach((path) => {
8259
+ this.filesMap.delete(path);
8260
+ });
8261
+ }
8776
8262
  updateId(task) {
8777
8263
  if (this.idMap.get(task.id) === task)
8778
8264
  return;
@@ -8783,23 +8269,111 @@ class StateManager {
8783
8269
  });
8784
8270
  }
8785
8271
  }
8786
- updateTasks(packs) {
8787
- for (const [id, result] of packs) {
8788
- if (this.idMap.has(id))
8789
- this.idMap.get(id).result = result;
8790
- }
8272
+ updateTasks(packs) {
8273
+ for (const [id, result] of packs) {
8274
+ if (this.idMap.has(id))
8275
+ this.idMap.get(id).result = result;
8276
+ }
8277
+ }
8278
+ updateUserLog(log) {
8279
+ const task = log.taskId && this.idMap.get(log.taskId);
8280
+ if (task) {
8281
+ if (!task.logs)
8282
+ task.logs = [];
8283
+ task.logs.push(log);
8284
+ }
8285
+ }
8286
+ }
8287
+
8288
+ class FilesStatsCache {
8289
+ constructor() {
8290
+ this.cache = /* @__PURE__ */ new Map();
8291
+ }
8292
+ getStats(fsPath) {
8293
+ return this.cache.get(fsPath);
8294
+ }
8295
+ async updateStats(fsPath) {
8296
+ if (!fs$8.existsSync(fsPath))
8297
+ return;
8298
+ const stats = await fs$8.promises.stat(fsPath);
8299
+ this.cache.set(fsPath, { size: stats.size });
8300
+ }
8301
+ removeStats(fsPath) {
8302
+ this.cache.delete(fsPath);
8303
+ }
8304
+ }
8305
+
8306
+ class ResultsCache {
8307
+ constructor() {
8308
+ this.cache = /* @__PURE__ */ new Map();
8309
+ this.cachePath = null;
8310
+ this.version = version$1;
8311
+ this.root = "/";
8312
+ }
8313
+ getCachePath() {
8314
+ return this.cachePath;
8315
+ }
8316
+ setConfig(root, config) {
8317
+ this.root = root;
8318
+ if (config)
8319
+ this.cachePath = resolve(config.dir, "results.json");
8320
+ }
8321
+ getResults(fsPath) {
8322
+ return this.cache.get(fsPath == null ? void 0 : fsPath.slice(this.root.length));
8323
+ }
8324
+ async readFromCache() {
8325
+ if (!this.cachePath)
8326
+ return;
8327
+ if (fs$8.existsSync(this.cachePath)) {
8328
+ const resultsCache = await fs$8.promises.readFile(this.cachePath, "utf8");
8329
+ const { results, version: version2 } = JSON.parse(resultsCache);
8330
+ this.cache = new Map(results);
8331
+ this.version = version2;
8332
+ }
8333
+ }
8334
+ updateResults(files) {
8335
+ files.forEach((file) => {
8336
+ var _a;
8337
+ const result = file.result;
8338
+ if (!result)
8339
+ return;
8340
+ const duration = result.duration || 0;
8341
+ const relativePath = (_a = file.filepath) == null ? void 0 : _a.slice(this.root.length);
8342
+ this.cache.set(relativePath, {
8343
+ duration: duration >= 0 ? duration : 0,
8344
+ failed: result.state === "fail"
8345
+ });
8346
+ });
8791
8347
  }
8792
- updateUserLog(log) {
8793
- const task = log.taskId && this.idMap.get(log.taskId);
8794
- if (task) {
8795
- if (!task.logs)
8796
- task.logs = [];
8797
- task.logs.push(log);
8798
- }
8348
+ removeFromCache(filepath) {
8349
+ this.cache.delete(filepath);
8350
+ }
8351
+ async writeToCache() {
8352
+ if (!this.cachePath)
8353
+ return;
8354
+ const results = Array.from(this.cache.entries());
8355
+ const cacheDirname = dirname(this.cachePath);
8356
+ if (!fs$8.existsSync(cacheDirname))
8357
+ await fs$8.promises.mkdir(cacheDirname, { recursive: true });
8358
+ const cache = JSON.stringify({
8359
+ version: this.version,
8360
+ results
8361
+ });
8362
+ await fs$8.promises.writeFile(this.cachePath, cache);
8799
8363
  }
8800
8364
  }
8801
8365
 
8802
8366
  class VitestCache {
8367
+ constructor() {
8368
+ this.results = new ResultsCache();
8369
+ this.stats = new FilesStatsCache();
8370
+ }
8371
+ getFileTestResults(id) {
8372
+ return this.results.getResults(id);
8373
+ }
8374
+ getFileStats(id) {
8375
+ return this.stats.getStats(id);
8376
+ }
8803
8377
  static resolveCacheDir(root, dir) {
8804
8378
  return resolve(root, slash$2(dir || "node_modules/.vitest"));
8805
8379
  }
@@ -8841,13 +8415,13 @@ class BaseSequencer {
8841
8415
  }).sort((a, b) => a.hash < b.hash ? -1 : a.hash > b.hash ? 1 : 0).slice(shardStart, shardEnd).map(({ file }) => file);
8842
8416
  }
8843
8417
  async sort(files) {
8844
- const { state } = this.ctx;
8418
+ const cache = this.ctx.cache;
8845
8419
  return [...files].sort((a, b) => {
8846
- const aState = state.getFileTestResults(a);
8847
- const bState = state.getFileTestResults(b);
8420
+ const aState = cache.getFileTestResults(a);
8421
+ const bState = cache.getFileTestResults(b);
8848
8422
  if (!aState || !bState) {
8849
- const statsA = state.getFileStats(a);
8850
- const statsB = state.getFileStats(b);
8423
+ const statsA = cache.getFileStats(a);
8424
+ const statsB = cache.getFileStats(b);
8851
8425
  if (!statsA || !statsB)
8852
8426
  return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0;
8853
8427
  return statsB.size - statsA.size;
@@ -8880,7 +8454,7 @@ const extraInlineDeps = [
8880
8454
  ];
8881
8455
  function resolveApiConfig(options) {
8882
8456
  let api;
8883
- if (options.ui && !options.api)
8457
+ if ((options.ui || options.browser) && !options.api)
8884
8458
  api = { port: defaultPort };
8885
8459
  else if (options.api === true)
8886
8460
  api = { port: defaultPort };
@@ -8930,1357 +8504,810 @@ function resolveConfig(options, viteConfig) {
8930
8504
  throw new Error("--shard <count> must be a positive number");
8931
8505
  if (isNaN(index) || index <= 0 || index > count)
8932
8506
  throw new Error("--shard <index> must be a positive number less then <count>");
8933
- resolved.shard = { index, count };
8934
- }
8935
- resolved.deps = resolved.deps || {};
8936
- if (resolved.deps.inline !== true) {
8937
- const ssrOptions = viteConfig.ssr;
8938
- if ((ssrOptions == null ? void 0 : ssrOptions.noExternal) === true && resolved.deps.inline == null) {
8939
- resolved.deps.inline = true;
8940
- } else {
8941
- (_b = resolved.deps).inline ?? (_b.inline = []);
8942
- resolved.deps.inline.push(...extraInlineDeps);
8943
- }
8944
- }
8945
- resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
8946
- const CI = !!process.env.CI;
8947
- const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
8948
- resolved.snapshotOptions = {
8949
- snapshotFormat: resolved.snapshotFormat || {},
8950
- updateSnapshot: CI && !UPDATE_SNAPSHOT ? "none" : UPDATE_SNAPSHOT ? "all" : "new",
8951
- resolveSnapshotPath: options.resolveSnapshotPath
8952
- };
8953
- if (options.resolveSnapshotPath)
8954
- delete resolved.resolveSnapshotPath;
8955
- if (process.env.VITEST_MAX_THREADS)
8956
- resolved.maxThreads = parseInt(process.env.VITEST_MAX_THREADS);
8957
- if (process.env.VITEST_MIN_THREADS)
8958
- resolved.minThreads = parseInt(process.env.VITEST_MIN_THREADS);
8959
- resolved.setupFiles = toArray$1(resolved.setupFiles || []).map((file) => normalize(resolveModule(file, { paths: [resolved.root] }) ?? resolve(resolved.root, file)));
8960
- resolved.api = resolveApiConfig(options);
8961
- if (options.related)
8962
- resolved.related = toArray$1(options.related).map((file) => resolve(resolved.root, file));
8963
- resolved.reporters = Array.from(/* @__PURE__ */ new Set([
8964
- ...toArray$1(resolved.reporters),
8965
- ...toArray$1(resolved.reporter)
8966
- ])).filter(Boolean);
8967
- if (!resolved.reporters.length)
8968
- resolved.reporters.push("default");
8969
- if (resolved.changed)
8970
- resolved.passWithNoTests ?? (resolved.passWithNoTests = true);
8971
- resolved.css ?? (resolved.css = {});
8972
- if (typeof resolved.css === "object")
8973
- (_c = resolved.css).include ?? (_c.include = [/\.module\./]);
8974
- resolved.cache ?? (resolved.cache = { dir: "" });
8975
- if (resolved.cache)
8976
- resolved.cache.dir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir);
8977
- if (!((_d = resolved.sequence) == null ? void 0 : _d.sequencer)) {
8978
- resolved.sequence ?? (resolved.sequence = {});
8979
- resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
8980
- }
8981
- return resolved;
8982
- }
8983
-
8984
- function fileFromParsedStack(stack) {
8985
- var _a, _b;
8986
- if ((_b = (_a = stack == null ? void 0 : stack.sourcePos) == null ? void 0 : _a.source) == null ? void 0 : _b.startsWith(".."))
8987
- return join(stack.file, "../", stack.sourcePos.source);
8988
- return stack.file;
8989
- }
8990
- async function printError(error, ctx, options = {}) {
8991
- const { showCodeFrame = true, fullStack = false, type } = options;
8992
- let e = error;
8993
- if (typeof error === "string") {
8994
- e = {
8995
- message: error.split(/\n/g)[0],
8996
- stack: error
8997
- };
8998
- }
8999
- const stacks = parseStacktrace(e, fullStack);
9000
- await interpretSourcePos(stacks, ctx);
9001
- const nearest = stacks.find((stack) => ctx.server.moduleGraph.getModuleById(stack.file) && existsSync(stack.file));
9002
- const errorProperties = getErrorProperties(e);
9003
- if (type)
9004
- printErrorType(type, ctx);
9005
- printErrorMessage(e, ctx.console);
9006
- printStack(ctx, stacks, nearest, errorProperties, (s, pos) => {
9007
- if (showCodeFrame && s === nearest && nearest) {
9008
- const file = fileFromParsedStack(nearest);
9009
- if (existsSync(file)) {
9010
- const sourceCode = readFileSync(file, "utf-8");
9011
- ctx.log(picocolors.exports.yellow(generateCodeFrame(sourceCode, 4, pos)));
9012
- }
9013
- }
9014
- });
9015
- if (e.cause) {
9016
- e.cause.name = `Caused by: ${e.cause.name}`;
9017
- await printError(e.cause, ctx, { fullStack, showCodeFrame: false });
9018
- }
9019
- handleImportOutsideModuleError(e.stack || e.stackStr || "", ctx);
9020
- if (e.showDiff) {
9021
- displayDiff(stringify$5(e.actual), stringify$5(e.expected), ctx.console, {
9022
- outputTruncateLength: ctx.config.outputTruncateLength,
9023
- outputDiffLines: ctx.config.outputDiffLines
9024
- });
9025
- }
9026
- }
9027
- function printErrorType(type, ctx) {
9028
- ctx.error(`
9029
- ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` ${type} `))))}`);
9030
- }
9031
- const skipErrorProperties = [
9032
- "message",
9033
- "name",
9034
- "nameStr",
9035
- "stack",
9036
- "cause",
9037
- "stacks",
9038
- "stackStr",
9039
- "type",
9040
- "showDiff",
9041
- "actual",
9042
- "expected",
9043
- "constructor",
9044
- "toString"
9045
- ];
9046
- function getErrorProperties(e) {
9047
- const errorObject = /* @__PURE__ */ Object.create(null);
9048
- if (e.name === "AssertionError")
9049
- return errorObject;
9050
- for (const key of Object.getOwnPropertyNames(e)) {
9051
- if (!skipErrorProperties.includes(key))
9052
- errorObject[key] = e[key];
9053
- }
9054
- return errorObject;
9055
- }
9056
- const esmErrors = [
9057
- "Cannot use import statement outside a module",
9058
- "Unexpected token 'export'"
9059
- ];
9060
- function handleImportOutsideModuleError(stack, ctx) {
9061
- if (!esmErrors.some((e) => stack.includes(e)))
9062
- return;
9063
- const path = normalize(stack.split("\n")[0].trim());
9064
- let name = path.split("/node_modules/").pop() || "";
9065
- if (name == null ? void 0 : name.startsWith("@"))
9066
- name = name.split("/").slice(0, 2).join("/");
9067
- else
9068
- name = name.split("/")[0];
9069
- ctx.error(picocolors.exports.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${picocolors.exports.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
9070
-
9071
- As a temporary workaround you can try to inline the package by updating your config:
9072
-
9073
- ` + picocolors.exports.gray(picocolors.exports.dim("// vitest.config.js")) + "\n" + picocolors.exports.green(`export default {
9074
- test: {
9075
- deps: {
9076
- inline: [
9077
- ${picocolors.exports.yellow(picocolors.exports.bold(`"${name}"`))}
9078
- ]
9079
- }
9080
- }
9081
- }
9082
- `)));
9083
- }
9084
- function displayDiff(actual, expected, console, options) {
9085
- console.error(picocolors.exports.gray(unifiedDiff(actual, expected, options)) + "\n");
9086
- }
9087
- function printErrorMessage(error, console) {
9088
- const errorName = error.name || error.nameStr || "Unknown Error";
9089
- console.error(picocolors.exports.red(`${picocolors.exports.bold(errorName)}: ${error.message}`));
9090
- }
9091
- function printStack(ctx, stack, highlight, errorProperties, onStack) {
9092
- if (!stack.length)
9093
- return;
9094
- for (const frame of stack) {
9095
- const pos = frame.sourcePos || frame;
9096
- const color = frame === highlight ? picocolors.exports.yellow : picocolors.exports.gray;
9097
- const file = fileFromParsedStack(frame);
9098
- const path = relative(ctx.config.root, file);
9099
- ctx.log(color(` ${picocolors.exports.dim(F_POINTER)} ${[frame.method, picocolors.exports.dim(`${path}:${pos.line}:${pos.column}`)].filter(Boolean).join(" ")}`));
9100
- onStack == null ? void 0 : onStack(frame, pos);
9101
- if (frame.file in ctx.state.filesMap)
9102
- break;
9103
- }
9104
- ctx.log();
9105
- const hasProperties = Object.keys(errorProperties).length > 0;
9106
- if (hasProperties) {
9107
- ctx.log(picocolors.exports.red(picocolors.exports.dim(divider())));
9108
- const propertiesString = stringify$5(errorProperties, 10, { printBasicPrototype: false });
9109
- ctx.log(picocolors.exports.red(picocolors.exports.bold("Serialized Error:")), picocolors.exports.gray(propertiesString));
9110
- }
9111
- }
9112
- function generateCodeFrame(source, indent = 0, start = 0, end, range = 2) {
9113
- var _a;
9114
- start = posToNumber(source, start);
9115
- end = end || start;
9116
- const lines = source.split(lineSplitRE);
9117
- let count = 0;
9118
- let res = [];
9119
- const columns = ((_a = process.stdout) == null ? void 0 : _a.columns) || 80;
9120
- function lineNo(no = "") {
9121
- return picocolors.exports.gray(`${String(no).padStart(3, " ")}| `);
9122
- }
9123
- for (let i = 0; i < lines.length; i++) {
9124
- count += lines[i].length + 1;
9125
- if (count >= start) {
9126
- for (let j = i - range; j <= i + range || end > count; j++) {
9127
- if (j < 0 || j >= lines.length)
9128
- continue;
9129
- const lineLength = lines[j].length;
9130
- if (lineLength > 200)
9131
- return "";
9132
- res.push(lineNo(j + 1) + cliTruncate(lines[j], columns - 5 - indent));
9133
- if (j === i) {
9134
- const pad = start - (count - lineLength);
9135
- const length = Math.max(1, end > count ? lineLength - pad : end - start);
9136
- res.push(lineNo() + " ".repeat(pad) + picocolors.exports.red("^".repeat(length)));
9137
- } else if (j > i) {
9138
- if (end > count) {
9139
- const length = Math.max(1, Math.min(end - count, lineLength));
9140
- res.push(lineNo() + picocolors.exports.red("^".repeat(length)));
9141
- }
9142
- count += lineLength + 1;
9143
- }
9144
- }
9145
- break;
8507
+ resolved.shard = { index, count };
8508
+ }
8509
+ resolved.deps = resolved.deps || {};
8510
+ if (resolved.deps.inline !== true) {
8511
+ const ssrOptions = viteConfig.ssr;
8512
+ if ((ssrOptions == null ? void 0 : ssrOptions.noExternal) === true && resolved.deps.inline == null) {
8513
+ resolved.deps.inline = true;
8514
+ } else {
8515
+ (_b = resolved.deps).inline ?? (_b.inline = []);
8516
+ resolved.deps.inline.push(...extraInlineDeps);
9146
8517
  }
9147
8518
  }
9148
- if (indent)
9149
- res = res.map((line) => " ".repeat(indent) + line);
9150
- return res.join("\n");
8519
+ resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
8520
+ const CI = !!process.env.CI;
8521
+ const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
8522
+ resolved.snapshotOptions = {
8523
+ snapshotFormat: resolved.snapshotFormat || {},
8524
+ updateSnapshot: CI && !UPDATE_SNAPSHOT ? "none" : UPDATE_SNAPSHOT ? "all" : "new",
8525
+ resolveSnapshotPath: options.resolveSnapshotPath
8526
+ };
8527
+ if (options.resolveSnapshotPath)
8528
+ delete resolved.resolveSnapshotPath;
8529
+ if (process.env.VITEST_MAX_THREADS)
8530
+ resolved.maxThreads = parseInt(process.env.VITEST_MAX_THREADS);
8531
+ if (process.env.VITEST_MIN_THREADS)
8532
+ resolved.minThreads = parseInt(process.env.VITEST_MIN_THREADS);
8533
+ resolved.setupFiles = toArray$1(resolved.setupFiles || []).map((file) => normalize(resolveModule(file, { paths: [resolved.root] }) ?? resolve(resolved.root, file)));
8534
+ resolved.api = resolveApiConfig(options);
8535
+ if (options.related)
8536
+ resolved.related = toArray$1(options.related).map((file) => resolve(resolved.root, file));
8537
+ resolved.reporters = Array.from(/* @__PURE__ */ new Set([
8538
+ ...toArray$1(resolved.reporters),
8539
+ ...toArray$1(resolved.reporter)
8540
+ ])).filter(Boolean);
8541
+ if (!resolved.reporters.length)
8542
+ resolved.reporters.push("default");
8543
+ if (resolved.changed)
8544
+ resolved.passWithNoTests ?? (resolved.passWithNoTests = true);
8545
+ resolved.css ?? (resolved.css = {});
8546
+ if (typeof resolved.css === "object")
8547
+ (_c = resolved.css).include ?? (_c.include = [/\.module\./]);
8548
+ resolved.cache ?? (resolved.cache = { dir: "" });
8549
+ if (resolved.cache)
8550
+ resolved.cache.dir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir);
8551
+ if (!((_d = resolved.sequence) == null ? void 0 : _d.sequencer)) {
8552
+ resolved.sequence ?? (resolved.sequence = {});
8553
+ resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
8554
+ }
8555
+ return resolved;
9151
8556
  }
9152
8557
 
9153
- function stripFinalNewline(input) {
9154
- const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt();
9155
- const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt();
9156
-
9157
- if (input[input.length - 1] === LF) {
9158
- input = input.slice(0, -1);
9159
- }
9160
-
9161
- if (input[input.length - 1] === CR) {
9162
- input = input.slice(0, -1);
9163
- }
9164
-
9165
- return input;
9166
- }
8558
+ const ESC = '\u001B[';
8559
+ const OSC = '\u001B]';
8560
+ const BEL = '\u0007';
8561
+ const SEP = ';';
8562
+ const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
9167
8563
 
9168
- function pathKey(options = {}) {
9169
- const {
9170
- env = process.env,
9171
- platform = process.platform
9172
- } = options;
8564
+ const ansiEscapes = {};
9173
8565
 
9174
- if (platform !== 'win32') {
9175
- return 'PATH';
8566
+ ansiEscapes.cursorTo = (x, y) => {
8567
+ if (typeof x !== 'number') {
8568
+ throw new TypeError('The `x` argument is required');
9176
8569
  }
9177
8570
 
9178
- return Object.keys(env).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path';
9179
- }
9180
-
9181
- function npmRunPath(options = {}) {
9182
- const {
9183
- cwd = process$1.cwd(),
9184
- path: path_ = process$1.env[pathKey()],
9185
- execPath = process$1.execPath,
9186
- } = options;
9187
-
9188
- let previous;
9189
- const cwdString = cwd instanceof URL ? url.fileURLToPath(cwd) : cwd;
9190
- let cwdPath = path$a.resolve(cwdString);
9191
- const result = [];
9192
-
9193
- while (previous !== cwdPath) {
9194
- result.push(path$a.join(cwdPath, 'node_modules/.bin'));
9195
- previous = cwdPath;
9196
- cwdPath = path$a.resolve(cwdPath, '..');
8571
+ if (typeof y !== 'number') {
8572
+ return ESC + (x + 1) + 'G';
9197
8573
  }
9198
8574
 
9199
- // Ensure the running `node` binary is used.
9200
- result.push(path$a.resolve(cwdString, execPath, '..'));
9201
-
9202
- return [...result, path_].join(path$a.delimiter);
9203
- }
9204
-
9205
- function npmRunPathEnv({env = process$1.env, ...options} = {}) {
9206
- env = {...env};
9207
-
9208
- const path = pathKey({env});
9209
- options.path = env[path];
9210
- env[path] = npmRunPath(options);
9211
-
9212
- return env;
9213
- }
9214
-
9215
- const copyProperty = (to, from, property, ignoreNonConfigurable) => {
9216
- // `Function#length` should reflect the parameters of `to` not `from` since we keep its body.
9217
- // `Function#prototype` is non-writable and non-configurable so can never be modified.
9218
- if (property === 'length' || property === 'prototype') {
9219
- return;
9220
- }
8575
+ return ESC + (y + 1) + ';' + (x + 1) + 'H';
8576
+ };
9221
8577
 
9222
- // `Function#arguments` and `Function#caller` should not be copied. They were reported to be present in `Reflect.ownKeys` for some devices in React Native (#41), so we explicitly ignore them here.
9223
- if (property === 'arguments' || property === 'caller') {
9224
- return;
8578
+ ansiEscapes.cursorMove = (x, y) => {
8579
+ if (typeof x !== 'number') {
8580
+ throw new TypeError('The `x` argument is required');
9225
8581
  }
9226
8582
 
9227
- const toDescriptor = Object.getOwnPropertyDescriptor(to, property);
9228
- const fromDescriptor = Object.getOwnPropertyDescriptor(from, property);
8583
+ let returnValue = '';
9229
8584
 
9230
- if (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) {
9231
- return;
8585
+ if (x < 0) {
8586
+ returnValue += ESC + (-x) + 'D';
8587
+ } else if (x > 0) {
8588
+ returnValue += ESC + x + 'C';
9232
8589
  }
9233
8590
 
9234
- Object.defineProperty(to, property, fromDescriptor);
9235
- };
9236
-
9237
- // `Object.defineProperty()` throws if the property exists, is not configurable and either:
9238
- // - one its descriptors is changed
9239
- // - it is non-writable and its value is changed
9240
- const canCopyProperty = function (toDescriptor, fromDescriptor) {
9241
- return toDescriptor === undefined || toDescriptor.configurable || (
9242
- toDescriptor.writable === fromDescriptor.writable &&
9243
- toDescriptor.enumerable === fromDescriptor.enumerable &&
9244
- toDescriptor.configurable === fromDescriptor.configurable &&
9245
- (toDescriptor.writable || toDescriptor.value === fromDescriptor.value)
9246
- );
9247
- };
9248
-
9249
- const changePrototype = (to, from) => {
9250
- const fromPrototype = Object.getPrototypeOf(from);
9251
- if (fromPrototype === Object.getPrototypeOf(to)) {
9252
- return;
8591
+ if (y < 0) {
8592
+ returnValue += ESC + (-y) + 'A';
8593
+ } else if (y > 0) {
8594
+ returnValue += ESC + y + 'B';
9253
8595
  }
9254
8596
 
9255
- Object.setPrototypeOf(to, fromPrototype);
9256
- };
9257
-
9258
- const wrappedToString = (withName, fromBody) => `/* Wrapped ${withName}*/\n${fromBody}`;
9259
-
9260
- const toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString');
9261
- const toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, 'name');
9262
-
9263
- // We call `from.toString()` early (not lazily) to ensure `from` can be garbage collected.
9264
- // We use `bind()` instead of a closure for the same reason.
9265
- // Calling `from.toString()` early also allows caching it in case `to.toString()` is called several times.
9266
- const changeToString = (to, from, name) => {
9267
- const withName = name === '' ? '' : `with ${name.trim()}() `;
9268
- const newToString = wrappedToString.bind(null, withName, from.toString());
9269
- // Ensure `to.toString.toString` is non-enumerable and has the same `same`
9270
- Object.defineProperty(newToString, 'name', toStringName);
9271
- Object.defineProperty(to, 'toString', {...toStringDescriptor, value: newToString});
8597
+ return returnValue;
9272
8598
  };
9273
8599
 
9274
- function mimicFunction(to, from, {ignoreNonConfigurable = false} = {}) {
9275
- const {name} = to;
9276
-
9277
- for (const property of Reflect.ownKeys(from)) {
9278
- copyProperty(to, from, property, ignoreNonConfigurable);
9279
- }
9280
-
9281
- changePrototype(to, from);
9282
- changeToString(to, from, name);
8600
+ ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A';
8601
+ ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B';
8602
+ ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C';
8603
+ ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D';
9283
8604
 
9284
- return to;
9285
- }
8605
+ ansiEscapes.cursorLeft = ESC + 'G';
8606
+ ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's';
8607
+ ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u';
8608
+ ansiEscapes.cursorGetPosition = ESC + '6n';
8609
+ ansiEscapes.cursorNextLine = ESC + 'E';
8610
+ ansiEscapes.cursorPrevLine = ESC + 'F';
8611
+ ansiEscapes.cursorHide = ESC + '?25l';
8612
+ ansiEscapes.cursorShow = ESC + '?25h';
9286
8613
 
9287
- const calledFunctions = new WeakMap();
8614
+ ansiEscapes.eraseLines = count => {
8615
+ let clear = '';
9288
8616
 
9289
- const onetime = (function_, options = {}) => {
9290
- if (typeof function_ !== 'function') {
9291
- throw new TypeError('Expected a function');
8617
+ for (let i = 0; i < count; i++) {
8618
+ clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : '');
9292
8619
  }
9293
8620
 
9294
- let returnValue;
9295
- let callCount = 0;
9296
- const functionName = function_.displayName || function_.name || '<anonymous>';
9297
-
9298
- const onetime = function (...arguments_) {
9299
- calledFunctions.set(onetime, ++callCount);
9300
-
9301
- if (callCount === 1) {
9302
- returnValue = function_.apply(this, arguments_);
9303
- function_ = null;
9304
- } else if (options.throw === true) {
9305
- throw new Error(`Function \`${functionName}\` can only be called once`);
9306
- }
9307
-
9308
- return returnValue;
9309
- };
9310
-
9311
- mimicFunction(onetime, function_);
9312
- calledFunctions.set(onetime, callCount);
9313
-
9314
- return onetime;
9315
- };
9316
-
9317
- onetime.callCount = function_ => {
9318
- if (!calledFunctions.has(function_)) {
9319
- throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`);
8621
+ if (count) {
8622
+ clear += ansiEscapes.cursorLeft;
9320
8623
  }
9321
8624
 
9322
- return calledFunctions.get(function_);
9323
- };
9324
-
9325
- const getRealtimeSignals=function(){
9326
- const length=SIGRTMAX-SIGRTMIN+1;
9327
- return Array.from({length},getRealtimeSignal);
9328
- };
9329
-
9330
- const getRealtimeSignal=function(value,index){
9331
- return {
9332
- name:`SIGRT${index+1}`,
9333
- number:SIGRTMIN+index,
9334
- action:"terminate",
9335
- description:"Application-specific signal (realtime)",
9336
- standard:"posix"};
9337
-
9338
- };
9339
-
9340
- const SIGRTMIN=34;
9341
- const SIGRTMAX=64;
9342
-
9343
- const SIGNALS=[
9344
- {
9345
- name:"SIGHUP",
9346
- number:1,
9347
- action:"terminate",
9348
- description:"Terminal closed",
9349
- standard:"posix"},
9350
-
9351
- {
9352
- name:"SIGINT",
9353
- number:2,
9354
- action:"terminate",
9355
- description:"User interruption with CTRL-C",
9356
- standard:"ansi"},
9357
-
9358
- {
9359
- name:"SIGQUIT",
9360
- number:3,
9361
- action:"core",
9362
- description:"User interruption with CTRL-\\",
9363
- standard:"posix"},
9364
-
9365
- {
9366
- name:"SIGILL",
9367
- number:4,
9368
- action:"core",
9369
- description:"Invalid machine instruction",
9370
- standard:"ansi"},
9371
-
9372
- {
9373
- name:"SIGTRAP",
9374
- number:5,
9375
- action:"core",
9376
- description:"Debugger breakpoint",
9377
- standard:"posix"},
9378
-
9379
- {
9380
- name:"SIGABRT",
9381
- number:6,
9382
- action:"core",
9383
- description:"Aborted",
9384
- standard:"ansi"},
9385
-
9386
- {
9387
- name:"SIGIOT",
9388
- number:6,
9389
- action:"core",
9390
- description:"Aborted",
9391
- standard:"bsd"},
9392
-
9393
- {
9394
- name:"SIGBUS",
9395
- number:7,
9396
- action:"core",
9397
- description:
9398
- "Bus error due to misaligned, non-existing address or paging error",
9399
- standard:"bsd"},
9400
-
9401
- {
9402
- name:"SIGEMT",
9403
- number:7,
9404
- action:"terminate",
9405
- description:"Command should be emulated but is not implemented",
9406
- standard:"other"},
9407
-
9408
- {
9409
- name:"SIGFPE",
9410
- number:8,
9411
- action:"core",
9412
- description:"Floating point arithmetic error",
9413
- standard:"ansi"},
9414
-
9415
- {
9416
- name:"SIGKILL",
9417
- number:9,
9418
- action:"terminate",
9419
- description:"Forced termination",
9420
- standard:"posix",
9421
- forced:true},
9422
-
9423
- {
9424
- name:"SIGUSR1",
9425
- number:10,
9426
- action:"terminate",
9427
- description:"Application-specific signal",
9428
- standard:"posix"},
9429
-
9430
- {
9431
- name:"SIGSEGV",
9432
- number:11,
9433
- action:"core",
9434
- description:"Segmentation fault",
9435
- standard:"ansi"},
9436
-
9437
- {
9438
- name:"SIGUSR2",
9439
- number:12,
9440
- action:"terminate",
9441
- description:"Application-specific signal",
9442
- standard:"posix"},
9443
-
9444
- {
9445
- name:"SIGPIPE",
9446
- number:13,
9447
- action:"terminate",
9448
- description:"Broken pipe or socket",
9449
- standard:"posix"},
9450
-
9451
- {
9452
- name:"SIGALRM",
9453
- number:14,
9454
- action:"terminate",
9455
- description:"Timeout or timer",
9456
- standard:"posix"},
9457
-
9458
- {
9459
- name:"SIGTERM",
9460
- number:15,
9461
- action:"terminate",
9462
- description:"Termination",
9463
- standard:"ansi"},
9464
-
9465
- {
9466
- name:"SIGSTKFLT",
9467
- number:16,
9468
- action:"terminate",
9469
- description:"Stack is empty or overflowed",
9470
- standard:"other"},
9471
-
9472
- {
9473
- name:"SIGCHLD",
9474
- number:17,
9475
- action:"ignore",
9476
- description:"Child process terminated, paused or unpaused",
9477
- standard:"posix"},
9478
-
9479
- {
9480
- name:"SIGCLD",
9481
- number:17,
9482
- action:"ignore",
9483
- description:"Child process terminated, paused or unpaused",
9484
- standard:"other"},
9485
-
9486
- {
9487
- name:"SIGCONT",
9488
- number:18,
9489
- action:"unpause",
9490
- description:"Unpaused",
9491
- standard:"posix",
9492
- forced:true},
9493
-
9494
- {
9495
- name:"SIGSTOP",
9496
- number:19,
9497
- action:"pause",
9498
- description:"Paused",
9499
- standard:"posix",
9500
- forced:true},
9501
-
9502
- {
9503
- name:"SIGTSTP",
9504
- number:20,
9505
- action:"pause",
9506
- description:"Paused using CTRL-Z or \"suspend\"",
9507
- standard:"posix"},
9508
-
9509
- {
9510
- name:"SIGTTIN",
9511
- number:21,
9512
- action:"pause",
9513
- description:"Background process cannot read terminal input",
9514
- standard:"posix"},
9515
-
9516
- {
9517
- name:"SIGBREAK",
9518
- number:21,
9519
- action:"terminate",
9520
- description:"User interruption with CTRL-BREAK",
9521
- standard:"other"},
9522
-
9523
- {
9524
- name:"SIGTTOU",
9525
- number:22,
9526
- action:"pause",
9527
- description:"Background process cannot write to terminal output",
9528
- standard:"posix"},
9529
-
9530
- {
9531
- name:"SIGURG",
9532
- number:23,
9533
- action:"ignore",
9534
- description:"Socket received out-of-band data",
9535
- standard:"bsd"},
9536
-
9537
- {
9538
- name:"SIGXCPU",
9539
- number:24,
9540
- action:"core",
9541
- description:"Process timed out",
9542
- standard:"bsd"},
9543
-
9544
- {
9545
- name:"SIGXFSZ",
9546
- number:25,
9547
- action:"core",
9548
- description:"File too big",
9549
- standard:"bsd"},
9550
-
9551
- {
9552
- name:"SIGVTALRM",
9553
- number:26,
9554
- action:"terminate",
9555
- description:"Timeout or timer",
9556
- standard:"bsd"},
9557
-
9558
- {
9559
- name:"SIGPROF",
9560
- number:27,
9561
- action:"terminate",
9562
- description:"Timeout or timer",
9563
- standard:"bsd"},
9564
-
9565
- {
9566
- name:"SIGWINCH",
9567
- number:28,
9568
- action:"ignore",
9569
- description:"Terminal window size changed",
9570
- standard:"bsd"},
9571
-
9572
- {
9573
- name:"SIGIO",
9574
- number:29,
9575
- action:"terminate",
9576
- description:"I/O is available",
9577
- standard:"other"},
9578
-
9579
- {
9580
- name:"SIGPOLL",
9581
- number:29,
9582
- action:"terminate",
9583
- description:"Watched event",
9584
- standard:"other"},
9585
-
9586
- {
9587
- name:"SIGINFO",
9588
- number:29,
9589
- action:"ignore",
9590
- description:"Request for process information",
9591
- standard:"other"},
9592
-
9593
- {
9594
- name:"SIGPWR",
9595
- number:30,
9596
- action:"terminate",
9597
- description:"Device running out of power",
9598
- standard:"systemv"},
9599
-
9600
- {
9601
- name:"SIGSYS",
9602
- number:31,
9603
- action:"core",
9604
- description:"Invalid system call",
9605
- standard:"other"},
9606
-
9607
- {
9608
- name:"SIGUNUSED",
9609
- number:31,
9610
- action:"terminate",
9611
- description:"Invalid system call",
9612
- standard:"other"}];
9613
-
9614
- const getSignals=function(){
9615
- const realtimeSignals=getRealtimeSignals();
9616
- const signals=[...SIGNALS,...realtimeSignals].map(normalizeSignal);
9617
- return signals;
9618
- };
9619
-
9620
-
9621
-
9622
-
9623
-
9624
-
9625
-
9626
- const normalizeSignal=function({
9627
- name,
9628
- number:defaultNumber,
9629
- description,
9630
- action,
9631
- forced=false,
9632
- standard})
9633
- {
9634
- const{
9635
- signals:{[name]:constantSignal}}=
9636
- constants$5;
9637
- const supported=constantSignal!==undefined;
9638
- const number=supported?constantSignal:defaultNumber;
9639
- return {name,number,description,supported,action,forced,standard};
9640
- };
9641
-
9642
- const getSignalsByName=function(){
9643
- const signals=getSignals();
9644
- return signals.reduce(getSignalByName,{});
9645
- };
9646
-
9647
- const getSignalByName=function(
9648
- signalByNameMemo,
9649
- {name,number,description,supported,action,forced,standard})
9650
- {
9651
- return {
9652
- ...signalByNameMemo,
9653
- [name]:{name,number,description,supported,action,forced,standard}};
9654
-
9655
- };
9656
-
9657
- const signalsByName=getSignalsByName();
9658
-
9659
-
9660
-
9661
-
9662
- const getSignalsByNumber=function(){
9663
- const signals=getSignals();
9664
- const length=SIGRTMAX+1;
9665
- const signalsA=Array.from({length},(value,number)=>
9666
- getSignalByNumber(number,signals));
9667
-
9668
- return Object.assign({},...signalsA);
9669
- };
9670
-
9671
- const getSignalByNumber=function(number,signals){
9672
- const signal=findSignalByNumber(number,signals);
9673
-
9674
- if(signal===undefined){
9675
- return {};
9676
- }
9677
-
9678
- const{name,description,supported,action,forced,standard}=signal;
9679
- return {
9680
- [number]:{
9681
- name,
9682
- number,
9683
- description,
9684
- supported,
9685
- action,
9686
- forced,
9687
- standard}};
9688
-
9689
-
8625
+ return clear;
9690
8626
  };
9691
8627
 
8628
+ ansiEscapes.eraseEndLine = ESC + 'K';
8629
+ ansiEscapes.eraseStartLine = ESC + '1K';
8630
+ ansiEscapes.eraseLine = ESC + '2K';
8631
+ ansiEscapes.eraseDown = ESC + 'J';
8632
+ ansiEscapes.eraseUp = ESC + '1J';
8633
+ ansiEscapes.eraseScreen = ESC + '2J';
8634
+ ansiEscapes.scrollUp = ESC + 'S';
8635
+ ansiEscapes.scrollDown = ESC + 'T';
9692
8636
 
8637
+ ansiEscapes.clearScreen = '\u001Bc';
9693
8638
 
9694
- const findSignalByNumber=function(number,signals){
9695
- const signal=signals.find(({name})=>constants$5.signals[name]===number);
8639
+ ansiEscapes.clearTerminal = process.platform === 'win32' ?
8640
+ `${ansiEscapes.eraseScreen}${ESC}0f` :
8641
+ // 1. Erases the screen (Only done in case `2` is not supported)
8642
+ // 2. Erases the whole screen including scrollback buffer
8643
+ // 3. Moves cursor to the top-left position
8644
+ // More info: https://www.real-world-systems.com/docs/ANSIcode.html
8645
+ `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`;
9696
8646
 
9697
- if(signal!==undefined){
9698
- return signal;
9699
- }
8647
+ ansiEscapes.beep = BEL;
9700
8648
 
9701
- return signals.find((signalA)=>signalA.number===number);
8649
+ ansiEscapes.link = (text, url) => {
8650
+ return [
8651
+ OSC,
8652
+ '8',
8653
+ SEP,
8654
+ SEP,
8655
+ url,
8656
+ BEL,
8657
+ text,
8658
+ OSC,
8659
+ '8',
8660
+ SEP,
8661
+ SEP,
8662
+ BEL
8663
+ ].join('');
9702
8664
  };
9703
8665
 
9704
- getSignalsByNumber();
9705
-
9706
- const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => {
9707
- if (timedOut) {
9708
- return `timed out after ${timeout} milliseconds`;
9709
- }
9710
-
9711
- if (isCanceled) {
9712
- return 'was canceled';
9713
- }
9714
-
9715
- if (errorCode !== undefined) {
9716
- return `failed with ${errorCode}`;
9717
- }
9718
-
9719
- if (signal !== undefined) {
9720
- return `was killed with ${signal} (${signalDescription})`;
9721
- }
9722
-
9723
- if (exitCode !== undefined) {
9724
- return `failed with exit code ${exitCode}`;
9725
- }
9726
-
9727
- return 'failed';
9728
- };
8666
+ ansiEscapes.image = (buffer, options = {}) => {
8667
+ let returnValue = `${OSC}1337;File=inline=1`;
9729
8668
 
9730
- const makeError = ({
9731
- stdout,
9732
- stderr,
9733
- all,
9734
- error,
9735
- signal,
9736
- exitCode,
9737
- command,
9738
- escapedCommand,
9739
- timedOut,
9740
- isCanceled,
9741
- killed,
9742
- parsed: {options: {timeout}},
9743
- }) => {
9744
- // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`.
9745
- // We normalize them to `undefined`
9746
- exitCode = exitCode === null ? undefined : exitCode;
9747
- signal = signal === null ? undefined : signal;
9748
- const signalDescription = signal === undefined ? undefined : signalsByName[signal].description;
9749
-
9750
- const errorCode = error && error.code;
9751
-
9752
- const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled});
9753
- const execaMessage = `Command ${prefix}: ${command}`;
9754
- const isError = Object.prototype.toString.call(error) === '[object Error]';
9755
- const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage;
9756
- const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n');
9757
-
9758
- if (isError) {
9759
- error.originalMessage = error.message;
9760
- error.message = message;
9761
- } else {
9762
- error = new Error(message);
8669
+ if (options.width) {
8670
+ returnValue += `;width=${options.width}`;
9763
8671
  }
9764
8672
 
9765
- error.shortMessage = shortMessage;
9766
- error.command = command;
9767
- error.escapedCommand = escapedCommand;
9768
- error.exitCode = exitCode;
9769
- error.signal = signal;
9770
- error.signalDescription = signalDescription;
9771
- error.stdout = stdout;
9772
- error.stderr = stderr;
9773
-
9774
- if (all !== undefined) {
9775
- error.all = all;
8673
+ if (options.height) {
8674
+ returnValue += `;height=${options.height}`;
9776
8675
  }
9777
8676
 
9778
- if ('bufferedData' in error) {
9779
- delete error.bufferedData;
8677
+ if (options.preserveAspectRatio === false) {
8678
+ returnValue += ';preserveAspectRatio=0';
9780
8679
  }
9781
8680
 
9782
- error.failed = true;
9783
- error.timedOut = Boolean(timedOut);
9784
- error.isCanceled = isCanceled;
9785
- error.killed = killed && !timedOut;
9786
-
9787
- return error;
8681
+ return returnValue + ':' + buffer.toString('base64') + BEL;
9788
8682
  };
9789
8683
 
9790
- const aliases = ['stdin', 'stdout', 'stderr'];
9791
-
9792
- const hasAlias = options => aliases.some(alias => options[alias] !== undefined);
8684
+ ansiEscapes.iTerm = {
8685
+ setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`,
9793
8686
 
9794
- const normalizeStdio = options => {
9795
- if (!options) {
9796
- return;
9797
- }
8687
+ annotation: (message, options = {}) => {
8688
+ let returnValue = `${OSC}1337;`;
9798
8689
 
9799
- const {stdio} = options;
8690
+ const hasX = typeof options.x !== 'undefined';
8691
+ const hasY = typeof options.y !== 'undefined';
8692
+ if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) {
8693
+ throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined');
8694
+ }
9800
8695
 
9801
- if (stdio === undefined) {
9802
- return aliases.map(alias => options[alias]);
9803
- }
8696
+ message = message.replace(/\|/g, '');
9804
8697
 
9805
- if (hasAlias(options)) {
9806
- throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`);
9807
- }
8698
+ returnValue += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation=';
9808
8699
 
9809
- if (typeof stdio === 'string') {
9810
- return stdio;
9811
- }
8700
+ if (options.length > 0) {
8701
+ returnValue +=
8702
+ (hasX ?
8703
+ [message, options.length, options.x, options.y] :
8704
+ [options.length, message]).join('|');
8705
+ } else {
8706
+ returnValue += message;
8707
+ }
9812
8708
 
9813
- if (!Array.isArray(stdio)) {
9814
- throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``);
8709
+ return returnValue + BEL;
9815
8710
  }
9816
-
9817
- const length = Math.max(stdio.length, aliases.length);
9818
- return Array.from({length}, (value, index) => stdio[index]);
9819
8711
  };
9820
8712
 
9821
- const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5;
8713
+ const restoreCursor = onetime.exports(() => {
8714
+ signalExit.exports(() => {
8715
+ process$1.stderr.write('\u001B[?25h');
8716
+ }, {alwaysLast: true});
8717
+ });
8718
+
8719
+ let isHidden = false;
9822
8720
 
9823
- // Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior
9824
- const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => {
9825
- const killResult = kill(signal);
9826
- setKillTimeout(kill, signal, options, killResult);
9827
- return killResult;
9828
- };
8721
+ const cliCursor = {};
9829
8722
 
9830
- const setKillTimeout = (kill, signal, options, killResult) => {
9831
- if (!shouldForceKill(signal, options, killResult)) {
8723
+ cliCursor.show = (writableStream = process$1.stderr) => {
8724
+ if (!writableStream.isTTY) {
9832
8725
  return;
9833
8726
  }
9834
8727
 
9835
- const timeout = getForceKillAfterTimeout(options);
9836
- const t = setTimeout(() => {
9837
- kill('SIGKILL');
9838
- }, timeout);
9839
-
9840
- // Guarded because there's no `.unref()` when `execa` is used in the renderer
9841
- // process in Electron. This cannot be tested since we don't run tests in
9842
- // Electron.
9843
- // istanbul ignore else
9844
- if (t.unref) {
9845
- t.unref();
9846
- }
8728
+ isHidden = false;
8729
+ writableStream.write('\u001B[?25h');
9847
8730
  };
9848
8731
 
9849
- const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => isSigterm(signal) && forceKillAfterTimeout !== false && killResult;
8732
+ cliCursor.hide = (writableStream = process$1.stderr) => {
8733
+ if (!writableStream.isTTY) {
8734
+ return;
8735
+ }
9850
8736
 
9851
- const isSigterm = signal => signal === require$$0.constants.signals.SIGTERM
9852
- || (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM');
8737
+ restoreCursor();
8738
+ isHidden = true;
8739
+ writableStream.write('\u001B[?25l');
8740
+ };
9853
8741
 
9854
- const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => {
9855
- if (forceKillAfterTimeout === true) {
9856
- return DEFAULT_FORCE_KILL_TIMEOUT;
8742
+ cliCursor.toggle = (force, writableStream) => {
8743
+ if (force !== undefined) {
8744
+ isHidden = force;
9857
8745
  }
9858
8746
 
9859
- if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) {
9860
- throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`);
8747
+ if (isHidden) {
8748
+ cliCursor.show(writableStream);
8749
+ } else {
8750
+ cliCursor.hide(writableStream);
9861
8751
  }
9862
-
9863
- return forceKillAfterTimeout;
9864
8752
  };
9865
8753
 
9866
- // `childProcess.cancel()`
9867
- const spawnedCancel = (spawned, context) => {
9868
- const killResult = spawned.kill();
8754
+ const ESCAPES = new Set([
8755
+ '\u001B',
8756
+ '\u009B',
8757
+ ]);
9869
8758
 
9870
- if (killResult) {
9871
- context.isCanceled = true;
9872
- }
9873
- };
8759
+ const END_CODE = 39;
8760
+ const ANSI_ESCAPE_BELL = '\u0007';
8761
+ const ANSI_CSI = '[';
8762
+ const ANSI_OSC = ']';
8763
+ const ANSI_SGR_TERMINATOR = 'm';
8764
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
9874
8765
 
9875
- const timeoutKill = (spawned, signal, reject) => {
9876
- spawned.kill(signal);
9877
- reject(Object.assign(new Error('Timed out'), {timedOut: true, signal}));
9878
- };
8766
+ const wrapAnsiCode = code => `${ESCAPES.values().next().value}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
8767
+ const wrapAnsiHyperlink = uri => `${ESCAPES.values().next().value}${ANSI_ESCAPE_LINK}${uri}${ANSI_ESCAPE_BELL}`;
9879
8768
 
9880
- // `timeout` option handling
9881
- const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => {
9882
- if (timeout === 0 || timeout === undefined) {
9883
- return spawnedPromise;
9884
- }
8769
+ // Calculate the length of words split on ' ', ignoring
8770
+ // the extra characters added by ansi escape codes
8771
+ const wordLengths = string => string.split(' ').map(character => stringWidth(character));
9885
8772
 
9886
- let timeoutId;
9887
- const timeoutPromise = new Promise((resolve, reject) => {
9888
- timeoutId = setTimeout(() => {
9889
- timeoutKill(spawned, killSignal, reject);
9890
- }, timeout);
9891
- });
8773
+ // Wrap a long word across multiple rows
8774
+ // Ansi escape codes do not count towards length
8775
+ const wrapWord = (rows, word, columns) => {
8776
+ const characters = [...word];
9892
8777
 
9893
- const safeSpawnedPromise = spawnedPromise.finally(() => {
9894
- clearTimeout(timeoutId);
9895
- });
8778
+ let isInsideEscape = false;
8779
+ let isInsideLinkEscape = false;
8780
+ let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
9896
8781
 
9897
- return Promise.race([timeoutPromise, safeSpawnedPromise]);
9898
- };
8782
+ for (const [index, character] of characters.entries()) {
8783
+ const characterLength = stringWidth(character);
9899
8784
 
9900
- const validateTimeout = ({timeout}) => {
9901
- if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) {
9902
- throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`);
9903
- }
9904
- };
8785
+ if (visible + characterLength <= columns) {
8786
+ rows[rows.length - 1] += character;
8787
+ } else {
8788
+ rows.push(character);
8789
+ visible = 0;
8790
+ }
9905
8791
 
9906
- // `cleanup` option handling
9907
- const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => {
9908
- if (!cleanup || detached) {
9909
- return timedPromise;
9910
- }
8792
+ if (ESCAPES.has(character)) {
8793
+ isInsideEscape = true;
8794
+ isInsideLinkEscape = characters.slice(index + 1).join('').startsWith(ANSI_ESCAPE_LINK);
8795
+ }
9911
8796
 
9912
- const removeExitHandler = signalExit.exports(() => {
9913
- spawned.kill();
9914
- });
8797
+ if (isInsideEscape) {
8798
+ if (isInsideLinkEscape) {
8799
+ if (character === ANSI_ESCAPE_BELL) {
8800
+ isInsideEscape = false;
8801
+ isInsideLinkEscape = false;
8802
+ }
8803
+ } else if (character === ANSI_SGR_TERMINATOR) {
8804
+ isInsideEscape = false;
8805
+ }
9915
8806
 
9916
- return timedPromise.finally(() => {
9917
- removeExitHandler();
9918
- });
9919
- };
8807
+ continue;
8808
+ }
9920
8809
 
9921
- function isStream(stream) {
9922
- return stream !== null
9923
- && typeof stream === 'object'
9924
- && typeof stream.pipe === 'function';
9925
- }
8810
+ visible += characterLength;
9926
8811
 
9927
- // `input` option
9928
- const handleInput = (spawned, input) => {
9929
- // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852
9930
- // @todo remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0
9931
- if (input === undefined || spawned.stdin === undefined) {
9932
- return;
8812
+ if (visible === columns && index < characters.length - 1) {
8813
+ rows.push('');
8814
+ visible = 0;
8815
+ }
9933
8816
  }
9934
8817
 
9935
- if (isStream(input)) {
9936
- input.pipe(spawned.stdin);
9937
- } else {
9938
- spawned.stdin.end(input);
8818
+ // It's possible that the last row we copy over is only
8819
+ // ansi escape characters, handle this edge-case
8820
+ if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) {
8821
+ rows[rows.length - 2] += rows.pop();
9939
8822
  }
9940
8823
  };
9941
8824
 
9942
- // `all` interleaves `stdout` and `stderr`
9943
- const makeAllStream = (spawned, {all}) => {
9944
- if (!all || (!spawned.stdout && !spawned.stderr)) {
9945
- return;
9946
- }
8825
+ // Trims spaces from a string ignoring invisible sequences
8826
+ const stringVisibleTrimSpacesRight = string => {
8827
+ const words = string.split(' ');
8828
+ let last = words.length;
9947
8829
 
9948
- const mixed = mergeStream();
8830
+ while (last > 0) {
8831
+ if (stringWidth(words[last - 1]) > 0) {
8832
+ break;
8833
+ }
9949
8834
 
9950
- if (spawned.stdout) {
9951
- mixed.add(spawned.stdout);
8835
+ last--;
9952
8836
  }
9953
8837
 
9954
- if (spawned.stderr) {
9955
- mixed.add(spawned.stderr);
8838
+ if (last === words.length) {
8839
+ return string;
9956
8840
  }
9957
8841
 
9958
- return mixed;
8842
+ return words.slice(0, last).join(' ') + words.slice(last).join('');
9959
8843
  };
9960
8844
 
9961
- // On failure, `result.stdout|stderr|all` should contain the currently buffered stream
9962
- const getBufferedData = async (stream, streamPromise) => {
9963
- if (!stream) {
9964
- return;
9965
- }
9966
-
9967
- stream.destroy();
9968
-
9969
- try {
9970
- return await streamPromise;
9971
- } catch (error) {
9972
- return error.bufferedData;
8845
+ // The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
8846
+ //
8847
+ // 'hard' will never allow a string to take up more than columns characters
8848
+ //
8849
+ // 'soft' allows long words to expand past the column length
8850
+ const exec = (string, columns, options = {}) => {
8851
+ if (options.trim !== false && string.trim() === '') {
8852
+ return '';
9973
8853
  }
9974
- };
9975
8854
 
9976
- const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => {
9977
- if (!stream || !buffer) {
9978
- return;
9979
- }
8855
+ let returnValue = '';
8856
+ let escapeCode;
8857
+ let escapeUrl;
9980
8858
 
9981
- if (encoding) {
9982
- return getStream.exports(stream, {encoding, maxBuffer});
9983
- }
8859
+ const lengths = wordLengths(string);
8860
+ let rows = [''];
9984
8861
 
9985
- return getStream.exports.buffer(stream, {maxBuffer});
9986
- };
8862
+ for (const [index, word] of string.split(' ').entries()) {
8863
+ if (options.trim !== false) {
8864
+ rows[rows.length - 1] = rows[rows.length - 1].trimStart();
8865
+ }
9987
8866
 
9988
- // Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all)
9989
- const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => {
9990
- const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer});
9991
- const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer});
9992
- const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2});
8867
+ let rowLength = stringWidth(rows[rows.length - 1]);
9993
8868
 
9994
- try {
9995
- return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]);
9996
- } catch (error) {
9997
- return Promise.all([
9998
- {error, signal: error.signal, timedOut: error.timedOut},
9999
- getBufferedData(stdout, stdoutPromise),
10000
- getBufferedData(stderr, stderrPromise),
10001
- getBufferedData(all, allPromise),
10002
- ]);
10003
- }
10004
- };
8869
+ if (index !== 0) {
8870
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
8871
+ // If we start with a new word but the current row length equals the length of the columns, add a new row
8872
+ rows.push('');
8873
+ rowLength = 0;
8874
+ }
10005
8875
 
10006
- const nativePromisePrototype = (async () => {})().constructor.prototype;
10007
- const descriptors = ['then', 'catch', 'finally'].map(property => [
10008
- property,
10009
- Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property),
10010
- ]);
8876
+ if (rowLength > 0 || options.trim === false) {
8877
+ rows[rows.length - 1] += ' ';
8878
+ rowLength++;
8879
+ }
8880
+ }
10011
8881
 
10012
- // The return value is a mixin of `childProcess` and `Promise`
10013
- const mergePromise = (spawned, promise) => {
10014
- for (const [property, descriptor] of descriptors) {
10015
- // Starting the main `promise` is deferred to avoid consuming streams
10016
- const value = typeof promise === 'function'
10017
- ? (...args) => Reflect.apply(descriptor.value, promise(), args)
10018
- : descriptor.value.bind(promise);
8882
+ // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
8883
+ if (options.hard && lengths[index] > columns) {
8884
+ const remainingColumns = (columns - rowLength);
8885
+ const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
8886
+ const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns);
8887
+ if (breaksStartingNextLine < breaksStartingThisLine) {
8888
+ rows.push('');
8889
+ }
10019
8890
 
10020
- Reflect.defineProperty(spawned, property, {...descriptor, value});
10021
- }
8891
+ wrapWord(rows, word, columns);
8892
+ continue;
8893
+ }
10022
8894
 
10023
- return spawned;
10024
- };
8895
+ if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
8896
+ if (options.wordWrap === false && rowLength < columns) {
8897
+ wrapWord(rows, word, columns);
8898
+ continue;
8899
+ }
10025
8900
 
10026
- // Use promises instead of `child_process` events
10027
- const getSpawnedPromise = spawned => new Promise((resolve, reject) => {
10028
- spawned.on('exit', (exitCode, signal) => {
10029
- resolve({exitCode, signal});
10030
- });
8901
+ rows.push('');
8902
+ }
10031
8903
 
10032
- spawned.on('error', error => {
10033
- reject(error);
10034
- });
8904
+ if (rowLength + lengths[index] > columns && options.wordWrap === false) {
8905
+ wrapWord(rows, word, columns);
8906
+ continue;
8907
+ }
10035
8908
 
10036
- if (spawned.stdin) {
10037
- spawned.stdin.on('error', error => {
10038
- reject(error);
10039
- });
8909
+ rows[rows.length - 1] += word;
10040
8910
  }
10041
- });
10042
8911
 
10043
- const normalizeArgs = (file, args = []) => {
10044
- if (!Array.isArray(args)) {
10045
- return [file];
8912
+ if (options.trim !== false) {
8913
+ rows = rows.map(row => stringVisibleTrimSpacesRight(row));
10046
8914
  }
10047
8915
 
10048
- return [file, ...args];
10049
- };
10050
-
10051
- const NO_ESCAPE_REGEXP = /^[\w.-]+$/;
10052
- const DOUBLE_QUOTES_REGEXP = /"/g;
10053
-
10054
- const escapeArg = arg => {
10055
- if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) {
10056
- return arg;
10057
- }
8916
+ const pre = [...rows.join('\n')];
10058
8917
 
10059
- return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`;
10060
- };
8918
+ for (const [index, character] of pre.entries()) {
8919
+ returnValue += character;
10061
8920
 
10062
- const joinCommand = (file, args) => normalizeArgs(file, args).join(' ');
8921
+ if (ESCAPES.has(character)) {
8922
+ const {groups} = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`).exec(pre.slice(index).join('')) || {groups: {}};
8923
+ if (groups.code !== undefined) {
8924
+ const code = Number.parseFloat(groups.code);
8925
+ escapeCode = code === END_CODE ? undefined : code;
8926
+ } else if (groups.uri !== undefined) {
8927
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
8928
+ }
8929
+ }
10063
8930
 
10064
- const getEscapedCommand = (file, args) => normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' ');
8931
+ const code = ansiStyles.codes.get(Number(escapeCode));
10065
8932
 
10066
- const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;
8933
+ if (pre[index + 1] === '\n') {
8934
+ if (escapeUrl) {
8935
+ returnValue += wrapAnsiHyperlink('');
8936
+ }
10067
8937
 
10068
- const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => {
10069
- const env = extendEnv ? {...process$1.env, ...envOption} : envOption;
8938
+ if (escapeCode && code) {
8939
+ returnValue += wrapAnsiCode(code);
8940
+ }
8941
+ } else if (character === '\n') {
8942
+ if (escapeCode && code) {
8943
+ returnValue += wrapAnsiCode(escapeCode);
8944
+ }
10070
8945
 
10071
- if (preferLocal) {
10072
- return npmRunPathEnv({env, cwd: localDir, execPath});
8946
+ if (escapeUrl) {
8947
+ returnValue += wrapAnsiHyperlink(escapeUrl);
8948
+ }
8949
+ }
10073
8950
  }
10074
8951
 
10075
- return env;
8952
+ return returnValue;
10076
8953
  };
10077
8954
 
10078
- const handleArguments = (file, args, options = {}) => {
10079
- const parsed = crossSpawn.exports._parse(file, args, options);
10080
- file = parsed.command;
10081
- args = parsed.args;
10082
- options = parsed.options;
10083
-
10084
- options = {
10085
- maxBuffer: DEFAULT_MAX_BUFFER,
10086
- buffer: true,
10087
- stripFinalNewline: true,
10088
- extendEnv: true,
10089
- preferLocal: false,
10090
- localDir: options.cwd || process$1.cwd(),
10091
- execPath: process$1.execPath,
10092
- encoding: 'utf8',
10093
- reject: true,
10094
- cleanup: true,
10095
- all: false,
10096
- windowsHide: true,
10097
- ...options,
10098
- };
8955
+ // For each newline, invoke the method separately
8956
+ function wrapAnsi(string, columns, options) {
8957
+ return String(string)
8958
+ .normalize()
8959
+ .replace(/\r\n/g, '\n')
8960
+ .split('\n')
8961
+ .map(line => exec(line, columns, options))
8962
+ .join('\n');
8963
+ }
10099
8964
 
10100
- options.env = getEnv(options);
8965
+ const defaultTerminalHeight = 24;
10101
8966
 
10102
- options.stdio = normalizeStdio(options);
8967
+ const getWidth = stream => {
8968
+ const {columns} = stream;
10103
8969
 
10104
- if (process$1.platform === 'win32' && path$a.basename(file, '.exe') === 'cmd') {
10105
- // #116
10106
- args.unshift('/q');
8970
+ if (!columns) {
8971
+ return 80;
10107
8972
  }
10108
8973
 
10109
- return {file, args, options, parsed};
8974
+ return columns;
10110
8975
  };
10111
8976
 
10112
- const handleOutput = (options, value, error) => {
10113
- if (typeof value !== 'string' && !Buffer.isBuffer(value)) {
10114
- // When `execaSync()` errors, we normalize it to '' to mimic `execa()`
10115
- return error === undefined ? undefined : '';
10116
- }
8977
+ const fitToTerminalHeight = (stream, text) => {
8978
+ const terminalHeight = stream.rows || defaultTerminalHeight;
8979
+ const lines = text.split('\n');
10117
8980
 
10118
- if (options.stripFinalNewline) {
10119
- return stripFinalNewline(value);
8981
+ const toRemove = lines.length - terminalHeight;
8982
+ if (toRemove <= 0) {
8983
+ return text;
10120
8984
  }
10121
8985
 
10122
- return value;
8986
+ return sliceAnsi(
8987
+ text,
8988
+ stripAnsi(lines.slice(0, toRemove).join('\n')).length + 1,
8989
+ );
10123
8990
  };
10124
8991
 
10125
- function execa(file, args, options) {
10126
- const parsed = handleArguments(file, args, options);
10127
- const command = joinCommand(file, args);
10128
- const escapedCommand = getEscapedCommand(file, args);
8992
+ function createLogUpdate(stream, {showCursor = false} = {}) {
8993
+ let previousLineCount = 0;
8994
+ let previousWidth = getWidth(stream);
8995
+ let previousOutput = '';
8996
+
8997
+ const render = (...arguments_) => {
8998
+ if (!showCursor) {
8999
+ cliCursor.hide();
9000
+ }
9001
+
9002
+ let output = arguments_.join(' ') + '\n';
9003
+ output = fitToTerminalHeight(stream, output);
9004
+ const width = getWidth(stream);
9005
+ if (output === previousOutput && previousWidth === width) {
9006
+ return;
9007
+ }
10129
9008
 
10130
- validateTimeout(parsed.options);
9009
+ previousOutput = output;
9010
+ previousWidth = width;
9011
+ output = wrapAnsi(output, width, {
9012
+ trim: false,
9013
+ hard: true,
9014
+ wordWrap: false,
9015
+ });
9016
+ stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
9017
+ previousLineCount = output.split('\n').length;
9018
+ };
10131
9019
 
10132
- let spawned;
10133
- try {
10134
- spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options);
10135
- } catch (error) {
10136
- // Ensure the returned error is always both a promise and a child process
10137
- const dummySpawned = new childProcess.ChildProcess();
10138
- const errorPromise = Promise.reject(makeError({
10139
- error,
10140
- stdout: '',
10141
- stderr: '',
10142
- all: '',
10143
- command,
10144
- escapedCommand,
10145
- parsed,
10146
- timedOut: false,
10147
- isCanceled: false,
10148
- killed: false,
10149
- }));
10150
- return mergePromise(dummySpawned, errorPromise);
10151
- }
9020
+ render.clear = () => {
9021
+ stream.write(ansiEscapes.eraseLines(previousLineCount));
9022
+ previousOutput = '';
9023
+ previousWidth = getWidth(stream);
9024
+ previousLineCount = 0;
9025
+ };
10152
9026
 
10153
- const spawnedPromise = getSpawnedPromise(spawned);
10154
- const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise);
10155
- const processDone = setExitHandler(spawned, parsed.options, timedPromise);
10156
-
10157
- const context = {isCanceled: false};
10158
-
10159
- spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned));
10160
- spawned.cancel = spawnedCancel.bind(null, spawned, context);
10161
-
10162
- const handlePromise = async () => {
10163
- const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone);
10164
- const stdout = handleOutput(parsed.options, stdoutResult);
10165
- const stderr = handleOutput(parsed.options, stderrResult);
10166
- const all = handleOutput(parsed.options, allResult);
10167
-
10168
- if (error || exitCode !== 0 || signal !== null) {
10169
- const returnedError = makeError({
10170
- error,
10171
- exitCode,
10172
- signal,
10173
- stdout,
10174
- stderr,
10175
- all,
10176
- command,
10177
- escapedCommand,
10178
- parsed,
10179
- timedOut,
10180
- isCanceled: context.isCanceled || (parsed.options.signal ? parsed.options.signal.aborted : false),
10181
- killed: spawned.killed,
10182
- });
10183
-
10184
- if (!parsed.options.reject) {
10185
- return returnedError;
10186
- }
9027
+ render.done = () => {
9028
+ previousOutput = '';
9029
+ previousWidth = getWidth(stream);
9030
+ previousLineCount = 0;
10187
9031
 
10188
- throw returnedError;
9032
+ if (!showCursor) {
9033
+ cliCursor.show();
10189
9034
  }
10190
-
10191
- return {
10192
- command,
10193
- escapedCommand,
10194
- exitCode: 0,
10195
- stdout,
10196
- stderr,
10197
- all,
10198
- failed: false,
10199
- timedOut: false,
10200
- isCanceled: false,
10201
- killed: false,
10202
- };
10203
9035
  };
10204
9036
 
10205
- const handlePromiseOnce = onetime(handlePromise);
9037
+ return render;
9038
+ }
9039
+
9040
+ createLogUpdate(process$1.stdout);
10206
9041
 
10207
- handleInput(spawned, parsed.options.input);
9042
+ createLogUpdate(process$1.stderr);
10208
9043
 
10209
- spawned.all = makeAllStream(spawned, parsed.options);
9044
+ var version = "0.19.0";
10210
9045
 
10211
- return mergePromise(spawned, handlePromiseOnce);
9046
+ function fileFromParsedStack(stack) {
9047
+ var _a, _b;
9048
+ if ((_b = (_a = stack == null ? void 0 : stack.sourcePos) == null ? void 0 : _a.source) == null ? void 0 : _b.startsWith(".."))
9049
+ return join(stack.file, "../", stack.sourcePos.source);
9050
+ return stack.file;
9051
+ }
9052
+ async function printError(error, ctx, options = {}) {
9053
+ const { showCodeFrame = true, fullStack = false, type } = options;
9054
+ let e = error;
9055
+ if (typeof error === "string") {
9056
+ e = {
9057
+ message: error.split(/\n/g)[0],
9058
+ stack: error
9059
+ };
9060
+ }
9061
+ const stacks = parseStacktrace(e, fullStack);
9062
+ await interpretSourcePos(stacks, ctx);
9063
+ const nearest = stacks.find((stack) => ctx.server.moduleGraph.getModuleById(stack.file) && existsSync(stack.file));
9064
+ const errorProperties = getErrorProperties(e);
9065
+ if (type)
9066
+ printErrorType(type, ctx);
9067
+ printErrorMessage(e, ctx.logger);
9068
+ printStack(ctx, stacks, nearest, errorProperties, (s, pos) => {
9069
+ if (showCodeFrame && s === nearest && nearest) {
9070
+ const file = fileFromParsedStack(nearest);
9071
+ if (existsSync(file)) {
9072
+ const sourceCode = readFileSync(file, "utf-8");
9073
+ ctx.logger.log(picocolors.exports.yellow(generateCodeFrame(sourceCode, 4, pos)));
9074
+ }
9075
+ }
9076
+ });
9077
+ if (e.cause) {
9078
+ e.cause.name = `Caused by: ${e.cause.name}`;
9079
+ await printError(e.cause, ctx, { fullStack, showCodeFrame: false });
9080
+ }
9081
+ handleImportOutsideModuleError(e.stack || e.stackStr || "", ctx);
9082
+ if (e.showDiff) {
9083
+ displayDiff(stringify$5(e.actual), stringify$5(e.expected), ctx.logger.console, {
9084
+ outputTruncateLength: ctx.config.outputTruncateLength,
9085
+ outputDiffLines: ctx.config.outputDiffLines
9086
+ });
9087
+ }
9088
+ }
9089
+ function printErrorType(type, ctx) {
9090
+ ctx.logger.error(`
9091
+ ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` ${type} `))))}`);
9092
+ }
9093
+ const skipErrorProperties = [
9094
+ "message",
9095
+ "name",
9096
+ "nameStr",
9097
+ "stack",
9098
+ "cause",
9099
+ "stacks",
9100
+ "stackStr",
9101
+ "type",
9102
+ "showDiff",
9103
+ "actual",
9104
+ "expected",
9105
+ "constructor",
9106
+ "toString"
9107
+ ];
9108
+ function getErrorProperties(e) {
9109
+ const errorObject = /* @__PURE__ */ Object.create(null);
9110
+ if (e.name === "AssertionError")
9111
+ return errorObject;
9112
+ for (const key of Object.getOwnPropertyNames(e)) {
9113
+ if (!skipErrorProperties.includes(key))
9114
+ errorObject[key] = e[key];
9115
+ }
9116
+ return errorObject;
10212
9117
  }
9118
+ const esmErrors = [
9119
+ "Cannot use import statement outside a module",
9120
+ "Unexpected token 'export'"
9121
+ ];
9122
+ function handleImportOutsideModuleError(stack, ctx) {
9123
+ if (!esmErrors.some((e) => stack.includes(e)))
9124
+ return;
9125
+ const path = normalize(stack.split("\n")[0].trim());
9126
+ let name = path.split("/node_modules/").pop() || "";
9127
+ if (name == null ? void 0 : name.startsWith("@"))
9128
+ name = name.split("/").slice(0, 2).join("/");
9129
+ else
9130
+ name = name.split("/")[0];
9131
+ ctx.logger.error(picocolors.exports.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${picocolors.exports.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
9132
+
9133
+ As a temporary workaround you can try to inline the package by updating your config:
10213
9134
 
10214
- class VitestGit {
10215
- constructor(cwd) {
10216
- this.cwd = cwd;
9135
+ ` + picocolors.exports.gray(picocolors.exports.dim("// vitest.config.js")) + "\n" + picocolors.exports.green(`export default {
9136
+ test: {
9137
+ deps: {
9138
+ inline: [
9139
+ ${picocolors.exports.yellow(picocolors.exports.bold(`"${name}"`))}
9140
+ ]
9141
+ }
10217
9142
  }
10218
- async resolveFilesWithGitCommand(args) {
10219
- let result;
10220
- try {
10221
- result = await execa("git", args, { cwd: this.root });
10222
- } catch (e) {
10223
- e.message = e.stderr;
10224
- throw e;
9143
+ }
9144
+ `)));
9145
+ }
9146
+ function displayDiff(actual, expected, console, options) {
9147
+ console.error(picocolors.exports.gray(unifiedDiff(actual, expected, options)) + "\n");
9148
+ }
9149
+ function printErrorMessage(error, logger) {
9150
+ const errorName = error.name || error.nameStr || "Unknown Error";
9151
+ logger.error(picocolors.exports.red(`${picocolors.exports.bold(errorName)}: ${error.message}`));
9152
+ }
9153
+ function printStack(ctx, stack, highlight, errorProperties, onStack) {
9154
+ if (!stack.length)
9155
+ return;
9156
+ const logger = ctx.logger;
9157
+ for (const frame of stack) {
9158
+ const pos = frame.sourcePos || frame;
9159
+ const color = frame === highlight ? picocolors.exports.yellow : picocolors.exports.gray;
9160
+ const file = fileFromParsedStack(frame);
9161
+ const path = relative(ctx.config.root, file);
9162
+ logger.log(color(` ${picocolors.exports.dim(F_POINTER)} ${[frame.method, picocolors.exports.dim(`${path}:${pos.line}:${pos.column}`)].filter(Boolean).join(" ")}`));
9163
+ onStack == null ? void 0 : onStack(frame, pos);
9164
+ if (frame.file in ctx.state.filesMap)
9165
+ break;
9166
+ }
9167
+ logger.log();
9168
+ const hasProperties = Object.keys(errorProperties).length > 0;
9169
+ if (hasProperties) {
9170
+ logger.log(picocolors.exports.red(picocolors.exports.dim(divider())));
9171
+ const propertiesString = stringify$5(errorProperties, 10, { printBasicPrototype: false });
9172
+ logger.log(picocolors.exports.red(picocolors.exports.bold("Serialized Error:")), picocolors.exports.gray(propertiesString));
9173
+ }
9174
+ }
9175
+ function generateCodeFrame(source, indent = 0, start = 0, end, range = 2) {
9176
+ var _a;
9177
+ start = posToNumber(source, start);
9178
+ end = end || start;
9179
+ const lines = source.split(lineSplitRE);
9180
+ let count = 0;
9181
+ let res = [];
9182
+ const columns = ((_a = process.stdout) == null ? void 0 : _a.columns) || 80;
9183
+ function lineNo(no = "") {
9184
+ return picocolors.exports.gray(`${String(no).padStart(3, " ")}| `);
9185
+ }
9186
+ for (let i = 0; i < lines.length; i++) {
9187
+ count += lines[i].length + 1;
9188
+ if (count >= start) {
9189
+ for (let j = i - range; j <= i + range || end > count; j++) {
9190
+ if (j < 0 || j >= lines.length)
9191
+ continue;
9192
+ const lineLength = lines[j].length;
9193
+ if (lineLength > 200)
9194
+ return "";
9195
+ res.push(lineNo(j + 1) + cliTruncate(lines[j].replace(/\t/g, " "), columns - 5 - indent));
9196
+ if (j === i) {
9197
+ const pad = start - (count - lineLength);
9198
+ const length = Math.max(1, end > count ? lineLength - pad : end - start);
9199
+ res.push(lineNo() + " ".repeat(pad) + picocolors.exports.red("^".repeat(length)));
9200
+ } else if (j > i) {
9201
+ if (end > count) {
9202
+ const length = Math.max(1, Math.min(end - count, lineLength));
9203
+ res.push(lineNo() + picocolors.exports.red("^".repeat(length)));
9204
+ }
9205
+ count += lineLength + 1;
9206
+ }
9207
+ }
9208
+ break;
10225
9209
  }
10226
- return result.stdout.split("\n").filter((s) => s !== "").map((changedPath) => resolve(this.root, changedPath));
10227
9210
  }
10228
- async findChangedFiles(options) {
10229
- const root = await this.getRoot(this.cwd);
10230
- if (!root)
10231
- return null;
10232
- this.root = root;
10233
- const changedSince = options.changedSince;
10234
- if (typeof changedSince === "string") {
10235
- const [committed, staged2, unstaged2] = await Promise.all([
10236
- this.getFilesSince(changedSince),
10237
- this.getStagedFiles(),
10238
- this.getUnstagedFiles()
10239
- ]);
10240
- return [...committed, ...staged2, ...unstaged2];
10241
- }
10242
- const [staged, unstaged] = await Promise.all([
10243
- this.getStagedFiles(),
10244
- this.getUnstagedFiles()
10245
- ]);
10246
- return [...staged, ...unstaged];
10247
- }
10248
- getFilesSince(hash) {
10249
- return this.resolveFilesWithGitCommand(["diff", "--name-only", `${hash}...HEAD`]);
10250
- }
10251
- getStagedFiles() {
10252
- return this.resolveFilesWithGitCommand(["diff", "--cached", "--name-only"]);
10253
- }
10254
- getUnstagedFiles() {
10255
- return this.resolveFilesWithGitCommand([
10256
- "ls-files",
10257
- "--other",
10258
- "--modified",
10259
- "--exclude-standard"
10260
- ]);
10261
- }
10262
- async getRoot(cwd) {
10263
- const options = ["rev-parse", "--show-cdup"];
10264
- try {
10265
- const result = await execa("git", options, { cwd });
10266
- return resolve(cwd, result.stdout);
10267
- } catch {
10268
- return null;
9211
+ if (indent)
9212
+ res = res.map((line) => " ".repeat(indent) + line);
9213
+ return res.join("\n");
9214
+ }
9215
+
9216
+ class Logger {
9217
+ constructor(ctx, console = globalThis.console) {
9218
+ this.ctx = ctx;
9219
+ this.console = console;
9220
+ this.outputStream = process.stdout;
9221
+ this.errorStream = process.stderr;
9222
+ this.logUpdate = createLogUpdate(process.stdout);
9223
+ }
9224
+ log(...args) {
9225
+ this._clearScreen();
9226
+ this.console.log(...args);
9227
+ }
9228
+ error(...args) {
9229
+ this._clearScreen();
9230
+ this.console.error(...args);
9231
+ }
9232
+ warn(...args) {
9233
+ this._clearScreen();
9234
+ this.console.warn(...args);
9235
+ }
9236
+ clearScreen(message, force = false) {
9237
+ if (this.ctx.server.config.clearScreen === false) {
9238
+ this.console.log(message);
9239
+ return;
10269
9240
  }
9241
+ this._clearScreenPending = message;
9242
+ if (force)
9243
+ this._clearScreen();
9244
+ }
9245
+ _clearScreen() {
9246
+ if (!this._clearScreenPending)
9247
+ return;
9248
+ const log = this._clearScreenPending;
9249
+ this._clearScreenPending = void 0;
9250
+ this.console.log(`\x1B[1;1H\x1B[J${log}`);
9251
+ }
9252
+ printError(err, fullStack = false, type) {
9253
+ return printError(err, this.ctx, {
9254
+ fullStack,
9255
+ type,
9256
+ showCodeFrame: true
9257
+ });
9258
+ }
9259
+ printNoTestFound(filters) {
9260
+ const config = this.ctx.config;
9261
+ const comma = picocolors.exports.dim(", ");
9262
+ if (filters == null ? void 0 : filters.length)
9263
+ this.console.error(picocolors.exports.dim("filter: ") + picocolors.exports.yellow(filters.join(comma)));
9264
+ if (config.include)
9265
+ this.console.error(picocolors.exports.dim("include: ") + picocolors.exports.yellow(config.include.join(comma)));
9266
+ if (config.exclude)
9267
+ this.console.error(picocolors.exports.dim("exclude: ") + picocolors.exports.yellow(config.exclude.join(comma)));
9268
+ if (config.watchExclude)
9269
+ this.console.error(picocolors.exports.dim("watch exclude: ") + picocolors.exports.yellow(config.watchExclude.join(comma)));
9270
+ if (config.passWithNoTests)
9271
+ this.log("No test files found, exiting with code 0\n");
9272
+ else
9273
+ this.error(picocolors.exports.red("\nNo test files found, exiting with code 1"));
9274
+ }
9275
+ printBanner() {
9276
+ var _a, _b, _c;
9277
+ this.log();
9278
+ const versionTest = this.ctx.config.watch ? picocolors.exports.blue(`v${version}`) : picocolors.exports.cyan(`v${version}`);
9279
+ const mode = this.ctx.config.watch ? picocolors.exports.blue(" DEV ") : picocolors.exports.cyan(" RUN ");
9280
+ this.log(`${picocolors.exports.inverse(picocolors.exports.bold(mode))} ${versionTest} ${picocolors.exports.gray(this.ctx.config.root)}`);
9281
+ if (this.ctx.config.browser)
9282
+ this.log(picocolors.exports.dim(picocolors.exports.green(` Browser runner started at http://${((_a = this.ctx.config.api) == null ? void 0 : _a.host) || "localhost"}:${picocolors.exports.bold(`${this.ctx.server.config.server.port}`)}`)));
9283
+ else if (this.ctx.config.ui)
9284
+ this.log(picocolors.exports.dim(picocolors.exports.green(` UI started at http://${((_b = this.ctx.config.api) == null ? void 0 : _b.host) || "localhost"}:${picocolors.exports.bold(`${this.ctx.server.config.server.port}`)}${this.ctx.config.uiBase}`)));
9285
+ else if (this.ctx.config.api)
9286
+ this.log(picocolors.exports.dim(picocolors.exports.green(` API started at http://${((_c = this.ctx.config.api) == null ? void 0 : _c.host) || "localhost"}:${picocolors.exports.bold(`${this.ctx.config.api.port}`)}`)));
9287
+ this.log();
9288
+ }
9289
+ async printUnhandledErrors(errors) {
9290
+ const errorMessage = picocolors.exports.red(picocolors.exports.bold(`
9291
+ Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run. This might cause false positive tests.
9292
+ Please, resolve all the errors to make sure your tests are not affected.`));
9293
+ this.log(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Errors ")))));
9294
+ this.log(errorMessage);
9295
+ await Promise.all(errors.map(async (err) => {
9296
+ await this.printError(err, true, err.type || "Unhandled Error");
9297
+ }));
9298
+ this.log(picocolors.exports.red(divider()));
10270
9299
  }
10271
9300
  }
10272
9301
 
10273
9302
  const WATCHER_DEBOUNCE = 100;
10274
- const CLOSE_TIMEOUT = 1e3;
10275
9303
  class Vitest {
10276
9304
  constructor() {
10277
9305
  this.config = void 0;
10278
9306
  this.server = void 0;
10279
9307
  this.state = void 0;
10280
9308
  this.snapshot = void 0;
9309
+ this.cache = void 0;
10281
9310
  this.reporters = void 0;
10282
- this.outputStream = process.stdout;
10283
- this.errorStream = process.stderr;
10284
9311
  this.vitenode = void 0;
10285
9312
  this.invalidates = /* @__PURE__ */ new Set();
10286
9313
  this.changedTests = /* @__PURE__ */ new Set();
@@ -10289,7 +9316,7 @@ class Vitest {
10289
9316
  this.runner = void 0;
10290
9317
  this._onRestartListeners = [];
10291
9318
  this.unregisterWatcher = noop$1;
10292
- this.console = globalThis.console;
9319
+ this.logger = new Logger(this);
10293
9320
  }
10294
9321
  async setServer(options, server) {
10295
9322
  var _a, _b;
@@ -10302,6 +9329,7 @@ class Vitest {
10302
9329
  this.server = server;
10303
9330
  this.config = resolved;
10304
9331
  this.state = new StateManager();
9332
+ this.cache = new VitestCache();
10305
9333
  this.snapshot = new SnapshotManager({ ...resolved.snapshotOptions });
10306
9334
  if (this.config.watch)
10307
9335
  this.registerWatcher();
@@ -10322,8 +9350,12 @@ class Vitest {
10322
9350
  this._onRestartListeners.forEach((fn) => fn());
10323
9351
  if (resolved.coverage.enabled)
10324
9352
  await cleanCoverage(resolved.coverage, resolved.coverage.clean);
10325
- this.state.results.setConfig(resolved.root, resolved.cache);
10326
- await this.state.results.readFromCache();
9353
+ this.cache.results.setConfig(resolved.root, resolved.cache);
9354
+ try {
9355
+ await this.cache.results.readFromCache();
9356
+ } catch (err) {
9357
+ this.logger.error(`[vitest] Error, while trying to parse cache in ${this.cache.results.getCachePath()}:`, err);
9358
+ }
10327
9359
  }
10328
9360
  getSerializableConfig() {
10329
9361
  return deepMerge({
@@ -10345,24 +9377,14 @@ class Vitest {
10345
9377
  const files = await this.filterTestsBySource(await this.globTestFiles(filters));
10346
9378
  if (!files.length) {
10347
9379
  const exitCode = this.config.passWithNoTests ? 0 : 1;
10348
- const comma = picocolors.exports.dim(", ");
10349
- if (filters == null ? void 0 : filters.length)
10350
- this.console.error(picocolors.exports.dim("filter: ") + picocolors.exports.yellow(filters.join(comma)));
10351
- if (this.config.include)
10352
- this.console.error(picocolors.exports.dim("include: ") + picocolors.exports.yellow(this.config.include.join(comma)));
10353
- if (this.config.watchExclude)
10354
- this.console.error(picocolors.exports.dim("watch exclude: ") + picocolors.exports.yellow(this.config.watchExclude.join(comma)));
10355
- if (this.config.passWithNoTests)
10356
- this.log("No test files found, exiting with code 0\n");
10357
- else
10358
- this.error(picocolors.exports.red("\nNo test files found, exiting with code 1"));
9380
+ this.logger.printNoTestFound(filters);
10359
9381
  process.exit(exitCode);
10360
9382
  }
10361
- await Promise.all(files.map((file) => this.state.stats.updateStats(file)));
9383
+ await Promise.all(files.map((file) => this.cache.stats.updateStats(file)));
10362
9384
  await this.runFiles(files);
10363
9385
  if (this.config.coverage.enabled)
10364
9386
  await reportCoverage(this);
10365
- if (this.config.watch)
9387
+ if (this.config.watch && !this.config.browser)
10366
9388
  await this.report("onWatcherStart");
10367
9389
  }
10368
9390
  async getTestDependencies(filepath) {
@@ -10386,12 +9408,13 @@ class Vitest {
10386
9408
  }
10387
9409
  async filterTestsBySource(tests) {
10388
9410
  if (this.config.changed && !this.config.related) {
9411
+ const { VitestGit } = await import('./chunk-node-git.9058b82a.mjs');
10389
9412
  const vitestGit = new VitestGit(this.config.root);
10390
9413
  const related2 = await vitestGit.findChangedFiles({
10391
9414
  changedSince: this.config.changed
10392
9415
  });
10393
9416
  if (!related2) {
10394
- this.error(picocolors.exports.red("Could not find Git root. Have you initialized git with `git init`?\n"));
9417
+ this.logger.error(picocolors.exports.red("Could not find Git root. Have you initialized git with `git init`?\n"));
10395
9418
  process.exit(1);
10396
9419
  }
10397
9420
  this.config.related = Array.from(new Set(related2));
@@ -10432,9 +9455,10 @@ class Vitest {
10432
9455
  const files = this.state.getFiles();
10433
9456
  if (hasFailed(files))
10434
9457
  process.exitCode = 1;
10435
- await this.report("onFinished", files, this.state.getUnhandledErrors());
10436
- this.state.results.updateResults(files);
10437
- await this.state.results.writeToCache();
9458
+ if (!this.config.browser)
9459
+ await this.report("onFinished", files, this.state.getUnhandledErrors());
9460
+ this.cache.results.updateResults(files);
9461
+ await this.cache.results.writeToCache();
10438
9462
  })().finally(() => {
10439
9463
  this.runningPromise = void 0;
10440
9464
  });
@@ -10443,7 +9467,8 @@ class Vitest {
10443
9467
  async rerunFiles(files = this.state.getFilepaths(), trigger) {
10444
9468
  await this.report("onWatcherRerun", files, trigger);
10445
9469
  await this.runFiles(files);
10446
- await this.report("onWatcherStart");
9470
+ if (!this.config.browser)
9471
+ await this.report("onWatcherStart");
10447
9472
  }
10448
9473
  async changeNamePattern(pattern, files = this.state.getFilepaths(), trigger) {
10449
9474
  this.config.testNamePattern = pattern ? new RegExp(pattern) : void 0;
@@ -10468,22 +9493,6 @@ class Vitest {
10468
9493
  this.configOverride = void 0;
10469
9494
  }
10470
9495
  }
10471
- log(...args) {
10472
- this.console.log(...args);
10473
- }
10474
- error(...args) {
10475
- this.console.error(...args);
10476
- }
10477
- clearScreen() {
10478
- var _a;
10479
- if (this.server.config.clearScreen === false)
10480
- return;
10481
- const repeatCount = (((_a = process.stdout) == null ? void 0 : _a.rows) ?? 0) - 2;
10482
- const blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
10483
- this.console.log(blank);
10484
- readline.cursorTo(process.stdout, 0, 0);
10485
- readline.clearScreenDown(process.stdout);
10486
- }
10487
9496
  async scheduleRerun(triggerId) {
10488
9497
  const currentCount = this.restartsCount;
10489
9498
  safeClearTimeout(this._rerunTimer);
@@ -10508,7 +9517,8 @@ class Vitest {
10508
9517
  await this.runFiles(files);
10509
9518
  if (this.config.coverage.enabled)
10510
9519
  await reportCoverage(this);
10511
- await this.report("onWatcherStart");
9520
+ if (!this.config.browser)
9521
+ await this.report("onWatcherStart");
10512
9522
  }, WATCHER_DEBOUNCE);
10513
9523
  }
10514
9524
  registerWatcher() {
@@ -10523,8 +9533,8 @@ class Vitest {
10523
9533
  this.invalidates.add(id);
10524
9534
  if (this.state.filesMap.has(id)) {
10525
9535
  this.state.filesMap.delete(id);
10526
- this.state.results.removeFromCache(id);
10527
- this.state.stats.removeStats(id);
9536
+ this.cache.results.removeFromCache(id);
9537
+ this.cache.stats.removeStats(id);
10528
9538
  this.changedTests.delete(id);
10529
9539
  this.report("onTestRemoved", id);
10530
9540
  }
@@ -10533,7 +9543,7 @@ class Vitest {
10533
9543
  id = slash$2(id);
10534
9544
  if (await this.isTargetFile(id)) {
10535
9545
  this.changedTests.add(id);
10536
- await this.state.stats.updateStats(id);
9546
+ await this.cache.stats.updateStats(id);
10537
9547
  this.scheduleRerun(id);
10538
9548
  }
10539
9549
  };
@@ -10584,7 +9594,7 @@ class Vitest {
10584
9594
  this.server.close()
10585
9595
  ].filter(Boolean)).then((results) => {
10586
9596
  results.filter((r) => r.status === "rejected").forEach((err) => {
10587
- this.error("error during close", err.reason);
9597
+ this.logger.error("error during close", err.reason);
10588
9598
  });
10589
9599
  });
10590
9600
  }
@@ -10592,9 +9602,9 @@ class Vitest {
10592
9602
  }
10593
9603
  async exit(force = false) {
10594
9604
  safeSetTimeout(() => {
10595
- console.warn(`close timed out after ${CLOSE_TIMEOUT}ms`);
9605
+ console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
10596
9606
  process.exit();
10597
- }, CLOSE_TIMEOUT).unref();
9607
+ }, this.config.teardownTimeout).unref();
10598
9608
  await this.close();
10599
9609
  if (force)
10600
9610
  process.exit();
@@ -10648,13 +9658,6 @@ class Vitest {
10648
9658
  isInSourceTestFile(code) {
10649
9659
  return code.includes("import.meta.vitest");
10650
9660
  }
10651
- printError(err, fullStack = false, type) {
10652
- return printError(err, this, {
10653
- fullStack,
10654
- type,
10655
- showCodeFrame: true
10656
- });
10657
- }
10658
9661
  onServerRestarted(fn) {
10659
9662
  this._onRestartListeners.push(fn);
10660
9663
  }
@@ -10731,9 +9734,9 @@ const GlobalSetupPlugin = (ctx) => {
10731
9734
  globalSetupFile.teardown = teardown;
10732
9735
  }
10733
9736
  } catch (e) {
10734
- ctx.error(`
9737
+ ctx.logger.error(`
10735
9738
  ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Error during global setup "))))}`);
10736
- await ctx.printError(e);
9739
+ await ctx.logger.printError(e);
10737
9740
  process.exit(1);
10738
9741
  }
10739
9742
  },
@@ -10744,7 +9747,7 @@ ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inve
10744
9747
  try {
10745
9748
  await ((_a = globalSetupFile.teardown) == null ? void 0 : _a.call(globalSetupFile));
10746
9749
  } catch (error) {
10747
- console.error(`error during global teardown of ${globalSetupFile.file}`, error);
9750
+ ctx.logger.error(`error during global teardown of ${globalSetupFile.file}`, error);
10748
9751
  }
10749
9752
  }
10750
9753
  }
@@ -10892,9 +9895,15 @@ function CSSEnablerPlugin(ctx) {
10892
9895
  async function VitestPlugin(options = {}, ctx = new Vitest()) {
10893
9896
  let haveStarted = false;
10894
9897
  async function UIPlugin() {
10895
- await ensurePackageInstalled("@vitest/ui");
9898
+ var _a;
9899
+ await ensurePackageInstalled("@vitest/ui", ((_a = ctx.config) == null ? void 0 : _a.root) || options.root || process.cwd());
10896
9900
  return (await import('@vitest/ui')).default(options.uiBase);
10897
9901
  }
9902
+ async function BrowserPlugin() {
9903
+ var _a;
9904
+ await ensurePackageInstalled("@vitest/browser", ((_a = ctx.config) == null ? void 0 : _a.root) || options.root || process.cwd());
9905
+ return (await import('@vitest/browser')).default("/");
9906
+ }
10898
9907
  return [
10899
9908
  {
10900
9909
  name: "vitest",
@@ -10929,10 +9938,15 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10929
9938
  }
10930
9939
  }
10931
9940
  options.defines = defines;
10932
- const open = preOptions.ui && preOptions.open ? preOptions.uiBase ?? "/__vitest__/" : void 0;
9941
+ let open;
9942
+ if (preOptions.ui && preOptions.open)
9943
+ open = preOptions.uiBase ?? "/__vitest__/";
9944
+ else if (preOptions.browser)
9945
+ open = "/";
10933
9946
  const config = {
10934
9947
  resolve: {
10935
- mainFields: []
9948
+ mainFields: [],
9949
+ alias: preOptions.alias
10936
9950
  },
10937
9951
  server: {
10938
9952
  ...preOptions.api,
@@ -10942,13 +9956,17 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10942
9956
  open,
10943
9957
  hmr: false,
10944
9958
  preTransformRequests: false
10945
- },
10946
- cacheDir: void 0,
10947
- optimizeDeps: {
10948
- disabled: true,
10949
- entries: []
10950
9959
  }
10951
9960
  };
9961
+ if (!options.browser) {
9962
+ Object.assign(config, {
9963
+ cacheDir: void 0,
9964
+ optimizeDeps: {
9965
+ disabled: true,
9966
+ entries: []
9967
+ }
9968
+ });
9969
+ }
10952
9970
  return config;
10953
9971
  },
10954
9972
  async configResolved(viteConfig) {
@@ -10956,6 +9974,8 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10956
9974
  const viteConfigTest = viteConfig.test || {};
10957
9975
  if (viteConfigTest.watch === false)
10958
9976
  viteConfigTest.run = true;
9977
+ if ("alias" in viteConfigTest)
9978
+ delete viteConfigTest.alias;
10959
9979
  options = deepMerge({}, configDefaults, viteConfigTest, options);
10960
9980
  options.api = resolveApiConfig(options);
10961
9981
  const { PROD, DEV, ...envs } = viteConfig.env;
@@ -10972,9 +9992,9 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10972
9992
  await ctx.setServer(options, server);
10973
9993
  haveStarted = true;
10974
9994
  if (options.api && options.watch)
10975
- (await import('./chunk-api-setup.c728e251.mjs')).setup(ctx);
9995
+ (await import('./chunk-api-setup.0cf2c96a.mjs')).setup(ctx);
10976
9996
  } catch (err) {
10977
- ctx.printError(err, true);
9997
+ ctx.logger.printError(err, true);
10978
9998
  process.exit(1);
10979
9999
  }
10980
10000
  if (!options.watch)
@@ -10984,6 +10004,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10984
10004
  EnvReplacerPlugin(),
10985
10005
  MocksPlugin(),
10986
10006
  GlobalSetupPlugin(ctx),
10007
+ ...options.browser ? await BrowserPlugin() : [],
10987
10008
  CSSEnablerPlugin(ctx),
10988
10009
  options.ui ? await UIPlugin() : null
10989
10010
  ].filter(notNullish);
@@ -11033,7 +10054,7 @@ function registerConsoleShortcuts(ctx) {
11033
10054
  if (name === "u")
11034
10055
  return ctx.updateSnapshot();
11035
10056
  if (name === "a" || name === "return")
11036
- return ctx.rerunFiles(void 0, "rerun all");
10057
+ return ctx.rerunFiles(void 0);
11037
10058
  if (name === "f")
11038
10059
  return ctx.rerunFailed();
11039
10060
  if (name === "t")
@@ -11058,8 +10079,8 @@ function registerConsoleShortcuts(ctx) {
11058
10079
  let rl;
11059
10080
  function on() {
11060
10081
  off();
11061
- rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 });
11062
- readline.emitKeypressEvents(process.stdin, rl);
10082
+ rl = require$$0$2.createInterface({ input: process.stdin, escapeCodeTimeout: 50 });
10083
+ require$$0$2.emitKeypressEvents(process.stdin, rl);
11063
10084
  if (process.stdin.isTTY)
11064
10085
  process.stdin.setRawMode(true);
11065
10086
  process.stdin.on("keypress", keypressHandler);
@@ -11081,7 +10102,10 @@ async function startVitest(cliFilters, options, viteOverrides) {
11081
10102
  (_a = process.env).NODE_ENV ?? (_a.NODE_ENV = options.mode || "test");
11082
10103
  if (options.run)
11083
10104
  options.watch = false;
11084
- if (!await ensurePackageInstalled("vite")) {
10105
+ if (options.browser)
10106
+ options.threads = false;
10107
+ const root = resolve(options.root || process.cwd());
10108
+ if (!await ensurePackageInstalled("vite", root)) {
11085
10109
  process.exitCode = 1;
11086
10110
  return false;
11087
10111
  }
@@ -11089,14 +10113,14 @@ async function startVitest(cliFilters, options, viteOverrides) {
11089
10113
  options.coverage = { enabled: options.coverage };
11090
10114
  const ctx = await createVitest(options, viteOverrides);
11091
10115
  if (ctx.config.coverage.enabled) {
11092
- if (!await ensurePackageInstalled("c8")) {
10116
+ if (!await ensurePackageInstalled("c8", root)) {
11093
10117
  process.exitCode = 1;
11094
10118
  return false;
11095
10119
  }
11096
10120
  }
11097
10121
  if (ctx.config.environment && ctx.config.environment !== "node") {
11098
10122
  const packageName = envPackageNames[ctx.config.environment];
11099
- if (!await ensurePackageInstalled(packageName)) {
10123
+ if (!await ensurePackageInstalled(packageName, root)) {
11100
10124
  process.exitCode = 1;
11101
10125
  return false;
11102
10126
  }
@@ -11110,8 +10134,8 @@ async function startVitest(cliFilters, options, viteOverrides) {
11110
10134
  await ctx.start(cliFilters);
11111
10135
  } catch (e) {
11112
10136
  process.exitCode = 1;
11113
- await ctx.printError(e, true, "Unhandled Error");
11114
- ctx.error("\n\n");
10137
+ await ctx.logger.printError(e, true, "Unhandled Error");
10138
+ ctx.logger.error("\n\n");
11115
10139
  return false;
11116
10140
  }
11117
10141
  if (!ctx.config.watch) {
@@ -11121,4 +10145,4 @@ async function startVitest(cliFilters, options, viteOverrides) {
11121
10145
  return true;
11122
10146
  }
11123
10147
 
11124
- export { BaseSequencer as B, VitestPlugin as V, createVitest as c, divider as d, startVitest as s, version as v };
10148
+ export { BaseSequencer as B, VitestPlugin as V, createVitest as c, divider as d, startVitest as s, version$1 as v };