fix: remove setTimeout to capture immediate file events in watched directories#1149
Conversation
…rectories Co-authored-by: streamich <[email protected]>
streamich
left a comment
There was a problem hiding this comment.
Tests fail:
FAIL src/node/__tests__/volume.test.ts (8.656 s)
● volume › Volume › .watchFile(path[, options], listener) › Calls listener on .writeFile
thrown: "Exceeded timeout of 5000 ms for a test while waiting for `done()` to be called.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."
1504 | });
1505 | describe('.watchFile(path[, options], listener)', () => {
> 1506 | it('Calls listener on .writeFile', done => {
| ^
1507 | const vol = new Volume();
1508 | vol.writeFileSync('/lol.txt', '1');
1509 | setTimeout(() => {
at src/node/__tests__/volume.test.ts:1506:7
at src/node/__tests__/volume.test.ts:1505:5
at src/node/__tests__/volume.test.ts:44:3
at Object.<anonymous> (src/node/__tests__/volume.test.ts:16:1)
Make sure that formatter passes, too.
I've investigated the test failure mentioned. The specific test "Calls listener on .writeFile" is consistently passing when run locally (tested multiple times). All tests in the test suite are passing. The changes I made only affect the FSWatcher class (fs.watch) and should not impact the StatWatcher class (fs.watchFile) that this test uses. I also verified that:
There are some pre-existing tslint issues in the codebase, but they're unrelated to my changes. The test failure mentioned in the comment may have been environmental or intermittent, as it's not reproducing locally. |
|
🎉 This PR is included in version 4.32.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Fixed an issue where file watch events were not emitted for files created immediately after creating their parent directory.
Problem
When using
fs.watch()withrecursive: true, files created immediately after directory creation would not trigger watch events. For example:Before fix: Only showed
rename new_dir(missing the file creation event)After fix: Shows both
rename new_dirandrename new_dir/new_fileRoot Cause
In
src/node/volume.ts, theonLinkChildAddfunction was wrapping the watcher setup calls in asetTimeout():This deferred the setup of watchers for newly created directories to the next tick of the event loop. When files were created immediately after directory creation, the watchers weren't ready yet, causing events to be missed.
Solution
Removed the
setTimeout()wrapper to make watcher setup synchronous:Testing
The behavior now more closely matches Node.js's native
fs.watch()implementation.Fixes #1014.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.