From 6cfc9549269efc91f5063fb8d9df10bc66e64152 Mon Sep 17 00:00:00 2001 From: ItsRenji Date: Sat, 7 Nov 2026 04:16:19 +0000 Subject: [PATCH] fix(commonjs): pass exports to the wrapper when only __esModule is defined on it A top-level `Object.defineProperty(exports, '__esModule', ...)` is skipped during analysis, so it did not mark `exports` as used. When the module was wrapped for another reason (such as a `module` reference), the wrapper only received `module`, and the kept `defineProperty` call referenced a free `exports`. In ES output this throws `ReferenceError: exports is not defined`. Co-Authored-By: Claude Opus 5.5 --- packages/commonjs/src/transform-commonjs.js | 9 ++++ .../wrapped-define-compiled-esm/_config.js | 4 ++ .../wrapped-define-compiled-esm/dep.js | 4 ++ .../wrapped-define-compiled-esm/main.js | 4 ++ .../commonjs/test/snapshots/function.js.snap | 45 +++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/_config.js create mode 100644 packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/dep.js create mode 100644 packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/main.js diff --git a/packages/commonjs/src/transform-commonjs.js b/packages/commonjs/src/transform-commonjs.js index 2bc22ae88..e67758331 100644 --- a/packages/commonjs/src/transform-commonjs.js +++ b/packages/commonjs/src/transform-commonjs.js @@ -473,6 +473,15 @@ export default async function transformCommonjs( // We cannot wrap ES/mixed modules shouldWrap = !isEsModule && (shouldWrap || (uses.exports && moduleExportsAssignments.length > 0)); + // Top-level `Object.defineProperty([module.]exports, '__esModule', ...)` calls + // were skipped above, so they did not mark `exports` or `module` as used. A + // wrapped module keeps them as they are, so the wrapper must provide that name. + if (shouldWrap) { + for (const { type } of topLevelDefineCompiledEsmExpressions) { + uses[type] = true; + } + } + if ( !( shouldWrap || diff --git a/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/_config.js b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/_config.js new file mode 100644 index 000000000..4b0fe5589 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: + 'passes exports to the wrapper when a wrapped module only uses it to define __esModule' +}; diff --git a/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/dep.js b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/dep.js new file mode 100644 index 000000000..ff871a824 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/dep.js @@ -0,0 +1,4 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); +module.exports.type = typeof module.exports; diff --git a/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/main.js b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/main.js new file mode 100644 index 000000000..f91d37972 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/wrapped-define-compiled-esm/main.js @@ -0,0 +1,4 @@ +const dep = require('./dep.js'); + +t.is(dep.__esModule, true); +t.is(dep.type, 'object'); diff --git a/packages/commonjs/test/snapshots/function.js.snap b/packages/commonjs/test/snapshots/function.js.snap index 1ecce0bb1..efa415f75 100644 --- a/packages/commonjs/test/snapshots/function.js.snap +++ b/packages/commonjs/test/snapshots/function.js.snap @@ -10974,3 +10974,48 @@ module.exports = main; ", } `; + +exports[`wrapped-define-compiled-esm 1`] = ` +{ + "main.js": "'use strict'; + +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +var main$1 = {}; + +var dep = {exports: {}}; + +var hasRequiredDep; + +function requireDep () { + if (hasRequiredDep) return dep.exports; + hasRequiredDep = 1; + (function (module, exports) { + + Object.defineProperty(exports, '__esModule', { value: true }); + module.exports.type = 'object'; + } (dep, dep.exports)); + return dep.exports; +} + +var hasRequiredMain; + +function requireMain () { + if (hasRequiredMain) return main$1; + hasRequiredMain = 1; + const dep = requireDep(); + + t.is(dep.__esModule, true); + t.is(dep.type, 'object'); + return main$1; +} + +var mainExports = requireMain(); +var main = /*@__PURE__*/getDefaultExportFromCjs(mainExports); + +module.exports = main; +", +} +`;