From 03248a8338ea0dade49a74cceae27f8eba227ab8 Mon Sep 17 00:00:00 2001 From: Orfeas Zafeiris Date: Mon, 26 Jan 2026 18:09:44 +0200 Subject: [PATCH 1/4] Check for compilation errors in OutputPlugin Previously, the RepackOutputPlugin would always assume compilation had succeeded. The `done` hook gets fired even after compilation finishes with errors, which would cause the plugin to try to copy around chunks that haven't been written to disk (due to said errors), resulting in cryptic errors about `index.bundle` not being found. This change adds a check for compilation errors, and aborts the bundling process if it finds any. --- packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts b/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts index 69a551c9e..3825204f0 100644 --- a/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts +++ b/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts @@ -184,6 +184,10 @@ export class OutputPlugin { ); compiler.hooks.done.tapPromise('RepackOutputPlugin', async (stats) => { + if (stats.hasErrors()) { + throw new Error('[RepackOutputPlugin] Compilation failed:\n' + stats.toString('errors-only')); + } + const compilationStats = stats.toJson({ all: false, assets: true, From 7209541e8270b875e900d8b748379db66d278740 Mon Sep 17 00:00:00 2001 From: OrfeasZ Date: Mon, 26 Jan 2026 18:18:58 +0200 Subject: [PATCH 2/4] Add changeset --- .changeset/frank-cougars-go.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/frank-cougars-go.md diff --git a/.changeset/frank-cougars-go.md b/.changeset/frank-cougars-go.md new file mode 100644 index 000000000..f4d2244c3 --- /dev/null +++ b/.changeset/frank-cougars-go.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Handle previous compiler errors and abort bundling in `RepackOutputPlugin` From 47680655818b67c4b45e1d534308794fcc1082ea Mon Sep 17 00:00:00 2001 From: OrfeasZ Date: Mon, 2 Feb 2026 20:01:07 +0200 Subject: [PATCH 3/4] Fix linter errors and add tests for OutputPlugin compiler error handling --- .../src/plugins/OutputPlugin/OutputPlugin.ts | 5 +- .../plugins/__tests__/OutputPlugin.test.ts | 69 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts b/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts index 3825204f0..c7270114f 100644 --- a/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts +++ b/packages/repack/src/plugins/OutputPlugin/OutputPlugin.ts @@ -185,7 +185,10 @@ export class OutputPlugin { compiler.hooks.done.tapPromise('RepackOutputPlugin', async (stats) => { if (stats.hasErrors()) { - throw new Error('[RepackOutputPlugin] Compilation failed:\n' + stats.toString('errors-only')); + throw new Error( + '[RepackOutputPlugin] Compilation failed:\n' + + stats.toString('errors-only') + ); } const compilationStats = stats.toJson({ diff --git a/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts b/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts index 15656d69b..12398c727 100644 --- a/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts +++ b/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts @@ -1,13 +1,69 @@ +import fs from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; import { type EntryNormalized, ModuleFilenameHelpers, type StatsChunk, + rspack, } from '@rspack/core'; +import RspackVirtualModulePlugin from 'rspack-plugin-virtual-module'; import { OutputPlugin, type OutputPluginConfig, } from '../OutputPlugin/index.js'; +async function testCompile(code: string, expectThrow?: string) { + // Create a temporary directory to write files to. + const tempDir = await fs.mkdtemp( + path.join(os.tmpdir(), 'output-plugin-test-') + ); + + // And then run the compiler with the provided code. + try { + const compiler = rspack({ + context: tempDir, + mode: 'production', + devtool: false, + entry: 'index.js', + output: { + filename: 'index.bundle', + path: '/out', + }, + plugins: [ + new OutputPlugin({ + context: tempDir, + platform: 'ios', + output: {}, + }), + new RspackVirtualModulePlugin({ + 'index.js': code, + }), + ], + }); + + const promise = new Promise((resolve, reject) => + compiler.run((error, _stats) => { + if (error) { + reject(error); + } else { + resolve(); + } + }) + ); + + // Depending on whether we expect an error or not, assert accordingly. + if (expectThrow) { + await expect(promise).rejects.toThrow(expectThrow); + } else { + await expect(promise).resolves.not.toThrow(); + } + } finally { + // Delete the temporary directory after the test + await fs.rm(tempDir, { recursive: true, force: true }); + } +} + const makeChunk = ({ name, entry = false, @@ -204,4 +260,17 @@ describe('OutputPlugin', () => { }); }); }); + + describe('apply', () => { + it('should throw an error when compilation has errors', async () => { + await testCompile( + 'const x = {{{', + '[RepackOutputPlugin] Compilation failed:' + ); + }); + + it('should complete successfully when compilation succeeds', async () => { + await testCompile('const x = {};'); + }); + }); }); From a6c24b6ea04583b290f9d00f1c02e0ef86e01382 Mon Sep 17 00:00:00 2001 From: OrfeasZ Date: Mon, 2 Feb 2026 20:55:52 +0200 Subject: [PATCH 4/4] Fix output plugin output folder --- packages/repack/src/plugins/__tests__/OutputPlugin.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts b/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts index 12398c727..90adedab0 100644 --- a/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts +++ b/packages/repack/src/plugins/__tests__/OutputPlugin.test.ts @@ -28,7 +28,7 @@ async function testCompile(code: string, expectThrow?: string) { entry: 'index.js', output: { filename: 'index.bundle', - path: '/out', + path: path.join(tempDir, 'out'), }, plugins: [ new OutputPlugin({