From 9584dbc29410ca4bc1ac2102a50c910ea26ebd0d Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 07:36:14 +0200 Subject: [PATCH 01/16] Null-proofing --- lib/internal/watch_mode/files_watcher.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 3c756c4b5d77c9..1a622f856aee64 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -90,8 +90,11 @@ class FilesWatcher extends EventEmitter { return; } const watcher = watch(path, { recursive }); - watcher.on('change', (eventType, fileName) => this - .#onChange(recursive ? resolve(path, fileName) : path)); + watcher.on('change', (eventType, fileName) => { + if (fileName !== null) { + this.#onChange(recursive ? resolve(path, fileName) : path); + } + }); this.#watchers.set(path, { handle: watcher, recursive }); if (recursive) { this.#removeWatchedChildren(path); From 2e1e2d205df8d2cc943868d9bf35365bbf9732f8 Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 09:04:49 +0200 Subject: [PATCH 02/16] Update fs.md Wath can pass null as filename --- doc/api/fs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 0623e1c5a9dacf..c82c18ca603f54 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1667,7 +1667,7 @@ added: should stop. * Returns: {AsyncIterator} of objects with the properties: * `eventType` {string} The type of change - * `filename` {string|Buffer} The name of the file changed. + * `filename` {string|Buffer|null} The name of the file changed. Returns an async iterator that watches for changes on `filename`, where `filename` is either a file or a directory. @@ -4282,8 +4282,8 @@ same directory: ```bash $ tree . . -├── mew -└── mewtwo -> ./mew ++¦¦ mew +L¦¦ mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` @@ -4490,7 +4490,7 @@ changes: * `signal` {AbortSignal} allows closing the watcher with an AbortSignal. * `listener` {Function|undefined} **Default:** `undefined` * `eventType` {string} - * `filename` {string|Buffer} + * `filename` {string|Buffer|null} * Returns: {fs.FSWatcher} Watch for changes on `filename`, where `filename` is either a file or a From 42980072e8b5881b4d60373ef6e81e587fedfe83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:16 +0200 Subject: [PATCH 03/16] Resore unicode glyphs --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index c82c18ca603f54..c8b5b02664381a 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4282,8 +4282,8 @@ same directory: ```bash $ tree . . -+¦¦ mew -L¦¦ mewtwo -> ./mew +├── mew +└── mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 6ec3d05be1b28d277f4c425bcfa50f7d9c4dd26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:37 +0200 Subject: [PATCH 04/16] MoLow suggestion --- lib/internal/watch_mode/files_watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 1a622f856aee64..90d2ffd33a9c7b 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -91,7 +91,7 @@ class FilesWatcher extends EventEmitter { } const watcher = watch(path, { recursive }); watcher.on('change', (eventType, fileName) => { - if (fileName !== null) { + if (fileName != null) { this.#onChange(recursive ? resolve(path, fileName) : path); } }); From 6b40a22fdf2053ced2fe38becb22ea95fc1d7299 Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 07:36:14 +0200 Subject: [PATCH 05/16] Null-proofing --- lib/internal/watch_mode/files_watcher.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 3c756c4b5d77c9..1a622f856aee64 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -90,8 +90,11 @@ class FilesWatcher extends EventEmitter { return; } const watcher = watch(path, { recursive }); - watcher.on('change', (eventType, fileName) => this - .#onChange(recursive ? resolve(path, fileName) : path)); + watcher.on('change', (eventType, fileName) => { + if (fileName !== null) { + this.#onChange(recursive ? resolve(path, fileName) : path); + } + }); this.#watchers.set(path, { handle: watcher, recursive }); if (recursive) { this.#removeWatchedChildren(path); From 3e91cf2538fa47a5d8150d51bc7fb9625d5c27b6 Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 09:04:49 +0200 Subject: [PATCH 06/16] Update fs.md Wath can pass null as filename --- doc/api/fs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index a4efd37018c413..68e4b7fa5d44b2 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1667,7 +1667,7 @@ added: should stop. * Returns: {AsyncIterator} of objects with the properties: * `eventType` {string} The type of change - * `filename` {string|Buffer} The name of the file changed. + * `filename` {string|Buffer|null} The name of the file changed. Returns an async iterator that watches for changes on `filename`, where `filename` is either a file or a directory. @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -├── mew -└── mewtwo -> ./mew ++¦¦ mew +L¦¦ mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` @@ -4489,7 +4489,7 @@ changes: * `signal` {AbortSignal} allows closing the watcher with an AbortSignal. * `listener` {Function|undefined} **Default:** `undefined` * `eventType` {string} - * `filename` {string|Buffer} + * `filename` {string|Buffer|null} * Returns: {fs.FSWatcher} Watch for changes on `filename`, where `filename` is either a file or a From 006abee7e7c95d32968c01d3b03d97a0eb9d4da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:16 +0200 Subject: [PATCH 07/16] Resore unicode glyphs --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 68e4b7fa5d44b2..7dd926f18eecaa 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -+¦¦ mew -L¦¦ mewtwo -> ./mew +├── mew +└── mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 267daf5ffb4a2d617501c29fce976d6860c063aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:37 +0200 Subject: [PATCH 08/16] MoLow suggestion --- lib/internal/watch_mode/files_watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 1a622f856aee64..90d2ffd33a9c7b 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -91,7 +91,7 @@ class FilesWatcher extends EventEmitter { } const watcher = watch(path, { recursive }); watcher.on('change', (eventType, fileName) => { - if (fileName !== null) { + if (fileName != null) { this.#onChange(recursive ? resolve(path, fileName) : path); } }); From 13a6c679fbe3b59673c51f2ab98f35c3ed8e672f Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 09:04:49 +0200 Subject: [PATCH 09/16] Update fs.md Wath can pass null as filename --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 7dd926f18eecaa..68e4b7fa5d44b2 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -├── mew -└── mewtwo -> ./mew ++¦¦ mew +L¦¦ mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 0c5e9b20a83f9933118ac269e2bb8d8f97b6a6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:16 +0200 Subject: [PATCH 10/16] Resore unicode glyphs --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 68e4b7fa5d44b2..7dd926f18eecaa 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -+¦¦ mew -L¦¦ mewtwo -> ./mew +├── mew +└── mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 4ef5a100556aa262e1cbdd83d96c5b00152c1e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 12:08:40 +0200 Subject: [PATCH 11/16] fix indent --- lib/internal/watch_mode/files_watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 90d2ffd33a9c7b..51d6ebe6154b64 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -94,7 +94,7 @@ class FilesWatcher extends EventEmitter { if (fileName != null) { this.#onChange(recursive ? resolve(path, fileName) : path); } - }); + }); this.#watchers.set(path, { handle: watcher, recursive }); if (recursive) { this.#removeWatchedChildren(path); From eb4ddbb36419de6bd4fad3f3a0723b815cfaa6d9 Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 07:36:14 +0200 Subject: [PATCH 12/16] Null-proofing --- lib/internal/watch_mode/files_watcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 90d2ffd33a9c7b..51d6ebe6154b64 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -94,7 +94,7 @@ class FilesWatcher extends EventEmitter { if (fileName != null) { this.#onChange(recursive ? resolve(path, fileName) : path); } - }); + }); this.#watchers.set(path, { handle: watcher, recursive }); if (recursive) { this.#removeWatchedChildren(path); From a065a3b0dc20cb27b878c1c7f8ab33430658d47f Mon Sep 17 00:00:00 2001 From: sosoba Date: Mon, 24 Apr 2023 09:04:49 +0200 Subject: [PATCH 13/16] Update fs.md Wath can pass null as filename --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 7dd926f18eecaa..68e4b7fa5d44b2 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -├── mew -└── mewtwo -> ./mew ++¦¦ mew +L¦¦ mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 8a5862f6fb49a3c68cefa3705708195e8406d7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 09:53:16 +0200 Subject: [PATCH 14/16] Resore unicode glyphs --- doc/api/fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 68e4b7fa5d44b2..7dd926f18eecaa 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4281,8 +4281,8 @@ same directory: ```bash $ tree . . -+¦¦ mew -L¦¦ mewtwo -> ./mew +├── mew +└── mewtwo -> ./mew ``` ### `fs.truncate(path[, len], callback)` From 5c013dbc2395198f4c46b0fba29cedf1bdf0f1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Mon, 24 Apr 2023 14:10:44 +0200 Subject: [PATCH 15/16] Add test --- lib/internal/watch_mode/files_watcher.js | 4 ++++ test/parallel/test-watch-mode-files_watcher.mjs | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 51d6ebe6154b64..c465668c9821b4 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -85,6 +85,10 @@ class FilesWatcher extends EventEmitter { return [...this.#watchers.keys()]; } + [Symbol.for('emitChangeEventWithoutFilename')]() { + this.#watchers.values().forEach(watcher => watcher.emit('change', 'change', null)); + } + watchPath(path, recursive = true) { if (this.#isPathWatched(path)) { return; diff --git a/test/parallel/test-watch-mode-files_watcher.mjs b/test/parallel/test-watch-mode-files_watcher.mjs index 19f71a04e40df8..94a88f87a3eeda 100644 --- a/test/parallel/test-watch-mode-files_watcher.mjs +++ b/test/parallel/test-watch-mode-files_watcher.mjs @@ -159,4 +159,12 @@ describe('watch mode file watcher', () => { } assert.deepStrictEqual(watcher.watchedPaths, expected); }); + + it('should ignore watch event without filename', async () => { + watcher.on('changed', common.mustNotCall()); + watcher.watchPath(tmpdir.path); + watcher[Symbol.for('emitChangeEventWithoutFilename')](); + // Wait for this long to make sure changes are not triggered + await setTimeout(1000); + }); }); From ad8329479a465c7c7254a6e3509ac20d3135996f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Osoba=20S=C5=82awomir?= Date: Tue, 25 Apr 2023 07:35:55 +0200 Subject: [PATCH 16/16] Remove a specific method used only by tests --- lib/internal/watch_mode/files_watcher.js | 10 ++++----- .../test-watch-mode-files_watcher.mjs | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index c465668c9821b4..015b50d54a948c 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -30,14 +30,16 @@ class FilesWatcher extends EventEmitter { #ownerDependencies = new SafeMap(); #throttle; #mode; + #createWatcher; - constructor({ throttle = 500, mode = 'filter' } = kEmptyObject) { + constructor({ throttle = 500, mode = 'filter', createWatcher = watch } = kEmptyObject) { super(); validateNumber(throttle, 'options.throttle', 0, TIMEOUT_MAX); validateOneOf(mode, 'options.mode', ['filter', 'all']); this.#throttle = throttle; this.#mode = mode; + this.#createWatcher = createWatcher; } #isPathWatched(path) { @@ -85,15 +87,11 @@ class FilesWatcher extends EventEmitter { return [...this.#watchers.keys()]; } - [Symbol.for('emitChangeEventWithoutFilename')]() { - this.#watchers.values().forEach(watcher => watcher.emit('change', 'change', null)); - } - watchPath(path, recursive = true) { if (this.#isPathWatched(path)) { return; } - const watcher = watch(path, { recursive }); + const watcher = this.#createWatcher(path, { recursive }); watcher.on('change', (eventType, fileName) => { if (fileName != null) { this.#onChange(recursive ? resolve(path, fileName) : path); diff --git a/test/parallel/test-watch-mode-files_watcher.mjs b/test/parallel/test-watch-mode-files_watcher.mjs index 94a88f87a3eeda..47a142d38f84c0 100644 --- a/test/parallel/test-watch-mode-files_watcher.mjs +++ b/test/parallel/test-watch-mode-files_watcher.mjs @@ -6,7 +6,7 @@ import path from 'node:path'; import assert from 'node:assert'; import process from 'node:process'; import { describe, it, beforeEach, afterEach } from 'node:test'; -import { writeFileSync, mkdirSync } from 'node:fs'; +import { writeFileSync, mkdirSync, watch } from 'node:fs'; import { setTimeout } from 'node:timers/promises'; import { once } from 'node:events'; import { spawn } from 'node:child_process'; @@ -161,10 +161,20 @@ describe('watch mode file watcher', () => { }); it('should ignore watch event without filename', async () => { - watcher.on('changed', common.mustNotCall()); - watcher.watchPath(tmpdir.path); - watcher[Symbol.for('emitChangeEventWithoutFilename')](); - // Wait for this long to make sure changes are not triggered - await setTimeout(1000); + let watcher; + const createWatcher = (filename, options, listener) => { + watcher = watch(filename, options, listener); + return watcher; + }; + const filesWatcher = new FilesWatcher({ throttle: 100, createWatcher }); + try { + filesWatcher.on('changed', common.mustNotCall()); + filesWatcher.watchPath(tmpdir.path); + watcher.emit('change', 'change', null); + // Wait for this long to make sure changes are not triggered + await setTimeout(1000); + } finally { + filesWatcher.clear(); + } }); });