diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-03-30 03:20:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-30 03:20:31 +0200 |
commit | 913e2875c1c31d5ffbc9c0c9ed0e8c63f6143024 (patch) | |
tree | 439fa7eef067893fde75dfe386d801a090e6c057 | |
parent | 89bbbd102c6050763105be39a49494a5ffdce35b (diff) |
refactor(ext/node): add NodeEnv::Fs associated type (#18484)
This commit adds associated type to "NodeEnv" trait, called "Fs".
The "Fs" type has a trait bound on "NodeFs", which specifies APIs
required for all ops and resolution APIs to function.
A "RealFs" implementation of "NodeFs" is exported from the "deno_node"
crate, that provides a default implementation for the trait.
All code in "deno_node" extension was changed to use the "NodeFs" trait
to handle file system operations, instead of relying on APIs from the
standard library.
-rw-r--r-- | cli/node/mod.rs | 54 | ||||
-rw-r--r-- | cli/npm/resolvers/local.rs | 6 | ||||
-rw-r--r-- | ext/node/clippy.toml | 21 | ||||
-rw-r--r-- | ext/node/lib.rs | 31 | ||||
-rw-r--r-- | ext/node/ops.rs | 25 | ||||
-rw-r--r-- | ext/node/package_json.rs | 9 | ||||
-rw-r--r-- | ext/node/resolution.rs | 90 | ||||
-rw-r--r-- | runtime/build.rs | 1 | ||||
-rw-r--r-- | runtime/lib.rs | 1 |
9 files changed, 150 insertions, 88 deletions
diff --git a/cli/node/mod.rs b/cli/node/mod.rs index 3df217722..0906deed0 100644 --- a/cli/node/mod.rs +++ b/cli/node/mod.rs @@ -31,6 +31,7 @@ use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_node::PathClean; +use deno_runtime::deno_node::RealFs; use deno_runtime::deno_node::RequireNpmResolver; use deno_runtime::deno_node::DEFAULT_CONDITIONS; use deno_runtime::permissions::PermissionsContainer; @@ -227,10 +228,11 @@ pub fn node_resolve( let path = url.to_file_path().unwrap(); // todo(16370): the module kind is not correct here. I think we need // typescript to tell us if the referrer is esm or cjs - let path = match path_to_declaration_path(path, NodeModuleKind::Esm) { - Some(path) => path, - None => return Ok(None), - }; + let path = + match path_to_declaration_path::<RealFs>(path, NodeModuleKind::Esm) { + Some(path) => path, + None => return Ok(None), + }; ModuleSpecifier::from_file_path(path).unwrap() } }; @@ -273,7 +275,8 @@ pub fn node_resolve_npm_reference( let resolved_path = match mode { NodeResolutionMode::Execution => resolved_path, NodeResolutionMode::Types => { - match path_to_declaration_path(resolved_path, node_module_kind) { + match path_to_declaration_path::<RealFs>(resolved_path, node_module_kind) + { Some(path) => path, None => return Ok(None), } @@ -312,7 +315,7 @@ pub fn node_resolve_binary_commands( let package_folder = npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?; let package_json_path = package_folder.join("package.json"); - let package_json = PackageJson::load( + let package_json = PackageJson::load::<RealFs>( npm_resolver, &mut PermissionsContainer::allow_all(), package_json_path, @@ -335,7 +338,7 @@ pub fn node_resolve_binary_export( let package_folder = npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?; let package_json_path = package_folder.join("package.json"); - let package_json = PackageJson::load( + let package_json = PackageJson::load::<RealFs>( npm_resolver, &mut PermissionsContainer::allow_all(), package_json_path, @@ -424,10 +427,13 @@ fn package_config_resolve( ) -> Result<Option<PathBuf>, AnyError> { let package_json_path = package_dir.join("package.json"); let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap(); - let package_config = - PackageJson::load(npm_resolver, permissions, package_json_path.clone())?; + let package_config = PackageJson::load::<RealFs>( + npm_resolver, + permissions, + package_json_path.clone(), + )?; if let Some(exports) = &package_config.exports { - let result = package_exports_resolve( + let result = package_exports_resolve::<RealFs>( &package_json_path, package_subpath.to_string(), exports, @@ -443,7 +449,7 @@ fn package_config_resolve( Err(exports_err) => { if mode.is_types() && package_subpath == "." { if let Ok(Some(path)) = - legacy_main_resolve(&package_config, referrer_kind, mode) + legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode) { return Ok(Some(path)); } else { @@ -455,7 +461,7 @@ fn package_config_resolve( } } if package_subpath == "." { - return legacy_main_resolve(&package_config, referrer_kind, mode); + return legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode); } Ok(Some(package_dir.join(package_subpath))) @@ -469,7 +475,7 @@ pub fn url_to_node_resolution( if url_str.starts_with("http") { Ok(NodeResolution::Esm(url)) } else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") { - let package_config = get_closest_package_json( + let package_config = get_closest_package_json::<RealFs>( &url, npm_resolver, &mut PermissionsContainer::allow_all(), @@ -556,7 +562,7 @@ fn module_resolve( // todo(dsherret): the node module kind is not correct and we // should use the value provided by typescript instead let declaration_path = - path_to_declaration_path(file_path, NodeModuleKind::Esm); + path_to_declaration_path::<RealFs>(file_path, NodeModuleKind::Esm); declaration_path.map(|declaration_path| { ModuleSpecifier::from_file_path(declaration_path).unwrap() }) @@ -565,7 +571,7 @@ fn module_resolve( } } else if specifier.starts_with('#') { Some( - package_imports_resolve( + package_imports_resolve::<RealFs>( specifier, referrer, NodeModuleKind::Esm, @@ -579,7 +585,7 @@ fn module_resolve( } else if let Ok(resolved) = Url::parse(specifier) { Some(resolved) } else { - package_resolve( + package_resolve::<RealFs>( specifier, referrer, NodeModuleKind::Esm, @@ -821,11 +827,14 @@ fn resolve( let package_json_path = module_dir.join("package.json"); if package_json_path.exists() { - let package_json = - PackageJson::load(npm_resolver, permissions, package_json_path.clone())?; + let package_json = PackageJson::load::<RealFs>( + npm_resolver, + permissions, + package_json_path.clone(), + )?; if let Some(exports) = &package_json.exports { - return package_exports_resolve( + return package_exports_resolve::<deno_node::RealFs>( &package_json_path, package_subpath, exports, @@ -846,8 +855,11 @@ fn resolve( // subdir might have a package.json that specifies the entrypoint let package_json_path = d.join("package.json"); if package_json_path.exists() { - let package_json = - PackageJson::load(npm_resolver, permissions, package_json_path)?; + let package_json = PackageJson::load::<RealFs>( + npm_resolver, + permissions, + package_json_path, + )?; if let Some(main) = package_json.main(NodeModuleKind::Cjs) { return Ok(d.join(main).clean()); } diff --git a/cli/npm/resolvers/local.rs b/cli/npm/resolvers/local.rs index 5a026f0a8..f9cc9b09b 100644 --- a/cli/npm/resolvers/local.rs +++ b/cli/npm/resolvers/local.rs @@ -159,9 +159,9 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { if sub_dir.is_dir() { // if doing types resolution, only resolve the package if it specifies a types property if mode.is_types() && !name.starts_with("@types/") { - let package_json = PackageJson::load_skip_read_permission( - sub_dir.join("package.json"), - )?; + let package_json = PackageJson::load_skip_read_permission::< + deno_runtime::deno_node::RealFs, + >(sub_dir.join("package.json"))?; if package_json.types.is_some() { return Ok(sub_dir); } diff --git a/ext/node/clippy.toml b/ext/node/clippy.toml new file mode 100644 index 000000000..3ce5624b3 --- /dev/null +++ b/ext/node/clippy.toml @@ -0,0 +1,21 @@ +disallowed-methods = [ + { path = "std::env::current_dir", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::path::Path::exists", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::canonicalize", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::copy", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::create_dir", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::create_dir_all", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::hard_link", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::metadata", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::read", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::read_dir", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::read_link", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::read_to_string", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::remove_dir", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::remove_dir_all", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::remove_file", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::rename", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::set_permissions", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::symlink_metadata", reason = "File system operations should be done using NodeFs trait" }, + { path = "std::fs::write", reason = "File system operations should be done using NodeFs trait" }, +] diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 1693a82ef..f3bdb7e5b 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -6,6 +6,7 @@ use deno_core::op; use deno_core::JsRuntime; use once_cell::sync::Lazy; use std::collections::HashSet; +use std::io; use std::path::Path; use std::path::PathBuf; use std::rc::Rc; @@ -41,18 +42,36 @@ pub use resolution::DEFAULT_CONDITIONS; pub trait NodeEnv { type P: NodePermissions; - // TODO(bartlomieju): - // type Fs: NodeFs; + type Fs: NodeFs; } pub trait NodePermissions { fn check_read(&mut self, path: &Path) -> Result<(), AnyError>; } -// TODO(bartlomieju): -// pub trait NodeFs { -// fn current_dir() -> Result<PathBuf, AnyError>; -// } +pub trait NodeFs { + fn current_dir() -> io::Result<PathBuf>; + fn metadata<P: AsRef<Path>>(path: P) -> io::Result<std::fs::Metadata>; + fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String>; +} + +pub struct RealFs; +impl NodeFs for RealFs { + fn current_dir() -> io::Result<PathBuf> { + #[allow(clippy::disallowed_methods)] + std::env::current_dir() + } + + fn metadata<P: AsRef<Path>>(path: P) -> io::Result<std::fs::Metadata> { + #[allow(clippy::disallowed_methods)] + std::fs::metadata(path) + } + + fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> { + #[allow(clippy::disallowed_methods)] + std::fs::read_to_string(path) + } +} pub trait RequireNpmResolver { fn resolve_package_folder_from_package( diff --git a/ext/node/ops.rs b/ext/node/ops.rs index 3dbab33c1..5ecf70f3e 100644 --- a/ext/node/ops.rs +++ b/ext/node/ops.rs @@ -14,6 +14,7 @@ use std::path::PathBuf; use std::rc::Rc; use crate::NodeEnv; +use crate::NodeFs; use super::resolution; use super::NodeModuleKind; @@ -98,7 +99,7 @@ where // Guarantee that "from" is absolute. let from = deno_core::resolve_path( &from, - &std::env::current_dir().context("Unable to get CWD")?, + &(Env::Fs::current_dir()).context("Unable to get CWD")?, ) .unwrap() .to_file_path() @@ -263,7 +264,7 @@ where { let path = PathBuf::from(path); ensure_read_permission::<Env::P>(state, &path)?; - if let Ok(metadata) = std::fs::metadata(&path) { + if let Ok(metadata) = Env::Fs::metadata(&path) { if metadata.is_file() { return Ok(0); } else { @@ -352,7 +353,7 @@ where if let Some(parent_id) = maybe_parent_id { if parent_id == "<repl>" || parent_id == "internal/preload" { - if let Ok(cwd) = std::env::current_dir() { + if let Ok(cwd) = Env::Fs::current_dir() { ensure_read_permission::<Env::P>(state, &cwd)?; return Ok(Some(cwd.to_string_lossy().to_string())); } @@ -376,7 +377,7 @@ where let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone(); let permissions = state.borrow_mut::<Env::P>(); - let pkg = resolution::get_package_scope_config( + let pkg = resolution::get_package_scope_config::<Env::Fs>( &Url::from_file_path(parent_path.unwrap()).unwrap(), &*resolver, permissions, @@ -407,7 +408,7 @@ where let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap(); if let Some(exports) = &pkg.exports { - resolution::package_exports_resolve( + resolution::package_exports_resolve::<Env::Fs>( &pkg.path, expansion, exports, @@ -434,7 +435,7 @@ where { let file_path = PathBuf::from(file_path); ensure_read_permission::<Env::P>(state, &file_path)?; - Ok(std::fs::read_to_string(file_path)?) + Ok(Env::Fs::read_to_string(file_path)?) } #[op] @@ -471,7 +472,7 @@ where } else { path_resolve(vec![modules_path, name]) }; - let pkg = PackageJson::load( + let pkg = PackageJson::load::<Env::Fs>( &*resolver, permissions, PathBuf::from(&pkg_path).join("package.json"), @@ -479,7 +480,7 @@ where if let Some(exports) = &pkg.exports { let referrer = Url::from_file_path(parent_path).unwrap(); - resolution::package_exports_resolve( + resolution::package_exports_resolve::<Env::Fs>( &pkg.path, format!(".{expansion}"), exports, @@ -510,7 +511,7 @@ where )?; let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone(); let permissions = state.borrow_mut::<Env::P>(); - resolution::get_closest_package_json( + resolution::get_closest_package_json::<Env::Fs>( &Url::from_file_path(filename).unwrap(), &*resolver, permissions, @@ -528,7 +529,7 @@ where let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone(); let permissions = state.borrow_mut::<Env::P>(); let package_json_path = PathBuf::from(package_json_path); - PackageJson::load(&*resolver, permissions, package_json_path).ok() + PackageJson::load::<Env::Fs>(&*resolver, permissions, package_json_path).ok() } #[op] @@ -544,7 +545,7 @@ where ensure_read_permission::<Env::P>(state, &parent_path)?; let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone(); let permissions = state.borrow_mut::<Env::P>(); - let pkg = PackageJson::load( + let pkg = PackageJson::load::<Env::Fs>( &*resolver, permissions, parent_path.join("package.json"), @@ -553,7 +554,7 @@ where if pkg.imports.is_some() { let referrer = deno_core::url::Url::from_file_path(&parent_filename).unwrap(); - let r = resolution::package_imports_resolve( + let r = resolution::package_imports_resolve::<Env::Fs>( &request, &referrer, NodeModuleKind::Cjs, diff --git a/ext/node/package_json.rs b/ext/node/package_json.rs index b0816dd85..60f50ad78 100644 --- a/ext/node/package_json.rs +++ b/ext/node/package_json.rs @@ -1,5 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::NodeFs; use crate::NodeModuleKind; use crate::NodePermissions; @@ -61,16 +62,16 @@ impl PackageJson { } } - pub fn load( + pub fn load<Fs: NodeFs>( resolver: &dyn RequireNpmResolver, permissions: &mut dyn NodePermissions, path: PathBuf, ) -> Result<PackageJson, AnyError> { resolver.ensure_read_permission(permissions, &path)?; - Self::load_skip_read_permission(path) + Self::load_skip_read_permission::<Fs>(path) } - pub fn load_skip_read_permission( + pub fn load_skip_read_permission<Fs: NodeFs>( path: PathBuf, ) -> Result<PackageJson, AnyError> { assert!(path.is_absolute()); @@ -79,7 +80,7 @@ impl PackageJson { return Ok(CACHE.with(|cache| cache.borrow()[&path].clone())); } - let source = match std::fs::read_to_string(&path) { + let source = match Fs::read_to_string(&path) { Ok(source) => source, Err(err) if err.kind() == ErrorKind::NotFound => { return Ok(PackageJson::empty(path)); diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs index 950485a1d..16b1efba6 100644 --- a/ext/node/resolution.rs +++ b/ext/node/resolution.rs @@ -15,6 +15,7 @@ use regex::Regex; use crate::errors; use crate::package_json::PackageJson; use crate::path::PathClean; +use crate::NodeFs; use crate::NodePermissions; use crate::RequireNpmResolver; @@ -40,11 +41,11 @@ impl NodeResolutionMode { } /// Checks if the resolved file has a corresponding declaration file. -pub fn path_to_declaration_path( +pub fn path_to_declaration_path<Fs: NodeFs>( path: PathBuf, referrer_kind: NodeModuleKind, ) -> Option<PathBuf> { - fn probe_extensions( + fn probe_extensions<Fs: NodeFs>( path: &Path, referrer_kind: NodeModuleKind, ) -> Option<PathBuf> { @@ -52,11 +53,11 @@ pub fn path_to_declaration_path( NodeModuleKind::Cjs => with_known_extension(path, "d.cts"), NodeModuleKind::Esm => with_known_extension(path, "d.mts"), }; - if specific_dts_path.exists() { + if Fs::metadata(&specific_dts_path).is_ok() { return Some(specific_dts_path); } let dts_path = with_known_extension(path, "d.ts"); - if dts_path.exists() { + if Fs::metadata(&dts_path).is_ok() { Some(dts_path) } else { None @@ -70,11 +71,13 @@ pub fn path_to_declaration_path( { return Some(path); } - if let Some(path) = probe_extensions(&path, referrer_kind) { + if let Some(path) = probe_extensions::<Fs>(&path, referrer_kind) { return Some(path); } if path.is_dir() { - if let Some(path) = probe_extensions(&path.join("index"), referrer_kind) { + if let Some(path) = + probe_extensions::<Fs>(&path.join("index"), referrer_kind) + { return Some(path); } } @@ -182,7 +185,7 @@ fn pattern_key_compare(a: &str, b: &str) -> i32 { 0 } -pub fn package_imports_resolve( +pub fn package_imports_resolve<Fs: NodeFs>( name: &str, referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, @@ -201,13 +204,13 @@ pub fn package_imports_resolve( } let package_config = - get_package_scope_config(referrer, npm_resolver, permissions)?; + get_package_scope_config::<Fs>(referrer, npm_resolver, permissions)?; let mut package_json_path = None; if package_config.exists { package_json_path = Some(package_config.path.clone()); if let Some(imports) = &package_config.imports { if imports.contains_key(name) && !name.contains('*') { - let maybe_resolved = resolve_package_target( + let maybe_resolved = resolve_package_target::<Fs>( package_json_path.as_ref().unwrap(), imports.get(name).unwrap().to_owned(), "".to_string(), @@ -250,7 +253,7 @@ pub fn package_imports_resolve( if !best_match.is_empty() { let target = imports.get(best_match).unwrap().to_owned(); - let maybe_resolved = resolve_package_target( + let maybe_resolved = resolve_package_target::<Fs>( package_json_path.as_ref().unwrap(), target, best_match_subpath.unwrap(), @@ -315,7 +318,7 @@ fn throw_invalid_subpath( } #[allow(clippy::too_many_arguments)] -fn resolve_package_target_string( +fn resolve_package_target_string<Fs: NodeFs>( target: String, subpath: String, match_: String, @@ -354,7 +357,7 @@ fn resolve_package_target_string( }; let package_json_url = ModuleSpecifier::from_file_path(package_json_path).unwrap(); - return match package_resolve( + return match package_resolve::<Fs>( &export_target, &package_json_url, referrer_kind, @@ -425,7 +428,7 @@ fn resolve_package_target_string( } #[allow(clippy::too_many_arguments)] -fn resolve_package_target( +fn resolve_package_target<Fs: NodeFs>( package_json_path: &Path, target: Value, subpath: String, @@ -440,7 +443,7 @@ fn resolve_package_target( permissions: &mut dyn NodePermissions, ) -> Result<Option<PathBuf>, AnyError> { if let Some(target) = target.as_str() { - return resolve_package_target_string( + return resolve_package_target_string::<Fs>( target.to_string(), subpath, package_subpath, @@ -456,7 +459,7 @@ fn resolve_package_target( ) .map(|path| { if mode.is_types() { - path_to_declaration_path(path, referrer_kind) + path_to_declaration_path::<Fs>(path, referrer_kind) } else { Some(path) } @@ -468,7 +471,7 @@ fn resolve_package_target( let mut last_error = None; for target_item in target_arr { - let resolved_result = resolve_package_target( + let resolved_result = resolve_package_target::<Fs>( package_json_path, target_item.to_owned(), subpath.clone(), @@ -518,7 +521,7 @@ fn resolve_package_target( { let condition_target = target_obj.get(key).unwrap().to_owned(); - let resolved = resolve_package_target( + let resolved = resolve_package_target::<Fs>( package_json_path, condition_target, subpath.clone(), @@ -566,7 +569,7 @@ fn throw_exports_not_found( } #[allow(clippy::too_many_arguments)] -pub fn package_exports_resolve( +pub fn package_exports_resolve<Fs: NodeFs>( package_json_path: &Path, package_subpath: String, package_exports: &Map<String, Value>, @@ -582,7 +585,7 @@ pub fn package_exports_resolve( && !package_subpath.ends_with('/') { let target = package_exports.get(&package_subpath).unwrap().to_owned(); - let resolved = resolve_package_target( + let resolved = resolve_package_target::<Fs>( package_json_path, target, "".to_string(), @@ -642,7 +645,7 @@ pub fn package_exports_resolve( if !best_match.is_empty() { let target = package_exports.get(best_match).unwrap().to_owned(); - let maybe_resolved = resolve_package_target( + let maybe_resolved = resolve_package_target::<Fs>( package_json_path, target, best_match_subpath.unwrap(), @@ -725,7 +728,7 @@ fn parse_package_name( Ok((package_name, package_subpath, is_scoped)) } -pub fn package_resolve( +pub fn package_resolve<Fs: NodeFs>( specifier: &str, referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, @@ -739,12 +742,12 @@ pub fn package_resolve( // ResolveSelf let package_config = - get_package_scope_config(referrer, npm_resolver, permissions)?; + get_package_scope_config::<Fs>(referrer, npm_resolver, permissions)?; if package_config.exists && package_config.name.as_ref() == Some(&package_name) { if let Some(exports) = &package_config.exports { - return package_exports_resolve( + return package_exports_resolve::<Fs>( &package_config.path, package_subpath, exports, @@ -781,9 +784,9 @@ pub fn package_resolve( // Package match. let package_json = - PackageJson::load(npm_resolver, permissions, package_json_path)?; + PackageJson::load::<Fs>(npm_resolver, permissions, package_json_path)?; if let Some(exports) = &package_json.exports { - return package_exports_resolve( + return package_exports_resolve::<Fs>( &package_json.path, package_subpath, exports, @@ -797,21 +800,21 @@ pub fn package_resolve( .map(Some); } if package_subpath == "." { - return legacy_main_resolve(&package_json, referrer_kind, mode); + return legacy_main_resolve::<Fs>(&package_json, referrer_kind, mode); } let file_path = package_json.path.parent().unwrap().join(&package_subpath); if mode.is_types() { let maybe_declaration_path = - path_to_declaration_path(file_path, referrer_kind); + path_to_declaration_path::<Fs>(file_path, referrer_kind); Ok(maybe_declaration_path) } else { Ok(Some(file_path)) } } -pub fn get_package_scope_config( +pub fn get_package_scope_config<Fs: NodeFs>( referrer: &ModuleSpecifier, npm_resolver: &dyn RequireNpmResolver, permissions: &mut dyn NodePermissions, @@ -819,26 +822,27 @@ pub fn get_package_scope_config( let root_folder = npm_resolver .resolve_package_folder_from_path(&referrer.to_file_path().unwrap())?; let package_json_path = root_folder.join("package.json"); - PackageJson::load(npm_resolver, permissions, package_json_path) + PackageJson::load::<Fs>(npm_resolver, permissions, package_json_path) } -pub fn get_closest_package_json( +pub fn get_closest_package_json<Fs: NodeFs>( url: &ModuleSpecifier, npm_resolver: &dyn RequireNpmResolver, permissions: &mut dyn NodePermissions, ) -> Result<PackageJson, AnyError> { - let package_json_path = get_closest_package_json_path(url, npm_resolver)?; - PackageJson::load(npm_resolver, permissions, package_json_path) + let package_json_path = + get_closest_package_json_path::<Fs>(url, npm_resolver)?; + PackageJson::load::<Fs>(npm_resolver, permissions, package_json_path) } -fn get_closest_package_json_path( +fn get_closest_package_json_path<Fs: NodeFs>( url: &ModuleSpecifier, npm_resolver: &dyn RequireNpmResolver, ) -> Result<PathBuf, AnyError> { let file_path = url.to_file_path().unwrap(); let mut current_dir = file_path.parent().unwrap(); let package_json_path = current_dir.join("package.json"); - if package_json_path.exists() { + if Fs::metadata(&package_json_path).is_ok() { return Ok(package_json_path); } let root_pkg_folder = npm_resolver @@ -846,7 +850,7 @@ fn get_closest_package_json_path( while current_dir.starts_with(&root_pkg_folder) { current_dir = current_dir.parent().unwrap(); let package_json_path = current_dir.join("package.json"); - if package_json_path.exists() { + if Fs::metadata(&package_json_path).is_ok() { return Ok(package_json_path); } } @@ -854,15 +858,15 @@ fn get_closest_package_json_path( bail!("did not find package.json in {}", root_pkg_folder.display()) } -fn file_exists(path: &Path) -> bool { - if let Ok(stats) = std::fs::metadata(path) { +fn file_exists<Fs: NodeFs>(path: &Path) -> bool { + if let Ok(stats) = Fs::metadata(path) { stats.is_file() } else { false } } -pub fn legacy_main_resolve( +pub fn legacy_main_resolve<Fs: NodeFs>( package_json: &PackageJson, referrer_kind: NodeModuleKind, mode: NodeResolutionMode, @@ -875,7 +879,9 @@ pub fn legacy_main_resolve( // a corresponding declaration file if let Some(main) = package_json.main(referrer_kind) { let main = package_json.path.parent().unwrap().join(main).clean(); - if let Some(path) = path_to_declaration_path(main, referrer_kind) { + if let Some(path) = + path_to_declaration_path::<Fs>(main, referrer_kind) + { return Ok(Some(path)); } } @@ -888,7 +894,7 @@ pub fn legacy_main_resolve( if let Some(main) = maybe_main { let guess = package_json.path.parent().unwrap().join(main).clean(); - if file_exists(&guess) { + if file_exists::<Fs>(&guess) { return Ok(Some(guess)); } @@ -917,7 +923,7 @@ pub fn legacy_main_resolve( .unwrap() .join(format!("{main}{ending}")) .clean(); - if file_exists(&guess) { + if file_exists::<Fs>(&guess) { // TODO(bartlomieju): emitLegacyIndexDeprecation() return Ok(Some(guess)); } @@ -940,7 +946,7 @@ pub fn legacy_main_resolve( .unwrap() .join(index_file_name) .clean(); - if file_exists(&guess) { + if file_exists::<Fs>(&guess) { // TODO(bartlomieju): emitLegacyIndexDeprecation() return Ok(Some(guess)); } diff --git a/runtime/build.rs b/runtime/build.rs index dac6dee88..abdd0e584 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -222,6 +222,7 @@ mod startup_snapshot { impl deno_node::NodeEnv for SnapshotNodeEnv { type P = Permissions; + type Fs = deno_node::RealFs; } deno_core::extension!(runtime, diff --git a/runtime/lib.rs b/runtime/lib.rs index 57108aa7e..994e043fd 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -40,4 +40,5 @@ pub use worker_bootstrap::BootstrapOptions; pub struct RuntimeNodeEnv; impl deno_node::NodeEnv for RuntimeNodeEnv { type P = permissions::PermissionsContainer; + type Fs = deno_node::RealFs; } |