Skip to content

Commit

Permalink
feat: faster and stable path hash for the cache
Browse files Browse the repository at this point in the history
closes #322
  • Loading branch information
Boshen committed Dec 5, 2024
1 parent 7255f9b commit 660aa50
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,20 @@ impl<Fs: FileSystem> Cache<Fs> {
}

pub fn value(&self, path: &Path) -> CachedPath {
// `Path::hash` is slow: https://doc.rust-lang.org/std/path/struct.Path.html#impl-Hash-for-Path
// `path.as_os_str()` hash is not stable because we may joined a path like `foo/bar` and `foo\\bar` on windows.
let hash = {
let mut hasher = FxHasher::default();
path.as_os_str().hash(&mut hasher);
for b in path
.as_os_str()
.as_encoded_bytes()
.iter()
.rev()
.filter(|&&b| b != b'/' && b != b'\\')
.take(10)
{
b.hash(&mut hasher);
}
hasher.finish()
};
if let Some(cache_entry) = self.paths.get((hash, path).borrow() as &dyn CacheKey) {
Expand Down
21 changes: 21 additions & 0 deletions src/tests/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,24 @@ fn resolve_hash_as_module() {
let resolution = resolver.resolve(f, "#a");
assert_eq!(resolution, Err(ResolveError::NotFound("#a".into())));
}

#[cfg(windows)]
#[test]
fn resolve_normalized_on_windows() {
use std::path::PathBuf;

use normalize_path::NormalizePath;

let f = super::fixture();
let absolute = f.join("./foo/index.js").normalize();
let absolute_str = absolute.to_string_lossy();
let normalized_absolute = absolute_str.replace('\\', "/");
let resolver = Resolver::new(ResolveOptions::default());

let resolution = resolver.resolve(&f, &normalized_absolute).map(|r| r.full_path());
assert_eq!(resolution, Ok(PathBuf::from(absolute_str.as_ref())));

let normalized_f = f.to_str().unwrap().replace('\\', "/");
let resolution = resolver.resolve(normalized_f, ".\\foo\\index.js").map(|r| r.full_path());
assert_eq!(resolution, Ok(PathBuf::from(absolute_str.as_ref())));
}

0 comments on commit 660aa50

Please # to comment.