diff --git a/doc/api/fs.md b/doc/api/fs.md index 5ea61f70c95c4d..3038b2d1724e7c 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4046,6 +4046,9 @@ this API: [`fs.utimes()`][]. diff --git a/lib/fs.js b/lib/fs.js index c794d8f678be5b..356328924f90f2 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1551,6 +1551,17 @@ function watch(filename, options, listener) { if (listener) { watcher.addListener('change', listener); } + if (options.signal) { + if (options.signal.aborted) { + process.nextTick(() => watcher.close()); + } else { + const listener = () => watcher.close(); + options.signal.addEventListener('abort', listener); + watcher.once('close', () => { + options.signal.removeEventListener('abort', listener); + }); + } + } return watcher; } diff --git a/test/parallel/test-fs-watch-abort-signal.js b/test/parallel/test-fs-watch-abort-signal.js new file mode 100644 index 00000000000000..e5589bc1140f8b --- /dev/null +++ b/test/parallel/test-fs-watch-abort-signal.js @@ -0,0 +1,32 @@ +// Flags: --expose-internals --experimental-abortcontroller +'use strict'; + +// Verify that AbortSignal integration works for fs.watch + +const common = require('../common'); + +if (common.isIBMi) + common.skip('IBMi does not support `fs.watch()`'); + +const fs = require('fs'); +const fixtures = require('../common/fixtures'); + + +{ + // Signal aborted after creating the watcher + const file = fixtures.path('empty.js'); + const ac = new AbortController(); + const { signal } = ac; + const watcher = fs.watch(file, { signal }); + watcher.once('close', common.mustCall()); + setImmediate(() => ac.abort()); +} +{ + // Signal aborted before creating the watcher + const file = fixtures.path('empty.js'); + const ac = new AbortController(); + const { signal } = ac; + ac.abort(); + const watcher = fs.watch(file, { signal }); + watcher.once('close', common.mustCall()); +}