GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — module: support 'module.exports' interop export name in require(esm) by guybedford · Pull Request #54563 · nodejs/node

Conversation

@guybedford

@guybedford guybedford commented Aug 26, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

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 under require(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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@nodejs-github-bot

nodejs-github-bot commented Aug 26, 2024

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/loaders
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot nodejs-github-bot added module Issues and PRs related to the module subsystem. needs-ci PRs that need a full CI run. labels Aug 26, 2024
@avivkeller avivkeller added the loaders Issues and PRs related to ES module loaders. label Aug 26, 2024
@codecov

codecov Bot commented Aug 26, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.40%. Comparing base (366e573) to head (78d41a2).
Report is 874 commits behind head on main.

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     
Files with missing lines Coverage Δ
lib/internal/modules/cjs/loader.js 97.42% <100.00%> (+<0.01%) ⬆️

... and 20 files with indirect coverage changes

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell jasnell mentioned this pull request Aug 26, 2024
Ensure CJS/MJS require interop in nodejs-compat cloudflare/workerd#2606
Closed
@guybedford guybedford changed the title module: support __cjsUnwrapDefault interop flag in require(esm) module: support cjsUnwrapDefault interop flag in require(esm) Sep 1, 2024
joyeecheung
joyeecheung reviewed Sep 1, 2024
View reviewed changes
Comment thread doc/api/modules.md Resolved

Uh oh!

There was an error while loading. Please reload this page.

@guybedford

guybedford commented Sep 1, 2024

Copy link
Copy Markdown
Contributor Author

//cc @nodejs/loaders this PR is ready for final review.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 2, 2024
mcollina
mcollina approved these changes Sep 2, 2024
View reviewed changes

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Sep 2, 2024
@nodejs-github-bot

nodejs-github-bot commented Sep 2, 2024

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/61808/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

aduh95
aduh95 approved these changes Sep 2, 2024
View reviewed changes
aduh95
aduh95 reviewed Sep 2, 2024
View reviewed changes
Comment thread test/es-module/test-require-as-esm-interop.mjs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@nodejs-github-bot

nodejs-github-bot commented Sep 2, 2024

Copy link
Copy Markdown
Collaborator

CI: https://ci.nodejs.org/job/node-test-pull-request/61825/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

joyeecheung
joyeecheung reviewed Sep 3, 2024
View reviewed changes

@joyeecheung joyeecheung left a comment

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread doc/api/modules.md Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread doc/api/modules.md Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread doc/api/modules.md Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Sep 3, 2024

Copy link
Copy Markdown
Member

default exports in ESM do not have live bindings, only named exports do.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@joyeecheung

joyeecheung commented Sep 4, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

default exports in ESM do not have live bindings, only named exports do.

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
ljharb reacted with eyes emoji
All reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ljharb

ljharb commented Sep 4, 2024

Copy link
Copy Markdown
Member

Oh interesting, you’re saying that when exported as a name, it does have live binding behavior - TIL.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guybedford
guybedford force-pushed the cjs-unwrap branch from 4afabbf to be6bc32 Compare September 6, 2024 23:34
@guybedford guybedford mentioned this pull request Sep 6, 2024
Naming bikeshed - require(esm) interop flag nodejs/loaders#221
Closed
@guybedford guybedford changed the title module: support cjsUnwrapDefault interop flag in require(esm) module: support __cjsUnwrapDefault interop flag in require(esm) Sep 6, 2024
jasnell
jasnell reviewed Sep 7, 2024
View reviewed changes
Comment thread lib/internal/modules/cjs/loader.js Resolved

Uh oh!

There was an error while loading. Please reload this page.

jasnell
jasnell approved these changes Sep 7, 2024
View reviewed changes
joyeecheung
joyeecheung requested changes Sep 7, 2024
View reviewed changes

@joyeecheung joyeecheung left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

JakobJingleheimer reacted with eyes emoji
All reactions
  • 👀 1 reaction
@joyeecheung joyeecheung added the tsc-agenda Issues and PRs to discuss during Technical Steering Committee meetings. label Sep 7, 2024
@guybedford

guybedford commented Sep 8, 2024

Copy link
Copy Markdown
Contributor Author

@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.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jasnell

jasnell commented Sep 8, 2024

Copy link
Copy Markdown
Member

I prefer the more explicit use of __cjsUnwrapDefault = true personally as it seems less magical and more explicit about the intent.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mhdawson mhdawson mentioned this pull request Sep 9, 2024
Node.js Technical Steering Committee (TSC) Meeting 2024-09-11 nodejs/TSC#1615
Closed
This was referenced Feb 6, 2025
Providing a custom representation for an ES module under require(esm) #54085
Closed
[v20.x] backport unflagging of require(esm) to v20 #56927
Closed
joyeecheung pushed a commit to joyeecheung/node that referenced this pull request Feb 10, 2025
@guybedford @joyeecheung
module: support 'module.exports' interop export in require(esm)
824d417
PR-URL: nodejs#54563
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
marco-ippolito pushed a commit that referenced this pull request Feb 11, 2025
@guybedford @marco-ippolito
module: support 'module.exports' interop export in require(esm)
dc66632
PR-URL: #54563
Backport-PR-URL: #56927
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Refs: #52697
@sapphi-red sapphi-red mentioned this pull request Feb 20, 2025
[Feature Request]: make require('./foo.json') work as expected even if the json is transformed to JS by a custom plugin rolldown/rolldown#3640
Closed
This was referenced Feb 25, 2025
feat: add module.exports named export for require(esm) compatibility eslint-stylistic/eslint-stylistic#700
Merged
[MAINT]: 20.x npm audit vulnerabilities octokit/rest.js#486
Closed
@wolfy1339 wolfy1339 mentioned this pull request Feb 26, 2025
Tracking issue: Port everything to ESM probot/probot#1958
Open
13 of 25 tasks
@dsherret dsherret mentioned this pull request Mar 3, 2025
fix(node): require esm should prefer module.exports export denoland/deno#28376
Merged
@marco-ippolito marco-ippolito mentioned this pull request Mar 6, 2025
v20.19.0 proposal #57349
Merged
This was referenced Mar 17, 2025
Update product-os/flowzone action to v19.11.13 klutchell/balena-mediaserver#1061
Merged
Update product-os/flowzone action to v19.11.12 klutchell/dnscrypt-proxy-docker#537
Merged
Update product-os/flowzone action to v19.11.12 klutchell/unbound-docker#568
Merged
Update product-os/flowzone action to v19.11.12 klutchell/balena-exit-node#270
Merged
mwalbeck pushed a commit to mwalbeck/docker-cyberchef that referenced this pull request Mar 22, 2025
renovate-bot @mwalbeck
Update Node.js to v20.19.0 (#375)
6b8b695
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [node](https://github.com/nodejs/node) | stage | minor | `20.18.3-bullseye` -> `20.19.0-bullseye` |

---

### Release Notes

<details>
<summary>nodejs/node (node)</summary>

### [`v20.19.0`](https://github.com/nodejs/node/releases/tag/v20.19.0): 2025-03-13, Version 20.19.0 &#x27;Iron&#x27; (LTS), @&#8203;marco-ippolito

[Compare Source](nodejs/node@v20.18.3...v20.19.0)

##### Notable Changes

##### require(esm) is now enabled by default

Support for loading native ES modules using require() had been available on v20.x under the command line flag --experimental-require-module, and available by default on v22.x and v23.x. In this release, it is now no longer behind a flag on v20.x.

This feature has been tested on v23.x and v22.x, and we are looking for user feedback from v20.x to make more final tweaks before fully stabilizing it.
It now no longer emits a warning unless `--trace-require-module` is explicitly used.
If there happens to be any regressions caused by this feature, users can report it to the Node.js issue tracker. Meanwhile this feature can also be disabled using `--no-experimental-require-module` as a workaround.

With this feature enabled, Node.js will no longer throw `ERR_REQUIRE_ESM` if `require()` is used to load a ES module. It can, however, throw `ERR_REQUIRE_ASYNC_MODULE` if the ES module being loaded or its dependencies contain top-level `await`. When the ES module is loaded successfully by `require()`, the returned object will either be a ES module namespace object similar to what's returned by `import()`, or what gets exported as `"module.exports"` in the ES module.

Users can check `process.features.require_module` to see whether `require(esm)` is enabled in the current Node.js instance. For packages, the `"module-sync"` exports condition can be used as a way to detect `require(esm)` support in the current Node.js instance and allow both `require()` and `import` to load the same native ES module. See [the documentation](https://nodejs.org/docs/latest/api/modules.html#loading-ecmascript-modules-using-require) for more details about this feature.

Contributed by Joyee Cheung in [#&#8203;55085](nodejs/node#55085)

##### Module syntax detection is now enabled by default

Module syntax detection (the `--experimental-detect-module` flag) is now
enabled by default. Use `--no-experimental-detect-module` to disable it if
needed.

Syntax detection attempts to run ambiguous files as CommonJS, and if the module
fails to parse as CommonJS due to ES module syntax, Node.js tries again and runs
the file as an ES module.
Ambiguous files are those with a `.js` or no extension, where the nearest parent
`package.json` has no `"type"` field (either `"type": "module"` or
`"type": "commonjs"`).
Syntax detection should have no performance impact on CommonJS modules, but it
incurs a slight performance penalty for ES modules; add `"type": "module"` to
the nearest parent `package.json` file to eliminate the performance cost.
A use case unlocked by this feature is the ability to use ES module syntax in
extensionless scripts with no nearby `package.json`.

Thanks to Geoffrey Booth for making this work on [#&#8203;53619](nodejs/node#53619).

##### Other Notable Changes

-   \[[`285bb4ee14`](nodejs/node@285bb4ee14)] - **crypto**: update root certificates to NSS 3.107 (Node.js GitHub Bot) [#&#8203;56566](nodejs/node#56566)
-   \[[`73b5c16684`](nodejs/node@73b5c16684)] - **(SEMVER-MINOR)** **worker**: add postMessageToThread (Paolo Insogna) [#&#8203;53682](nodejs/node#53682)
-   \[[`de313b2336`](nodejs/node@de313b2336)] - **(SEMVER-MINOR)** **module**: only emit require(esm) warning under --trace-require-module (Joyee Cheung) [#&#8203;56194](nodejs/node#56194)
-   \[[`4fba01911d`](nodejs/node@4fba01911d)] - **(SEMVER-MINOR)** **process**: add process.features.require_module (Joyee Cheung) [#&#8203;55241](nodejs/node#55241)
-   \[[`df8a045afe`](nodejs/node@df8a045afe)] - **(SEMVER-MINOR)** **module**: implement the "module-sync" exports condition (Joyee Cheung) [#&#8203;54648](nodejs/node#54648)
-   \[[`f9dc1eaef5`](nodejs/node@f9dc1eaef5)] - **(SEMVER-MINOR)** **module**: add \__esModule to require()'d ESM (Joyee Cheung) [#&#8203;52166](nodejs/node#52166)

<details>
<summary>
Commits
</summary>

-   \[[`d84be843e3`](nodejs/node@d84be843e3)] - **benchmark**: add validateStream to styleText bench (Rafael Gonzaga) [#&#8203;56556](nodejs/node#56556)
-   \[[`d8eaf5b9b8`](nodejs/node@d8eaf5b9b8)] - **build**: fix compatibility with V8's `depot_tools` (Richard Lau) [#&#8203;57330](nodejs/node#57330)
-   \[[`1ee4bf9690`](nodejs/node@1ee4bf9690)] - **build**: test macos-13 on GitHub actions (Michaël Zasso) [#&#8203;56307](nodejs/node#56307)
-   \[[`1cc8d69882`](nodejs/node@1cc8d69882)] - **build**: build v8 with -fvisibility=hidden on macOS (Joyee Cheung) [#&#8203;56275](nodejs/node#56275)
-   \[[`52f1f7e22b`](nodejs/node@52f1f7e22b)] - **child_process**: fix parsing messages with splitted length field (Maksim Gorkov) [#&#8203;56106](nodejs/node#56106)
-   \[[`5ef3c3c996`](nodejs/node@5ef3c3c996)] - **crypto**: add missing return value check (Michael Dawson) [#&#8203;56615](nodejs/node#56615)
-   \[[`285bb4ee14`](nodejs/node@285bb4ee14)] - **crypto**: update root certificates to NSS 3.107 (Node.js GitHub Bot) [#&#8203;56566](nodejs/node#56566)
-   \[[`46ceb9dc1c`](nodejs/node@46ceb9dc1c)] - **deps**: update timezone to 2025a (Node.js GitHub Bot) [#&#8203;56876](nodejs/node#56876)
-   \[[`d4ca38fe8e`](nodejs/node@d4ca38fe8e)] - **deps**: macro ENODATA is deprecated in libc++ (Cheng) [#&#8203;56698](nodejs/node#56698)
-   \[[`15214e6508`](nodejs/node@15214e6508)] - **deps**: update simdutf to 6.0.3 (Node.js GitHub Bot) [#&#8203;56567](nodejs/node#56567)
-   \[[`1e44f5d84b`](nodejs/node@1e44f5d84b)] - **deps**: update simdutf to 5.7.2 (Node.js GitHub Bot) [#&#8203;56388](nodejs/node#56388)
-   \[[`b92ff7be38`](nodejs/node@b92ff7be38)] - **deps**: update googletest to [`7d76a23`](nodejs/node@7d76a23) (Node.js GitHub Bot) [#&#8203;56387](nodejs/node#56387)
-   \[[`e1b71a81a9`](nodejs/node@e1b71a81a9)] - **deps**: update googletest to [`e54519b`](nodejs/node@e54519b) (Node.js GitHub Bot) [#&#8203;56370](nodejs/node#56370)
-   \[[`c0d45e7f38`](nodejs/node@c0d45e7f38)] - **deps**: update simdutf to 5.7.0 (Node.js GitHub Bot) [#&#8203;56332](nodejs/node#56332)
-   \[[`d69107f5a8`](nodejs/node@d69107f5a8)] - **deps**: update icu to 76.1 (Node.js GitHub Bot) [#&#8203;55551](nodejs/node#55551)
-   \[[`5c9a397699`](nodejs/node@5c9a397699)] - **deps**: V8: backport [`9ab4059`](nodejs/node@9ab40592f697) (Lu Yahan) [#&#8203;56781](nodejs/node#56781)
-   \[[`8342233f6d`](nodejs/node@8342233f6d)] - **deps**: update corepack to 0.31.0 (Node.js GitHub Bot) [#&#8203;56795](nodejs/node#56795)
-   \[[`561493d35e`](nodejs/node@561493d35e)] - **deps,src**: simplify base64 encoding (Daniel Lemire) [#&#8203;52714](nodejs/node#52714)
-   \[[`6207b2936c`](nodejs/node@6207b2936c)] - **doc**: move anatoli to emeritus (Michael Dawson) [#&#8203;56592](nodejs/node#56592)
-   \[[`b0ab483400`](nodejs/node@b0ab483400)] - **doc**: fix styles of the expandable TOC (Antoine du Hamel) [#&#8203;56755](nodejs/node#56755)
-   \[[`53e4dc2a82`](nodejs/node@53e4dc2a82)] - **doc**: add "Skip to content" button (Antoine du Hamel) [#&#8203;56750](nodejs/node#56750)
-   \[[`33ee4645c3`](nodejs/node@33ee4645c3)] - **doc**: improve accessibility of expandable lists (Antoine du Hamel) [#&#8203;56749](nodejs/node#56749)
-   \[[`b514438418`](nodejs/node@b514438418)] - **doc**: add note regarding commit message trailers (Dario Piotrowicz) [#&#8203;56736](nodejs/node#56736)
-   \[[`627f2997e3`](nodejs/node@627f2997e3)] - **doc**: fix typo in example code for util.styleText (Robin Mehner) [#&#8203;56720](nodejs/node#56720)
-   \[[`68548dcb48`](nodejs/node@68548dcb48)] - **doc**: fix inconsistencies in `WeakSet` and `WeakMap` comparison details (Shreyans Pathak) [#&#8203;56683](nodejs/node#56683)
-   \[[`337cfb2549`](nodejs/node@337cfb2549)] - **doc**: add RafaelGSS as latest sec release stewards (Rafael Gonzaga) [#&#8203;56682](nodejs/node#56682)
-   \[[`e890c86d7b`](nodejs/node@e890c86d7b)] - **doc**: clarify cjs/esm diff in `queueMicrotask()` vs `process.nextTick()` (Dario Piotrowicz) [#&#8203;56659](nodejs/node#56659)
-   \[[`978263923f`](nodejs/node@978263923f)] - **doc**: `WeakSet` and `WeakMap` comparison details (Shreyans Pathak) [#&#8203;56648](nodejs/node#56648)
-   \[[`aba280ccd8`](nodejs/node@aba280ccd8)] - **doc**: mention prepare --security (Rafael Gonzaga) [#&#8203;56617](nodejs/node#56617)
-   \[[`0a009a527b`](nodejs/node@0a009a527b)] - **doc**: tweak info on reposts in ambassador program (Michael Dawson) [#&#8203;56589](nodejs/node#56589)
-   \[[`d2f09e2ab3`](nodejs/node@d2f09e2ab3)] - **doc**: add type stripping to ambassadors program (Marco Ippolito) [#&#8203;56598](nodejs/node#56598)
-   \[[`b0b77d7fbe`](nodejs/node@b0b77d7fbe)] - **doc**: improve internal documentation on built-in snapshot (Joyee Cheung) [#&#8203;56505](nodejs/node#56505)
-   \[[`4b3e7fee94`](nodejs/node@4b3e7fee94)] - **doc**: document CLI way to open the nodejs/bluesky PR (Antoine du Hamel) [#&#8203;56506](nodejs/node#56506)
-   \[[`03878b0384`](nodejs/node@03878b0384)] - **doc**: update gcc-version for ubuntu-lts (Kunal Kumar) [#&#8203;56553](nodejs/node#56553)
-   \[[`acbbd7c1a6`](nodejs/node@acbbd7c1a6)] - **doc**: fix parentheses in options (Tobias Nießen) [#&#8203;56563](nodejs/node#56563)
-   \[[`3fe80c30b8`](nodejs/node@3fe80c30b8)] - **doc**: include CVE to EOL lines as sec release process (Rafael Gonzaga) [#&#8203;56520](nodejs/node#56520)
-   \[[`ff8af58046`](nodejs/node@ff8af58046)] - **doc**: add esm examples to node:trace_events (Alfredo González) [#&#8203;56514](nodejs/node#56514)
-   \[[`27b9cfd135`](nodejs/node@27b9cfd135)] - **doc**: add message for Ambassadors to promote (Michael Dawson) [#&#8203;56235](nodejs/node#56235)
-   \[[`020c939da1`](nodejs/node@020c939da1)] - **doc**: allow request for TSC reviews via the GitHub UI (Antoine du Hamel) [#&#8203;56493](nodejs/node#56493)
-   \[[`1ef9c9a354`](nodejs/node@1ef9c9a354)] - **doc**: add example for piping ReadableStream (Gabriel Schulhof) [#&#8203;56415](nodejs/node#56415)
-   \[[`e675c3a7fc`](nodejs/node@e675c3a7fc)] - **doc**: expand description of `parseArg`'s `default` (Kevin Gibbons) [#&#8203;54431](nodejs/node#54431)
-   \[[`bc756da876`](nodejs/node@bc756da876)] - **doc**: use `<ul>` instead of `<ol>` in `SECURITY.md` (Antoine du Hamel) [#&#8203;56346](nodejs/node#56346)
-   \[[`ad59c82a49`](nodejs/node@ad59c82a49)] - **doc**: clarify that WASM is trusted (Matteo Collina) [#&#8203;56345](nodejs/node#56345)
-   \[[`8e76cc69e5`](nodejs/node@8e76cc69e5)] - **doc**: move dual package shipping docs to separate repo (Joyee Cheung) [#&#8203;55444](nodejs/node#55444)
-   \[[`9fda8e29cd`](nodejs/node@9fda8e29cd)] - **doc**: mark `--env-file-if-exists` flag as experimental (Juan José) [#&#8203;56893](nodejs/node#56893)
-   \[[`9e975f1a7d`](nodejs/node@9e975f1a7d)] - **doc**: fix link and history of `SourceMap` sections (Antoine du Hamel) [#&#8203;57098](nodejs/node#57098)
-   \[[`64ce95b8fc`](nodejs/node@64ce95b8fc)] - **doc**: update `require(ESM)` history and stability status (Antoine du Hamel) [#&#8203;55199](nodejs/node#55199)
-   \[[`697a39248b`](nodejs/node@697a39248b)] - **doc**: fix history of `process.features` (Antoine du Hamel) [#&#8203;54897](nodejs/node#54897)
-   \[[`7c38e503a3`](nodejs/node@7c38e503a3)] - **doc**: add documentation for process.features (Marco Ippolito) [#&#8203;54897](nodejs/node#54897)
-   \[[`c85b386a39`](nodejs/node@c85b386a39)] - **esm**: fix jsdoc type refs to `ModuleJobBase` in esm/loader (Jacob Smith) [#&#8203;56499](nodejs/node#56499)
-   \[[`4813a6a66c`](nodejs/node@4813a6a66c)] - **esm**: throw `ERR_REQUIRE_ESM` instead of `ERR_INTERNAL_ASSERTION` (Antoine du Hamel) [#&#8203;54868](nodejs/node#54868)
-   \[[`0d327c8e47`](nodejs/node@0d327c8e47)] - **esm**: refactor `get_format` (Antoine du Hamel) [#&#8203;53872](nodejs/node#53872)
-   \[[`e87db6c9bc`](nodejs/node@e87db6c9bc)] - **events**: add hasEventListener util for validate (Sunghoon) [#&#8203;55230](nodejs/node#55230)
-   \[[`674b932f33`](nodejs/node@674b932f33)] - **http**: don't emit error after destroy (Robert Nagy) [#&#8203;55457](nodejs/node#55457)
-   \[[`4c24ef8f71`](nodejs/node@4c24ef8f71)] - **http2**: omit server name when HTTP2 host is IP address (islandryu) [#&#8203;56530](nodejs/node#56530)
-   \[[`533afe8124`](nodejs/node@533afe8124)] - **lib**: reduce amount of caught URL errors (Yagiz Nizipli) [#&#8203;52658](nodejs/node#52658)
-   \[[`34221a1d6e`](nodejs/node@34221a1d6e)] - **lib**: allow CJS source map cache to be reclaimed (Chengzhong Wu) [#&#8203;51711](nodejs/node#51711)
-   \[[`f13589f1f9`](nodejs/node@f13589f1f9)] - **lib,src**: iterate module requests of a module wrap in JS (Chengzhong Wu) [#&#8203;52058](nodejs/node#52058)
-   \[[`6afee9ea43`](nodejs/node@6afee9ea43)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#&#8203;56580](nodejs/node#56580)
-   \[[`85bb738739`](nodejs/node@85bb738739)] - **meta**: add codeowners of security release document (Rafael Gonzaga) [#&#8203;56521](nodejs/node#56521)
-   \[[`48f9ca0992`](nodejs/node@48f9ca0992)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#&#8203;56342](nodejs/node#56342)
-   \[[`4d724121b4`](nodejs/node@4d724121b4)] - **meta**: move MoLow to TSC regular member (Moshe Atlow) [#&#8203;56276](nodejs/node#56276)
-   \[[`5e2dab7868`](nodejs/node@5e2dab7868)] - **module**: fix bad `require.resolve` with option paths for `.` and `..` (Dario Piotrowicz) [#&#8203;56735](nodejs/node#56735)
-   \[[`f507c05060`](nodejs/node@f507c05060)] - **module**: simplify --inspect-brk handling (Joyee Cheung) [#&#8203;55679](nodejs/node#55679)
-   \[[`ed2d373e5a`](nodejs/node@ed2d373e5a)] - **module**: disable require(esm) for policy and network import (Joyee Cheung) [#&#8203;56927](nodejs/node#56927)
-   \[[`de313b2336`](nodejs/node@de313b2336)] - **(SEMVER-MINOR)** **module**: only emit require(esm) warning under --trace-require-module (Joyee Cheung) [#&#8203;56194](nodejs/node#56194)
-   \[[`3d89e6b6fa`](nodejs/node@3d89e6b6fa)] - **module**: mark evaluation rejection in require(esm) as handled (Joyee Cheung) [#&#8203;56122](nodejs/node#56122)
-   \[[`e01dd4bd4f`](nodejs/node@e01dd4bd4f)] - **module**: do not warn when require(esm) comes from node_modules (Joyee Cheung) [#&#8203;55960](nodejs/node#55960)
-   \[[`011e6e0032`](nodejs/node@011e6e0032)] - **module**: fix error thrown from require(esm) hitting TLA repeatedly (Joyee Cheung) [#&#8203;55520](nodejs/node#55520)
-   \[[`fdf50289c6`](nodejs/node@fdf50289c6)] - **module**: trim off internal stack frames for require(esm) warnings (Joyee Cheung) [#&#8203;55496](nodejs/node#55496)
-   \[[`8d33f78ca5`](nodejs/node@8d33f78ca5)] - **module**: allow ESM that failed to be required to be re-imported (Joyee Cheung) [#&#8203;55502](nodejs/node#55502)
-   \[[`8192dd6cf3`](nodejs/node@8192dd6cf3)] - **module**: include module information in require(esm) warning (Joyee Cheung) [#&#8203;55397](nodejs/node#55397)
-   \[[`1db210a0ec`](nodejs/node@1db210a0ec)] - **module**: check --experimental-require-module separately from detection (Joyee Cheung) [#&#8203;55250](nodejs/node#55250)
-   \[[`cf8701c866`](nodejs/node@cf8701c866)] - **module**: use kNodeModulesRE to detect node_modules (Joyee Cheung) [#&#8203;55243](nodejs/node#55243)
-   \[[`dc66632261`](nodejs/node@dc66632261)] - **module**: support 'module.exports' interop export in require(esm) (Guy Bedford) [#&#8203;54563](nodejs/node#54563)
-   \[[`1ac1dda9a4`](nodejs/node@1ac1dda9a4)] - **(SEMVER-MINOR)** **module**: unflag --experimental-require-module (Joyee Cheung) [#&#8203;55085](nodejs/node#55085)
-   \[[`683c93f45f`](nodejs/node@683c93f45f)] - **module**: refator ESM loader for adding future synchronous hooks (Joyee Cheung) [#&#8203;54769](nodejs/node#54769)
-   \[[`df8a045afe`](nodejs/node@df8a045afe)] - **(SEMVER-MINOR)** **module**: implement the "module-sync" exports condition (Joyee Cheung) [#&#8203;54648](nodejs/node#54648)
-   \[[`249d82b686`](nodejs/node@249d82b686)] - **module**: report unfinished TLA in ambiguous modules (Antoine du Hamel) [#&#8203;54980](nodejs/node#54980)
-   \[[`1925d729f9`](nodejs/node@1925d729f9)] - **module**: remove bogus assertion in CJS entrypoint handling with --import (Joyee Cheung) [#&#8203;54592](nodejs/node#54592)
-   \[[`d1331fccb2`](nodejs/node@d1331fccb2)] - **module**: do not warn for typeless package.json when there isn't one (Joyee Cheung) [#&#8203;54045](nodejs/node#54045)
-   \[[`9916458b44`](nodejs/node@9916458b44)] - **(SEMVER-MINOR)** **module**: unflag detect-module (Geoffrey Booth) [#&#8203;53619](nodejs/node#53619)
-   \[[`f9dc1eaef5`](nodejs/node@f9dc1eaef5)] - **(SEMVER-MINOR)** **module**: add \__esModule to require()'d ESM (Joyee Cheung) [#&#8203;52166](nodejs/node#52166)
-   \[[`b86f575504`](nodejs/node@b86f575504)] - **module**: do not set CJS variables for Worker eval (Antoine du Hamel) [#&#8203;53050](nodejs/node#53050)
-   \[[`30ed93db12`](nodejs/node@30ed93db12)] - **module**: cache synchronous module jobs before linking (Joyee Cheung) [#&#8203;52868](nodejs/node#52868)
-   \[[`a03faf289d`](nodejs/node@a03faf289d)] - **module**: support ESM detection in the CJS loader (Joyee Cheung) [#&#8203;52047](nodejs/node#52047)
-   \[[`b07ad39bda`](nodejs/node@b07ad39bda)] - **module**: detect ESM syntax by trying to recompile as SourceTextModule (Joyee Cheung) [#&#8203;52413](nodejs/node#52413)
-   \[[`132a5c190f`](nodejs/node@132a5c190f)] - **module**: eliminate performance cost of detection for cjs entry (Geoffrey Booth) [#&#8203;52093](nodejs/node#52093)
-   \[[`55a57a189f`](nodejs/node@55a57a189f)] - **node-api**: remove deprecated attribute from napi_module_register (Vladimir Morozov) [#&#8203;56162](nodejs/node#56162)
-   \[[`4fba01911d`](nodejs/node@4fba01911d)] - **(SEMVER-MINOR)** **process**: add process.features.require_module (Joyee Cheung) [#&#8203;55241](nodejs/node#55241)
-   \[[`c0fad18ac0`](nodejs/node@c0fad18ac0)] - **src**: add nullptr handling from X509\_STORE_new() (Burkov Egor) [#&#8203;56700](nodejs/node#56700)
-   \[[`5b88d48cbb`](nodejs/node@5b88d48cbb)] - **src**: add default value for RSACipherConfig mode field (Burkov Egor) [#&#8203;56701](nodejs/node#56701)
-   \[[`e3b69e57a6`](nodejs/node@e3b69e57a6)] - **src**: fix build with GCC 15 (tjuhaszrh) [#&#8203;56740](nodejs/node#56740)
-   \[[`a7c1d8c0e8`](nodejs/node@a7c1d8c0e8)] - **src**: initialize FSReqWrapSync in path that uses it (Michaël Zasso) [#&#8203;56613](nodejs/node#56613)
-   \[[`c06ac66356`](nodejs/node@c06ac66356)] - **src**: fix undefined script name in error source (Chengzhong Wu) [#&#8203;56502](nodejs/node#56502)
-   \[[`500f3ccc66`](nodejs/node@500f3ccc66)] - **src**: lock the thread properly in snapshot builder (Joyee Cheung) [#&#8203;56327](nodejs/node#56327)
-   \[[`cf25a5edeb`](nodejs/node@cf25a5edeb)] - **src**: drain platform tasks before creating startup snapshot (Chengzhong Wu) [#&#8203;56403](nodejs/node#56403)
-   \[[`8af1b53bb8`](nodejs/node@8af1b53bb8)] - **src**: safely remove the last line from dotenv (Shima Ryuhei) [#&#8203;55982](nodejs/node#55982)
-   \[[`bb57e909aa`](nodejs/node@bb57e909aa)] - **src**: remove `base64` from `process.versions` (Richard Lau) [#&#8203;53442](nodejs/node#53442)
-   \[[`b8c89a693e`](nodejs/node@b8c89a693e)] - **src**: add `--env-file-if-exists` flag (Bosco Domingo) [#&#8203;53060](nodejs/node#53060)
-   \[[`9097de073a`](nodejs/node@9097de073a)] - **src**: don't match after `--` in `Dotenv::GetPathFromArgs` (Aviv Keller) [#&#8203;54237](nodejs/node#54237)
-   \[[`ececd225b6`](nodejs/node@ececd225b6)] - **src**: implement IsInsideNodeModules() in C++ (Joyee Cheung) [#&#8203;55286](nodejs/node#55286)
-   \[[`18593b7d3e`](nodejs/node@18593b7d3e)] - **src**: refactor embedded entrypoint loading (Joyee Cheung) [#&#8203;53573](nodejs/node#53573)
-   \[[`d7aefc0524`](nodejs/node@d7aefc0524)] - **stream**: fix typo in ReadableStreamBYOBReader.readIntoRequests (Mattias Buelens) [#&#8203;56560](nodejs/node#56560)
-   \[[`fe5f7bcd47`](nodejs/node@fe5f7bcd47)] - **stream**: validate undefined sizeAlgorithm in WritableStream (Jason Zhang) [#&#8203;56067](nodejs/node#56067)
-   \[[`12744c1fd4`](nodejs/node@12744c1fd4)] - **test**: reduce number of written chunks (Luigi Pinca) [#&#8203;56757](nodejs/node#56757)
-   \[[`e121d7d62c`](nodejs/node@e121d7d62c)] - **test**: fix invalid common.mustSucceed() usage (Luigi Pinca) [#&#8203;56756](nodejs/node#56756)
-   \[[`11b82de7ed`](nodejs/node@11b82de7ed)] - **test**: use strict mode in global setters test (Rich Trott) [#&#8203;56742](nodejs/node#56742)
-   \[[`f9d6e35c5e`](nodejs/node@f9d6e35c5e)] - **test**: cleanup and simplify test-crypto-aes-wrap (James M Snell) [#&#8203;56748](nodejs/node#56748)
-   \[[`792ce98699`](nodejs/node@792ce98699)] - **test**: do not use common.isMainThread (Luigi Pinca) [#&#8203;56768](nodejs/node#56768)
-   \[[`4f0cf475e0`](nodejs/node@4f0cf475e0)] - **test**: add test that uses multibyte for path and resolves modules (yamachu) [#&#8203;56696](nodejs/node#56696)
-   \[[`3bc8d273c2`](nodejs/node@3bc8d273c2)] - **test**: add missing test for env file (Jonas) [#&#8203;56642](nodejs/node#56642)
-   \[[`ad39367712`](nodejs/node@ad39367712)] - **test**: enforce strict mode in test-zlib-const (Rich Trott) [#&#8203;56689](nodejs/node#56689)
-   \[[`ca79914137`](nodejs/node@ca79914137)] - **test**: test-stream-compose.js doesn't need internals (Meghan Denny) [#&#8203;56619](nodejs/node#56619)
-   \[[`08bde67101`](nodejs/node@08bde67101)] - **test**: add maxCount and gcOptions to gcUntil() (Joyee Cheung) [#&#8203;56522](nodejs/node#56522)
-   \[[`40a0f6f6e3`](nodejs/node@40a0f6f6e3)] - **test**: mark test-worker-prof as flaky on smartos (Joyee Cheung) [#&#8203;56583](nodejs/node#56583)
-   \[[`d17bf2f62a`](nodejs/node@d17bf2f62a)] - **test**: update test-child-process-bad-stdio to use node:test (Colin Ihrig) [#&#8203;56562](nodejs/node#56562)
-   \[[`5660b99b43`](nodejs/node@5660b99b43)] - **test**: disable openssl 3.4.0 incompatible tests (Jelle van der Waa) [#&#8203;56160](nodejs/node#56160)
-   \[[`861c99f351`](nodejs/node@861c99f351)] - **test**: make test-crypto-hash compatible with OpenSSL > 3.4.0 (Jelle van der Waa) [#&#8203;56160](nodejs/node#56160)
-   \[[`597a39b5f9`](nodejs/node@597a39b5f9)] - **test**: update error code in tls-psk-circuit for for OpenSSL 3.4 (sebastianas) [#&#8203;56420](nodejs/node#56420)
-   \[[`721e9e1217`](nodejs/node@721e9e1217)] - **test**: add initial test426 coverage (Chengzhong Wu) [#&#8203;56436](nodejs/node#56436)
-   \[[`cfe5380c44`](nodejs/node@cfe5380c44)] - **test**: update test-set-http-max-http-headers to use node:test (Colin Ihrig) [#&#8203;56439](nodejs/node#56439)
-   \[[`51ff71a87a`](nodejs/node@51ff71a87a)] - **test**: update test-child-process-windows-hide to use node:test (Colin Ihrig) [#&#8203;56437](nodejs/node#56437)
-   \[[`d6aca0cd89`](nodejs/node@d6aca0cd89)] - **test**: increase spin for eventloop test on s390 (Michael Dawson) [#&#8203;56228](nodejs/node#56228)
-   \[[`82461af6ec`](nodejs/node@82461af6ec)] - **test**: migrate message eval tests from Python to JS (Yiyun Lei) [#&#8203;50482](nodejs/node#50482)
-   \[[`5083bbb2bb`](nodejs/node@5083bbb2bb)] - **test**: remove async-hooks/test-writewrap flaky designation (Luigi Pinca) [#&#8203;56048](nodejs/node#56048)
-   \[[`b4b26e973d`](nodejs/node@b4b26e973d)] - **test**: deflake test-esm-loader-hooks-inspect-brk (Luigi Pinca) [#&#8203;56050](nodejs/node#56050)
-   \[[`182be26b8a`](nodejs/node@182be26b8a)] - **test**: update WPT for url to [`67880a4`](nodejs/node@67880a4) (Node.js GitHub Bot) [#&#8203;55999](nodejs/node#55999)
-   \[[`e67a84902f`](nodejs/node@e67a84902f)] - **test_runner**: remove unused errors (Pietro Marchini) [#&#8203;56607](nodejs/node#56607)
-   \[[`4274c6a015`](nodejs/node@4274c6a015)] - **test_runner**: run single test file benchmark (Pietro Marchini) [#&#8203;56479](nodejs/node#56479)
-   \[[`e57004458b`](nodejs/node@e57004458b)] - **tools**: update doc to new version (Node.js GitHub Bot) [#&#8203;56259](nodejs/node#56259)
-   \[[`e039f2b571`](nodejs/node@e039f2b571)] - **tools**: do not throw on missing `create-release-proposal.sh` (Antoine du Hamel) [#&#8203;56704](nodejs/node#56704)
-   \[[`9a1e314498`](nodejs/node@9a1e314498)] - **tools**: fix tools-deps-update (Daniel Lemire) [#&#8203;56684](nodejs/node#56684)
-   \[[`d6469b5287`](nodejs/node@d6469b5287)] - **tools**: do not throw on missing `create-release-proposal.sh` (Antoine du Hamel) [#&#8203;56695](nodejs/node#56695)
-   \[[`e162476fdc`](nodejs/node@e162476fdc)] - **tools**: fix permissions in `lint-release-proposal` workflow (Antoine du Hamel) [#&#8203;56614](nodejs/node#56614)
-   \[[`914b4675c8`](nodejs/node@914b4675c8)] - **tools**: edit `create-release-proposal` workflow (Antoine du Hamel) [#&#8203;56540](nodejs/node#56540)
-   \[[`4ff9aa7235`](nodejs/node@4ff9aa7235)] - **tools**: validate commit list as part of `lint-release-commit` (Antoine du Hamel) [#&#8203;56291](nodejs/node#56291)
-   \[[`589d0ae8ea`](nodejs/node@589d0ae8ea)] - **tools**: fix loong64 build failed (Xiao-Tao) [#&#8203;56466](nodejs/node#56466)
-   \[[`bc8c39bff8`](nodejs/node@bc8c39bff8)] - **tools**: disable unneeded rule ignoring in Python linting (Rich Trott) [#&#8203;56429](nodejs/node#56429)
-   \[[`3b130002bb`](nodejs/node@3b130002bb)] - **tools**: add release line label when opening release proposal (Antoine du Hamel) [#&#8203;56317](nodejs/node#56317)
-   \[[`73b5c16684`](nodejs/node@73b5c16684)] - **(SEMVER-MINOR)** **worker**: add postMessageToThread (Paolo Insogna) [#&#8203;53682](nodejs/node#53682)

</details>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xOTEuNCIsInVwZGF0ZWRJblZlciI6IjM5LjIwNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.walbeck.it/mwalbeck/docker-cyberchef/pulls/375
Co-authored-by: renovate-bot <[email protected]>
Co-committed-by: renovate-bot <[email protected]>
This was referenced Apr 2, 2025
Update product-os/flowzone action to v19.13.15 klutchell/dnscrypt-proxy-docker#544
Merged
Update product-os/flowzone action to v19.13.20 klutchell/balena-mediaserver#1082
Merged
Update product-os/flowzone action to v19.13.20 klutchell/unbound-docker#574
Merged
Update product-os/flowzone action to v19.13.20 klutchell/balena-exit-node#277
Merged
@andrewbranch andrewbranch mentioned this pull request Jun 2, 2025
Add --module node20 microsoft/TypeScript#61805
Merged
@sapphi-red sapphi-red mentioned this pull request Jun 18, 2025
[Feature Request]: module.exports export support rolldown/rolldown#4997
Closed
@sapphi-red sapphi-red mentioned this pull request Jun 30, 2025
invalid typescript declaration vitejs/vite-plugin-vue#616
Closed
9 tasks done
@dynst dynst mentioned this pull request Oct 31, 2025
doc: clarify require(esm) description #60520
Merged
Copilot AI mentioned this pull request Nov 12, 2025
feat: support Node.js module.exports ESM export rolldown/rolldown#6967
Merged
14 tasks done
graphite-app Bot pushed a commit to rolldown/rolldown that referenced this pull request Nov 13, 2025
feat: support Node.js module.exports ESM export (#6967)
53fced9
## Plan for module.exports export support ✅

Understanding the issue:
- Node.js introduced a new `module.exports` ESM export (nodejs/node#54563)
- When an ESM module exports `module.exports`, it should be prioritized over the default ESM-to-CJS conversion
- Need to check if module has `module.exports` property and use it directly

Tasks:
- [x] Explore repository structure and understand the codebase
- [x] Build the project and verify all tests pass
- [x] Update `__toCommonJS` implementation in runtime files
- [x] Create comprehensive tests for `module.exports` export feature
- [x] Run tests to verify the changes work correctly
- [x] Code review and security check
- [x] Address PR feedback:
  - [x] Updated comment above `__toCommonJS` in index.js
  - [x] Removed `"config": { "treeshake": false }` from all `_config.json`
  - [x] Reorganized tests under subdirectories (basic, fallback, priority, with_default)
  - [x] Removed `format: "cjs"` config to output tests as ESM
  - [x] Added CJS wrapper files to test `__toCommonJS` behavior
  - [x] Used `assert.deepStrictEqual` for all tests
  - [x] Resolved merge conflict with main branch

## Implementation Summary

### Changes Made
1. **Runtime Code Changes**: Updated `__toCommonJS` with improved comment and implementation
2. **Test Structure**: Reorganized into subdirectories under `crates/rolldown/tests/rolldown/cjs_compat/module.exports_export/`:
   - `basic/` - Basic module.exports behavior
   - `fallback/` - Backward compatibility without module.exports
   - `priority/` - Priority over other exports
   - `with_default/` - Works alongside default exports
3. **Test Format**: Tests output ESM format while testing CJS interop via wrapper files
   - `esm.js` - ESM module with or without `module.exports` export
   - `cjs.js` - CJS wrapper that requires the ESM module (triggers `__toCommonJS`)
   - `main.js` - ESM entry point that imports from CJS wrapper and asserts behavior
4. **Merge Conflict Resolution**: Updated `__export` function in runtime-base.js to accept new `symbols` parameter

### Test Results
- All 616 tests pass ✅
- All 4 module.exports tests pass with ESM output ✅
- Snapshots updated correctly ✅
- Merge conflict resolved ✅

Fixes #4997

<!-- START COPILOT CODING AGENT SUFFIX -->

<details>

<summary>Original prompt</summary>

>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>[Feature Request]: `module.exports` export support</issue_title>
> <issue_description>### What problem does this feature solve?
>
> Node.js introduced `module.exports` export (nodejs/node#54563). This feature will be required to bundle some packages properly.
>
> [REPL](https://repl.rolldown.rs/#eNpVjt0KwjAMhV+l5KYTZtyuhIKXvsVu5paJo2u1P6KMvrvZH8yLNpyTnHwZoQM1Apngvtj0fhIG1M7IoWHdWOODGGwbNV0/T+uCFxfh6BUfjjKJp85aHHovD5WpzDRtNaG29+wvw11eSKCCi5RyWFMbdZN7JntMGqeqhORfilQ5pvCjeatoqaujnkd37hwRtRdyOQEX3695SMx/M6bEAovjjUKN5RnSDzGYXOs=) (input code shows `{ foo: 'foo' }`, while output code shows `{ default: [Getter], 'module.exports': [Getter] }`)
>
> It's not yet used by many packages. But I guess it'll be used in more places once the `require(ESM)` gets adopted.
>
> refs #3640
>
>
> ### What does the proposed API look like?
>
> No API change.</issue_description>
>
> <agent_instructions>Change `export var __toCommonJS = mod => __copyProps(__defProp({}, '__esModule', { value: true }), mod)` to `export var __toCommonJS = mod => __hasOwnProp.call(mod, 'module.exports') ? mod['module.exports'] : __copyProps(__defProp({}, '__esModule', { value: true }), mod)`.
> Add extensive tests based on nodejs/node#54563 under `crates/rolldown/tests/rolldown/cjs_compat/module.exports_export`
> </agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> <comment_new><author>@hyf0</author><body>
> Looks like `__toCommonJS` needs to have `node mode`.</body></comment_new>
> </comments>
>

</details>

- Fixes #4997

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.
graphite-app Bot pushed a commit to rolldown/rolldown that referenced this pull request Nov 13, 2025
feat: support Node.js module.exports ESM export (#6967)
79a9118
## Plan for module.exports export support ✅

Understanding the issue:
- Node.js introduced a new `module.exports` ESM export (nodejs/node#54563)
- When an ESM module exports `module.exports`, it should be prioritized over the default ESM-to-CJS conversion
- Need to check if module has `module.exports` property and use it directly

Tasks:
- [x] Explore repository structure and understand the codebase
- [x] Build the project and verify all tests pass
- [x] Update `__toCommonJS` implementation in runtime files
- [x] Create comprehensive tests for `module.exports` export feature
- [x] Run tests to verify the changes work correctly
- [x] Code review and security check
- [x] Address PR feedback:
  - [x] Updated comment above `__toCommonJS` in index.js
  - [x] Removed `"config": { "treeshake": false }` from all `_config.json`
  - [x] Reorganized tests under subdirectories (basic, fallback, priority, with_default)
  - [x] Removed `format: "cjs"` config to output tests as ESM
  - [x] Added CJS wrapper files to test `__toCommonJS` behavior
  - [x] Used `assert.deepStrictEqual` for all tests
  - [x] Resolved merge conflict with main branch

## Implementation Summary

### Changes Made
1. **Runtime Code Changes**: Updated `__toCommonJS` with improved comment and implementation
2. **Test Structure**: Reorganized into subdirectories under `crates/rolldown/tests/rolldown/cjs_compat/module.exports_export/`:
   - `basic/` - Basic module.exports behavior
   - `fallback/` - Backward compatibility without module.exports
   - `priority/` - Priority over other exports
   - `with_default/` - Works alongside default exports
3. **Test Format**: Tests output ESM format while testing CJS interop via wrapper files
   - `esm.js` - ESM module with or without `module.exports` export
   - `cjs.js` - CJS wrapper that requires the ESM module (triggers `__toCommonJS`)
   - `main.js` - ESM entry point that imports from CJS wrapper and asserts behavior
4. **Merge Conflict Resolution**: Updated `__export` function in runtime-base.js to accept new `symbols` parameter

### Test Results
- All 616 tests pass ✅
- All 4 module.exports tests pass with ESM output ✅
- Snapshots updated correctly ✅
- Merge conflict resolved ✅

Fixes #4997

<!-- START COPILOT CODING AGENT SUFFIX -->

<details>

<summary>Original prompt</summary>

>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>[Feature Request]: `module.exports` export support</issue_title>
> <issue_description>### What problem does this feature solve?
>
> Node.js introduced `module.exports` export (nodejs/node#54563). This feature will be required to bundle some packages properly.
>
> [REPL](https://repl.rolldown.rs/#eNpVjt0KwjAMhV+l5KYTZtyuhIKXvsVu5paJo2u1P6KMvrvZH8yLNpyTnHwZoQM1Apngvtj0fhIG1M7IoWHdWOODGGwbNV0/T+uCFxfh6BUfjjKJp85aHHovD5WpzDRtNaG29+wvw11eSKCCi5RyWFMbdZN7JntMGqeqhORfilQ5pvCjeatoqaujnkd37hwRtRdyOQEX3695SMx/M6bEAovjjUKN5RnSDzGYXOs=) (input code shows `{ foo: 'foo' }`, while output code shows `{ default: [Getter], 'module.exports': [Getter] }`)
>
> It's not yet used by many packages. But I guess it'll be used in more places once the `require(ESM)` gets adopted.
>
> refs #3640
>
>
> ### What does the proposed API look like?
>
> No API change.</issue_description>
>
> <agent_instructions>Change `export var __toCommonJS = mod => __copyProps(__defProp({}, '__esModule', { value: true }), mod)` to `export var __toCommonJS = mod => __hasOwnProp.call(mod, 'module.exports') ? mod['module.exports'] : __copyProps(__defProp({}, '__esModule', { value: true }), mod)`.
> Add extensive tests based on nodejs/node#54563 under `crates/rolldown/tests/rolldown/cjs_compat/module.exports_export`
> </agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> <comment_new><author>@hyf0</author><body>
> Looks like `__toCommonJS` needs to have `node mode`.</body></comment_new>
> </comments>
>

</details>

- Fixes #4997

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.
@chirsz-ever chirsz-ever mentioned this pull request Apr 29, 2026
Is esbuild translating `const somelib = require("somelib"); into the appropriate ESM notation? evanw/esbuild#4459
Closed
@coderabbitai coderabbitai Bot mentioned this pull request Aug 11, 2026
initial plugin version marcomq/mq-bridge-pulsar#1
Merged
@robobun robobun mentioned this pull request Sep 9, 2026
bundler: return the module.exports export from require() of an ES module oven-sh/bun#42092
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@aduh95 aduh95 aduh95 approved these changes
@mcollina mcollina mcollina approved these changes
@jasnell jasnell jasnell approved these changes
@joyeecheung joyeecheung joyeecheung approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

backported-to-v22.x PRs backported to the v22.x-staging branch. loaders Issues and PRs related to ES module loaders. module Issues and PRs related to the module subsystem.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

9 participants

@guybedford @nodejs-github-bot @ljharb @joyeecheung @jasnell @anonrig @mcollina @aduh95 @avivkeller
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.