Skip to content

Fix Windows module resolution for reserved path segments - #64658

Open
Daniel Rosenwasser (DanielRosenwasser) with Copilot wants to merge 7 commits into
mainfrom
copilot/fix-module-resolution-con-path
Open

Daniel Rosenwasser (DanielRosenwasser) with Copilot wants to merge 7 commits into
mainfrom
copilot/fix-module-resolution-con-path

Conversation

Copilot AI commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Windows module resolution failed when a path contained a reserved device-name segment such as con. This prevented declarations like the following from resolving:

export * from "./con/foo.js";

Changes

  • Open Windows realpaths through the extended path namespace, preventing reserved components from being interpreted as devices.
  • Preserve drive, UNC, and existing device-path handling.
  • Add Windows regression coverage for both a con directory and a declaration file beneath it.

Copilot AI and others added 2 commits October 6, 2026 17:05
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix module resolution issue for paths containing con directory Fix Windows module resolution for reserved path segments Oct 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot address

Comment on lines +58 to +64
switch {
case len(path) >= 4 && (path[:4] == `\\?\` || path[:4] == `\\.\`):
case len(path) >= 2 && path[:2] == `\\`:
path = `\\?\UNC\` + path[2:]
default:
path = `\\?\` + path
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this allocate a ton? Find another way or a mitigation.

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>

Copilot AI commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Copilot address

Addressed in be35d25. Ordinary paths now retain the original fast paths; an allocation-free component scan gates FullPath and prefix creation to reserved-name paths only. Added explicit zero-allocation coverage for the detector.

@DanielRosenwasser

Copy link
Copy Markdown
Member

Copilot does it make sense to just try realpath and do the scan only if that doesn't work? It's extremely uncommon to have these device names.

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>

Copilot AI commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Copilot does it make sense to just try realpath and do the scan only if that doesn't work? It's extremely uncommon to have these device names.

Yes—updated in 196c2ef. The original short/long path open runs first; only a failure triggers the reserved-component scan and extended-path retry. Successful ordinary realpaths now pay no scan cost.


// Works on directories too since https://go.dev/cl/405275.
h = windows.Handle(f.Fd())
if err != nil && hasReservedPathComponent(path) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot leave a comment because this is some extremely subtle and annoying behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 03cdc4c. The comment explains the normal namespace's device-name interpretation, why the extended namespace works, and why detection is deferred until the ordinary open fails.

@DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) marked this pull request as ready for review October 8, 2026 07:19
Copilot AI balanced review requested due to automatic review settings October 8, 2026 07:19
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation addresses the reported failure with focused Windows regression coverage and no identified correctness issues.

0 open findings

What changed in this PR

Fixes Windows realpath resolution for paths containing reserved device-name segments.

Changes:

  • Retries failed realpath opens using extended Windows paths.
  • Preserves drive, UNC, and device-path handling.
  • Adds regression and reserved-name detection tests.
File Description
tsc/​internal/​nativepath/​realpath_windows.go Adds reserved-component detection and extended-path retry.
tsc/​internal/​nativepath/​realpath_windows_test.go Tests reserved directories, files, detection, and allocations.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@jakebailey

Copy link
Copy Markdown
Member

This fails linting and testing

@DanielRosenwasser

Copy link
Copy Markdown
Member

Copilot address the issues. From CI:

=== FAIL: internal/nativepath TestRealpathReservedDeviceName (0.01s)
    realpath_windows_test.go:28: assertion failed: C:\Users\runneradmin\AppData\Local\Temp\TestRealpathReservedDeviceName1201972869\001\con (got string) != C:\Users\RUNNER~1\AppData\Local\Temp\TestRealpathReservedDeviceName1201972869\001\con (path string)

=== FAIL: internal/nativepath TestHasReservedPathComponent (0.00s)
panic: testing: AllocsPerRun called during parallel test [recovered, repanicked]

goroutine 4 [running]:
testing.tRunner.func1.2({0x7ff76eac1b20, 0x7ff76e80b0c0})
	C:/hostedtoolcache/windows/go-87ee608c/1.27.1/x64/src/testing/testing.go:2123 +0x239
testing.tRunner.func1()
	C:/hostedtoolcache/windows/go-87ee608c/1.27.1/x64/src/testing/testing.go:2126 +0x329
panic({0x7ff76eac1b20?, 0x7ff76e80b0c0?})
	C:/hostedtoolcache/windows/go-87ee608c/1.27.1/x64/src/runtime/panic.go:859 +0x125
testing.AllocsPerRun(0x64?, 0x3e4a2aa19f48?)
	C:/hostedtoolcache/windows/go-87ee608c/1.27.1/x64/src/testing/allocs.go:22 +0x1a5
github.com/microsoft/TypeScript/tsc/internal/nativepath.TestHasReservedPathComponent(0x3e4a2a7f8a00)
	D:/a/TypeScript/TypeScript/tsc/internal/nativepath/realpath_windows_test.go:53 +0x25a
testing.tRunner(0x3e4a2a7f8a00, 0x7ff76eb009e8)
	C:/hostedtoolcache/windows/go-87ee608c/1.27.1/x64/src/testing/testing.go:2193 +0xc3
created by testing.(*T).Run in goroutine 1

Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>

Copilot AI commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Copilot address the issues. From CI:

Fixed the Windows short-path expectation, removed t.Parallel() from the allocation test, and adjusted cleanup to satisfy custom lint in 230869a.

@jakebailey

Copy link
Copy Markdown
Member

I don't think you can just remove Parallel without a nolint directive that says why

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: module resolution fails for paths containing a con/ directory segment (reserved device name)

4 participants