Title: Always run async loader hooks synchronously from the non-loader thread · Issue #59666 · nodejs/node · GitHub
Open Graph Title: Always run async loader hooks synchronously from the non-loader thread · Issue #59666 · nodejs/node
X Title: Always run async loader hooks synchronously from the non-loader thread · Issue #59666 · nodejs/node
Description: This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly. This is related to #55782 and will allow us to Eliminate the races in ESM cache h...
Open Graph Description: This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly. This is related to #55782 and will allow ...
X Description: This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly. This is related to #55782 and will allow ...
Opengraph URL: https://github.com/nodejs/node/issues/59666
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Always run async loader hooks synchronously from the non-loader thread","articleBody":"This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly.\n\nThis is related to https://github.com/nodejs/node/issues/55782 and will allow us to\n\n1. Eliminate the races in ESM cache handling when `require(esm)` needs the linking to be synchronous but `import esm` may populate an asynchronous linking job in the cache. There were multiple band-aids applied to work around this, like https://github.com/nodejs/node/pull/59519 and https://github.com/nodejs/node/pull/57187, but to fully eliminate the races, this would be necessary to finish https://github.com/nodejs/node/issues/55782\n2. Go back to using the authentic `require()` in imported CJS instead of re-inventing a separate `require()` and eliminate its quirks, which currently includes\n 1. The re-invented `require` lacks a lot of properties like `require.cache`, which is a documented caveat https://nodejs.org/api/module.html#caveat-in-the-asynchronous-load-hook - this means a lot of code may not be able to load when the async customization hooks are registered, as they directly rely on these properties.\n 2. The source code for CJS ended up being loaded twice https://github.com/nodejs/node/blob/0fd1ecded6476378b207cacc8fb4e2f1698830c6/lib/internal/modules/esm/load.js#L97-L99\n 3. As a side-effect of the previous quirk, when the module format is CJS, the user hook can't assume the `source` is available and need to cope with `source` being `null`, usually by reading directly from the file system (not necessarily correct), like what's [being done in import-in-the-middle](https://github.com/nodejs/import-in-the-middle/blob/53a33a9b07799bff815864089a0c072d223df47b/lib/get-exports.js#L100), see https://github.com/nodejs/node/issues/57327#issuecomment-2701382020\n 4. Also as a side-effect, if they don't override the nullish value by supplementing source code that they obtain through other means, the `require` in imported CommonJS won't trigger the hooks.\n 5. The `resolve` hook gets `\"import\"` in its conditions array for `require()`, instead of `\"require\"` (because it's using ESM resolution). This can lead to wrong modules being loaded when loading packages that split the conditional exports.\n 6. The `resolve` hook gets the full URL, not the specifier passed to `require()`\n 7. Invoking the sync hooks twice for CJS, one from the re-invented require, one from the `Module._load` invocation in the evaluation step.\n\nRefs: https://github.com/nodejs/node/issues/57327\nRefs: https://github.com/nodejs/node/issues/55808\nRefs: https://github.com/nodejs/node/issues/52697\nRefs: https://github.com/nodejs/node/issues/56241\nRefs: https://github.com/nodejs/node/issues/55782\n\ncc @nodejs/loaders ","author":{"url":"https://github.com/joyeecheung","@type":"Person","name":"joyeecheung"},"datePublished":"2025-08-28T13:18:08.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/59666/node/issues/59666"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:dfa61071-2d8f-c363-e1e0-74c19867a52c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 80EC:3AAB0D:AA25C:E5E3D:6969A375 |
| html-safe-nonce | 8b9d7ecc6c29855c0d779db91c5a1a8931384bbf023638d72104e43c5066d226 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4MEVDOjNBQUIwRDpBQTI1QzpFNUUzRDo2OTY5QTM3NSIsInZpc2l0b3JfaWQiOiIxMzI0MjgzOTQxMjA3MjUzODc3IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 76f8b58950814479b9d9f68696c9f766993fdf2e5f8c16862d2e2a1b865311ae |
| hovercard-subject-tag | issue:3363305726 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/59666/issue_layout |
| twitter:image | https://opengraph.githubassets.com/b6b93f613accd61271d64730629654297c6481ab7a384335d373b3f6dc7c261b/nodejs/node/issues/59666 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/b6b93f613accd61271d64730629654297c6481ab7a384335d373b3f6dc7c261b/nodejs/node/issues/59666 |
| og:image:alt | This was an idea discussed in the loaders group a few times in the past as well as in the last collaboration summit. Opening an issue to track it properly. This is related to #55782 and will allow ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | joyeecheung |
| hostname | github.com |
| expected-hostname | github.com |
| None | 24c4c97a2d520cb286b35e1a4c22d7a4df3c26a2fa28dd7cdf0e65db327b4de7 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 124667f43168afb6c9c03b7c02eb5b1d2e1be3d9 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width