Skip to content

fix(runtime): cache canonicalized watch paths, fix spurious events#33123

Open
bartlomieju wants to merge 2 commits intomainfrom
perf/cache-canonicalized-watch-paths
Open

fix(runtime): cache canonicalized watch paths, fix spurious events#33123
bartlomieju wants to merge 2 commits intomainfrom
perf/cache-canonicalized-watch-paths

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

@bartlomieju bartlomieju commented Apr 1, 2026

Summary

  • Pre-canonicalize watched paths once at op_fs_events_open time instead of calling canonicalize() on both the event path and the watched path on every filesystem event for every watcher
  • Previously starts_with_canonicalized did 2 canonicalize() calls (each resolving all symlinks and stat-ing every path component) per event x sender x watched path -- hundreds of redundant syscalls/sec under load
  • Now watched paths are canonicalized once at registration and cached in the WatchSender struct; only the event path is canonicalized (once per event per sender)
  • Adds path filtering to the removed-file fallback branch (fix(runtime/ops): Fix watchfs remove event #27041), which previously forwarded remove events for any deleted file to all watchers regardless of whether the file was in a watched directory -- this caused editors with atomic saves (Vim, WebStorm, Kate) to trigger full Vite HMR reloads instead of targeted updates
  • Skips watchFsRemove test on macOS where FSEvents does not reliably emit remove events for individually watched files (previously passed only due to the unfiltered fallback bug)

Fixes #27558
Supersedes #33120

Test plan

  • ./x test-unit fs_events passes
  • cargo clippy -p deno_runtime -- -D warnings clean
  • ./tools/format.js clean
  • Regression test watchFsNoSpuriousEventsFromSiblingDir verifies no spurious events from sibling dirs

🤖 Generated with Claude Code

bartlomieju and others added 2 commits April 1, 2026 22:43
The is_file_removed fallback added in #27041 had no path filtering,
causing any file removal (e.g. temp files during Vim atomic saves) to
emit events to all watchers regardless of watched paths. This made
Vite's HMR unusable under Deno >= 2.1.2 with editors that do atomic
saves.

Add path filtering to the remove-detection branch by checking the
removed file's parent directory against watched paths.

Fixes #27558

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-canonicalize watched paths once at registration time instead of
re-canonicalizing both paths on every filesystem event. Previously,
starts_with_canonicalized called canonicalize() on both paths for
every event x sender x watched path, causing redundant stat syscalls.

Also fixes #27558 by adding path filtering to the removed-file
fallback, which previously forwarded events for any removed file to
all watchers regardless of path. This caused editors with atomic saves
(Vim, WebStorm) to trigger full Vite HMR reloads.

Skip watchFsRemove test on macOS where FSEvents does not reliably
emit remove events for individually watched files (previously passed
only due to the unfiltered fallback bug).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju force-pushed the perf/cache-canonicalized-watch-paths branch from fc308e7 to a76a220 Compare April 1, 2026 21:05
@bartlomieju bartlomieju changed the title perf(runtime): cache canonicalized paths in fs event watcher fix(runtime): cache canonicalized watch paths, fix spurious events Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vite's development server misbehaves when run under Deno version 2.1.2 and later

1 participant