Skip to content

Commit

Permalink
fix: don't panic when resolving / with roots (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Nov 18, 2024
1 parent 57fcd6e commit b7f78c3
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
Empty file.
25 changes: 19 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
return Ok(path);
}
}
if let Some(path) = self.load_roots(specifier, ctx) {
if let Some(path) = self.load_roots(cached_path, specifier, ctx) {
return Ok(path);
}
// 2. If X begins with '/'
Expand Down Expand Up @@ -1086,15 +1086,28 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
/// defaults to context configuration option.
///
/// On non-Windows systems these requests are resolved as an absolute path first.
fn load_roots(&self, specifier: &str, ctx: &mut Ctx) -> Option<CachedPath> {
fn load_roots(
&self,
cached_path: &CachedPath,
specifier: &str,
ctx: &mut Ctx,
) -> Option<CachedPath> {
if self.options.roots.is_empty() {
return None;
}
if let Some(specifier) = specifier.strip_prefix(SLASH_START) {
for root in &self.options.roots {
let cached_path = self.cache.value(root);
if let Ok(path) = self.require_relative(&cached_path, specifier, ctx) {
return Some(path);
if specifier.is_empty() {
if self.options.roots.iter().any(|root| root.as_path() == cached_path.path()) {
if let Ok(path) = self.require_relative(cached_path, "./", ctx) {
return Some(path);
}
}
} else {
for root in &self.options.roots {
let cached_path = self.cache.value(root);
if let Ok(path) = self.require_relative(&cached_path, specifier, ctx) {
return Some(path);
}
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions src/tests/roots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,34 @@ fn roots_fall_through() {
Ok(absolute_path)
);
}

#[test]
fn should_resolve_slash() {
let f = super::fixture();
let dir_with_index = super::fixture_root().join("./misc/dir-with-index");

#[rustfmt::skip]
let pass = [
("should resolve if importer is root", vec![dir_with_index.clone()], &dir_with_index, dir_with_index.join("index.js")),
];

for (comment, roots, directory, expected) in pass {
let resolver =
Resolver::new(ResolveOptions { roots: roots.clone(), ..ResolveOptions::default() });
let resolved_path = resolver.resolve(directory, "/").map(|r| r.full_path());
assert_eq!(resolved_path, Ok(expected), "{comment} {roots:?}");
}

#[rustfmt::skip]
let fail = [
("should not resolve if not found", vec![f.clone()], &f),
("should not resolve if importer is not root", vec![dir_with_index], &f)
];

for (comment, roots, directory) in fail {
let resolver =
Resolver::new(ResolveOptions { roots: roots.clone(), ..ResolveOptions::default() });
let resolution = resolver.resolve(directory, "/");
assert_eq!(resolution, Err(ResolveError::NotFound("/".into())), "{comment} {roots:?}");
}
}

0 comments on commit b7f78c3

Please # to comment.