fix(node:path): win32 normalize/basename/toNamespacedPath edge cases (#1728)#1749
Merged
Conversation
…1728) path.win32 diverged from Node on several Windows path edge cases (POSIX path was already correct): - normalize(".\\") dropped the trailing separator; Node keeps it. - normalize("\\\\?\\C:\\") and bare UNC roots ("\\\\server\\share") dropped the root's trailing separator. - basename("\\\\server\\share\\") returned "" instead of the share segment. - toNamespacedPath of a UNC root lost its trailing separator (follows from the normalize fix). Rewrite normalize_win32_str as a faithful port of Node's win32.normalize assembly (device + root separator + tail), replacing the accumulated special-cases that only handled the bare-drive "C:" -> "C:." case. Rewrite win32_basename_inner to match Node: skip a leading drive letter, then take the last non-empty separator-delimited segment, so UNC server/share segments count as ordinary segments. Adds a node-suite parity fixture (byte-for-byte with Node v25) and crate unit tests for the drive-relative, trailing-separator, UNC-root, and basename cases. All previously-passing path fixtures are unchanged.
4 tasks
proggeramlug
added a commit
that referenced
this pull request
May 25, 2026
7 PRs landed on main after the v0.5.1027 bump (50c391f) without per-PR tags. Neither v0.5.1026 nor v0.5.1027 were tagged on the remote — v0.5.1028 is the first tag in this window. - #1738 feat(compile): --trace/--focus debugging flags. - #1723/#1741 fix(lockdown): #503 ns[dynamicKey].staticMember. - #1673/#1742 fix(dynamic-import): literal node: builtin specifier. - #1724/#1747 fix(node): Blob/URL globals trigger http-client feature. - #1728/#1749 fix(node:path): win32 normalize/basename/toNamespacedPath. - #1751 test(parity): stream consumers/promises/static batch. - #1754 test(node-core): enrich common shim for #800.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1728 —
path.win32.{normalize,basename,toNamespacedPath}diverged from Node on several Windows path edge cases. POSIXpathwas already correct; this is isolated towin32.normalize_win32_stris rewritten as a faithful port of Node'swin32.normalizeassembly (device + root separator + tail), replacing the special-case pile that only handled the bare-drive case.win32_basename_innernow matches Node's algorithm (skip a leading drive letter, then take the last non-empty segment — UNC server/share segments count as ordinary segments).toNamespacedPathneeded no direct change; it follows oncenormalizekeeps the UNC root's trailing separator.Cases fixed (Perry now byte-for-byte with Node v25)
win32.normalize("C:")C:(already fixed on main)C:.win32.normalize(".\\")..\win32.normalize("\\\\?\\C:\\")\\?\C:\\?\C:\win32.normalize("\\\\server\\share")\\server\share\\server\share\win32.basename("\\\\server\\share\\")sharewin32.toNamespacedPath("\\\\server\\share")\\?\UNC\server\share\\?\UNC\server\share\Root causes (from the issue): a bare drive letter is a drive-relative ref (the drive's cwd, →
C:.); a trailing separator the input carried must be preserved; andwin32.basenameof a UNC root returns the share segment.Validation
test-parity/node-suite/path/win32/drive-relative-trailing-unc.ts— diffs byte-for-byte against Node v25.0 (15/15 lines identical).path::win32_normalize_tests(drive-relative, trailing-sep, UNC root, basename) — all pass.pathnode-suite fixtures (join-normalize, basename-dirname, unc-and-drive, parse-format, relative-resolve) unchanged — no regressions.Out of scope
toNamespacedPathof a relative/driveless path (foo,/tmp/x) is cwd-dependent in Node (it resolves against cwd first); the issue flagged this as lower priority and it is not addressed here.const w = path.win32; w.normalize(...), and likewisepath.posix) segfaults — a pre-existing namespace-aliasing codegen bug, unrelated to this fix. The existingunc-and-drive-relative.tsfixture already crashes for the same reason. Filed/tracked separately.