summaryrefslogtreecommitdiff
path: root/core/module_specifier.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-07-16 10:53:07 +0200
committerGitHub <noreply@github.com>2020-07-16 10:53:07 +0200
commit98e0ed54db5bbd8befcb5afbb1d63f2b80677f51 (patch)
tree7f8ab9b27a75840ed08ea6d4c33576f1886b3c6d /core/module_specifier.rs
parentb0f2bd4a2d1a75d7c8e4643a4b5b9478c1935668 (diff)
fix: ModuleSpecifier removes relative path parts (#6762)
Diffstat (limited to 'core/module_specifier.rs')
-rw-r--r--core/module_specifier.rs67
1 files changed, 65 insertions, 2 deletions
diff --git a/core/module_specifier.rs b/core/module_specifier.rs
index 9cf449302..1ad4bcc93 100644
--- a/core/module_specifier.rs
+++ b/core/module_specifier.rs
@@ -1,6 +1,8 @@
use std::env::current_dir;
use std::error::Error;
use std::fmt;
+use std::path::Component;
+use std::path::Path;
use std::path::PathBuf;
use url::ParseError;
use url::Url;
@@ -150,6 +152,7 @@ impl ModuleSpecifier {
path_str: &str,
) -> Result<ModuleSpecifier, ModuleResolutionError> {
let path = current_dir().unwrap().join(path_str);
+ let path = normalize_path(&path);
Url::from_file_path(path.clone())
.map(ModuleSpecifier)
.map_err(|()| ModuleResolutionError::InvalidPath(path))
@@ -203,6 +206,39 @@ impl PartialEq<String> for ModuleSpecifier {
}
}
+/// Normalize all itermediate components of the path (ie. remove "./" and "../" components).
+/// Similar to `fs::canonicalize()` but doesn't resolve symlinks.
+///
+/// Taken from Cargo
+/// https://github.com/rust-lang/cargo/blob/af307a38c20a753ec60f0ad18be5abed3db3c9ac/src/cargo/util/paths.rs#L60-L85
+pub fn normalize_path(path: &Path) -> PathBuf {
+ let mut components = path.components().peekable();
+ let mut ret =
+ if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
+ components.next();
+ PathBuf::from(c.as_os_str())
+ } else {
+ PathBuf::new()
+ };
+
+ for component in components {
+ match component {
+ Component::Prefix(..) => unreachable!(),
+ Component::RootDir => {
+ ret.push(component.as_os_str());
+ }
+ Component::CurDir => {}
+ Component::ParentDir => {
+ ret.pop();
+ }
+ Component::Normal(c) => {
+ ret.push(c);
+ }
+ }
+ }
+ ret
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -415,7 +451,12 @@ mod tests {
);
tests.extend(vec![
(r"/deno/tests/006_url_imports.ts", expected_url.to_string()),
- (r"\deno\tests\006_url_imports.ts", expected_url),
+ (r"\deno\tests\006_url_imports.ts", expected_url.to_string()),
+ (
+ r"\deno\..\deno\tests\006_url_imports.ts",
+ expected_url.to_string(),
+ ),
+ (r"\deno\.\tests\006_url_imports.ts", expected_url),
]);
// Relative local path.
@@ -450,7 +491,12 @@ mod tests {
let expected_url = format!("file://{}/tests/006_url_imports.ts", cwd_str);
tests.extend(vec![
("tests/006_url_imports.ts", expected_url.to_string()),
- ("./tests/006_url_imports.ts", expected_url),
+ ("./tests/006_url_imports.ts", expected_url.to_string()),
+ (
+ "tests/../tests/006_url_imports.ts",
+ expected_url.to_string(),
+ ),
+ ("tests/./006_url_imports.ts", expected_url),
]);
}
@@ -511,4 +557,21 @@ mod tests {
assert_eq!(result, expected);
}
}
+
+ #[test]
+ fn test_normalize_path() {
+ assert_eq!(normalize_path(Path::new("a/../b")), PathBuf::from("b"));
+ assert_eq!(normalize_path(Path::new("a/./b/")), PathBuf::from("a/b/"));
+ assert_eq!(
+ normalize_path(Path::new("a/./b/../c")),
+ PathBuf::from("a/c")
+ );
+
+ if cfg!(windows) {
+ assert_eq!(
+ normalize_path(Path::new("C:\\a\\.\\b\\..\\c")),
+ PathBuf::from("C:\\a\\c")
+ );
+ }
+ }
}