diff --git a/lib/internal/fs/recursive_watch.js b/lib/internal/fs/recursive_watch.js index 2f71aeda9f79..559399e9767e 100644 --- a/lib/internal/fs/recursive_watch.js +++ b/lib/internal/fs/recursive_watch.js @@ -234,8 +234,9 @@ class FSWatcher extends EventEmitter { this.#watchFolder(filename); } } catch (error) { - if (!this.#options.throwIfNoEntry && error.code === 'ENOENT') { + if (this.#options.throwIfNoEntry || error.code !== 'ENOENT') { error.filename = filename; + this.close(); throw error; } } diff --git a/test/parallel/test-fs-watch-enoent.js b/test/parallel/test-fs-watch-enoent.js index e363b3e9325c..39c2a14b0713 100644 --- a/test/parallel/test-fs-watch-enoent.js +++ b/test/parallel/test-fs-watch-enoent.js @@ -17,6 +17,8 @@ const { UV_ENODEV, UV_ENOENT } = internalBinding('uv'); +const { FSWatcher: RecursiveFSWatcher } = require('internal/fs/recursive_watch'); +const { kFSWatchStart } = require('internal/fs/watchers'); tmpdir.refresh(); @@ -66,6 +68,61 @@ tmpdir.refresh(); } } +{ + assert.throws( + () => fs.watch(nonexistentFile, { + recursive: true, + throwIfNoEntry: true, + }, common.mustNotCall()), + { + path: nonexistentFile, + filename: nonexistentFile, + code: 'ENOENT', + }, + ); +} + +{ + const watcher = fs.watch(nonexistentFile, { + recursive: true, + throwIfNoEntry: false, + }, common.mustNotCall()); + watcher.close(); +} + +{ + const directory = tmpdir.resolve('recursive-watch-error'); + const expected = new Error('recursive watcher failed'); + const originalWatch = fs.watch; + const watcher = new RecursiveFSWatcher({ recursive: true }); + const close = common.mustCall(); + let calls = 0; + + expected.code = 'ENOSPC'; + fs.mkdirSync(directory); + fs.writeFileSync(`${directory}/file`, ''); + fs.watch = common.mustCall(() => { + if (calls++ === 0) { + return { close }; + } + throw expected; + }, 2); + + try { + assert.throws( + () => watcher[kFSWatchStart](directory), + (error) => { + assert.strictEqual(error, expected); + assert.strictEqual(error.filename, directory); + return true; + }, + ); + } finally { + fs.watch = originalWatch; + watcher.close(); + } +} + { if (common.isMacOS || common.isWindows) { const file = tmpdir.resolve('file-to-watch');