From 9215aa60a6e043b4ddb8ed6c43644cc1b11a5f58 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 2 Jan 2025 10:05:52 -0500 Subject: [PATCH] refactor(node/npm): separate out permission check from npm resolvers (#27511) Decouples permissions from the npm resolvers (towards moving the resolvers out of the cli crate) --- cli/factory.rs | 20 ++++- cli/module_loader.rs | 21 ++++-- cli/npm/byonm.rs | 18 ----- cli/npm/managed/mod.rs | 10 +-- cli/npm/managed/resolvers/common.rs | 110 ---------------------------- cli/npm/managed/resolvers/global.rs | 37 +++++----- cli/npm/managed/resolvers/local.rs | 17 ----- cli/npm/managed/resolvers/mod.rs | 1 - cli/npm/mod.rs | 11 +-- cli/npm/permission_checker.rs | 105 ++++++++++++++++++++++++++ cli/standalone/mod.rs | 24 +++++- tools/generate_types_deno.ts | 2 +- 12 files changed, 185 insertions(+), 191 deletions(-) create mode 100644 cli/npm/permission_checker.rs diff --git a/cli/factory.rs b/cli/factory.rs index fc6bca33fd..c507d8388d 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -71,6 +71,8 @@ use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::CreateInNpmPkgCheckerOptions; +use crate::npm::NpmRegistryReadPermissionChecker; +use crate::npm::NpmRegistryReadPermissionCheckerMode; use crate::resolver::CjsTracker; use crate::resolver::CliDenoResolver; use crate::resolver::CliNpmReqResolver; @@ -941,6 +943,19 @@ impl CliFactory { let cjs_tracker = self.cjs_tracker()?.clone(); let pkg_json_resolver = self.pkg_json_resolver().clone(); let npm_req_resolver = self.npm_req_resolver().await?; + let npm_registry_permission_checker = { + let mode = if cli_options.use_byonm() { + NpmRegistryReadPermissionCheckerMode::Byonm + } else if let Some(node_modules_dir) = cli_options.node_modules_dir_path() + { + NpmRegistryReadPermissionCheckerMode::Local(node_modules_dir.clone()) + } else { + NpmRegistryReadPermissionCheckerMode::Global( + self.npm_cache_dir()?.root_dir().to_path_buf(), + ) + }; + Arc::new(NpmRegistryReadPermissionChecker::new(self.sys(), mode)) + }; Ok(CliMainWorkerFactory::new( self.blob_store().clone(), @@ -968,13 +983,14 @@ impl CliFactory { self.module_load_preparer().await?.clone(), node_code_translator.clone(), node_resolver.clone(), - npm_req_resolver.clone(), - cli_npm_resolver.clone(), NpmModuleLoader::new( self.cjs_tracker()?.clone(), fs.clone(), node_code_translator.clone(), ), + npm_registry_permission_checker, + npm_req_resolver.clone(), + cli_npm_resolver.clone(), self.parsed_source_cache().clone(), self.resolver().await?.clone(), self.sys(), diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 174e06e266..8256c56781 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -66,6 +66,7 @@ use crate::graph_util::ModuleGraphBuilder; use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeResolver; use crate::npm::CliNpmResolver; +use crate::npm::NpmRegistryReadPermissionChecker; use crate::resolver::CjsTracker; use crate::resolver::CliNpmReqResolver; use crate::resolver::CliResolver; @@ -221,9 +222,10 @@ struct SharedCliModuleLoaderState { module_load_preparer: Arc, node_code_translator: Arc, node_resolver: Arc, + npm_module_loader: NpmModuleLoader, + npm_registry_permission_checker: Arc, npm_req_resolver: Arc, npm_resolver: Arc, - npm_module_loader: NpmModuleLoader, parsed_source_cache: Arc, resolver: Arc, sys: CliSys, @@ -281,9 +283,10 @@ impl CliModuleLoaderFactory { module_load_preparer: Arc, node_code_translator: Arc, node_resolver: Arc, + npm_module_loader: NpmModuleLoader, + npm_registry_permission_checker: Arc, npm_req_resolver: Arc, npm_resolver: Arc, - npm_module_loader: NpmModuleLoader, parsed_source_cache: Arc, resolver: Arc, sys: CliSys, @@ -307,9 +310,10 @@ impl CliModuleLoaderFactory { module_load_preparer, node_code_translator, node_resolver, + npm_module_loader, + npm_registry_permission_checker, npm_req_resolver, npm_resolver, - npm_module_loader, parsed_source_cache, resolver, sys, @@ -348,7 +352,10 @@ impl CliModuleLoaderFactory { sys: self.shared.sys.clone(), graph_container, in_npm_pkg_checker: self.shared.in_npm_pkg_checker.clone(), - npm_resolver: self.shared.npm_resolver.clone(), + npm_registry_permission_checker: self + .shared + .npm_registry_permission_checker + .clone(), }); CreateModuleLoaderResult { module_loader, @@ -1095,7 +1102,7 @@ struct CliNodeRequireLoader { sys: CliSys, graph_container: TGraphContainer, in_npm_pkg_checker: Arc, - npm_resolver: Arc, + npm_registry_permission_checker: Arc, } impl NodeRequireLoader @@ -1112,7 +1119,9 @@ impl NodeRequireLoader return Ok(std::borrow::Cow::Borrowed(path)); } } - self.npm_resolver.ensure_read_permission(permissions, path) + self + .npm_registry_permission_checker + .ensure_read_permission(permissions, path) } fn load_text_file_lossy( diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs index 7a0a450c11..2c11a417f3 100644 --- a/cli/npm/byonm.rs +++ b/cli/npm/byonm.rs @@ -1,15 +1,12 @@ // Copyright 2018-2025 the Deno authors. MIT license. -use std::borrow::Cow; use std::path::Path; use std::sync::Arc; -use deno_core::error::AnyError; use deno_core::serde_json; use deno_resolver::npm::ByonmNpmResolver; use deno_resolver::npm::ByonmNpmResolverCreateOptions; use deno_resolver::npm::CliNpmReqResolver; -use deno_runtime::deno_node::NodePermissions; use deno_runtime::ops::process::NpmProcessStateProvider; use node_resolver::NpmPackageFolderResolver; @@ -73,21 +70,6 @@ impl CliNpmResolver for CliByonmNpmResolver { self.root_node_modules_dir() } - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError> { - if !path - .components() - .any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules") - { - permissions.check_read_path(path).map_err(Into::into) - } else { - Ok(Cow::Borrowed(path)) - } - } - fn check_state_hash(&self) -> Option { // it is very difficult to determine the check state hash for byonm // so we just return None to signify check caching is not supported diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs index 4a4d593bbf..55421f41e8 100644 --- a/cli/npm/managed/mod.rs +++ b/cli/npm/managed/mod.rs @@ -24,7 +24,6 @@ use deno_npm_cache::NpmCacheSetting; use deno_path_util::fs::canonicalize_path_maybe_not_exists; use deno_resolver::npm::CliNpmReqResolver; use deno_runtime::colors; -use deno_runtime::deno_node::NodePermissions; use deno_runtime::ops::process::NpmProcessStateProvider; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; @@ -167,6 +166,7 @@ fn create_inner( sys.clone(), npm_rc.clone(), )); + let fs_resolver = create_npm_fs_resolver( npm_cache.clone(), &npm_install_deps_provider, @@ -754,14 +754,6 @@ impl CliNpmResolver for ManagedCliNpmResolver { self.fs_resolver.node_modules_path() } - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError> { - self.fs_resolver.ensure_read_permission(permissions, path) - } - fn check_state_hash(&self) -> Option { // We could go further and check all the individual // npm packages, but that's probably overkill. diff --git a/cli/npm/managed/resolvers/common.rs b/cli/npm/managed/resolvers/common.rs index 6a859ea9fd..66d991bd49 100644 --- a/cli/npm/managed/resolvers/common.rs +++ b/cli/npm/managed/resolvers/common.rs @@ -3,30 +3,17 @@ pub mod bin_entries; pub mod lifecycle_scripts; -use std::borrow::Cow; -use std::collections::HashMap; -use std::io::ErrorKind; use std::path::Path; use std::path::PathBuf; -use std::sync::Arc; -use std::sync::Mutex; use async_trait::async_trait; use deno_ast::ModuleSpecifier; -use deno_core::anyhow::Context; use deno_core::error::AnyError; -use deno_core::futures; -use deno_core::futures::StreamExt; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; -use deno_npm::NpmResolutionPackage; -use deno_runtime::deno_node::NodePermissions; use node_resolver::errors::PackageFolderResolveError; -use sys_traits::FsCanonicalize; use super::super::PackageCaching; -use crate::npm::CliNpmTarballCache; -use crate::sys::CliSys; /// Part of the resolution that interacts with the file system. #[async_trait(?Send)] @@ -63,101 +50,4 @@ pub trait NpmPackageFsResolver: Send + Sync { &self, caching: PackageCaching<'a>, ) -> Result<(), AnyError>; - - #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError>; -} - -#[derive(Debug)] -pub struct RegistryReadPermissionChecker { - sys: CliSys, - cache: Mutex>, - registry_path: PathBuf, -} - -impl RegistryReadPermissionChecker { - pub fn new(sys: CliSys, registry_path: PathBuf) -> Self { - Self { - sys, - registry_path, - cache: Default::default(), - } - } - - pub fn ensure_registry_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError> { - if permissions.query_read_all() { - return Ok(Cow::Borrowed(path)); // skip permissions checks below - } - - // allow reading if it's in the node_modules - let is_path_in_node_modules = path.starts_with(&self.registry_path) - && path - .components() - .all(|c| !matches!(c, std::path::Component::ParentDir)); - - if is_path_in_node_modules { - let mut cache = self.cache.lock().unwrap(); - let mut canonicalize = - |path: &Path| -> Result, AnyError> { - match cache.get(path) { - Some(canon) => Ok(Some(canon.clone())), - None => match self.sys.fs_canonicalize(path) { - Ok(canon) => { - cache.insert(path.to_path_buf(), canon.clone()); - Ok(Some(canon)) - } - Err(e) => { - if e.kind() == ErrorKind::NotFound { - return Ok(None); - } - Err(AnyError::from(e)).with_context(|| { - format!("failed canonicalizing '{}'", path.display()) - }) - } - }, - } - }; - if let Some(registry_path_canon) = canonicalize(&self.registry_path)? { - if let Some(path_canon) = canonicalize(path)? { - if path_canon.starts_with(registry_path_canon) { - return Ok(Cow::Owned(path_canon)); - } - } else if path.starts_with(registry_path_canon) - || path.starts_with(&self.registry_path) - { - return Ok(Cow::Borrowed(path)); - } - } - } - - permissions.check_read_path(path).map_err(Into::into) - } -} - -/// Caches all the packages in parallel. -pub async fn cache_packages( - packages: &[NpmResolutionPackage], - tarball_cache: &Arc, -) -> Result<(), AnyError> { - let mut futures_unordered = futures::stream::FuturesUnordered::new(); - for package in packages { - futures_unordered.push(async move { - tarball_cache - .ensure_package(&package.id.nv, &package.dist) - .await - }); - } - while let Some(result) = futures_unordered.next().await { - // surface the first error - result?; - } - Ok(()) } diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs index 18b7911c2f..417345cefe 100644 --- a/cli/npm/managed/resolvers/global.rs +++ b/cli/npm/managed/resolvers/global.rs @@ -10,27 +10,25 @@ use std::sync::Arc; use async_trait::async_trait; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; +use deno_core::futures::stream::FuturesUnordered; +use deno_core::futures::StreamExt; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; -use deno_runtime::deno_node::NodePermissions; use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; use super::super::resolution::NpmResolution; -use super::common::cache_packages; use super::common::lifecycle_scripts::LifecycleScriptsStrategy; use super::common::NpmPackageFsResolver; -use super::common::RegistryReadPermissionChecker; use crate::args::LifecycleScriptsConfig; use crate::cache::FastInsecureHasher; use crate::colors; use crate::npm::managed::PackageCaching; use crate::npm::CliNpmCache; use crate::npm::CliNpmTarballCache; -use crate::sys::CliSys; /// Resolves packages from the global npm cache. #[derive(Debug)] @@ -39,7 +37,6 @@ pub struct GlobalNpmPackageResolver { tarball_cache: Arc, resolution: Arc, system_info: NpmSystemInfo, - registry_read_permission_checker: RegistryReadPermissionChecker, lifecycle_scripts: LifecycleScriptsConfig, } @@ -48,15 +45,10 @@ impl GlobalNpmPackageResolver { cache: Arc, tarball_cache: Arc, resolution: Arc, - sys: CliSys, system_info: NpmSystemInfo, lifecycle_scripts: LifecycleScriptsConfig, ) -> Self { Self { - registry_read_permission_checker: RegistryReadPermissionChecker::new( - sys, - cache.root_dir_path().to_path_buf(), - ), cache, tarball_cache, resolution, @@ -186,16 +178,25 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { Ok(()) } +} - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError> { - self - .registry_read_permission_checker - .ensure_registry_read_permission(permissions, path) +async fn cache_packages( + packages: &[NpmResolutionPackage], + tarball_cache: &Arc, +) -> Result<(), AnyError> { + let mut futures_unordered = FuturesUnordered::new(); + for package in packages { + futures_unordered.push(async move { + tarball_cache + .ensure_package(&package.id.nv, &package.dist) + .await + }); } + while let Some(result) = futures_unordered.next().await { + // surface the first error + result?; + } + Ok(()) } struct GlobalLifecycleScripts<'a> { diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs index eb806ad02c..63f0e4f36c 100644 --- a/cli/npm/managed/resolvers/local.rs +++ b/cli/npm/managed/resolvers/local.rs @@ -33,7 +33,6 @@ use deno_npm::NpmSystemInfo; use deno_path_util::fs::atomic_write_file_with_retries; use deno_path_util::fs::canonicalize_path_maybe_not_exists; use deno_resolver::npm::normalize_pkg_name_for_node_modules_deno_folder; -use deno_runtime::deno_node::NodePermissions; use deno_semver::package::PackageNv; use deno_semver::StackString; use node_resolver::errors::PackageFolderResolveError; @@ -47,7 +46,6 @@ use sys_traits::FsMetadata; use super::super::resolution::NpmResolution; use super::common::bin_entries; use super::common::NpmPackageFsResolver; -use super::common::RegistryReadPermissionChecker; use crate::args::LifecycleScriptsConfig; use crate::args::NpmInstallDepsProvider; use crate::cache::CACHE_PERM; @@ -75,7 +73,6 @@ pub struct LocalNpmPackageResolver { root_node_modules_path: PathBuf, root_node_modules_url: Url, system_info: NpmSystemInfo, - registry_read_permission_checker: RegistryReadPermissionChecker, lifecycle_scripts: LifecycleScriptsConfig, } @@ -98,10 +95,6 @@ impl LocalNpmPackageResolver { progress_bar, resolution, tarball_cache, - registry_read_permission_checker: RegistryReadPermissionChecker::new( - sys.clone(), - node_modules_folder.clone(), - ), sys, root_node_modules_url: Url::from_directory_path(&node_modules_folder) .unwrap(), @@ -275,16 +268,6 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { ) .await } - - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError> { - self - .registry_read_permission_checker - .ensure_registry_read_permission(permissions, path) - } } /// `node_modules/.deno//node_modules/` diff --git a/cli/npm/managed/resolvers/mod.rs b/cli/npm/managed/resolvers/mod.rs index b52a7e0e39..cc4c735c7c 100644 --- a/cli/npm/managed/resolvers/mod.rs +++ b/cli/npm/managed/resolvers/mod.rs @@ -48,7 +48,6 @@ pub fn create_npm_fs_resolver( npm_cache, tarball_cache, resolution, - sys, system_info, lifecycle_scripts, )), diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index e0c10fa7a7..710c24f98d 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -2,8 +2,8 @@ mod byonm; mod managed; +mod permission_checker; -use std::borrow::Cow; use std::path::Path; use std::sync::Arc; @@ -17,7 +17,6 @@ use deno_resolver::npm::ByonmInNpmPackageChecker; use deno_resolver::npm::ByonmNpmResolver; use deno_resolver::npm::CliNpmReqResolver; use deno_resolver::npm::ResolvePkgFolderFromDenoReqError; -use deno_runtime::deno_node::NodePermissions; use deno_runtime::ops::process::NpmProcessStateProvider; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; @@ -34,6 +33,8 @@ pub use self::managed::CliManagedNpmResolverCreateOptions; pub use self::managed::CliNpmResolverManagedSnapshotOption; pub use self::managed::ManagedCliNpmResolver; pub use self::managed::PackageCaching; +pub use self::permission_checker::NpmRegistryReadPermissionChecker; +pub use self::permission_checker::NpmRegistryReadPermissionCheckerMode; use crate::file_fetcher::CliFileFetcher; use crate::http_util::HttpClientProvider; use crate::sys::CliSys; @@ -183,12 +184,6 @@ pub trait CliNpmResolver: NpmPackageFolderResolver + CliNpmReqResolver { fn root_node_modules_path(&self) -> Option<&Path>; - fn ensure_read_permission<'a>( - &self, - permissions: &mut dyn NodePermissions, - path: &'a Path, - ) -> Result, AnyError>; - /// Returns a hash returning the state of the npm resolver /// or `None` if the state currently can't be determined. fn check_state_hash(&self) -> Option; diff --git a/cli/npm/permission_checker.rs b/cli/npm/permission_checker.rs new file mode 100644 index 0000000000..01fed08954 --- /dev/null +++ b/cli/npm/permission_checker.rs @@ -0,0 +1,105 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +use std::borrow::Cow; +use std::collections::HashMap; +use std::io::ErrorKind; +use std::path::Path; +use std::path::PathBuf; + +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_core::parking_lot::Mutex; +use deno_runtime::deno_node::NodePermissions; +use sys_traits::FsCanonicalize; + +use crate::sys::CliSys; + +#[derive(Debug)] +pub enum NpmRegistryReadPermissionCheckerMode { + Byonm, + Global(PathBuf), + Local(PathBuf), +} + +#[derive(Debug)] +pub struct NpmRegistryReadPermissionChecker { + sys: CliSys, + cache: Mutex>, + mode: NpmRegistryReadPermissionCheckerMode, +} + +impl NpmRegistryReadPermissionChecker { + pub fn new(sys: CliSys, mode: NpmRegistryReadPermissionCheckerMode) -> Self { + Self { + sys, + cache: Default::default(), + mode, + } + } + + #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] + pub fn ensure_read_permission<'a>( + &self, + permissions: &mut dyn NodePermissions, + path: &'a Path, + ) -> Result, AnyError> { + if permissions.query_read_all() { + return Ok(Cow::Borrowed(path)); // skip permissions checks below + } + + match &self.mode { + NpmRegistryReadPermissionCheckerMode::Byonm => { + if path.components().any(|c| c.as_os_str() == "node_modules") { + Ok(Cow::Borrowed(path)) + } else { + permissions.check_read_path(path).map_err(Into::into) + } + } + NpmRegistryReadPermissionCheckerMode::Global(registry_path) + | NpmRegistryReadPermissionCheckerMode::Local(registry_path) => { + // allow reading if it's in the node_modules + let is_path_in_node_modules = path.starts_with(registry_path) + && path + .components() + .all(|c| !matches!(c, std::path::Component::ParentDir)); + + if is_path_in_node_modules { + let mut cache = self.cache.lock(); + let mut canonicalize = + |path: &Path| -> Result, AnyError> { + match cache.get(path) { + Some(canon) => Ok(Some(canon.clone())), + None => match self.sys.fs_canonicalize(path) { + Ok(canon) => { + cache.insert(path.to_path_buf(), canon.clone()); + Ok(Some(canon)) + } + Err(e) => { + if e.kind() == ErrorKind::NotFound { + return Ok(None); + } + Err(AnyError::from(e)).with_context(|| { + format!("failed canonicalizing '{}'", path.display()) + }) + } + }, + } + }; + if let Some(registry_path_canon) = canonicalize(registry_path)? { + if let Some(path_canon) = canonicalize(path)? { + if path_canon.starts_with(registry_path_canon) { + return Ok(Cow::Owned(path_canon)); + } + } else if path.starts_with(registry_path_canon) + || path.starts_with(registry_path) + { + return Ok(Cow::Borrowed(path)); + } + } + } + + permissions.check_read_path(path).map_err(Into::into) + } + } + } +} diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 4768c742f1..6ed192071f 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -6,6 +6,7 @@ #![allow(unused_imports)] use std::borrow::Cow; +use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; @@ -88,6 +89,8 @@ use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::CreateInNpmPkgCheckerOptions; +use crate::npm::NpmRegistryReadPermissionChecker; +use crate::npm::NpmRegistryReadPermissionCheckerMode; use crate::resolver::CjsTracker; use crate::resolver::CliNpmReqResolver; use crate::resolver::NpmModuleLoader; @@ -123,6 +126,7 @@ struct SharedModuleLoaderState { node_code_translator: Arc, node_resolver: Arc, npm_module_loader: Arc, + npm_registry_permission_checker: NpmRegistryReadPermissionChecker, npm_req_resolver: Arc, npm_resolver: Arc, source_maps: SourceMapStore, @@ -557,7 +561,7 @@ impl NodeRequireLoader for EmbeddedModuleLoader { self .shared - .npm_resolver + .npm_registry_permission_checker .ensure_read_permission(permissions, path) } @@ -662,6 +666,23 @@ pub async fn run( let npm_global_cache_dir = root_path.join(".deno_compile_node_modules"); let cache_setting = CacheSetting::Only; let pkg_json_resolver = Arc::new(CliPackageJsonResolver::new(sys.clone())); + let npm_registry_permission_checker = { + let mode = match &metadata.node_modules { + Some(binary::NodeModules::Managed { + node_modules_dir: Some(path), + }) => NpmRegistryReadPermissionCheckerMode::Local(PathBuf::from(path)), + Some(binary::NodeModules::Byonm { .. }) => { + NpmRegistryReadPermissionCheckerMode::Byonm + } + Some(binary::NodeModules::Managed { + node_modules_dir: None, + }) + | None => NpmRegistryReadPermissionCheckerMode::Global( + npm_global_cache_dir.clone(), + ), + }; + NpmRegistryReadPermissionChecker::new(sys.clone(), mode) + }; let (in_npm_pkg_checker, npm_resolver) = match metadata.node_modules { Some(binary::NodeModules::Managed { node_modules_dir }) => { // create an npmrc that uses the fake npm_registry_url to resolve packages @@ -889,6 +910,7 @@ pub async fn run( fs.clone(), node_code_translator, )), + npm_registry_permission_checker, npm_resolver: npm_resolver.clone(), npm_req_resolver, source_maps, diff --git a/tools/generate_types_deno.ts b/tools/generate_types_deno.ts index e88b4bfa6f..fa60f51a4b 100755 --- a/tools/generate_types_deno.ts +++ b/tools/generate_types_deno.ts @@ -76,7 +76,7 @@ async function createDenoDtsFile() { file.insertStatements( 0, - "// Copyright 2018-2024 the Deno authors. MIT license.\n\n", + "// Copyright 2018-2025 the Deno authors. MIT license.\n\n", ); file.saveSync();