Repository: denoland/deno
Pull request: fix(node): do not look up node_module paths when using global resolver

It doesn't make sense for the global resolver to search for npm packages because the structure of the folder there doesn't do node_resolution.

Also fixes https://github.com/denoland/deno/issues/20484

Probably doing this in addition to https://github.com/denoland/deno/pull/29397 would be good.

Changed files:
filename: cli/module_loader.rs
patch: @@ -410,6 +410,7 @@ impl CliModuleLoaderFactory {
     let node_require_loader = Rc::new(CliNodeRequireLoader {
       cjs_tracker: self.shared.cjs_tracker.clone(),
       emitter: self.shared.emitter.clone(),
+      npm_resolver: self.shared.npm_resolver.clone(),
       sys: self.shared.sys.clone(),
       graph_container,
       in_npm_pkg_checker: self.shared.in_npm_pkg_checker.clone(),
@@ -1268,6 +1269,7 @@ impl ModuleGraphUpdatePermit for WorkerModuleGraphUpdatePermit {
 struct CliNodeRequireLoader<TGraphContainer: ModuleGraphContainer> {
   cjs_tracker: Arc<CliCjsTracker>,
   emitter: Arc<Emitter>,
+  npm_resolver: CliNpmResolver,
   sys: CliSys,
   graph_container: TGraphContainer,
   in_npm_pkg_checker: DenoInNpmPackageChecker,
@@ -1338,6 +1340,21 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
     let media_type = MediaType::from_specifier(specifier);
     self.cjs_tracker.is_maybe_cjs(specifier, media_type)
   }
+
+  fn resolve_require_node_module_paths(&self, from: &Path) -> Vec<String> {
+    let is_global_resolver_and_from_in_global_cache = self
+      .npm_resolver
+      .as_managed()
+      .filter(|r| r.root_node_modules_path().is_none())
+      .map(|r| r.global_cache_root_path())
+      .filter(|global_cache_path| from.starts_with(global_cache_path))
+      .is_some();
+    if is_global_resolver_and_from_in_global_cache {
+      Vec::new()
+    } else {
+      deno_runtime::deno_node::default_resolve_require_node_module_paths(from)
+    }
+  }
 }
 
 #[derive(Debug, Default)]

filename: ext/node/lib.rs
patch: @@ -172,6 +172,25 @@ pub trait NodeRequireLoader {
   /// Get if the module kind is maybe CJS and loading should determine
   /// if its CJS or ESM.
   fn is_maybe_cjs(&self, specifier: &Url) -> Result<bool, ClosestPkgJsonError>;
+
+  fn resolve_require_node_module_paths(&self, from: &Path) -> Vec<String> {
+    default_resolve_require_node_module_paths(from)
+  }
+}
+
+pub fn default_resolve_require_node_module_paths(from: &Path) -> Vec<String> {
+  let mut paths = Vec::with_capacity(from.components().count());
+  let mut current_path = from;
+  let mut maybe_parent = Some(current_path);
+  while let Some(parent) = maybe_parent {
+    if !parent.ends_with("node_modules") {
+      paths.push(parent.join("node_modules").to_string_lossy().into_owned());
+    }
+    current_path = parent;
+    maybe_parent = current_path.parent();
+  }
+
+  paths
 }
 
 pub static NODE_ENV_VAR_ALLOWLIST: Lazy<HashSet<String>> = Lazy::new(|| {

filename: ext/node/ops/require.rs
patch: @@ -214,18 +214,8 @@ pub fn op_require_node_module_paths<
     }
   }
 
-  let mut paths = Vec::with_capacity(from.components().count());
-  let mut current_path = from.as_path();
-  let mut maybe_parent = Some(current_path);
-  while let Some(parent) = maybe_parent {
-    if !parent.ends_with("node_modules") {
-      paths.push(parent.join("node_modules").to_string_lossy().into_owned());
-    }
-    current_path = parent;
-    maybe_parent = current_path.parent();
-  }
-
-  Ok(paths)
+  let loader = state.borrow::<NodeRequireLoaderRc>();
+  Ok(loader.resolve_require_node_module_paths(&from))
 }
 
 #[op2]