-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
module: support 'module.exports' interop export name in require(esm) #54563
Conversation
Review requested:
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #54563 +/- ##
==========================================
- Coverage 88.40% 88.40% -0.01%
==========================================
Files 652 652
Lines 186565 186568 +3
Branches 36038 36043 +5
==========================================
- Hits 164935 164929 -6
+ Misses 14914 14911 -3
- Partials 6716 6728 +12
|
//cc @nodejs/loaders this PR is ready for final review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wish we used __cjsUnwrapDefault
instead, but I'm ok with this as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is another caveat of the default live-binding being broken (compared to ESM import semantics). Though I guess that's rather an edge case that most won't care about - this feature is intended for library authors who migrate from CommonJS, which doesn't support re-assigning module.exports
once it's cached anyway.
|
I am talking about this (which can't be mimicked with native CommonJS, but then it has never been, so for CommonJS -> ESM module migration, it doesn't matter as the original CommonJS module is unlikely to expect re-assigning module.exports to be effective in consumer code. It's only a problem for existing ESM that re-assigns default exports and tries to extend support to CommonJS consumers, which should be rare): // a.mjs
let a = 1;
export function increment() {
a++;
}
export { a as default };
// b.mjs
import a, { increment } from './a.mjs';
increment();
console.log(a); // 2 |
Oh interesting, you’re saying that when exported as a name, it does have live binding behavior - TIL. |
4afabbf
to
be6bc32
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have an alternative proposal in nodejs/loaders#221 which people seem to like over there:
function foo() {}
export { foo as "module.exports" };
export default foo;
I think we should do a poll of this v.s. what this PR currently proposes:
function foo() {}
export const __cjsUnwrapDefault = true;
export default foo;
and decide which one we should go with. I am not sure what the poll audience should be though, should it be:
- TSC, as usual
- collaborators, because this is a naming choice and seems fun to vote on
- Broader user base (social media poll?)
placing a block until we have a decision.
@joyeecheung given there's quite a bit of nuance here, I'd suggest we discuss this within the TSC. I'll make myself available for the next meeting on the 11th. I'd like us to come to a conclusion as swiftly as possible though and encourage a vote / decision in the meeting, as this has discussion has now dragged on since July 14. I'll commit to whatever decision is made there for this PR and align that result with #53848. |
I prefer the more explicit use of |
74f1a93
to
3f4455d
Compare
I believe all outstanding comments have been addressed. It's been a ride, we might finally be there. Will aim to land shortly unless anyone would like to engage in further debate. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
PR-URL: #54563 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Landed in d24c731. |
PR-URL: nodejs#54563 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
The backport-requested labels should be applied by releasers - if land cleanly, they could be cherry-picked directly. I'll backport it to v22.x in #55217 first. |
PR-URL: nodejs#54563 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: nodejs#54563 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This adds support for
export { foo as 'module.exports' }
in a CJS module to imply that this export value should always be used as the module value when requiring that ESM module underrequire(esm)
, allowing other types than just module namespaces in this interop.This effectively splits off the non-major change from #53848 as discussed in the Node.js loaders meeting, under a rename of this flag to use the
'module.exports'
pattern, where that PR will be updated to use the name that lands here on the ESM wrapper as a major change further.The naming bikeshed took place in nodejs/loaders#221 and was determined by TSC vote.
//cc @nodejs/loaders