Version
v26.10.0 (also v26.8.1)
Platform
Microsoft Windows NT 10.0.26100.0 x64
, package maps
Subsystem
module, package maps
What steps will reproduce the bug?
A CommonJS module cannot require() one of its own package's "imports" entries when a package map is active. ESM import of the same specifier works.
pkg/package.json {"name":"pkg","version":"1.0.0","imports":{"#*":"./src/*"},"main":"./index.cjs"}
pkg/index.cjs module.exports = require('#util.cjs');
pkg/src/util.cjs module.exports = 'ok';
app/package.json {"type":"module"}
app/a.cjs console.log(require('pkg'));
map.json {"packages":{"app":{"url":"./app","dependencies":{"pkg":"pkg"}},"pkg":{"url":"./pkg","dependencies":{}}}}
$ node --experimental-package-map=map.json app/a.cjs
Error: Cannot find module '#util.cjs'
How often does it reproduce? Is there a required condition?
Always, when --experimental-package-map is set and a CommonJS module requires a # specifier.
What is the expected behavior? Why is that the expected behavior?
ok is printed, as it is without the flag.
The require() algorithm in modules.md runs LOAD_PACKAGE_IMPORTS (step 4) and LOAD_PACKAGE_SELF (step 5) before LOAD_PACKAGE_MAP (step 6). The ESM resolver also sends # specifiers to packageImportsResolve and asks the map only in packageResolve.
What do you see instead?
Error: Cannot find module '#util.cjs'
code: 'MODULE_NOT_FOUND'
Additional information
Cause, in lib/internal/modules/cjs/loader.js (main at c89ec29):
Suggested fix: do the map lookup after the # imports step (and after trySelf), as the documented algorithm does, or skip the lookup for requests that start with #.
Published packages that use "imports" from CommonJS fail to load under a package map. For example, dependency-cruiser 18.2.0 has require("#utl/try-require.cjs") in src/extract/transpile/vue-template-wrap.cjs. I found it through pnpm's nodeExperimentalPackageMap setting.
This was triaged using Opus 5.5 but verified by me to the best of my ability and filed by myself.
Version
v26.10.0 (also v26.8.1)
Platform
Subsystem
module, package maps
What steps will reproduce the bug?
A CommonJS module cannot
require()one of its own package's"imports"entries when a package map is active. ESMimportof the same specifier works.How often does it reproduce? Is there a required condition?
Always, when
--experimental-package-mapis set and a CommonJS module requires a#specifier.What is the expected behavior? Why is that the expected behavior?
okis printed, as it is without the flag.The
require()algorithm in modules.md runsLOAD_PACKAGE_IMPORTS(step 4) andLOAD_PACKAGE_SELF(step 5) beforeLOAD_PACKAGE_MAP(step 6). The ESM resolver also sends#specifiers topackageImportsResolveand asks the map only inpackageResolve.What do you see instead?
Additional information
Cause, in
lib/internal/modules/cjs/loader.js(main at c89ec29):Module._resolveFilenamecallstryPackageMapResolveCJSfor every request that is not relative and not absolute.#requests are included.tryPackageMapResolveCJSthrows MODULE_NOT_FOUND when the map has no entry for the request.#imports block is never reached.Suggested fix: do the map lookup after the
#imports step (and aftertrySelf), as the documented algorithm does, or skip the lookup for requests that start with#.Published packages that use
"imports"from CommonJS fail to load under a package map. For example, dependency-cruiser 18.2.0 hasrequire("#utl/try-require.cjs")insrc/extract/transpile/vue-template-wrap.cjs. I found it through pnpm'snodeExperimentalPackageMapsetting.This was triaged using Opus 5.5 but verified by me to the best of my ability and filed by myself.