From c0d06c55980ed3dbe7c26d466f267acc8f5b6326 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 23 Jul 2023 18:10:06 +0800 Subject: [PATCH] feat(resolver): check for directory before loading a directory (#590) --- crates/oxc_resolver/src/cache.rs | 17 ++++++++++++++++- crates/oxc_resolver/src/file_system.rs | 13 ++++++++++--- crates/oxc_resolver/src/lib.rs | 6 ++++-- crates/oxc_resolver/tests/memory_fs.rs | 3 ++- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/oxc_resolver/src/cache.rs b/crates/oxc_resolver/src/cache.rs index c92252a6a..72ba43887 100644 --- a/crates/oxc_resolver/src/cache.rs +++ b/crates/oxc_resolver/src/cache.rs @@ -26,9 +26,16 @@ impl Cache { } pub fn is_file(&self, path: &Path) -> bool { - self.cache_value(path).meta(&self.fs).is_some_and(|m| m.is_file) + self.cache_value(path).is_file(&self.fs) } + pub fn is_dir(&self, path: &Path) -> bool { + self.cache_value(path).is_dir(&self.fs) + } + + /// # Panics + /// + /// * Path is file but does not have a parent pub fn dirname(&self, path: &Path) -> PathBuf { (if self.is_file(path) { path.parent().unwrap() } else { path }).to_path_buf() } @@ -97,6 +104,14 @@ impl CacheValue { *self.meta.get_or_init(|| fs.metadata(&self.path).ok()) } + fn is_file(&self, fs: &Fs) -> bool { + self.meta(fs).is_some_and(|meta| meta.is_file) + } + + fn is_dir(&self, fs: &Fs) -> bool { + self.meta(fs).is_some_and(|meta| meta.is_dir) + } + fn symlink(&self, fs: &Fs) -> Option { self.symlink.get_or_init(|| fs.canonicalize(&self.path).ok()).clone() } diff --git a/crates/oxc_resolver/src/file_system.rs b/crates/oxc_resolver/src/file_system.rs index bddcdd134..42abd81ff 100644 --- a/crates/oxc_resolver/src/file_system.rs +++ b/crates/oxc_resolver/src/file_system.rs @@ -37,11 +37,18 @@ pub trait FileSystem: Default + Send + Sync { #[derive(Debug, Clone, Copy)] pub struct FileMetadata { pub(crate) is_file: bool, + pub(crate) is_dir: bool, } impl FileMetadata { - pub fn new(is_file: bool) -> Self { - Self { is_file } + pub fn new(is_file: bool, is_dir: bool) -> Self { + Self { is_file, is_dir } + } +} + +impl From for FileMetadata { + fn from(metadata: fs::Metadata) -> Self { + Self::new(metadata.is_file(), metadata.is_dir()) } } @@ -55,7 +62,7 @@ impl FileSystem for FileSystemOs { } fn metadata>(&self, path: P) -> io::Result { - fs::metadata(path).map(|metadata| FileMetadata { is_file: metadata.is_file() }) + fs::metadata(path).map(FileMetadata::from) } fn canonicalize>(&self, path: P) -> io::Result { diff --git a/crates/oxc_resolver/src/lib.rs b/crates/oxc_resolver/src/lib.rs index a039c13aa..834e9fd51 100644 --- a/crates/oxc_resolver/src/lib.rs +++ b/crates/oxc_resolver/src/lib.rs @@ -268,8 +268,10 @@ impl ResolverGeneric { } } // c. LOAD_AS_DIRECTORY(DIR/X) - if let Some(path) = self.load_as_directory(&node_module_file)? { - return Ok(Some(path)); + if self.cache.is_dir(&node_module_file) { + if let Some(path) = self.load_as_directory(&node_module_file)? { + return Ok(Some(path)); + } } } Ok(None) diff --git a/crates/oxc_resolver/tests/memory_fs.rs b/crates/oxc_resolver/tests/memory_fs.rs index 8fe6f9ac4..eeb924fb5 100644 --- a/crates/oxc_resolver/tests/memory_fs.rs +++ b/crates/oxc_resolver/tests/memory_fs.rs @@ -58,7 +58,8 @@ impl FileSystem for MemoryFS { .metadata(path.as_ref().to_string_lossy().as_ref()) .map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?; let is_file = metadata.file_type == vfs::VfsFileType::File; - Ok(FileMetadata::new(is_file)) + let is_dir = metadata.file_type == vfs::VfsFileType::Directory; + Ok(FileMetadata::new(is_file, is_dir)) } fn canonicalize>(&self, path: P) -> io::Result {