Skip to content

Commit 23e7cb4

Browse files
committed
Merge remote-tracking branch 'origin/markjm/context-timestamps' into markjm/context-timestamps
2 parents 8867bc1 + 7025319 commit 23e7cb4

5 files changed

Lines changed: 165 additions & 60 deletions

File tree

lib/WatchIgnorePlugin.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,20 @@ class IgnoringWatchFileSystem {
8787
fileTimestamps.set(path, IGNORE_TIME_ENTRY);
8888
}
8989
return fileTimestamps;
90-
}
90+
},
91+
getInfo:
92+
watcher.getInfo &&
93+
(() => {
94+
const info = watcher.getInfo();
95+
const { fileTimeInfoEntries, contextTimeInfoEntries } = info;
96+
for (const path of ignoredFiles) {
97+
fileTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
98+
}
99+
for (const path of ignoredDirs) {
100+
contextTimeInfoEntries.set(path, IGNORE_TIME_ENTRY);
101+
}
102+
return info;
103+
})
91104
};
92105
}
93106
}

lib/Watching.js

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -109,30 +109,44 @@ class Watching {
109109
this.lastWatcherStartTime = Date.now();
110110
}
111111
this.compiler.fsStartTime = Date.now();
112-
this._mergeWithCollected(
113-
changedFiles ||
114-
(this.pausedWatcher &&
112+
if (
113+
changedFiles &&
114+
removedFiles &&
115+
fileTimeInfoEntries &&
116+
contextTimeInfoEntries
117+
) {
118+
this._mergeWithCollected(changedFiles, removedFiles);
119+
this.compiler.fileTimestamps = fileTimeInfoEntries;
120+
this.compiler.contextTimestamps = contextTimeInfoEntries;
121+
} else if (this.pausedWatcher) {
122+
if (this.pausedWatcher.getInfo) {
123+
const {
124+
changes,
125+
removals,
126+
fileTimeInfoEntries,
127+
contextTimeInfoEntries
128+
} = this.pausedWatcher.getInfo();
129+
this._mergeWithCollected(changes, removals);
130+
this.compiler.fileTimestamps = fileTimeInfoEntries;
131+
this.compiler.contextTimestamps = contextTimeInfoEntries;
132+
} else {
133+
this._mergeWithCollected(
115134
this.pausedWatcher.getAggregatedChanges &&
116-
this.pausedWatcher.getAggregatedChanges()),
117-
(this.compiler.removedFiles =
118-
removedFiles ||
119-
(this.pausedWatcher &&
135+
this.pausedWatcher.getAggregatedChanges(),
120136
this.pausedWatcher.getAggregatedRemovals &&
121-
this.pausedWatcher.getAggregatedRemovals()))
122-
);
123-
137+
this.pausedWatcher.getAggregatedRemovals()
138+
);
139+
this.compiler.fileTimestamps =
140+
this.pausedWatcher.getFileTimeInfoEntries();
141+
this.compiler.contextTimestamps =
142+
this.pausedWatcher.getContextTimeInfoEntries();
143+
}
144+
}
124145
this.compiler.modifiedFiles = this._collectedChangedFiles;
125146
this._collectedChangedFiles = undefined;
126147
this.compiler.removedFiles = this._collectedRemovedFiles;
127148
this._collectedRemovedFiles = undefined;
128149

129-
this.compiler.fileTimestamps =
130-
fileTimeInfoEntries ||
131-
(this.pausedWatcher && this.pausedWatcher.getFileTimeInfoEntries());
132-
this.compiler.contextTimestamps =
133-
contextTimeInfoEntries ||
134-
(this.pausedWatcher && this.pausedWatcher.getContextTimeInfoEntries());
135-
136150
const run = () => {
137151
if (this.compiler.idle) {
138152
return this.compiler.cache.endIdle(err => {

lib/node/NodeWatchFileSystem.js

Lines changed: 84 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
"use strict";
77

8+
const util = require("util");
89
const Watchpack = require("watchpack");
910

1011
/** @typedef {import("../../declarations/WebpackOptions").WatchOptions} WatchOptions */
@@ -69,8 +70,21 @@ class NodeWatchFileSystem {
6970
this.watcher.once("change", callbackUndelayed);
7071
}
7172

72-
let fileMap, directoryMap;
73+
const fetchTimeInfo = () => {
74+
const fileTimeInfoEntries = new Map();
75+
const contextTimeInfoEntries = new Map();
76+
if (this.watcher) {
77+
this.watcher.collectTimeInfoEntries(
78+
fileTimeInfoEntries,
79+
contextTimeInfoEntries
80+
);
81+
}
82+
return { fileTimeInfoEntries, contextTimeInfoEntries };
83+
};
7384
this.watcher.once("aggregated", (changes, removals) => {
85+
// pause emitting events (avoids clearing aggregated changes and removals on timeout)
86+
this.watcher.pause();
87+
7488
if (this.inputFileSystem && this.inputFileSystem.purge) {
7589
const fs = this.inputFileSystem;
7690
for (const item of changes) {
@@ -80,10 +94,14 @@ class NodeWatchFileSystem {
8094
fs.purge(item);
8195
}
8296
}
83-
fileMap = new Map();
84-
directoryMap = new Map();
85-
this.watcher.collectTimeInfoEntries(fileMap, directoryMap);
86-
callback(null, fileMap, directoryMap, changes, removals);
97+
const { fileTimeInfoEntries, contextTimeInfoEntries } = fetchTimeInfo();
98+
callback(
99+
null,
100+
fileTimeInfoEntries,
101+
contextTimeInfoEntries,
102+
changes,
103+
removals
104+
);
87105
});
88106

89107
this.watcher.watch({ files, directories, missing, startTime });
@@ -103,47 +121,71 @@ class NodeWatchFileSystem {
103121
this.watcher.pause();
104122
}
105123
},
106-
getAggregatedRemovals: () => {
107-
const items = this.watcher && this.watcher.aggregatedRemovals;
108-
if (items && this.inputFileSystem && this.inputFileSystem.purge) {
109-
const fs = this.inputFileSystem;
110-
for (const item of items) {
111-
fs.purge(item);
124+
getAggregatedRemovals: util.deprecate(
125+
() => {
126+
const items = this.watcher && this.watcher.aggregatedRemovals;
127+
if (items && this.inputFileSystem && this.inputFileSystem.purge) {
128+
const fs = this.inputFileSystem;
129+
for (const item of items) {
130+
fs.purge(item);
131+
}
112132
}
113-
}
114-
return items;
115-
},
116-
getAggregatedChanges: () => {
117-
const items = this.watcher && this.watcher.aggregatedChanges;
118-
if (items && this.inputFileSystem && this.inputFileSystem.purge) {
133+
return items;
134+
},
135+
"Watcher.getAggregatedRemovals is deprecated in favor of Watcher.getInfo since that's more performant.",
136+
"DEP_WEBPACK_WATCHER_GET_AGGREGATED_REMOVALS"
137+
),
138+
getAggregatedChanges: util.deprecate(
139+
() => {
140+
const items = this.watcher && this.watcher.aggregatedChanges;
141+
if (items && this.inputFileSystem && this.inputFileSystem.purge) {
142+
const fs = this.inputFileSystem;
143+
for (const item of items) {
144+
fs.purge(item);
145+
}
146+
}
147+
return items;
148+
},
149+
"Watcher.getAggregatedChanges is deprecated in favor of Watcher.getInfo since that's more performant.",
150+
"DEP_WEBPACK_WATCHER_GET_AGGREGATED_CHANGES"
151+
),
152+
getFileTimeInfoEntries: util.deprecate(
153+
() => {
154+
return fetchTimeInfo().fileTimeInfoEntries;
155+
},
156+
"Watcher.getFileTimeInfoEntries is deprecated in favor of Watcher.getInfo since that's more performant.",
157+
"DEP_WEBPACK_WATCHER_FILE_TIME_INFO_ENTRIES"
158+
),
159+
getContextTimeInfoEntries: util.deprecate(
160+
() => {
161+
return fetchTimeInfo().contextTimeInfoEntries;
162+
},
163+
"Watcher.getContextTimeInfoEntries is deprecated in favor of Watcher.getInfo since that's more performant.",
164+
"DEP_WEBPACK_WATCHER_CONTEXT_TIME_INFO_ENTRIES"
165+
),
166+
getInfo: () => {
167+
const removals = this.watcher && this.watcher.aggregatedRemovals;
168+
const changes = this.watcher && this.watcher.aggregatedChanges;
169+
if (this.inputFileSystem && this.inputFileSystem.purge) {
119170
const fs = this.inputFileSystem;
120-
for (const item of items) {
121-
fs.purge(item);
171+
if (removals) {
172+
for (const item of removals) {
173+
fs.purge(item);
174+
}
175+
}
176+
if (changes) {
177+
for (const item of changes) {
178+
fs.purge(item);
179+
}
122180
}
123181
}
124-
return items;
125-
},
126-
getFileTimeInfoEntries: () => {
127-
if (fileMap) return fileMap;
128-
if (this.watcher) {
129-
this.watcher.collectTimeInfoEntries(
130-
(fileMap = new Map()),
131-
(directoryMap = new Map())
132-
);
133-
return fileMap;
134-
}
135-
return new Map();
136-
},
137-
getContextTimeInfoEntries: () => {
138-
if (directoryMap) return directoryMap;
139-
if (this.watcher) {
140-
this.watcher.collectTimeInfoEntries(
141-
(fileMap = new Map()),
142-
(directoryMap = new Map())
143-
);
144-
return directoryMap;
145-
}
146-
return new Map();
182+
const { fileTimeInfoEntries, contextTimeInfoEntries } = fetchTimeInfo();
183+
return {
184+
changes,
185+
removals,
186+
fileTimeInfoEntries,
187+
contextTimeInfoEntries
188+
};
147189
}
148190
};
149191
}

lib/util/fs.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ const path = require("path");
6161
/** @typedef {function((NodeJS.ErrnoException | Error | null)=, any=): void} ReadJsonCallback */
6262
/** @typedef {function((NodeJS.ErrnoException | Error | null)=, IStats|string=): void} LstatReadlinkAbsoluteCallback */
6363

64+
/**
65+
* @typedef {Object} WatcherInfo
66+
* @property {Set<string>} changes get current aggregated changes that have not yet send to callback
67+
* @property {Set<string>} removals get current aggregated removals that have not yet send to callback
68+
* @property {Map<string, FileSystemInfoEntry | "ignore">} fileTimeInfoEntries get info about files
69+
* @property {Map<string, FileSystemInfoEntry | "ignore">} contextTimeInfoEntries get info about directories
70+
*/
71+
72+
// TODO webpack 6 deprecate missing getInfo
6473
/**
6574
* @typedef {Object} Watcher
6675
* @property {function(): void} close closes the watcher and all underlying file watchers
@@ -69,6 +78,7 @@ const path = require("path");
6978
* @property {function(): Set<string>=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
7079
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getFileTimeInfoEntries get info about files
7180
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getContextTimeInfoEntries get info about directories
81+
* @property {function(): WatcherInfo=} getInfo get info about timestamps and changes
7282
*/
7383

7484
/**

types.d.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11741,6 +11741,32 @@ declare interface Watcher {
1174111741
* get info about directories
1174211742
*/
1174311743
getContextTimeInfoEntries: () => Map<string, FileSystemInfoEntry | "ignore">;
11744+
11745+
/**
11746+
* get info about timestamps and changes
11747+
*/
11748+
getInfo?: () => WatcherInfo;
11749+
}
11750+
declare interface WatcherInfo {
11751+
/**
11752+
* get current aggregated changes that have not yet send to callback
11753+
*/
11754+
changes: Set<string>;
11755+
11756+
/**
11757+
* get current aggregated removals that have not yet send to callback
11758+
*/
11759+
removals: Set<string>;
11760+
11761+
/**
11762+
* get info about files
11763+
*/
11764+
fileTimeInfoEntries: Map<string, FileSystemInfoEntry | "ignore">;
11765+
11766+
/**
11767+
* get info about directories
11768+
*/
11769+
contextTimeInfoEntries: Map<string, FileSystemInfoEntry | "ignore">;
1174411770
}
1174511771
declare abstract class Watching {
1174611772
startTime: null | number;

0 commit comments

Comments
 (0)