From 08f6a1a6fb25252aae5536d87835143cde221ae8 Mon Sep 17 00:00:00 2001 From: Mark Molinaro Date: Fri, 12 Nov 2021 19:57:02 +0000 Subject: [PATCH 1/3] Allow function in watchOptions.ignored --- README.md | 1 + lib/watchpack.js | 6 ++++-- test/Watchpack.js | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64a7686..19ada68 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ var wp = new Watchpack({ // ignored: "string" - a glob pattern for files or folders that should not be watched // ignored: ["string", "string"] - multiple glob patterns that should be ignored // ignored: /regexp/ - a regular expression for files or folders that should not be watched + // ignored: (entry) => boolean - an arbirary function which must return truthy to ignore an entry // All subdirectories are ignored too }); diff --git a/lib/watchpack.js b/lib/watchpack.js index 9f1dca1..e4ea83a 100644 --- a/lib/watchpack.js +++ b/lib/watchpack.js @@ -31,13 +31,15 @@ const stringToRegexp = ignored => { return matchingStart; }; -const ignoredToRegexp = ignored => { +const ignoredToRegexpLike = ignored => { if (Array.isArray(ignored)) { return new RegExp(ignored.map(i => stringToRegexp(i)).join("|")); } else if (typeof ignored === "string") { return new RegExp(stringToRegexp(ignored)); } else if (ignored instanceof RegExp) { return ignored; + } else if (ignored instanceof Function) { + return { test: ignored }; } else if (ignored) { throw new Error(`Invalid option for 'ignored': ${ignored}`); } else { @@ -48,7 +50,7 @@ const ignoredToRegexp = ignored => { const normalizeOptions = options => { return { followSymlinks: !!options.followSymlinks, - ignored: ignoredToRegexp(options.ignored), + ignored: ignoredToRegexpLike(options.ignored), poll: options.poll }; }; diff --git a/test/Watchpack.js b/test/Watchpack.js index ade8021..0312175 100644 --- a/test/Watchpack.js +++ b/test/Watchpack.js @@ -118,6 +118,32 @@ describe("Watchpack", function() { }); }); + it("should not watch a single ignored file (function)", function(done) { + var w = new Watchpack({ + aggregateTimeout: 300, + ignored: (entry) => entry.includes("a") + }); + var changeEvents = 0; + var aggregatedEvents = 0; + w.on("change", () => { + changeEvents++; + }); + w.on("aggregated", () => { + aggregatedEvents++; + }); + w.watch([path.join(fixtures, "a")], []); + testHelper.tick(() => { + testHelper.file("a"); + testHelper.tick(1000, () => { + changeEvents.should.be.eql(0); + aggregatedEvents.should.be.eql(0); + testHelper.getNumberOfWatchers().should.be.eql(0); + w.close(); + done(); + }); + }); + }); + it("should watch multiple files", function(done) { var w = new Watchpack({ aggregateTimeout: 1000 From 2f8e1fb7495e0c949b563dfd55a905ed0d0680f5 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 24 Nov 2021 10:49:29 +0100 Subject: [PATCH 2/3] avoid RegexpLike in favor of a function move path normalization to option normalization --- README.md | 1 + lib/DirectoryWatcher.js | 14 ++++---------- lib/watchpack.js | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 19ada68..ced50e6 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ var wp = new Watchpack({ // ignored: ["string", "string"] - multiple glob patterns that should be ignored // ignored: /regexp/ - a regular expression for files or folders that should not be watched // ignored: (entry) => boolean - an arbirary function which must return truthy to ignore an entry + // For all cases expect the arbirary function the path will have path separator normalized to '/'. // All subdirectories are ignored too }); diff --git a/lib/DirectoryWatcher.js b/lib/DirectoryWatcher.js index f18dbef..e31112c 100644 --- a/lib/DirectoryWatcher.js +++ b/lib/DirectoryWatcher.js @@ -71,7 +71,7 @@ class DirectoryWatcher extends EventEmitter { this.directories = new Map(); this.lastWatchEvent = 0; this.initialScan = true; - this.ignored = options.ignored; + this.ignored = options.ignored || (() => false); this.nestedWatching = false; this.polledWatching = typeof options.poll === "number" @@ -96,12 +96,6 @@ class DirectoryWatcher extends EventEmitter { this.doScan(true); } - checkIgnore(path) { - if (!this.ignored) return false; - path = path.replace(/\\/g, "/"); - return this.ignored.test(path); - } - createWatcher() { try { if (this.polledWatching) { @@ -178,7 +172,7 @@ class DirectoryWatcher extends EventEmitter { setFileTime(filePath, mtime, initial, ignoreWhenEqual, type) { const now = Date.now(); - if (this.checkIgnore(filePath)) return; + if (this.ignored(filePath)) return; const old = this.files.get(filePath); @@ -237,7 +231,7 @@ class DirectoryWatcher extends EventEmitter { } setDirectory(directoryPath, birthtime, initial, type) { - if (this.checkIgnore(directoryPath)) return; + if (this.ignored(directoryPath)) return; if (directoryPath === this.path) { if (!initial) { this.forEachWatcher(this.path, w => @@ -398,7 +392,7 @@ class DirectoryWatcher extends EventEmitter { } const filePath = path.join(this.path, filename); - if (this.checkIgnore(filePath)) return; + if (this.ignored(filePath)) return; if (this._activeEvents.get(filename) === undefined) { this._activeEvents.set(filename, false); diff --git a/lib/watchpack.js b/lib/watchpack.js index e4ea83a..151dc6c 100644 --- a/lib/watchpack.js +++ b/lib/watchpack.js @@ -31,26 +31,28 @@ const stringToRegexp = ignored => { return matchingStart; }; -const ignoredToRegexpLike = ignored => { +const ignoredToFunction = ignored => { if (Array.isArray(ignored)) { - return new RegExp(ignored.map(i => stringToRegexp(i)).join("|")); + const regexp = new RegExp(ignored.map(i => stringToRegexp(i)).join("|")); + return x => regexp.test(x.replace(/\\/g, "/")); } else if (typeof ignored === "string") { - return new RegExp(stringToRegexp(ignored)); + const regexp = new RegExp(stringToRegexp(ignored)); + return x => regexp.test(x.replace(/\\/g, "/")); } else if (ignored instanceof RegExp) { - return ignored; + return x => ignored.test(x.replace(/\\/g, "/")); } else if (ignored instanceof Function) { - return { test: ignored }; + return ignored; } else if (ignored) { throw new Error(`Invalid option for 'ignored': ${ignored}`); } else { - return undefined; + return () => false; } }; const normalizeOptions = options => { return { followSymlinks: !!options.followSymlinks, - ignored: ignoredToRegexpLike(options.ignored), + ignored: ignoredToFunction(options.ignored), poll: options.poll }; }; @@ -104,9 +106,7 @@ class Watchpack extends EventEmitter { const oldFileWatchers = this.fileWatchers; const oldDirectoryWatchers = this.directoryWatchers; const ignored = this.watcherOptions.ignored; - const filter = ignored - ? path => !ignored.test(path.replace(/\\/g, "/")) - : () => true; + const filter = path => !ignored(path); const addToMap = (map, key, item) => { const list = map.get(key); if (list === undefined) { From b308647c5f5959d52831d25f791f95083ae992e2 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 24 Nov 2021 10:57:42 +0100 Subject: [PATCH 3/3] fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ced50e6..5d36285 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ var wp = new Watchpack({ // ignored: "string" - a glob pattern for files or folders that should not be watched // ignored: ["string", "string"] - multiple glob patterns that should be ignored // ignored: /regexp/ - a regular expression for files or folders that should not be watched - // ignored: (entry) => boolean - an arbirary function which must return truthy to ignore an entry - // For all cases expect the arbirary function the path will have path separator normalized to '/'. + // ignored: (entry) => boolean - an arbitrary function which must return truthy to ignore an entry + // For all cases expect the arbitrary function the path will have path separator normalized to '/'. // All subdirectories are ignored too });