Skip to content

Commit c7f8b29

Browse files
committed
fix(watch): purge the dropped paths in one exact call
A prefix purge scans the whole cache once per path, so a rebuild dropping a 641-file package took 132 ms in watch() against 1.35 ms before; one exact purge of the list takes 1.85 ms. The case now also covers a package.json main, a file a loader reads through this.fs, and the filesystem cache.
1 parent 51c1f7c commit c7f8b29

16 files changed

Lines changed: 66 additions & 16 deletions

File tree

‎lib/node/NodeWatchFileSystem.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,15 @@ class NodeWatchFileSystem {
119119
if (previous === undefined || !fs || !fs.purge) return;
120120
const filesSet = toLookup(files);
121121
const missingSet = toLookup(missing);
122+
/** @type {string[]} */
123+
const dropped = [];
122124
for (const list of [previous.files, previous.missing]) {
123125
for (const item of list) {
124-
if (!filesSet.has(item) && !missingSet.has(item)) fs.purge(item);
126+
if (!filesSet.has(item) && !missingSet.has(item)) dropped.push(item);
125127
}
126128
}
129+
// a prefix purge scans the whole cache once per path
130+
if (dropped.length > 0) fs.purge(dropped, { exact: true });
127131
}
128132

129133
/** @type {WatchMethod} */

‎test/unitCases/NodeWatchFileSystem.unittest.js‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ describe("NodeWatchFileSystem", () => {
109109
});
110110

111111
it("purges what a later call stops watching", () => {
112-
/** @type {string[]} */
113-
const purged = [];
112+
/** @type {unknown[][]} */
113+
const purges = [];
114114
const wfs = new NodeWatchFileSystem(
115115
/** @type {import("../../lib/fs/fs").InputFileSystem} */ ({
116-
purge: (item) => {
117-
purged.push(/** @type {string} */ (item));
116+
purge: (items, options) => {
117+
purges.push([items, options]);
118118
}
119119
})
120120
);
@@ -140,9 +140,11 @@ describe("NodeWatchFileSystem", () => {
140140
)
141141
);
142142
start([kept, moved, dropped], [missing]);
143-
expect(purged).toEqual([]);
143+
expect(purges).toEqual([]);
144144
start([kept], [moved]);
145-
expect(purged).toEqual([dropped, missing]);
145+
expect(purges).toEqual([[[dropped, missing], { exact: true }]]);
146+
start([kept], [moved]);
147+
expect(purges).toHaveLength(1);
146148
});
147149

148150
it("leaves an unsupported ignored option to watchpack", () => {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
"use strict";
22

3-
module.exports = [[/Module not found/, /Can't resolve '\.\/later'/]];
3+
const error = [/Module not found/, /Can't resolve '\.\/later'/];
4+
5+
module.exports = [error, error];
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import value from "./module.js";
22
import gone from "./gone.js";
3+
import pkg from "./pkg";
4+
import data from "./loader.js!./with-loader.js";
35

46
it("should read paths changed while nothing watched them", () => {
57
expect(value).toBe(1);
68
expect(gone).toBe(1);
9+
expect(pkg).toBe("a");
10+
expect(data).toBe("1");
711
expect(() => require("./later")).toThrow(/Cannot find module/);
812
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"use strict";
2+
3+
const path = require("path");
4+
5+
/** @type {import("../../../../../").LoaderDefinition} */
6+
module.exports = function loader() {
7+
const callback = this.async();
8+
const file = path.join(this.context, "data.txt");
9+
this.addDependency(file);
10+
this.fs.readFile(file, (err, content) => {
11+
if (err) return callback(err);
12+
callback(null, `module.exports = ${JSON.stringify(String(content).trim())};`);
13+
});
14+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = "a";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = "b";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "name": "pkg", "main": "a.js" }

‎test/watchCases/cache/change-file-while-unwatched/0/with-loader.js‎

Whitespace-only changes.

0 commit comments

Comments
 (0)