Bump packages to fix linter

This commit is contained in:
Henry Mercer 2023-01-18 20:50:03 +00:00
parent ed9506bbaf
commit 0a11e3fdd9
6063 changed files with 378752 additions and 306784 deletions

17
node_modules/ava/lib/api.js generated vendored
View file

@ -16,6 +16,7 @@ import fork from './fork.js';
import * as globs from './globs.js';
import isCi from './is-ci.js';
import {getApplicableLineNumbers} from './line-numbers.js';
import {setCappedTimeout} from './now-and-timers.cjs';
import {observeWorkerProcess} from './plugin-support/shared-workers.js';
import RunStatus from './run-status.js';
import scheduler from './scheduler.js';
@ -52,7 +53,7 @@ class TimeoutTrigger {
debounce() {
if (this.timer === undefined) {
this.timer = setTimeout(() => this.trigger(), this.waitMs);
this.timer = setCappedTimeout(() => this.trigger(), this.waitMs);
} else {
this.timer.refresh();
}
@ -246,14 +247,16 @@ export default class Api extends Emittery {
}
}));
// Resolve the correct concurrency value.
let concurrency = Math.min(os.cpus().length, isCi ? 2 : Number.POSITIVE_INFINITY);
if (apiOptions.concurrency > 0) {
concurrency = apiOptions.concurrency;
}
// Resolve the correct concurrency value. Note that `os.cpus()` can return empty arrays on
// platforms not officially supported by Node.js. Use 1 as a minimum.
// See <https://github.com/nodejs/node/issues/38190>.
let concurrency = Math.max(1, os.cpus().length);
if (apiOptions.serial) {
concurrency = 1;
} else if (apiOptions.concurrency > 0) {
concurrency = apiOptions.concurrency;
} else if (isCi) {
concurrency = 2;
}
const deregisteredSharedWorkers = [];

13
node_modules/ava/lib/assert.js generated vendored
View file

@ -8,8 +8,10 @@ import {SnapshotError, VersionMismatchError} from './snapshot-manager.js';
function formatDescriptorDiff(actualDescriptor, expectedDescriptor, options) {
options = {...options, ...concordanceOptions};
const {diffGutters} = options.theme;
const {insertLine, deleteLine} = options.theme.string.diff;
return {
label: 'Difference:',
label: `Difference (${diffGutters.actual}${deleteLine.open}actual${deleteLine.close}, ${diffGutters.expected}${insertLine.open}expected${insertLine.close}):`,
formatted: concordance.diffDescriptors(actualDescriptor, expectedDescriptor, options),
};
}
@ -48,7 +50,7 @@ export class AssertionError extends Error {
// use the values for custom diff views
this.raw = options.raw;
this.savedError = options.savedError ? options.savedError : getErrorWithLongStackTrace();
this.savedError = options.savedError || getErrorWithLongStackTrace();
}
}
@ -141,14 +143,17 @@ function validateExpectations(assertion, expectations, numberArgs) { // eslint-d
case 'is':
case 'message':
case 'name':
case 'code':
case 'code': {
continue;
default:
}
default: {
throw new AssertionError({
assertion,
message: `The second argument to \`t.${assertion}()\` contains unexpected properties`,
values: [formatWithLabel('Called with:', expectations)],
});
}
}
}
}

16
node_modules/ava/lib/cli.js generated vendored
View file

@ -5,10 +5,10 @@ import process from 'node:process';
import arrify from 'arrify';
import ciParallelVars from 'ci-parallel-vars';
import del from 'del';
import {deleteAsync} from 'del';
import figures from 'figures';
import yargs from 'yargs';
import {hideBin} from 'yargs/helpers'; // eslint-disable-line node/file-extension-in-import
import {hideBin} from 'yargs/helpers'; // eslint-disable-line n/file-extension-in-import
import Api from './api.js';
import {chalk} from './chalk.js';
@ -124,7 +124,7 @@ export default async function loadCli() { // eslint-disable-line complexity
// run AVA with the debug command, though it's allowed.
let activeInspector = false;
try {
const {default: inspector} = await import('node:inspector'); // eslint-disable-line node/no-unsupported-features/es-syntax
const {default: inspector} = await import('node:inspector');
activeInspector = inspector.url() !== undefined;
} catch {}
@ -242,16 +242,16 @@ export default async function loadCli() { // eslint-disable-line complexity
const chalkOptions = {level: 0};
if (combined.color !== false) {
const {supportsColor: {level}} = await import('chalk'); // eslint-disable-line node/no-unsupported-features/es-syntax, unicorn/import-style
const {supportsColor: {level}} = await import('chalk'); // eslint-disable-line unicorn/import-style
chalkOptions.level = level;
}
const {set: setChalk} = await import('./chalk.js'); // eslint-disable-line node/no-unsupported-features/es-syntax
const {set: setChalk} = await import('./chalk.js');
setChalk(chalkOptions);
if (confError) {
if (confError.parent) {
exit(`${confError.message}\n\n${chalk.gray((confError.parent && confError.parent.stack) || confError.parent)}`);
if (confError.cause) {
exit(`${confError.message}\n\n${chalk.gray(confError.cause?.stack ?? confError.cause)}`);
} else {
exit(confError.message);
}
@ -262,7 +262,7 @@ export default async function loadCli() { // eslint-disable-line complexity
const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'ava');
try {
const deletedFilePaths = await del('*', {cwd: cacheDir});
const deletedFilePaths = await deleteAsync('*', {cwd: cacheDir});
if (deletedFilePaths.length === 0) {
console.log(`\n${chalk.green(figures.tick)} No cache files to remove`);

View file

@ -43,7 +43,7 @@ export default function exceptCode(source, options = {}) {
const coloredLineNumber = isErrorSource ? lineNumber : chalk.grey(lineNumber);
const result = ` ${coloredLineNumber} ${item.value.padEnd(extendedWidth)}`;
return isErrorSource ? chalk.bgRed(result) : result;
return isErrorSource ? chalk.bgRed.bold(result) : result;
})
.join('\n');
}

View file

@ -85,7 +85,7 @@ const colorTheme = {
undefined: ansiStyles.yellow,
};
const plainTheme = JSON.parse(JSON.stringify(colorTheme), value => typeof value === 'string' ? stripAnsi(value) : value);
const plainTheme = JSON.parse(JSON.stringify(colorTheme), (_name, value) => typeof value === 'string' ? stripAnsi(value) : value);
const theme = chalk.level > 0 ? colorTheme : plainTheme;

View file

@ -33,7 +33,7 @@ const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFi
cwd: projectDir,
...normalizeGlobs({
extensions,
files: overrideFiles ? overrideFiles : conf.files,
files: overrideFiles || conf.files,
providers,
}),
};
@ -69,5 +69,5 @@ const handleMessage = async ({projectDir, overrideExtensions, overrideFiles}) =>
};
parentPort.on('message', handleMessage);
handleMessage(workerData.firstMessage);
handleMessage(workerData.firstMessage); // eslint-disable-line unicorn/prefer-top-level-await
delete workerData.firstMessage;

11
node_modules/ava/lib/fork.js generated vendored
View file

@ -109,9 +109,11 @@ export default function loadFork(file, options, execArgv = process.execArgv) {
}
switch (message.ava.type) {
case 'ready-for-options':
case 'ready-for-options': {
send({type: 'options', options});
break;
}
case 'shared-worker-connect': {
const {channelId, filename, initialData, port} = message.ava;
emitter.emit('connectSharedWorker', {
@ -125,11 +127,14 @@ export default function loadFork(file, options, execArgv = process.execArgv) {
break;
}
case 'ping':
case 'ping': {
send({type: 'pong'});
break;
default:
}
default: {
emitStateChange(message.ava);
}
}
});

View file

@ -1,6 +1,6 @@
'use strict';
const path = require('path');
const process = require('process');
const path = require('node:path');
const process = require('node:process');
const ignoreByDefault = require('ignore-by-default');
const picomatch = require('picomatch');

22
node_modules/ava/lib/load-config.js generated vendored
View file

@ -11,7 +11,7 @@ const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
const EXPERIMENTS = new Set();
const importConfig = async ({configFile, fileForErrorMessage}) => {
const {default: config = MISSING_DEFAULT_EXPORT} = await import(url.pathToFileURL(configFile)); // eslint-disable-line node/no-unsupported-features/es-syntax
const {default: config = MISSING_DEFAULT_EXPORT} = await import(url.pathToFileURL(configFile));
if (config === MISSING_DEFAULT_EXPORT) {
throw new Error(`${fileForErrorMessage} must have a default export`);
}
@ -29,17 +29,13 @@ const loadConfigFile = async ({projectDir, configFile}) => {
return null;
}
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {parent: error});
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {cause: error});
}
};
function resolveConfigFile(configFile) {
if (configFile) {
configFile = path.resolve(configFile); // Relative to CWD
if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
throw new Error('Config files must have .js, .cjs or .mjs extensions');
}
}
return configFile;
@ -78,7 +74,7 @@ async function checkJsonFile(searchDir) {
}
}
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity
let packageConf = await packageConfig('ava', {cwd: resolveFrom});
const filepath = packageJsonPath(packageConf);
const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath);
@ -94,7 +90,17 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
let fileForErrorMessage;
let conflicting = [];
if (configFile) {
const loaded = await loadConfigFile({projectDir, configFile});
let loaded;
try {
loaded = await loadConfigFile({projectDir, configFile});
} catch (error) {
if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
throw Object.assign(new Error('Could not load config file; it should have .js, .cjs or .mjs extension'), {cause: error});
}
throw error;
}
if (loaded !== null) {
({config: fileConf, fileForErrorMessage} = loaded);
}

30
node_modules/ava/lib/module-types.js generated vendored
View file

@ -6,21 +6,28 @@ const requireTrueValue = value => {
const normalize = (extension, type, defaultModuleType) => {
switch (extension) {
case 'cjs':
case 'cjs': {
requireTrueValue(type);
return 'commonjs';
case 'mjs':
}
case 'mjs': {
requireTrueValue(type);
return 'module';
case 'js':
}
case 'js': {
requireTrueValue(type);
return defaultModuleType;
default:
}
default: {
if (type !== 'commonjs' && type !== 'module') {
throw new TypeError(`Module type for ${extension} must be commonjs or module`);
}
return type;
}
}
};
@ -37,17 +44,24 @@ const deriveFromArray = (extensions, defaultModuleType) => {
const moduleTypes = {};
for (const extension of extensions) {
switch (extension) {
case 'cjs':
case 'cjs': {
moduleTypes.cjs = 'commonjs';
break;
case 'mjs':
}
case 'mjs': {
moduleTypes.mjs = 'module';
break;
case 'js':
}
case 'js': {
moduleTypes.js = defaultModuleType;
break;
default:
}
default: {
moduleTypes[extension] = 'commonjs';
}
}
}

View file

@ -1,5 +1,16 @@
'use strict';
const timers = require('timers');
const timers = require('node:timers');
Object.assign(exports, timers);
exports.now = Date.now;
// Any delay larger than this value is ignored by Node.js, with a delay of `1`
// used instead. See <https://nodejs.org/api/timers.html#settimeoutcallback-delay-args>.
const MAX_DELAY = (2 ** 31) - 1;
function setCappedTimeout(callback, delay) {
const safeDelay = Math.min(delay, MAX_DELAY);
return timers.setTimeout(callback, safeDelay);
}
exports.setCappedTimeout = setCappedTimeout;

View file

@ -156,7 +156,7 @@ function broadcastMessage(data) {
}
async function loadFactory() {
const {default: factory} = await import(workerData.filename); // eslint-disable-line node/no-unsupported-features/es-syntax
const {default: factory} = await import(workerData.filename);
return factory;
}
@ -166,7 +166,8 @@ let signalAvailable = () => {
};
let fatal;
loadFactory(workerData.filename).then(factory => {
try {
const factory = await loadFactory(workerData.filename);
if (typeof factory !== 'function') {
throw new TypeError(`Missing default factory function export for shared worker plugin at ${workerData.filename}`);
}
@ -236,14 +237,12 @@ loadFactory(workerData.filename).then(factory => {
};
},
});
}).catch(error => {
if (fatal === undefined) {
fatal = error;
}
}).finally(() => {
} catch (error) {
fatal = fatal ?? error;
} finally {
if (fatal !== undefined) {
process.nextTick(() => {
throw fatal;
});
}
});
}

View file

@ -49,35 +49,54 @@ function launchWorker(filename, initialData) {
}
export async function observeWorkerProcess(fork, runStatus) {
let registrationCount = 0;
let signalDeregistered;
const deregistered = new Promise(resolve => {
signalDeregistered = resolve;
let signalDone;
const done = new Promise(resolve => {
signalDone = () => {
resolve();
};
});
fork.promise.finally(() => {
if (registrationCount === 0) {
signalDeregistered();
const activeInstances = new Set();
const removeInstance = instance => {
instance.worker.unref();
activeInstances.delete(instance);
if (activeInstances.size === 0) {
signalDone();
}
};
const removeAllInstances = () => {
if (activeInstances.size === 0) {
signalDone();
return;
}
for (const instance of activeInstances) {
removeInstance(instance);
}
};
fork.promise.finally(() => {
removeAllInstances();
});
fork.onConnectSharedWorker(async ({filename, initialData, port, signalError}) => {
const launched = launchWorker(filename, initialData);
activeInstances.add(launched);
const handleWorkerMessage = async message => {
if (message.type === 'deregistered-test-worker' && message.id === fork.threadId) {
launched.worker.off('message', handleWorkerMessage);
registrationCount--;
if (registrationCount === 0) {
signalDeregistered();
}
removeInstance(launched);
}
};
launched.statePromises.error.then(error => {
signalDeregistered();
launched.worker.off('message', handleWorkerMessage);
removeAllInstances();
runStatus.emitStateChange({type: 'shared-worker-error', err: serializeError('Shared worker error', true, error)});
signalError();
});
@ -85,8 +104,6 @@ export async function observeWorkerProcess(fork, runStatus) {
try {
await launched.statePromises.available;
registrationCount++;
port.postMessage({type: 'ready'});
launched.worker.postMessage({
@ -104,15 +121,8 @@ export async function observeWorkerProcess(fork, runStatus) {
});
launched.worker.on('message', handleWorkerMessage);
} catch {
return;
} finally {
// Attaching listeners has the side-effect of referencing the worker.
// Explicitly unreference it now so it does not prevent the main process
// from exiting.
launched.worker.unref();
}
} catch {}
});
return deregistered;
return done;
}

View file

@ -15,7 +15,7 @@ const levelsByProtocol = {
async function load(providerModule, projectDir) {
const ava = {version: pkg.version};
const {default: makeProvider} = await import(providerModule); // eslint-disable-line node/no-unsupported-features/es-syntax
const {default: makeProvider} = await import(providerModule);
let fatal;
let level;

View file

@ -233,6 +233,16 @@ export default class Reporter {
break;
}
case 'process-exit': {
this.write(colors.error(`${figures.cross} Exiting due to process.exit() when running ${this.relativeFile(event.testFile)}`));
this.lineWriter.writeLine();
this.lineWriter.writeLine(colors.errorStack(event.stack));
this.lineWriter.writeLine();
break;
}
case 'hook-finished': {
if (event.logs.length > 0) {
this.lineWriter.writeLine(` ${this.prefixTitle(event.testFile, event.title)}`);
@ -244,9 +254,9 @@ export default class Reporter {
case 'selected-test': {
if (event.skip) {
this.lineWriter.writeLine(colors.skip(`- ${this.prefixTitle(event.testFile, event.title)}`));
this.lineWriter.writeLine(colors.skip(`- [skip] ${this.prefixTitle(event.testFile, event.title)}`));
} else if (event.todo) {
this.lineWriter.writeLine(colors.todo(`- ${this.prefixTitle(event.testFile, event.title)}`));
this.lineWriter.writeLine(colors.todo(`- [todo] ${this.prefixTitle(event.testFile, event.title)}`));
}
break;
@ -360,8 +370,11 @@ export default class Reporter {
}
this.lineWriter.writeLine(`${testsInFile.size} tests were pending in ${this.relativeFile(file)}\n`);
const testTitleToLogs = evt.pendingTestsLogs.get(file);
for (const title of testsInFile) {
const logs = testTitleToLogs?.get(title);
this.lineWriter.writeLine(`${figures.circleDotted} ${this.prefixTitle(file, title)}`);
this.writeLogs({logs});
}
this.lineWriter.writeLine('');
@ -504,15 +517,30 @@ export default class Reporter {
}
writeTestSummary(event) {
// Prefix icon indicates matched expectations vs. not.
// Prefix color indicates passed-as-expected vs. not (fail or unexpected pass).
// This yields four possibilities, which in the standard configuration render as:
// * normal test, pass: <green>✔</green>
// * normal test, fail: <red>✘ [fail]</red>
// * fail-expected test, fail: <red>✔ [expected fail]</red>
// * fail-expected test, pass: <red>✘ [unexpected pass]</red>
let prefix;
let suffix;
if (event.type === 'hook-failed' || event.type === 'test-failed') {
this.write(`${colors.error(figures.cross)} ${this.prefixTitle(event.testFile, event.title)} ${colors.error(event.err.message)}`);
const type = event.knownFailing ? '[unexpected pass]' : '[fail]';
prefix = colors.error(`${figures.cross} ${type}:`);
suffix = chalk.italic(colors.error(event.err.message));
} else if (event.knownFailing) {
this.write(`${colors.error(figures.tick)} ${colors.error(this.prefixTitle(event.testFile, event.title))}`);
prefix = colors.error(figures.tick + ' [expected fail]');
} else {
const duration = event.duration > this.durationThreshold ? colors.duration(' (' + prettyMs(event.duration) + ')') : '';
this.write(`${colors.pass(figures.tick)} ${this.prefixTitle(event.testFile, event.title)}${duration}`);
prefix = colors.pass(figures.tick);
if (event.duration > this.durationThreshold) {
suffix = colors.duration(`(${prettyMs(event.duration)})`);
}
}
const label = this.prefixTitle(event.testFile, event.title);
this.write(`${prefix} ${label}${suffix ? ' ' + suffix : ''}`);
this.writeLogs(event);
}
@ -658,8 +686,8 @@ export default class Reporter {
this.lineWriter.writeLine(colors.error(`${this.stats.uncaughtExceptions} uncaught ${plur('exception', this.stats.uncaughtExceptions)}`));
}
if (this.stats.timeouts > 0) {
this.lineWriter.writeLine(colors.error(`${this.stats.timeouts} ${plur('test', this.stats.timeouts)} remained pending after a timeout`));
if (this.stats.timedOutTests > 0) {
this.lineWriter.writeLine(colors.error(`${this.stats.timedOutTests} ${plur('test', this.stats.timedOutTests)} remained pending after a timeout`));
}
if (this.previousFailures > 0) {

View file

@ -29,7 +29,7 @@ function dumpError(error) {
}
if (error.values.length > 0) {
object.values = Object.fromEntries(error.values.map(({label, formatted}) => [label, stripAnsi(formatted)]));
object.values = Object.fromEntries(error.values.map(({label, formatted}) => [stripAnsi(label), stripAnsi(formatted)]));
}
}
@ -128,6 +128,17 @@ export default class TapReporter {
}
}
writeProcessExit(evt) {
const error = new Error(`Exiting due to process.exit() when running ${this.relativeFile(evt.testFile)}`);
error.stack = evt.stack;
for (const [testFile, tests] of evt.pendingTests) {
for (const title of tests) {
this.writeTest({testFile, title, err: error}, {passed: false, todo: false, skip: false});
}
}
}
writeTimeout(evt) {
const error = new Error(`Exited because no new tests completed within the last ${evt.period}ms of inactivity`);
@ -142,23 +153,38 @@ export default class TapReporter {
const fileStats = this.stats && evt.testFile ? this.stats.byFile.get(evt.testFile) : null;
switch (evt.type) {
case 'declared-test':
case 'declared-test': {
// Ignore
break;
case 'hook-failed':
}
case 'hook-failed': {
this.writeTest(evt, {passed: false, todo: false, skip: false});
break;
case 'hook-finished':
}
case 'hook-finished': {
this.writeComment(evt, {});
break;
case 'internal-error':
}
case 'internal-error': {
this.writeCrash(evt);
break;
case 'missing-ava-import':
}
case 'missing-ava-import': {
this.filesWithMissingAvaImports.add(evt.testFile);
this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}, make sure to import "ava" at the top of your test file`);
break;
case 'selected-test':
}
case 'process-exit': {
this.writeProcessExit(evt);
break;
}
case 'selected-test': {
if (evt.skip) {
this.writeTest(evt, {passed: true, todo: false, skip: true});
} else if (evt.todo) {
@ -166,25 +192,39 @@ export default class TapReporter {
}
break;
case 'stats':
}
case 'stats': {
this.stats = evt.stats;
break;
case 'test-failed':
}
case 'test-failed': {
this.writeTest(evt, {passed: false, todo: false, skip: false});
break;
case 'test-passed':
}
case 'test-passed': {
this.writeTest(evt, {passed: true, todo: false, skip: false});
break;
case 'timeout':
}
case 'timeout': {
this.writeTimeout(evt);
break;
case 'uncaught-exception':
}
case 'uncaught-exception': {
this.writeCrash(evt);
break;
case 'unhandled-rejection':
}
case 'unhandled-rejection': {
this.writeCrash(evt);
break;
case 'worker-failed':
}
case 'worker-failed': {
if (!this.filesWithMissingAvaImports.has(evt.testFile)) {
if (evt.nonZeroExitCode) {
this.writeCrash(evt, `${this.relativeFile(evt.testFile)} exited with a non-zero exit code: ${evt.nonZeroExitCode}`);
@ -194,7 +234,9 @@ export default class TapReporter {
}
break;
case 'worker-finished':
}
case 'worker-finished': {
if (!evt.forcedExit && !this.filesWithMissingAvaImports.has(evt.testFile)) {
if (fileStats.declaredTests === 0) {
this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}`);
@ -204,12 +246,17 @@ export default class TapReporter {
}
break;
}
case 'worker-stderr':
case 'worker-stdout':
case 'worker-stdout': {
this.stdStream.write(evt.chunk);
break;
default:
}
default: {
break;
}
}
}
}

84
node_modules/ava/lib/run-status.js generated vendored
View file

@ -9,6 +9,7 @@ export default class RunStatus extends Emittery {
super();
this.pendingTests = new Map();
this.pendingTestsLogs = new Map();
this.emptyParallelRun = parallelRuns
&& parallelRuns.currentFileCount === 0
@ -33,6 +34,7 @@ export default class RunStatus extends Emittery {
selectedTests: 0,
sharedWorkerErrors: 0,
skippedTests: 0,
timedOutTests: 0,
timeouts: 0,
todoTests: 0,
uncaughtExceptions: 0,
@ -59,31 +61,39 @@ export default class RunStatus extends Emittery {
});
this.pendingTests.set(testFile, new Set());
this.pendingTestsLogs.set(testFile, new Map());
worker.onStateChange(data => this.emitStateChange(data));
}
// eslint-disable-next-line complexity
emitStateChange(event) {
const {stats} = this;
const fileStats = stats.byFile.get(event.testFile);
let changedStats = true;
switch (event.type) {
case 'declared-test':
case 'declared-test': {
stats.declaredTests++;
fileStats.declaredTests++;
break;
case 'hook-failed':
}
case 'hook-failed': {
stats.failedHooks++;
fileStats.failedHooks++;
break;
case 'internal-error':
}
case 'internal-error': {
stats.internalErrors++;
if (event.testFile) {
fileStats.internalErrors++;
}
break;
case 'selected-test':
}
case 'selected-test': {
stats.selectedTests++;
fileStats.selectedTests++;
if (event.skip) {
@ -99,17 +109,23 @@ export default class RunStatus extends Emittery {
}
break;
case 'shared-worker-error':
}
case 'shared-worker-error': {
stats.sharedWorkerErrors++;
break;
case 'test-failed':
}
case 'test-failed': {
stats.failedTests++;
fileStats.failedTests++;
stats.remainingTests--;
fileStats.remainingTests--;
this.removePendingTest(event);
break;
case 'test-passed':
}
case 'test-passed': {
if (event.knownFailing) {
stats.passedKnownFailingTests++;
fileStats.passedKnownFailingTests++;
@ -122,35 +138,68 @@ export default class RunStatus extends Emittery {
fileStats.remainingTests--;
this.removePendingTest(event);
break;
case 'timeout':
}
case 'test-register-log-reference': {
this.addPendingTestLogs(event);
break;
}
case 'timeout': {
stats.timeouts++;
event.pendingTests = this.pendingTests;
event.pendingTestsLogs = this.pendingTestsLogs;
this.pendingTests = new Map();
this.pendingTestsLogs = new Map();
for (const testsInFile of event.pendingTests.values()) {
stats.timeouts += testsInFile.size;
stats.timedOutTests += testsInFile.size;
}
break;
case 'interrupt':
}
case 'interrupt': {
event.pendingTests = this.pendingTests;
event.pendingTestsLogs = this.pendingTestsLogs;
this.pendingTests = new Map();
this.pendingTestsLogs = new Map();
break;
case 'uncaught-exception':
}
case 'process-exit': {
event.pendingTests = this.pendingTests;
event.pendingTestsLogs = this.pendingTestsLogs;
this.pendingTests = new Map();
this.pendingTestsLogs = new Map();
break;
}
case 'uncaught-exception': {
stats.uncaughtExceptions++;
fileStats.uncaughtExceptions++;
break;
case 'unhandled-rejection':
}
case 'unhandled-rejection': {
stats.unhandledRejections++;
fileStats.unhandledRejections++;
break;
case 'worker-failed':
}
case 'worker-failed': {
stats.failedWorkers++;
break;
case 'worker-finished':
}
case 'worker-finished': {
stats.finishedWorkers++;
break;
default:
}
default: {
changedStats = false;
break;
}
}
if (changedStats) {
@ -175,6 +224,7 @@ export default class RunStatus extends Emittery {
|| this.stats.failedHooks > 0
|| this.stats.failedTests > 0
|| this.stats.failedWorkers > 0
|| this.stats.remainingTests > 0
|| this.stats.sharedWorkerErrors > 0
|| this.stats.timeouts > 0
|| this.stats.uncaughtExceptions > 0
@ -190,6 +240,10 @@ export default class RunStatus extends Emittery {
return 0;
}
addPendingTestLogs(event) {
this.pendingTestsLogs.get(event.testFile)?.set(event.title, event.logs);
}
addPendingTest(event) {
if (this.pendingTests.has(event.testFile)) {
this.pendingTests.get(event.testFile).add(event.title);

6
node_modules/ava/lib/runner.js generated vendored
View file

@ -358,6 +358,12 @@ export default class Runner extends Emittery {
notifyTimeoutUpdate: this.notifyTimeoutUpdate,
});
this.emit('stateChange', {
type: 'test-register-log-reference',
title: task.title,
logs: test.logs,
});
const result = await this.runSingle(test);
testOk = result.passed;

2
node_modules/ava/lib/test.js generated vendored
View file

@ -405,7 +405,7 @@ export default class Test {
this.clearTimeout();
this.timeoutMs = ms;
this.timeoutTimer = nowAndTimers.setTimeout(() => {
this.timeoutTimer = nowAndTimers.setCappedTimeout(() => {
this.saveFirstError(new Error(message || 'Test timeout exceeded'));
if (this.finishDueToTimeout) {

8
node_modules/ava/lib/watcher.js generated vendored
View file

@ -294,14 +294,18 @@ export default class Watcher {
switch (evt.type) {
case 'hook-failed':
case 'internal-error':
case 'process-exit':
case 'test-failed':
case 'uncaught-exception':
case 'unhandled-rejection':
case 'worker-failed':
case 'worker-failed': {
this.countFailure(evt.testFile, currentVector);
break;
default:
}
default: {
break;
}
}
});
});

63
node_modules/ava/lib/worker/base.js generated vendored
View file

@ -19,6 +19,41 @@ import {flags, refs, sharedWorkerTeardowns} from './state.cjs';
import {isRunningInThread, isRunningInChildProcess} from './utils.cjs';
const currentlyUnhandled = setUpCurrentlyUnhandled();
let runner;
// Override process.exit with an undetectable replacement
// to report when it is called from a test (which it should never be).
const {apply} = Reflect;
const realExit = process.exit;
async function exit(code, forceSync = false) {
dependencyTracking.flush();
const flushing = channel.flush();
if (!forceSync) {
await flushing;
}
apply(realExit, process, [code]);
}
const handleProcessExit = (fn, receiver, args) => {
const error = new Error('Unexpected process.exit()');
Error.captureStackTrace(error, handleProcessExit);
const {stack} = serializeError('', true, error);
channel.send({type: 'process-exit', stack});
// Make sure to extract the code only from `args` rather than e.g. `Array.prototype`.
// This level of paranoia is usually unwarranted, but we're dealing with test code
// that has already colored outside the lines.
const code = args.length > 0 ? args[0] : undefined;
// Force a synchronous exit as guaranteed by the real process.exit().
exit(code, true);
};
process.exit = new Proxy(realExit, {
apply: handleProcessExit,
});
const run = async options => {
setOptions(options);
@ -29,16 +64,6 @@ const run = async options => {
global.console = Object.assign(global.console, new console.Console({stdout, stderr, colorMode: true}));
}
async function exit(code) {
if (!process.exitCode) {
process.exitCode = code;
}
dependencyTracking.flush();
await channel.flush();
process.exit(); // eslint-disable-line unicorn/no-process-exit
}
let checkSelectedByLineNumbers;
try {
checkSelectedByLineNumbers = lineNumberSelection({
@ -50,7 +75,7 @@ const run = async options => {
checkSelectedByLineNumbers = () => false;
}
const runner = new Runner({
runner = new Runner({
checkSelectedByLineNumbers,
experiments: options.experiments,
failFast: options.failFast,
@ -141,7 +166,7 @@ const run = async options => {
for (const extension of extensionsToLoadAsModules) {
if (ref.endsWith(`.${extension}`)) {
return import(pathToFileURL(ref)); // eslint-disable-line node/no-unsupported-features/es-syntax
return import(pathToFileURL(ref));
}
}
@ -161,7 +186,7 @@ const run = async options => {
if (options.debug && options.debug.port !== undefined && options.debug.host !== undefined) {
// If an inspector was active when the main process started, and is
// already active for the worker process, do not open a new one.
const {default: inspector} = await import('node:inspector'); // eslint-disable-line node/no-unsupported-features/es-syntax
const {default: inspector} = await import('node:inspector');
if (!options.debug.active || inspector.url() === undefined) {
inspector.open(options.debug.port, options.debug.host, true);
}
@ -197,12 +222,18 @@ const onError = error => {
});
};
let options;
if (isRunningInThread) {
channel.send({type: 'starting'}); // AVA won't terminate the worker thread until it's seen this message.
const {options} = workerData;
({options} = workerData);
delete workerData.options; // Don't allow user code access.
run(options).catch(onError);
} else if (isRunningInChildProcess) {
channel.send({type: 'ready-for-options'});
channel.options.then(run).catch(onError);
options = await channel.options;
}
try {
await run(options);
} catch (error) {
onError(error);
}

View file

@ -1,7 +1,7 @@
'use strict';
const events = require('events');
const process = require('process');
const {MessageChannel, threadId} = require('worker_threads');
const events = require('node:events');
const process = require('node:process');
const {MessageChannel, threadId} = require('node:worker_threads');
const timers = require('../now-and-timers.cjs');
@ -15,7 +15,7 @@ let pEvent = async (emitter, event, options) => {
emitter.on(event, addToBuffer);
try {
({pEvent} = await import('p-event')); // eslint-disable-line node/no-unsupported-features/es-syntax
({pEvent} = await import('p-event'));
} finally {
emitter.off(event, addToBuffer);
}
@ -125,7 +125,7 @@ if (isRunningInChildProcess) {
const {controlFlow} = require('../ipc-flow-control.cjs');
handle = new IpcHandle(controlFlow(process));
} else if (isRunningInThread) {
const {parentPort} = require('worker_threads');
const {parentPort} = require('node:worker_threads');
handle = new MessagePortHandle(parentPort);
}
@ -133,7 +133,7 @@ if (isRunningInChildProcess) {
// Node.js. In order to keep track, explicitly reference before attaching.
handle.ref();
exports.options = pEvent(handle.channel, 'message', selectAvaMessage('options')).then(message => message.ava.options);
exports.options = pEvent(handle.channel, 'message', selectAvaMessage('options')).then(message => message.ava.options); // eslint-disable-line unicorn/prefer-top-level-await
exports.peerFailed = pEvent(handle.channel, 'message', selectAvaMessage('peer-failed'));
exports.send = handle.send.bind(handle);
exports.unref = handle.unref.bind(handle);

View file

@ -1,6 +1,6 @@
'use strict';
const path = require('path');
const process = require('process');
const path = require('node:path');
const process = require('node:process');
const {isRunningInThread, isRunningInChildProcess} = require('./utils.cjs');

View file

@ -12,7 +12,7 @@ function parse(file) {
const walk = require('acorn-walk');
const ast = acorn.parse(fs.readFileSync(file, 'utf8'), {
ecmaVersion: 11,
ecmaVersion: 'latest',
locations: true,
sourceType: 'module',
});

View file

@ -1,7 +1,7 @@
'use strict';
require('./guard-environment.cjs'); // eslint-disable-line import/no-unassigned-import
const assert = require('assert');
const assert = require('node:assert');
const {flags, refs} = require('./state.cjs');

View file

@ -1,6 +1,6 @@
'use strict';
const process = require('process');
const {isMainThread} = require('worker_threads');
const process = require('node:process');
const {isMainThread} = require('node:worker_threads');
exports.isRunningInThread = isMainThread === false;
exports.isRunningInChildProcess = typeof process.send === 'function';