Repository: eslint/eslint
File: lib/eslint/eslint.js (JavaScript)

Code before:
	/**
	 * A promise executor function that starts a worker thread on each invocation.
	 * @param {() => void} resolve_ Called when the worker thread terminates successfully.
	 * @param {(error: Error) => void} reject Called when the worker thread terminates with an error.
	 * @returns {void}
	 */
	function workerExecutor(resolve_, reject) {
		const workerStartTime = hrtimeBigint();
		const worker = new Worker(workerURL, workerOptions);
		worker.once(
			"message",
			(/** @type {WorkerLintResults} */ indexedResults) => {
				const workerDuration = hrtimeBigint() - workerStartTime;

				// The net linting ratio provides an approximate measure of worker thread efficiency, defined as the net linting duration divided by the thread's total runtime.
				const netLintingRatio =
					Number(indexedResults.netLintingDuration) /
					Number(workerDuration);

				worstNetLintingRatio = Math.min(
					worstNetLintingRatio,
					netLintingRatio,
				);

				if (timing.enabled) {
					timing.mergeData(indexedResults.timings);
				}

				for (const result of indexedResults) {
					const { index } = result;
					delete result.index;
					results[index] = result;
				}
				resolve_();
			},
		);
		worker.once("error", error => {
			abortController.abort(error);
			reject(error);
		});
		abortSignal.addEventListener("abort", () => worker.terminate());
	}

	const promises = Array(workerCount);
	for (let index = 0; index < workerCount; ++index) {
		promises[index] = new Promise(workerExecutor);
	}
	await Promise.all(promises);

	if (worstNetLintingRatio < LOW_NET_LINTING_RATIO) {
		warnOnLowNetLintingRatio();

Review comment (bug):
If an error is thrown while processing files, for example because a rule crashes, an empty header is printed:

```shell
$ TIMING=10 node ./bin/eslint.js --concurrency=2
(node:57750) ESLintIgnoreWarning: The ".eslintignore" file is no longer supported. Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files
(Use `node --trace-warnings ...` to show where the warning was created)

Oops! Something went wrong! :(

ESLint: 9.37.0

TypeError: Cannot read properties of null (reading 'length')
Occurred while linting .../eslint/.trunk/configs/svgo.config.js:1
Rule: "strict"
    at Program (.../eslint/lib/rules/strict.js:282:27)
    at .../eslint/lib/linter/timing.js:147:19
    at ruleErrorHandler (.../eslint/lib/linter/linter.js:1173:33)
    at .../eslint/lib/linter/source-code-visitor.js:76:46
    at Array.forEach (<anonymous>)
    at SourceCodeVisitor.callSync (.../eslint/lib/linter/source-code-visitor.js:76:30)
    at .../eslint/lib/linter/source-code-traverser.js:291:18
    at Array.forEach (<anonymous>)
    at SourceCodeTraverser.traverseSync (.../eslint/lib/linter/source-code-traverser.js:290:10)
    at runRules (.../eslint/lib/linter/linter.js:1214:12)
Rule | Time (ms) | Relative
:----|----------:|--------:
```

Without concurrency, the timing report is always printed.

Code after:
	/**
	 * A promise executor function that starts a worker thread on each invocation.
	 * @param {() => void} resolve_ Called when the worker thread terminates successfully.
	 * @param {(error: Error) => void} reject Called when the worker thread terminates with an error.
	 * @returns {void}
	 */
	function workerExecutor(resolve_, reject) {
		const workerStartTime = hrtimeBigint();
		const worker = new Worker(workerURL, workerOptions);
		worker.once(
			"message",
			(/** @type {WorkerLintResults} */ indexedResults) => {
				const workerDuration = hrtimeBigint() - workerStartTime;

				// The net linting ratio provides an approximate measure of worker thread efficiency, defined as the net linting duration divided by the thread's total runtime.
				const netLintingRatio =
					Number(indexedResults.netLintingDuration) /
					Number(workerDuration);

				worstNetLintingRatio = Math.min(
					worstNetLintingRatio,
					netLintingRatio,
				);

				if (timing.enabled && indexedResults.timings) {
					timing.mergeData(indexedResults.timings);
				}

				for (const result of indexedResults) {
					const { index } = result;
					delete result.index;
					results[index] = result;
				}
				resolve_();
			},
		);
		worker.once("error", error => {
			abortController.abort(error);
			reject(error);
		});
		abortSignal.addEventListener("abort", () => worker.terminate());
	}

	const promises = Array(workerCount);
	for (let index = 0; index < workerCount; ++index) {
		promises[index] = new Promise(workerExecutor);
	}

	try {
		await Promise.all(promises);
	} catch (error) {