From 4704ab3d6a5265f15ff0b6371ca2f09885ef5d4a Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 14 Jun 2025 08:16:27 +0200 Subject: [PATCH] fix(commonjs): fix crash with invalidated proxy modules In watch mode when the code imports CommonJS from ESM, depending on the setup, it can happen that the ES to Commonjs proxy module is re-evaluated. If that happens, its meta information is lost, leading to a weird crash. --- .../commonjs/src/resolve-require-sources.js | 2 +- packages/commonjs/test/test.js | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/commonjs/src/resolve-require-sources.js b/packages/commonjs/src/resolve-require-sources.js index be662ee0f..84b42fa66 100644 --- a/packages/commonjs/src/resolve-require-sources.js +++ b/packages/commonjs/src/resolve-require-sources.js @@ -141,7 +141,7 @@ export function getRequireResolver(extensions, detectCyclesAndConditional, curre return ( (await getTypeForImportedModule( ( - await this.load({ id: resolved.id }) + await this.load(resolved) ).meta.commonjs.resolved, this.load )) !== IS_WRAPPED_COMMONJS diff --git a/packages/commonjs/test/test.js b/packages/commonjs/test/test.js index 1ef56aa0d..cd1c8bbc9 100644 --- a/packages/commonjs/test/test.js +++ b/packages/commonjs/test/test.js @@ -1285,6 +1285,48 @@ test('handles external dependencies when using the cache', async (t) => { t.is(await getCodeFromBundle(bundle), code); }); +test('Correctly processes meta data when using the cache but invalidating proxy modules', async (t) => { + const modules = {}; + const resetModules = () => { + modules['main.js'] = "import first from 'first.js';export default first;"; + modules['first.js'] = "import second from 'second.js';export default second;"; + modules['second.js'] = 'module.exports = 42;'; + }; + const options = { + input: 'main.js', + external: ['external'], + plugins: [ + { + name: 'test', + shouldTransformCachedModule({ id }) { + if (id.endsWith('?commonjs-es-import')) { + return true; + } + return null; + }, + transform(code, id) { + if (id.endsWith('?commonjs-es-import')) { + return `${code}\n//${Date.now()}`; + } + return null; + } + }, + commonjs(), + loader(modules) + ], + onwarn + }; + + resetModules(); + let bundle = await rollup(options); + t.is((await executeBundle(bundle, t)).exports, 42); + + options.cache = bundle.cache; + modules['main.js'] = "import first from 'first.js';export default first + 1;"; + bundle = await rollup(options); + t.is((await executeBundle(bundle, t)).exports, 43); +}); + test('allows the config to be reused', async (t) => { const config = { preserveModules: true,