2.0 KiB
jest-resolve — agent notes
Resolution order
resolveModule(from, name) tries, in order:
moduleNameMapper— first matching regex wins. On match, the mapped path must resolve or an error is thrown (unlike regular resolution which returnsnull). Supports$1/$2capture substitution and array fallbacks.- Cache —
_moduleNameCachekeyed by(dir, name, options). - Haste module —
getModule(name)against the haste map. node_modules— viadefaultResolver(unrs-resolver, a Rust-backed OXC resolver) or a user-supplied custom resolver.- Haste package —
package.jsonfiles registered in the haste map. - Throw
ModuleNotFoundError(carriesrequireStack,hint,moduleName).
Key facts
defaultResolver uses unrs-resolver (OXC, Rust/WASM). The singleton lives in fileWalkers.ts and is cloneWithOptions-d per call. Resolver.clearDefaultResolverCache() flushes it plus statSyncCached/readPackageCached — call it in tests that mutate the filesystem.
Custom resolvers export SyncResolver ((path, options) => string), or {sync, async}. The options object includes defaultResolver and defaultAsyncResolver for fall-through. When only async is exported, canResolveSync() returns false and EsmLoader routes to the async path.
canResolveSync() is memoized on first call per Resolver instance. A throwing resolver module is treated as false.
shouldLoadAsEsm(path, extensionsToTreatAsEsm) checks extension (.mjs → always ESM, .cjs → never) then package.json#type. Results are cached; call clearCachedLookups() in tests that add/remove package.json files.
Hard rules
- A
moduleNameMappermatch that can't be resolved always throws — there's no "try next strategy" fallback. moduleNameMapperis checked before haste andnode_modules. If a mapper intercepts a name, the haste map is never consulted for it.- Don't cache resolved paths across projects;
Resolver.clearDefaultResolverCache()is process-global and clears all instances.