-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CJS named export "default" is not recognized as the default export entry #48899
Comments
☝️ - because it sure seems like unexpected - even magical - behavior to me. If nothing else, your expected behavior is a backwards incompatible change. The interpretation of the CJS export object becomes context-dependent on whether the importer is a CJS or ESM module; a bit like the Confusing at best, but more likely downright wrong. Consider what happens when you |
The original problem here is that I found a typescript module written as: const foo = 'foo';
export {
foo as default
}; is compiled as the following when targeting CJS: (playground) "use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = void 0;
const foo = 'foo';
exports.default = foo; If the module is imported from an ESM module in Node.js, the default export entry would not be the expected one written originally in typescript. |
I sympathize, but TS bugs shouldn't result in Node hacks. |
I think this is set in stone anyway. This behavior has been released for too long to be changed. It's certain that people now rely on it. |
I don't understand why this is a TS bug. Its source and compiled products are valid as ESM and CJS sources, respectively. There isn't a mechanism that allows tools like TS to transform the compiled CJS "default" export entry as an ESM default entry.
I understand the concern here. As TS is one of the tools that is largely used in the wild, I'd also like to know if this is a problem worth addressing for CJS/ESM interoperability in Node.js. |
Not if it breaks backward compatibility (which it would.) |
The behavior is the same for all CJS modules imported from ESM:
I understand your problem here, but changing the behavior when there is an export named "default" would be breaking and inconsistent. |
☝️ – that's the key behavior that never changed (and cannot ever change at this point) when consuming CJS from ESM. This is a known limitation from the get go, you can check out the discussions over at #35249 and the related issues for more context. Closing as Won't fix.
You're right, it's not, the same thing would happen without TS; there's simply no way to have a |
Continuing discussion at #50981. |
Version
v20.5.0
Platform
Darwin my.local 21.6.0 Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:22 PDT 2022; root:xnu-8020.140.41~1/RELEASE_ARM64_T6000 arm64
Subsystem
module
What steps will reproduce the bug?
With two scripts, namely "my-mod.mjs" and "my-cjs.cjs", and their contents as:
Run with
node my-mod.mjs
.How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
Output
foo
.What do you see instead?
Output
{ default: 'foo' }
Additional information
The original problem here is that I found a typescript module written as:
is compiled as the following when targeting CJS: (playground)
If the module is imported from an ESM module in Node.js, the default export entry would not be the expected one written originally in typescript.
The spec https://tc39.es/ecma262/#sec-static-semantics-importentriesformodule states that ImportedDefaultBinding imports the
"default"
entry from the requested module.When using with
vm.SyntheticModule
, the following script outputs the expected result:The text was updated successfully, but these errors were encountered: