Conversation
…ckWatcher Summary: On Windows, libuv reports a change with no filename when changes to a watched directory overflow the 4KB buffer they're read into ([`fs-event.c`](https://github.com/libuv/libuv/blob/9be264a4efa515dcb6ced36267dac7a03f308be3/src/win/fs-event.c#L460-L592)). That's easy to hit when a package manager writes a new package into `node_modules`, and when it happens we have no idea which entries changed, or how many. `FallbackWatcher` handled these with `sane`'s `#detectChangedFile` heuristic: `lstat` every file registered in the directory and report either the first one that's missing or the most recently modified one. So at most one change was reported, any others were missed until restart, and for a directory with no registered files yet (like a newly created package directory) the event was dropped entirely. This diff replaces that heuristic. On an unnamed change, `FallbackWatcher` lists the directory to watch and register anything new, so later changes under it are reported, then emits a `recrawl` event for it. `FileMap` already handles `recrawl` (`NativeWatcher` emits it for directory renames) by crawling that subtree and applying the difference, so additions, modifications and deletions are all picked up. `recrawl` goes through the usual debounce, so a burst of overflows costs one crawl. Follows expo/expo#49363, which lists a new directory on an unnamed change in Expo's fork of `metro-file-map`. That covers the new-directory case only. Changelog: ``` - **[Fix]**: Fix the fallback (Linux/Windows) watcher missing changes when Windows overflows its change buffer for a directory ``` Test plan: Two new tests in `FallbackWatcher-test.js` call the `fs.watch` listener for a directory with no filename, as libuv does on overflow, with that directory's (and the root's) real events withheld. On `main` neither the `recrawl` nor the watch on a new subdirectory happens; both pass with this diff. Run on macOS only - I haven't reproduced a real overflow on Windows. ``` yarn jest packages/metro-file-map yarn flow check yarn eslint packages/metro-file-map/src/watchers ```
robhogan
added this pull request to stack #1969
September 24, 2026 17:30
robhogan
removed this pull request from stack #1969
September 24, 2026 17:31
Collaborator
Author
|
Folded into #1967. |
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:
On Windows, libuv reports a change with no filename when changes to a watched directory overflow the 4KB buffer they're read into (
fs-event.c). That's easy to hit when a package manager writes a new package intonode_modules, and when it happens we have no idea which entries changed, or how many.FallbackWatcherhandled these withsane's#detectChangedFileheuristic:lstatevery file registered in the directory and report either the first one that's missing or the most recently modified one. So at most one change was reported, any others were missed until restart, and for a directory with no registered files yet (like a newly created package directory) the event was dropped entirely.This diff replaces that heuristic. On an unnamed change,
FallbackWatcherlists the directory to watch and register anything new, so later changes under it are reported, then emits arecrawlevent for it.FileMapalready handlesrecrawl(NativeWatcheremits it for directory renames) by crawling that subtree and applying the difference, so additions, modifications and deletions are all picked up.recrawlgoes through the usual debounce, so a burst of overflows costs one crawl.Follows expo/expo#49363, which lists a new directory on an unnamed change in Expo's fork of
metro-file-map. That covers the new-directory case only.Changelog:
Test plan:
Two new tests in
FallbackWatcher-test.jscall thefs.watchlistener for a directory with no filename, as libuv does on overflow, with that directory's (and the root's) real events withheld. Onmainneither therecrawlnor the watch on a new subdirectory happens; both pass with this diff. Run on macOS only - I haven't reproduced a real overflow on Windows.