diff --git a/packages/plugin-vite/src/plugins/patches/commonjs.ts b/packages/plugin-vite/src/plugins/patches/commonjs.ts index 40f1991227e..8d967f9d6a2 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs.ts @@ -189,19 +189,14 @@ export function cjsPlugin( ); } - const exportNamed = new Map(); - const idExports: types.ExportSpecifier[] = []; for (const name of exported) { if (name === "default") { - exportNamed.set(name, name); continue; } const id = path.scope.generateUidIdentifier(name); - exportNamed.set(id.name, name); - path.pushContainer( "body", t.variableDeclaration( @@ -227,40 +222,61 @@ export function cjsPlugin( ); } - if (exportNamed.size > 0 || exportedNs.size > 0 || hasEsModule) { + if (exported.size > 0 || exportedNs.size > 0 || hasEsModule) { const id = path.scope.generateUidIdentifier("__default"); path.pushContainer( "body", - t.variableDeclaration("const", [ + t.variableDeclaration("let", [ t.variableDeclarator( id, + ), + ]), + ); + + path.pushContainer( + "body", + t.ifStatement( + t.logicalExpression( + "&&", t.logicalExpression( - "??", - t.memberExpression( + "&&", + t.binaryExpression( + "===", + t.unaryExpression("typeof", t.identifier("exports")), + t.stringLiteral("object"), + ), + t.binaryExpression( + "!==", t.identifier("exports"), - t.identifier("default"), + t.nullLiteral(), ), + ), + t.binaryExpression( + "in", + t.stringLiteral("default"), t.identifier("exports"), ), ), - ]), - ); - - for (const [local, exported] of exportNamed.entries()) { - if (exported === "default") continue; - - path.pushContainer( - "body", - t.expressionStatement( - t.assignmentExpression( - "=", - t.memberExpression(id, t.identifier(exported)), - t.identifier(local), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression( + "=", + id, + t.memberExpression( + t.identifier("exports"), + t.identifier("default"), + ), + ), ), - ), - ); - } + ]), + t.blockStatement([ + t.expressionStatement( + t.assignmentExpression("=", id, t.identifier("exports")), + ), + ]), + ), + ); for (let i = 0; i < mappedNs.length; i++) { const mapped = mappedNs[i]; @@ -268,53 +284,79 @@ export function cjsPlugin( const key = path.scope.generateUid("k"); path.pushContainer( "body", - t.forInStatement( - t.variableDeclaration("var", [ - t.variableDeclarator(t.identifier(key)), - ]), - t.identifier(mapped), - t.ifStatement( + t.ifStatement( + t.logicalExpression( + "&&", t.logicalExpression( "&&", + t.binaryExpression( + "===", + t.unaryExpression("typeof", t.identifier("exports")), + t.stringLiteral("object"), + ), + t.binaryExpression( + "!==", + t.identifier("exports"), + t.nullLiteral(), + ), + ), + t.unaryExpression( + "!", + t.binaryExpression( + "in", + t.stringLiteral("default"), + t.identifier("exports"), + ), + ), + ), + t.forInStatement( + t.variableDeclaration("var", [ + t.variableDeclarator(t.identifier(key)), + ]), + t.identifier(mapped), + t.ifStatement( t.logicalExpression( "&&", - t.binaryExpression( - "!==", - t.identifier(key), - t.stringLiteral("default"), - ), - t.binaryExpression( - "!==", - t.identifier(key), - t.stringLiteral("__esModule"), + t.logicalExpression( + "&&", + t.binaryExpression( + "!==", + t.identifier(key), + t.stringLiteral("default"), + ), + t.binaryExpression( + "!==", + t.identifier(key), + t.stringLiteral("__esModule"), + ), ), - ), - t.callExpression( - t.memberExpression( + t.callExpression( t.memberExpression( t.memberExpression( - t.identifier("Object"), - t.identifier("prototype"), + t.memberExpression( + t.identifier("Object"), + t.identifier("prototype"), + ), + t.identifier("hasOwnProperty"), ), - t.identifier("hasOwnProperty"), + t.identifier("call"), ), - t.identifier("call"), + [t.identifier(mapped), t.identifier(key)], ), - [t.identifier(mapped), t.identifier(key)], ), - ), - t.expressionStatement( - t.assignmentExpression( - "=", - t.memberExpression( - t.cloneNode(id, true), - t.identifier(key), - true, - ), - t.memberExpression( - t.identifier(mapped), - t.identifier(key), - true, + t.expressionStatement( + t.assignmentExpression( + "=", + t.memberExpression( + t.cloneNode(id, true), + t.identifier(key), + true, + ), + t.memberExpression( + t.identifier(mapped), + t.identifier(key), + true, + ), ), ), ), @@ -663,6 +705,7 @@ export function cjsPlugin( state.set(HAS_ES_MODULE, true); } else if (left.isMemberExpression()) { if (isModuleExports(t, left.node)) { + // Should always try to create synthetic default export in this case. exported.add("default"); if (t.isObjectExpression(expr.node.right)) { diff --git a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts index 1f4e55444b9..99695c56c2a 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts @@ -26,7 +26,13 @@ Object.defineProperty(module, "exports", { } });`; -const DEFAULT_EXPORT = `const _default = exports.default ?? exports;`; +const DEFAULT_EXPORT = `let _default; +if (typeof exports === "object" && exports !== null && "default" in exports) { + _default = exports.default; +} else { + _default = exports; +}`; + const DEFAULT_EXPORT_END = `export default _default; export var __require = exports;`; const IMPORT_REQUIRE = `import { createRequire } from "node:module"; @@ -65,7 +71,6 @@ exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -83,7 +88,6 @@ module.exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -104,7 +108,6 @@ const foo = 'also bar'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -125,7 +128,6 @@ exports.foo = 'bar'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -137,9 +139,8 @@ Deno.test("commonjs - esModule flag only", () => { expected: `Object.defineProperty(exports, "__esModule", { value: true }); -const _default = exports.default ?? exports; -export default _default; -export var __require = exports; +${DEFAULT_EXPORT} +${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); }); @@ -151,9 +152,8 @@ Deno.test("commonjs - esModule flag only #2", () => { expected: `Object.defineProperty(module.exports, "__esModule", { value: true }); -const _default = exports.default ?? exports; -export default _default; -export var __require = exports; +${DEFAULT_EXPORT} +${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); }); @@ -164,9 +164,8 @@ Deno.test("commonjs - esModule flag only minified #3", () => { expected: `Object.defineProperty(exports, '__esModule', { value: !0 }); -const _default = exports.default ?? exports; -export default _default; -export var __require = exports; +${DEFAULT_EXPORT} +${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); }); @@ -187,8 +186,6 @@ var _foo = exports.foo; var _bar = exports.bar; export { _foo as foo, _bar as bar }; ${DEFAULT_EXPORT} -_default.foo = _foo; -_default.bar = _bar; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -271,7 +268,6 @@ exports.trace = 'foo'; var _trace = exports.trace; export { _trace as trace }; ${DEFAULT_EXPORT} -_default.trace = _trace; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -290,7 +286,6 @@ exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -307,7 +302,6 @@ exports.foo = utils_1.foo; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END}`, }); }); @@ -323,7 +317,6 @@ exports.foo = utils_1.foo; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END}`, }); }); @@ -342,7 +335,6 @@ exports._globalThis = typeof globalThis === 'object' ? globalThis : global; var _globalThis = exports._globalThis; export { _globalThis }; ${DEFAULT_EXPORT} -_default._globalThis = _globalThis; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -362,7 +354,6 @@ exports.foo = foo; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -375,7 +366,7 @@ Deno.test("commonjs - detect esbuild shims", () => { import * as _ns from "./globalThis"; export * from "./globalThis"; ${DEFAULT_EXPORT} -for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; +if (typeof exports === "object" && exports !== null && !("default" in exports)) for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; ${DEFAULT_EXPORT_END}`, }); }); @@ -400,7 +391,6 @@ exports.VERSION = '1.9.0'; var _VERSION = exports.VERSION; export { _VERSION as VERSION }; ${DEFAULT_EXPORT} -_default.VERSION = _VERSION; ${DEFAULT_EXPORT_END}`, }); }); @@ -425,7 +415,6 @@ var DiagLogLevel; var _DiagLogLevel = exports.DiagLogLevel; export { _DiagLogLevel as DiagLogLevel }; ${DEFAULT_EXPORT} -_default.DiagLogLevel = _DiagLogLevel; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -461,7 +450,6 @@ module.exports = { var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -479,7 +467,6 @@ Deno.test("commonjs - detect iife wrapper", () => { var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END}`, }); }); @@ -521,7 +508,7 @@ Object.defineProperty(exports, "__esModule", { }); export * from "./node"; ${DEFAULT_EXPORT} -for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; +if (typeof exports === "object" && exports !== null && !("default" in exports)) for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -537,7 +524,6 @@ module.exports = { var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END}`, }); }); @@ -634,7 +620,6 @@ Deno.test("commonjs - wrapped iife binding", () => { var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} -_default.foo = _foo; ${DEFAULT_EXPORT_END}`, }); }); @@ -719,3 +704,22 @@ var __importDefault = this && this.__importDefault || function (mod) { const node_events_1 = __importDefault(_mod.default ?? _mod);`, }); }); + +Deno.test("commonjs imitating esm - default export exists", () => { + runTest({ + input: `module.exports = { + 'default': 'string', + otherExport: 1 +}; +`, + expected: `${INIT} +module.exports = { + 'default': 'string', + otherExport: 1 +}; +var _otherExport = exports.otherExport; +export { _otherExport as otherExport }; +${DEFAULT_EXPORT} +${DEFAULT_EXPORT_END}`, + }); +});