summaryrefslogtreecommitdiff
path: root/ext/node_resolver/path.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-07-30 16:46:15 -0400
committerGitHub <noreply@github.com>2024-07-30 16:46:15 -0400
commitfe884c557a76fd288f7457aa433052f65be70c81 (patch)
tree2e1c114eb128ce1baa1d7c8dc145423b8de86af7 /ext/node_resolver/path.rs
parent7a3810195de532bf360afcbf85a0d9cf6ef662be (diff)
fix(compile/windows): handle cjs re-export of relative path with parent component (#24795)
Closes https://github.com/denoland/deno/issues/24785
Diffstat (limited to 'ext/node_resolver/path.rs')
-rw-r--r--ext/node_resolver/path.rs39
1 files changed, 38 insertions, 1 deletions
diff --git a/ext/node_resolver/path.rs b/ext/node_resolver/path.rs
index 8c33285db..ece270cd9 100644
--- a/ext/node_resolver/path.rs
+++ b/ext/node_resolver/path.rs
@@ -13,8 +13,31 @@ pub trait PathClean<T> {
impl PathClean<PathBuf> for PathBuf {
fn clean(&self) -> PathBuf {
+ fn is_clean_path(path: &Path) -> bool {
+ let path = path.to_string_lossy();
+ let mut current_index = 0;
+ while let Some(index) = path[current_index..].find("\\.") {
+ let trailing_index = index + current_index + 2;
+ let mut trailing_chars = path[trailing_index..].chars();
+ match trailing_chars.next() {
+ Some('.') => match trailing_chars.next() {
+ Some('/') | Some('\\') | None => {
+ return false;
+ }
+ _ => {}
+ },
+ Some('/') | Some('\\') => {
+ return false;
+ }
+ _ => {}
+ }
+ current_index = trailing_index;
+ }
+ true
+ }
+
let path = path_clean::PathClean::clean(self);
- if cfg!(windows) && path.to_string_lossy().contains("..\\") {
+ if cfg!(windows) && !is_clean_path(&path) {
// temporary workaround because path_clean::PathClean::clean is
// not good enough on windows
let mut components = Vec::new();
@@ -105,6 +128,20 @@ pub fn strip_unc_prefix(path: PathBuf) -> PathBuf {
mod test {
#[cfg(windows)]
#[test]
+ fn test_path_clean() {
+ use super::*;
+
+ run_test("C:\\test\\./file.txt", "C:\\test\\file.txt");
+ run_test("C:\\test\\../other/file.txt", "C:\\other\\file.txt");
+ run_test("C:\\test\\../other\\file.txt", "C:\\other\\file.txt");
+
+ fn run_test(input: &str, expected: &str) {
+ assert_eq!(PathBuf::from(input).clean(), PathBuf::from(expected));
+ }
+ }
+
+ #[cfg(windows)]
+ #[test]
fn test_strip_unc_prefix() {
use std::path::PathBuf;