Skip to content

Commit

Permalink
Support splitting of files and directories in getTimeInfoEntries
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Molinaro committed Nov 17, 2021
1 parent c651129 commit 4c9c76f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 52 deletions.
45 changes: 15 additions & 30 deletions lib/DirectoryWatcher.js
Expand Up @@ -39,7 +39,6 @@ class Watcher extends EventEmitter {
this.directoryWatcher = directoryWatcher;
this.path = filePath;
this.startTime = startTime && +startTime;
this._cachedTimeInfoEntries = undefined;
}

checkStartTime(mtime, initial) {
Expand Down Expand Up @@ -136,8 +135,6 @@ class DirectoryWatcher extends EventEmitter {
}

setMissing(itemPath, initial, type) {
this._cachedTimeInfoEntries = undefined;

if (this.initialScan) {
this.initialScanRemoved.add(itemPath);
}
Expand Down Expand Up @@ -206,7 +203,6 @@ class DirectoryWatcher extends EventEmitter {
accuracy,
timestamp: mtime
});
this._cachedTimeInfoEntries = undefined;

if (!old) {
const key = withoutCase(filePath);
Expand Down Expand Up @@ -249,7 +245,6 @@ class DirectoryWatcher extends EventEmitter {
if (!old) {
const now = Date.now();

this._cachedTimeInfoEntries = undefined;
if (this.nestedWatching) {
this.createNestedWatcher(directoryPath);
} else {
Expand Down Expand Up @@ -280,7 +275,6 @@ class DirectoryWatcher extends EventEmitter {
createNestedWatcher(directoryPath) {
const watcher = this.watcherManager.watchDirectory(directoryPath, 1);
watcher.on("change", (filePath, mtime, type, initial) => {
this._cachedTimeInfoEntries = undefined;
this.forEachWatcher(this.path, w => {
if (!initial || w.checkStartTime(mtime, initial)) {
w.emit("change", filePath, mtime, type, initial);
Expand All @@ -293,7 +287,6 @@ class DirectoryWatcher extends EventEmitter {
setNestedWatching(flag) {
if (this.nestedWatching !== !!flag) {
this.nestedWatching = !!flag;
this._cachedTimeInfoEntries = undefined;
if (this.nestedWatching) {
for (const directory of this.directories.keys()) {
this.createNestedWatcher(directory);
Expand Down Expand Up @@ -431,7 +424,6 @@ class DirectoryWatcher extends EventEmitter {
}
}
this.lastWatchEvent = Date.now();
this._cachedTimeInfoEntries = undefined;
if (!stats) {
this.setMissing(filePath, false, eventType);
} else if (stats.isDirectory()) {
Expand Down Expand Up @@ -714,48 +706,41 @@ class DirectoryWatcher extends EventEmitter {
return obj;
}

getTimeInfoEntries() {
if (this._cachedTimeInfoEntries !== undefined)
return this._cachedTimeInfoEntries;
const map = new Map();
let safeTime = this.lastWatchEvent;
getTimeInfoEntries(fileTimestamps, directoryTimestamps, safeTime) {
safeTime.value = Math.max(safeTime.value, this.lastWatchEvent);
for (const [file, entry] of this.files) {
fixupEntryAccuracy(entry);
safeTime = Math.max(safeTime, entry.safeTime);
map.set(file, entry);
safeTime.value = Math.max(safeTime.value, entry.safeTime);
fileTimestamps.set(file, entry);
}
if (this.nestedWatching) {
for (const w of this.directories.values()) {
const timeInfoEntries = w.directoryWatcher.getTimeInfoEntries();
for (const [file, entry] of timeInfoEntries) {
if (entry) {
safeTime = Math.max(safeTime, entry.safeTime);
}
map.set(file, entry);
}
w.directoryWatcher.getTimeInfoEntries(
fileTimestamps,
directoryTimestamps,
safeTime
);
}
map.set(this.path, {
safeTime
directoryTimestamps.set(this.path, {
safeTime: safeTime.value
});
} else {
for (const dir of this.directories.keys()) {
// No additional info about this directory
map.set(dir, EXISTANCE_ONLY_TIME_ENTRY);
directoryTimestamps.set(dir, EXISTANCE_ONLY_TIME_ENTRY);
}
map.set(this.path, EXISTANCE_ONLY_TIME_ENTRY);
directoryTimestamps.set(this.path, EXISTANCE_ONLY_TIME_ENTRY);
}
if (!this.initialScan) {
for (const watchers of this.watchers.values()) {
for (const watcher of watchers) {
const path = watcher.path;
if (!map.has(path)) {
map.set(path, null);
if (!directoryTimestamps.has(path)) {
directoryTimestamps.set(path, null);
}
}
}
this._cachedTimeInfoEntries = map;
}
return map;
}

close() {
Expand Down
33 changes: 11 additions & 22 deletions lib/watchpack.js
Expand Up @@ -275,29 +275,18 @@ class Watchpack extends EventEmitter {
return obj;
}

getTimeInfoEntries() {
if (EXISTANCE_ONLY_TIME_ENTRY === undefined) {
EXISTANCE_ONLY_TIME_ENTRY = require("./DirectoryWatcher")
.EXISTANCE_ONLY_TIME_ENTRY;
}
const directoryWatchers = new Set();
addWatchersToSet(this.fileWatchers.values(), directoryWatchers);
addWatchersToSet(this.directoryWatchers.values(), directoryWatchers);
getTimeInfoEntries(fileTimestamps, directoryTimestamps) {
const allWatchers = new Set();
addWatchersToSet(this.fileWatchers.values(), allWatchers);
addWatchersToSet(this.directoryWatchers.values(), allWatchers);
const map = new Map();
for (const w of directoryWatchers) {
const times = w.getTimeInfoEntries();
for (const [path, entry] of times) {
if (map.has(path)) {
if (entry === EXISTANCE_ONLY_TIME_ENTRY) continue;
const value = map.get(path);
if (value === entry) continue;
if (value !== EXISTANCE_ONLY_TIME_ENTRY) {
map.set(path, Object.assign({}, value, entry));
continue;
}
}
map.set(path, entry);
}
// if timestamp maps are passed in, populate them, otherwise return a new map with both file and directory timestamps.
if (!fileTimestamps && !directoryTimestamps) {
fileTimestamps = directoryTimestamps = map;
}
const safeTime = { value: 0 };
for (const w of allWatchers) {
w.getTimeInfoEntries(fileTimestamps, directoryTimestamps, safeTime);
}
return map;
}
Expand Down
File renamed without changes.
38 changes: 38 additions & 0 deletions test/Watchpack.js
Expand Up @@ -524,6 +524,44 @@ describe("Watchpack", function() {
});
});

it("should watch file in a sub directory (passed in maps)", function(done) {
var w = new Watchpack({
aggregateTimeout: 1000
});
var changeEvents = [];
w.on("change", function(file) {
if (changeEvents[changeEvents.length - 1] === file) return;
changeEvents.push(file);
});
w.on("aggregated", function(changes) {
Array.from(changes).should.be.eql([path.join(fixtures, "dir")]);
changeEvents.should.be.eql([path.join(fixtures, "dir", "sub", "a")]);
const files = new Map();
const directories = new Map();
const times = w.getTimeInfoEntries();
w.getTimeInfoEntries(files, directories);
// aggregated results should be the same as seperated maps
Array.from(times).sort().should.be.eql([...Array.from(files), ...Array.from(directories)].sort())
const dir = directories.get(path.join(fixtures, "dir"));
const sub = directories.get(path.join(fixtures, "dir", "sub"));
const a = files.get(path.join(fixtures, "dir", "sub", "a"));
dir.should.be.type("object");
dir.should.have.property("safeTime");
sub.safeTime.should.be.aboveOrEqual(a.safeTime);
dir.safeTime.should.be.aboveOrEqual(sub.safeTime);
w.close();
done();
});
testHelper.dir("dir");
testHelper.dir(path.join("dir", "sub"));
testHelper.tick(function() {
w.watch([], [path.join(fixtures, "dir")]);
testHelper.tick(function() {
testHelper.file(path.join("dir", "sub", "a"));
});
});
});

it("should watch 2 files in a not-existing directory", function(done) {
var w = new Watchpack({
aggregateTimeout: 1000
Expand Down

0 comments on commit 4c9c76f

Please sign in to comment.