Fix FSEvents routing for differently cased watch paths - #64191
Draft
Jake Bailey (jakebailey) wants to merge 3 commits into
Draft
Fix FSEvents routing for differently cased watch paths#64191Jake Bailey (jakebailey) wants to merge 3 commits into
Jake Bailey (jakebailey) wants to merge 3 commits into
Conversation
Use the watched volume's case sensitivity when routing FSEvents and filtering file watches. Preserve caller-visible root casing, including shared callbacks, overflow matching, and root deletion handling.
Skip shared path prefixes eight bytes at a time and handle ASCII case
folding without component splitting. Retain the Unicode fallback for
case-equivalent paths with different UTF-8 lengths.
Reuse the parent directory's comparer for WatchFile instead of querying
filesystem case sensitivity twice. Add routing benchmarks and expand
boundary and Unicode alignment coverage.
Compare against the initial casing fix on Apple M1. Allocations are
unchanged: zero for exact matches and rejections, and one for rebasing
a differently cased event path.
goos: darwin
goarch: arm64
pkg: github.com/microsoft/TypeScript/tsc/internal/fswatch
cpu: Apple M1
│ before │ after │
│ sec/op │ sec/op vs base │
FSEventsDisplayPath/exact-match-8 9.031n ± ∞ ¹ 8.958n ± ∞ ¹ ~ (p=0.548 n=5)
FSEventsDisplayPath/case-mismatch-8 130.50n ± ∞ ¹ 80.89n ± ∞ ¹ -38.02% (p=0.008 n=5)
FSEventsDisplayPath/sibling-miss-8 103.20n ± ∞ ¹ 14.26n ± ∞ ¹ -86.18% (p=0.008 n=5)
FSEventsDisplayPath/unrelated-miss-8 26.120n ± ∞ ¹ 6.676n ± ∞ ¹ -74.44% (p=0.008 n=5)
FSEventsDisplayPath/unicode-match-8 115.30n ± ∞ ¹ 74.29n ± ∞ ¹ -35.57% (p=0.008 n=5)
FSEventsDisplayPath/unicode-length-match-8 98.83n ± ∞ ¹ 52.34n ± ∞ ¹ -47.04% (p=0.008 n=5)
FSEventsRoutingFanout/100-8 10.799µ ± ∞ ¹ 1.634µ ± ∞ ¹ -84.87% (p=0.008 n=5)
FSEventsRoutingFanout/1000-8 109.21µ ± ∞ ¹ 15.10µ ± ∞ ¹ -86.18% (p=0.008 n=5)
geomean 284.3n 94.97n -66.60%
¹ need >= 6 samples for confidence interval at level 0.95
Use CoreFoundation case folding and NFC normalization for non-ASCII comparisons on case-insensitive Darwin watches. Recognize expanding aliases such as sharp s and SS without merging distinct dotted-I, dotless-I, circled-letter, or fullwidth spellings. Preserve the ASCII fast path, prepare watch-root comparison forms, and share lazy event folding across routing and callback filtering. Rebase using original path boundaries rather than folded byte lengths. Cover file and directory watches, shared callbacks, symlinks, overflow, and root termination with filesystem regressions and routing benchmarks. Keep fswatch isolated and leave Windows and case-sensitive behavior unchanged.
Copilot started reviewing on behalf of
Jake Bailey (jakebailey)
September 7, 2026 18:38
View session
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Darwin-specific filesystem semantics, Unicode folding, and assembly-backed CoreFoundation integration warrant final human validation.
Pull request overview
Fixes FSEvents event routing when requested path casing differs from disk casing.
Changes:
- Adds volume-aware, Unicode-capable path comparison.
- Applies case-aware routing to directory, file, overflow, and deletion events.
- Adds macOS integration tests, unit tests, benchmarks, and documentation.
File summaries
| File | Description |
|---|---|
tsc/internal/fswatch/watcher.go |
Integrates comparers into watch sharing and callback routing. |
tsc/internal/fswatch/watcher_test.go |
Updates file callback tests. |
tsc/internal/fswatch/README.md |
Documents FSEvents casing behavior. |
tsc/internal/fswatch/pathcompare.go |
Implements path comparison, folding, and rebasing. |
tsc/internal/fswatch/pathcompare_test.go |
Tests comparison and file filtering. |
tsc/internal/fswatch/fsevents_darwin.go |
Adds case-aware FSEvents routing. |
tsc/internal/fswatch/fsevents_darwin_fold_test.go |
Tests Unicode folding and aliases. |
tsc/internal/fswatch/fsevents_darwin_ffi.s |
Adds the CoreFoundation folding trampoline. |
tsc/internal/fswatch/fsevents_darwin_ffi.go |
Implements native CoreFoundation path folding. |
tsc/internal/fswatch/fsevents_darwin_case_test.go |
Tests casing differences on macOS filesystems. |
tsc/internal/fswatch/fsevents_darwin_bench_test.go |
Benchmarks routing and folding fan-out. |
tsc/internal/fswatch/CHANGES.md |
Records the behavior change. |
tsc/internal/fswatch/canonicalize_other.go |
Provides non-Darwin comparer behavior. |
tsc/internal/fswatch/canonicalize_darwin.go |
Detects per-volume case sensitivity. |
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
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.
Fixes #64089