From 10e099df31d0be028b7cf12ebd06d6e1d492b2a6 Mon Sep 17 00:00:00 2001 From: alexander-akait <4567934+alexander-akait@users.noreply.github.com> Date: Mon, 14 Sep 2026 16:15:18 +0000 Subject: [PATCH] fix: end a build whose output report has nowhere to go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `writeOutputFile` guards against a compiler with no output file system by returning from inside the promise it answers with — which settles nothing. What awaits it is `processAssets`'s own callback, so the guard did not skip the write, it hung the build: no error, no report, no end. It answers now, which is what the guard meant to do. --- .../output-report-without-a-file-system.md | 5 +++++ src/utils.js | 8 ++++++- test/utils.test.js | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 .changeset/output-report-without-a-file-system.md diff --git a/.changeset/output-report-without-a-file-system.md b/.changeset/output-report-without-a-file-system.md new file mode 100644 index 0000000..8ac0489 --- /dev/null +++ b/.changeset/output-report-without-a-file-system.md @@ -0,0 +1,5 @@ +--- +"diagnostics-webpack-plugin": patch +--- + +End the build rather than hanging it where an `outputReport` has no file system to be written to. diff --git a/src/utils.js b/src/utils.js index 47600b7..a7ef6d4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -190,7 +190,13 @@ const jsonStringifyReplacerSortKeys = (_, value) => { function writeOutputFile(compiler, name, content) { return /** @type {Promise} */ ( new Promise((finish, bail) => { - if (!compiler.outputFileSystem) return; + // Nothing to write it to. Answering rather than returning: what awaits + // this is the compilation's own callback, so a promise left unsettled + // is a build that never ends. + if (!compiler.outputFileSystem) { + finish(); + return; + } const { mkdir, writeFile } = compiler.outputFileSystem; diff --git a/test/utils.test.js b/test/utils.test.js index dc6e570..8ffb278 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -7,6 +7,7 @@ import { parseFiles, parseFoldersToGlobs, toPosixPath, + writeOutputFile, } from "../src/utils.js"; // `parseFoldersToGlobs` reads what it is given, so the fixtures have to exist. @@ -85,6 +86,27 @@ describe("utils", () => { ]); }); + it("writeOutputFile should answer where there is nothing to write to", async () => { + // What awaits this is the compilation's own callback, so a promise left + // unsettled is a build that never ends rather than one that reports. + /** @type {NodeJS.Timeout} */ + let waiting; + const answered = await Promise.race([ + writeOutputFile( + /** @type {EXPECTED_ANY} */ ({}), + join(directory, "report.json"), + "{}", + ).then(() => "answered"), + new Promise((done) => { + waiting = setTimeout(() => done("never answered"), 1000); + }), + ]); + + clearTimeout(waiting); + + assert.strictEqual(answered, "answered"); + }); + it("parseFoldersToGlobs should cover a path that is not there yet both ways", async () => { const absent = join(directory, "not-written-yet");