Skip to content

Conversation

@joyeecheung
Copy link
Member

Previously, when require()-ing builtins with the node: prefix, the sync resolve hooks were not properly invoked, and load hooks could not override the builtin's format. This fixes the handling and enables redirecting prefixed built-ins to on-disk files and overriding them with other module types via hooks.

Fixes: #60005

Previously, when require()-ing builtins with the node: prefix,
the sync resolve hooks were not properly invoked, and load hooks
could not override the builtin's format. This fixes the
handling and enables redirecting prefixed built-ins to on-disk
files and overriding them with other module types via hooks.
@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/loaders

@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 Dec 16, 2025
@codecov
Copy link

codecov bot commented Dec 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.52%. Comparing base (4f24aff) to head (bac0a34).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61088      +/-   ##
==========================================
- Coverage   88.53%   88.52%   -0.01%     
==========================================
  Files         703      703              
  Lines      208546   208589      +43     
  Branches    40217    40236      +19     
==========================================
+ Hits       184634   184658      +24     
- Misses      15926    15948      +22     
+ Partials     7986     7983       -3     
Files with missing lines Coverage Δ
lib/internal/modules/cjs/loader.js 98.11% <100.00%> (+0.13%) ⬆️

... and 44 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

getCjsConditionsArray(), getDefaultLoad(url, id), validateLoadStrict);
if (resultFromHook.format && resultFromHook.format !== 'builtin') {
debug('loadBuiltinWithHooks overriding module', id, url, resultFromHook);
return { resultFromHook }; // Format has been overridden, return result for the caller to continue loading.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return { resultFromHook }; // Format has been overridden, return result for the caller to continue loading.
return { __proto__: null, resultFromHook }; // Format has been overridden, return result for the caller to continue loading.

or

Suggested change
return { resultFromHook }; // Format has been overridden, return result for the caller to continue loading.
return { resultFromHook, builtinExports: undefined }; // Format has been overridden, return result for the caller to continue loading.

otherwise we'll be hitting potential user-defined getters

// exports.
const mod = loadBuiltinModule(id);
return mod.exports;
return { builtinExports: mod.exports };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@ljharb
Copy link
Member

ljharb commented Dec 17, 2025

i'm confused; i thought the prefix was meant to prevent any kind of user intervention in accessing the core module, with require.extensions OR loaders - does this PR change that?

@joyeecheung
Copy link
Member Author

joyeecheung commented Dec 17, 2025

i thought the prefix was meant to prevent any kind of user intervention in accessing the core module, with require.extensions OR loaders - does this PR change that?

module.register already allows customizations of modules prefixed with node: (as far back as 20)

echo "require('node:tls')" > test.cjs
node --import ./test/fixtures/module-hooks/register-logger-async-hooks.mjs test.cjs

resolve file:///Users/joyee/projects/node/test.cjs from undefined
load file:///Users/joyee/projects/node/test.cjs
resolve node:tls from file:///Users/joyee/projects/node/test.cjs
load node:tls

@ljharb
Copy link
Member

ljharb commented Dec 17, 2025

wow, ok, that's unfortunate - that was one of the primary justifications for adding the prefix in the first place, the performance and reliability benefit of not being able to intercept it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module Issues and PRs related to the module subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot read properties of undefined when requiring node:fs with hooks

4 participants