Commit 3e576f7
fix: resolve multiple module resolution issues in VFS hooks (#9)
* fix: resolve multiple module resolution issues in VFS hooks
This fixes several module resolution issues found when using VFS with
real-world applications (e.g., mongoose, pino, got):
1. **Built-in module shadowing**: Bare specifiers like `require('buffer')`
were resolved to userland polyfills in node_modules instead of Node.js
built-ins. Added `isNodeBuiltin()` check before VFS resolution for
both ESM and CJS hooks.
2. **File-before-directory resolution order**: When both `schema.js` and
`schema/` directory exist, `require('./schema')` incorrectly resolved
to `schema/index.js` instead of `schema.js`. Reordered to try file
extensions before directory entry resolution, matching Node.js CJS
resolution order.
3. **require.resolve() not intercepted**: `Module.registerHooks()` in
Node.js 22 does not intercept `require.resolve()` calls. The
`_resolveFilename` patch is now always installed alongside
`registerHooks`, not as a mutually exclusive fallback.
4. **Trailing slash in specifiers**: `require('process/')` produced
`packageSubpath: './'` which didn't match the `=== '.'` check,
preventing entry point resolution.
5. **Main pointing to directory**: When `package.json` has
`"main": "dist/source"` and that path is a directory, the resolver
now tries `index.js` inside it (matching Node.js behavior).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: DRY module resolution helpers and add tests
- Extract CJS_INDEX_FILES constant and tryCJSIndexFiles() helper to
eliminate 4 duplicated inline index-file loops
- Extract makeResolveResult() helper to replace ~15 repeated
{ url, format, shortCircuit } object constructions
- Cache NodeModule reference and use Set for O(1) builtin lookups
in isNodeBuiltin() instead of require() + indexOf on every call
- Remove unnecessary bare block in resolveVFSPath
- Document double-resolution trade-off when registerHooks and
_resolveFilename coexist, and ESM vs CJS index file divergence
- Add test/module_resolution.test.js covering all 5 fixes:
built-in shadowing, file-before-directory, require.resolve(),
trailing slash, and main-points-to-directory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add wildcard exports, #imports, CJS exports field, and CJS subpath directory support
- Wildcard pattern support in package.json exports (e.g. "./bindings/*")
for both ESM and CJS resolution, per Node.js subpath patterns spec.
- Package #imports (subpath imports) with wildcard and bare specifier
re-resolution support via new resolveHashImport() function.
- CJS exports field resolution with dedicated resolveCJSExportsPath,
resolveCJSConditions, and resolveCJSPackageExports helpers. Exports
field is now checked before main/index fallback in CJS resolution.
- CJS subpath directory resolution: require('pkg/subdir') now checks
subdir/package.json main and subdir/index.js when subpath is a dir.
- Extracted matchWildcardPattern() shared helper to eliminate 3x
duplicate wildcard matching logic.
- Single package.json read in resolveCJSPackageInVFS (was reading twice).
- Fixed dirname() -> dirnameVFS() bug in resolveBareSpecifier for
correct Windows VFS path handling.
- 16 new tests covering all new resolution features.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: unify ESM/CJS resolution helpers and fix bugs
- Fix dirname() → dirnameVFS() in getVFSPackageType for Windows VFS paths
- Fix resolveHashImport nested conditions (now properly recursive)
- Fix .mjs/.cjs extensions leaking into CJS resolution (parameterized)
- Add CJS #imports support in _resolveFilename patch
- Fix double internalModuleStat calls via resolveMainField helper
- Unify resolvePackageExports/resolveCJSPackageExports into resolveExportsToPath
- Unify resolveConditionsWithPattern/resolveCJSConditions into resolveConditionsToPath
- Extract expandPattern, findVFSForPath, resolveMainField shared helpers
- Consistent use of joinVFSParts/dirnameVFS in ESM paths
- Move isNodeBuiltin to utility section, remove redundant node: check
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 2a4ea7d commit 3e576f7
2 files changed
Lines changed: 861 additions & 166 deletions
0 commit comments