fix(ext/node): support ignore option in fs.promises.watch#33606
fix(ext/node): support ignore option in fs.promises.watch#33606nathanwhitbot wants to merge 1 commit intodenoland:mainfrom
ignore option in fs.promises.watch#33606Conversation
Implement the `ignore` option for `fs.promises.watch`, accepting a string (minimatch glob), RegExp, function, or array of those. Filters watch events whose filename matches any pattern. Mirrors Node's `createIgnoreMatcher` / `validateIgnoreOption` from https://github.com/nodejs/node/blob/main/lib/internal/fs/watchers.js. Reuses the minimatch dep already vendored at `ext:deno_node/deps/minimatch.js`. Enables 5 node compat tests: - `test-fs-promises-watch-ignore-function.mjs` - `test-fs-promises-watch-ignore-glob.mjs` - `test-fs-promises-watch-ignore-invalid.mjs` - `test-fs-promises-watch-ignore-mixed.mjs` - `test-fs-promises-watch-ignore-regexp.mjs`
fibibot
left a comment
There was a problem hiding this comment.
The implementation is solid — validateIgnoreOption / validateIgnoreOptionElement cleanly mirror Node's lib/internal/validators.js (string-or-RegExp-or-function with empty-string ERR_INVALID_ARG_VALUE, array recursion, null/undefined no-op). createIgnoreMatcher builds an OR'd list of matchers and the while (true) await fsIterable.next() loop in watchPromise correctly skips events the matcher rejects without losing positional state. Reusing the already-vendored minimatch.js via core.createLazyLoader is the right move — keeps the import lazy so non-glob callers don't pay for it.
But CI is red on prefer-primordials lint across all 3 platforms — same pattern as #33574 had:
value instanceof RegExp(line 3252)Array.isArray(value)(line 3263)Array.isArray(ignore)(line 3276, increateIgnoreMatcher)matcher instanceof RegExp(line 3295, increateIgnoreMatcher)
The fix is mechanical. Inline guidance below.
(Probably copied from #33574 before that PR's primordials fix landed — the fix is identical here.)
| } | ||
| return; | ||
| } | ||
| if (value instanceof RegExp) return; |
There was a problem hiding this comment.
Lint blocker — prefer-primordials rejects all four hits in this PR:
- L3252:
value instanceof RegExp→ObjectPrototypeIsPrototypeOf(RegExpPrototype, value) - L3263:
Array.isArray(value)→ArrayIsArray(value) - L3276:
Array.isArray(ignore)→ArrayIsArray(ignore) - L3295:
matcher instanceof RegExp→ObjectPrototypeIsPrototypeOf(RegExpPrototype, matcher)
The file already imports ObjectPrototypeIsPrototypeOf from primordials at line 174. After #33574 landed, RegExpPrototype and ArrayIsArray should also already be in the destructure — if not, add them.
Full failure: https://github.com/denoland/deno/actions/runs/25018807704/job/73273702258
#33574 had the exact same pattern fixed in the same way; you can crib that fix verbatim.
| | RegExp | ||
| | ((filename: string) => boolean) | ||
| | (string | RegExp | ((filename: string) => boolean))[] | ||
| | undefined |
There was a problem hiding this comment.
Minor — let _lazyMinimatch: any = null is using any for the lazy-loader handle. This is contagious: _lazyMinimatch ??= core.createLazyLoader(...) then _lazyMinimatch() returns any, and getMinimatch().default is therefore any too.
Not blocking, but typing it as something narrower (e.g. () => typeof import("...") or just () => unknown and then asserting at the destructure site) would catch a mistyped property access at compile time. The current shape would silently break if Minimatch got renamed in the dep.
|
Superseded by #33610 which adds the same fix for both |
Summary
Implement the
ignoreoption forfs.promises.watch, accepting a string (minimatch glob),RegExp, function, or array of those. Watch events whose filename matches any pattern are filtered out. Mirrors Node'screateIgnoreMatcherandvalidateIgnoreOption, reusing the minimatch dep already vendored atext:deno_node/deps/minimatch.js.Enables 5 node compat tests:
test-fs-promises-watch-ignore-function.mjstest-fs-promises-watch-ignore-glob.mjstest-fs-promises-watch-ignore-invalid.mjstest-fs-promises-watch-ignore-mixed.mjstest-fs-promises-watch-ignore-regexp.mjsTest plan
cargo test --test node_compat -- fs-promises-watch-ignorefs-watch*tests still pass (test-fs-promises-watch-iterator.js,test-fs-watch.js,test-fs-watch-ref-unref.js)