fix(ext/node): resolve global cache packages when require referrer is outside DENODIR#34497
Merged
Conversation
… outside DENODIR Closes denoland/orchid#276 In global-cache mode (`--no-node-modules-dir`), a CJS `require()` whose referrer module lives outside of DENODIR could not resolve top-level npm dependencies by bare specifier. The npm folder resolver requires the referrer to be inside the cache so it can anchor the lookup, and when it isn't (for example, a transpiled user-project file invoked from a require-hook installed by a cached package) the request would fall through to a fruitless `node_modules` walk and throw `Cannot find module`. This is the Playwright config-transpile scenario from #25189: Playwright lives in the global cache, installs a `require()` hook, transpiles the user's `playwright.config.js` to CJS, and then re-issues `require("playwright/test")` with the user's config file as the parent module. `op_require_resolve_deno_dir` now falls back, when the referrer-based resolution fails and the referrer is not inside an npm package, to looking up the bare specifier's package name as a top-level dependency in the managed npm graph. A new `NodeRequireLoader` trait method, `resolve_package_folder_from_name`, lets the CLI plug in the actual resolution; the default returns `None`, and the byonm/local node_modules paths are unaffected because they already handle this case via the ancestor `node_modules` walk. Co-Authored-By: Divy Srivastava <[email protected]>
Co-Authored-By: Divy Srivastava <[email protected]>
littledivy
pushed a commit
to crowlKats/deno
that referenced
this pull request
Jun 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
In global-cache mode (
--no-node-modules-dir), a CJSrequire()whosereferrer module lives outside of DENODIR could not resolve top-level
npm dependencies by bare specifier. The managed npm folder resolver
requires the referrer to be inside the cache so it can anchor the
lookup; when it isn't, the request fell through to a fruitless
node_modulesancestor walk and threwCannot find module.This is the Playwright config-transpile scenario described in
#25189: Playwright lives in the global cache, installs a
require()hook, transpiles the user's
playwright.config.jsto CJS, and thenre-issues
require("playwright/test")with the user's config file asthe parent module. The user's config file is not in the cache, so
resolve_package_folder_from_packagebails out withReferrerNotFoundError, no global-cache path is added toModule._resolveLookupPaths, and the lookup fails.What this does
op_require_resolve_deno_dirnow falls back, when the referrer-basedresolution fails and the referrer is not inside an npm package, to
looking up the bare specifier's package name as a top-level dependency
in the npm graph. The new
NodeRequireLoader::resolve_package_folder_from_nametrait method lets the CLI plug in the actual resolution; the default
returns
None, and the CLI implementation only resolves in managed +global-cache mode (byonm and local
node_modulesare unaffectedbecause they already handle this case via the ancestor
node_moduleswalk).
This is also consistent with the JS-side fallback at
Module._resolveFilenamethat fires whenoptions.pathsis providedand exercised by the existing
tests/specs/npm/require_resolve_bad_paths_global_cachetest —that fallback resolves the same way through the global cache, just for
a different trigger.
Fixes #25189.
Closes denoland/orchid#276
Test plan
cargo check --bin denopassescargo fmt --check/rustfmt --checkpassestests/specs/npm/require_resolve_outside_cachespec