Skip to content

metro-file-map: Recrawl a directory after an unnamed change in FallbackWatcher - #1968

Closed
robhogan wants to merge 1 commit into
pr1967from
pr1968
Closed

robhogan wants to merge 1 commit into
pr1967from
pr1968

Conversation

@robhogan

Copy link
Copy Markdown
Collaborator

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 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

…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
robhogan added this pull request to stack #1969 September 24, 2026 17:30
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 24, 2026
@robhogan
robhogan removed this pull request from stack #1969 September 24, 2026 17:31
@robhogan

Copy link
Copy Markdown
Collaborator Author

Folded into #1967.

@robhogan robhogan closed this Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant