Skip to content

Commit 2a8dcea

Browse files
committed
fix
1 parent 518e5df commit 2a8dcea

File tree

4 files changed

+42
-53
lines changed

4 files changed

+42
-53
lines changed

src/error.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ pub enum ResolveError {
4141
#[error("{0}")]
4242
IOError(IOError),
4343

44-
/// For example, Windows UNC path with Volume GUID is not supported.
45-
#[error("Path {0:?} contains unsupported construct.")]
46-
PathNotSupported(PathBuf),
47-
4844
/// Node.js builtin module when `Options::builtin_modules` is enabled.
4945
///
5046
/// `is_runtime_module` can be used to determine whether the request

src/file_system.rs

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::{
33
path::{Path, PathBuf},
44
};
55

6+
use crate::path::dunce;
7+
68
use cfg_if::cfg_if;
79
#[cfg(feature = "yarn_pnp")]
810
use pnp::fs::{LruZipCache, VPath, VPathInfo, ZipCache};
@@ -155,28 +157,11 @@ impl FileSystemOs {
155157
/// See [std::fs::read_link]
156158
#[inline]
157159
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
158-
fs::read_link(path).map(adjust_canonicalization)
160+
let path = fs::read_link(path)?;
161+
Ok(dunce(path))
159162
}
160163
}
161164

162-
#[cfg(not(target_os = "windows"))]
163-
#[inline]
164-
fn adjust_canonicalization(p: PathBuf) -> PathBuf {
165-
p
166-
}
167-
168-
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
169-
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
170-
/// i.e. Remove `\\?\`, `\\.\` prefix then `\\?\UNC` prefix.
171-
/// Code adapted from <https://stackoverflow.com/questions/50322817/how-do-i-remove-the-prefix-from-a-canonical-windows-path>
172-
#[cfg(target_os = "windows")]
173-
#[inline]
174-
fn adjust_canonicalization(p: PathBuf) -> PathBuf {
175-
let p = p.strip_prefix(r#"\\?\"#).map(|p| p.to_path_buf()).unwrap_or(p);
176-
let p = p.strip_prefix(r#"\\.\"#).map(|p| p.to_path_buf()).unwrap_or(p);
177-
dunce::simplified(&p).to_path_buf()
178-
}
179-
180165
impl FileSystem for FileSystemOs {
181166
fn read_to_string(&self, path: &Path) -> io::Result<String> {
182167
cfg_if! {
@@ -240,21 +225,3 @@ fn metadata() {
240225
);
241226
let _ = meta;
242227
}
243-
244-
#[cfg(target_os = "windows")]
245-
#[test]
246-
fn test_strip_windows_prefix() {
247-
let cases = [
248-
(r"\\?\C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
249-
(r"\\.\C:\Users\user\Documents\file2.txt", r"C:\Users\user\Documents\file2.txt"),
250-
(r"\\?\UNC\server\share\file3.txt", r"\\server\share\file3.txt"),
251-
(
252-
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file4.txt",
253-
r"\\?\BootPartition\file4.txt",
254-
),
255-
];
256-
257-
for (path, expected) in cases {
258-
assert_eq!(adjust_canonicalization(PathBuf::from(path)), PathBuf::from(expected));
259-
}
260-
}

src/fs_cache.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
TsConfigSerde,
2323
cache::{Cache, CachedPath},
2424
context::ResolveContext as Ctx,
25-
path::PathUtil,
25+
path::{PathUtil, dunce},
2626
};
2727

2828
static THREAD_COUNT: AtomicU64 = AtomicU64::new(1);
@@ -77,17 +77,7 @@ impl<Fs: FileSystem> Cache for FsCache<Fs> {
7777

7878
fn canonicalize(&self, path: &Self::Cp) -> Result<PathBuf, ResolveError> {
7979
let cached_path = self.canonicalize_impl(path)?;
80-
let path = cached_path.to_path_buf();
81-
cfg_if! {
82-
if #[cfg(windows)] {
83-
match crate::FileSystemOs::try_strip_windows_prefix(&path) {
84-
Some(path) => Ok(path),
85-
None => Err(ResolveError::PathNotSupported(path)),
86-
}
87-
} else {
88-
Ok(path)
89-
}
90-
}
80+
Ok(dunce(cached_path.to_path_buf()))
9181
}
9282

9383
fn is_file(&self, path: &Self::Cp, ctx: &mut Ctx) -> bool {

src/path.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,24 @@ impl PathUtil for Path {
100100
}
101101
}
102102

103+
#[cfg(not(target_os = "windows"))]
104+
#[inline]
105+
pub fn dunce(p: PathBuf) -> PathBuf {
106+
p
107+
}
108+
109+
/// When applicable, converts a [DOS device path](https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths)
110+
/// to a normal path (usually, "Traditional DOS paths" or "UNC path") that can be consumed by the `import`/`require` syntax of Node.js.
111+
/// i.e. Remove `\\?\`, `\\.\` prefix then `\\?\UNC` prefix.
112+
/// Code adapted from <https://stackoverflow.com/questions/50322817/how-do-i-remove-the-prefix-from-a-canonical-windows-path>
113+
#[cfg(target_os = "windows")]
114+
#[inline]
115+
pub fn dunce(p: PathBuf) -> PathBuf {
116+
let p = p.strip_prefix(r#"\\?\"#).map(|p| p.to_path_buf()).unwrap_or(p);
117+
let p = p.strip_prefix(r#"\\.\"#).map(|p| p.to_path_buf()).unwrap_or(p);
118+
dunce::simplified(&p).to_path_buf()
119+
}
120+
103121
// https://github.com/webpack/enhanced-resolve/blob/main/test/path.test.js
104122
#[test]
105123
fn is_invalid_exports_target() {
@@ -130,3 +148,21 @@ fn normalize() {
130148
assert_eq!(Path::new("C:").normalize(), Path::new("C:"));
131149
assert_eq!(Path::new(r"\\server\share").normalize(), Path::new(r"\\server\share"));
132150
}
151+
152+
#[cfg(target_os = "windows")]
153+
#[test]
154+
fn dunce() {
155+
let cases = [
156+
(r"\\?\C:\Users\user\Documents\file1.txt", r"C:\Users\user\Documents\file1.txt"),
157+
(r"\\.\C:\Users\user\Documents\file2.txt", r"C:\Users\user\Documents\file2.txt"),
158+
(r"\\?\UNC\server\share\file3.txt", r"\\server\share\file3.txt"),
159+
(
160+
r"\\?\Volume{c8ec34d8-3ba6-45c3-9b9d-3e4148e12d00}\file4.txt",
161+
r"\\?\BootPartition\file4.txt",
162+
),
163+
];
164+
165+
for (path, expected) in cases {
166+
assert_eq!(dunce(PathBuf::from(path)), PathBuf::from(expected));
167+
}
168+
}

0 commit comments

Comments
 (0)