Socket
Socket
Sign inDemoInstall

watchpack

Package Overview
Dependencies
2
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-beta.13 to 2.0.0-beta.14

lib/reducePlan.js

252

lib/DirectoryWatcher.js

@@ -11,2 +11,4 @@ /*

const watchEventSource = require("./watchEventSource");
const EXISTANCE_ONLY_TIME_ENTRY = Object.freeze({});

@@ -81,2 +83,3 @@

: false;
this.timeout = undefined;
this.initialScanRemoved = new Set();

@@ -107,9 +110,8 @@ this.initialScanFinished = undefined;

if (this.polledWatching) {
// Poll for changes
const interval = setInterval(() => {
this.doScan(false);
}, this.polledWatching);
this.watcher = {
close: () => {
clearInterval(interval);
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = undefined;
}
}

@@ -121,3 +123,3 @@ };

}
this.watcher = fs.watch(this.path);
this.watcher = watchEventSource.watch(this.path);
this.watcher.on("change", this.onWatchEvent.bind(this));

@@ -155,3 +157,3 @@ this.watcher.on("error", this.onWatcherError.bind(this));

this.forEachWatcher(this.path, w =>
w.emit("change", itemPath, null, type)
w.emit("change", itemPath, null, type, initial)
);

@@ -175,3 +177,3 @@ }

this.forEachWatcher(this.path, w =>
w.emit("change", itemPath, null, type)
w.emit("change", itemPath, null, type, initial)
);

@@ -220,4 +222,4 @@ }

if (count !== undefined) {
// There is already a file with case-insenstive-equal name
// On a case-insenstive filesystem we may miss the renaming
// There is already a file with case-insensitive-equal name
// On a case-insensitive filesystem we may miss the renaming
// when only casing is changed.

@@ -239,3 +241,3 @@ // To be sure that our information is correct

if (!initial || w.checkStartTime(safeTime, initial)) {
w.emit("change", filePath, safeTime, type);
w.emit("change", filePath, safeTime, type, initial);
}

@@ -250,3 +252,3 @@ });

this.forEachWatcher(this.path, w =>
w.emit("change", directoryPath, mtime, type)
w.emit("change", directoryPath, mtime, type, initial)
);

@@ -280,3 +282,3 @@ }

if (!initial || w.checkStartTime(safeTime, initial)) {
w.emit("change", directoryPath, safeTime, type);
w.emit("change", directoryPath, safeTime, type, initial);
}

@@ -290,7 +292,7 @@ });

const watcher = this.watcherManager.watchDirectory(directoryPath, 1);
watcher.on("change", (filePath, mtime, type) => {
watcher.on("change", (filePath, mtime, type, initial) => {
this._cachedTimeInfoEntries = undefined;
this.forEachWatcher(this.path, w => {
if (w.checkStartTime(mtime, false)) {
w.emit("change", filePath, mtime, type);
if (!initial || w.checkStartTime(mtime, initial)) {
w.emit("change", filePath, mtime, type, initial);
}

@@ -478,4 +480,14 @@ });

}
this.onScanFinished();
}
onScanFinished() {
if (this.polledWatching) {
this.timeout = setTimeout(() => {
if (this.closed) return;
this.doScan(false);
}, this.polledWatching);
}
}
onDirectoryRemoved(reason) {

@@ -520,3 +532,3 @@ if (this.watcher) {

this.forEachWatcher(this.path, w =>
w.emit("change", this.path, mtime, type)
w.emit("change", this.path, mtime, type, false)
);

@@ -542,120 +554,128 @@ }

this.scanning = true;
fs.readdir(this.path, (err, items) => {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = undefined;
}
process.nextTick(() => {
if (this.closed) return;
if (err) {
if (err.code === "ENOENT" || err.code === "EPERM") {
this.onDirectoryRemoved("scan readdir failed");
} else {
this.onScanError(err);
}
this.initialScan = false;
this.initialScanFinished = Date.now();
if (initial) {
for (const watchers of this.watchers.values()) {
for (const watcher of watchers) {
if (watcher.checkStartTime(this.initialScanFinished, false)) {
watcher.emit(
"initial-missing",
"scan (parent directory missing in initial scan)"
);
fs.readdir(this.path, (err, items) => {
if (this.closed) return;
if (err) {
if (err.code === "ENOENT" || err.code === "EPERM") {
this.onDirectoryRemoved("scan readdir failed");
} else {
this.onScanError(err);
}
this.initialScan = false;
this.initialScanFinished = Date.now();
if (initial) {
for (const watchers of this.watchers.values()) {
for (const watcher of watchers) {
if (watcher.checkStartTime(this.initialScanFinished, false)) {
watcher.emit(
"initial-missing",
"scan (parent directory missing in initial scan)"
);
}
}
}
}
if (this.scanAgain) {
this.scanAgain = false;
this.doScan(this.scanAgainInitial);
} else {
this.scanning = false;
}
return;
}
if (this.scanAgain) {
this.scanAgain = false;
this.doScan(this.scanAgainInitial);
} else {
this.scanning = false;
const itemPaths = new Set(
items.map(item => path.join(this.path, item.normalize("NFC")))
);
for (const file of this.files.keys()) {
if (!itemPaths.has(file)) {
this.setMissing(file, initial, "scan (missing)");
}
}
return;
}
const itemPaths = new Set(
items.map(item => path.join(this.path, item.normalize("NFC")))
);
for (const file of this.files.keys()) {
if (!itemPaths.has(file)) {
this.setMissing(file, initial, "scan (missing)");
}
}
for (const directory of this.directories.keys()) {
if (!itemPaths.has(directory)) {
this.setMissing(directory, initial, "scan (missing)");
}
}
if (this.scanAgain) {
// Early repeat of scan
this.scanAgain = false;
this.doScan(initial);
return;
}
const itemFinished = needCalls(itemPaths.size + 1, () => {
if (this.closed) return;
this.initialScan = false;
this.initialScanRemoved = null;
this.initialScanFinished = Date.now();
if (initial) {
const missingWatchers = new Map(this.watchers);
missingWatchers.delete(withoutCase(this.path));
for (const item of itemPaths) {
missingWatchers.delete(withoutCase(item));
for (const directory of this.directories.keys()) {
if (!itemPaths.has(directory)) {
this.setMissing(directory, initial, "scan (missing)");
}
for (const watchers of missingWatchers.values()) {
for (const watcher of watchers) {
if (watcher.checkStartTime(this.initialScanFinished, false)) {
watcher.emit(
"initial-missing",
"scan (missing in initial scan)"
);
}
}
}
}
if (this.scanAgain) {
// Early repeat of scan
this.scanAgain = false;
this.doScan(this.scanAgainInitial);
} else {
this.scanning = false;
this.doScan(initial);
return;
}
});
for (const itemPath of itemPaths) {
fs.lstat(itemPath, (err2, stats) => {
const itemFinished = needCalls(itemPaths.size + 1, () => {
if (this.closed) return;
if (err2) {
if (
err2.code === "ENOENT" ||
err2.code === "EPERM" ||
err2.code === "EBUSY"
) {
this.setMissing(itemPath, initial, "scan (" + err2.code + ")");
} else {
this.onScanError(err2);
this.initialScan = false;
this.initialScanRemoved = null;
this.initialScanFinished = Date.now();
if (initial) {
const missingWatchers = new Map(this.watchers);
missingWatchers.delete(withoutCase(this.path));
for (const item of itemPaths) {
missingWatchers.delete(withoutCase(item));
}
itemFinished();
return;
for (const watchers of missingWatchers.values()) {
for (const watcher of watchers) {
if (watcher.checkStartTime(this.initialScanFinished, false)) {
watcher.emit(
"initial-missing",
"scan (missing in initial scan)"
);
}
}
}
}
if (stats.isFile() || stats.isSymbolicLink()) {
if (stats.mtime) {
ensureFsAccuracy(stats.mtime);
if (this.scanAgain) {
this.scanAgain = false;
this.doScan(this.scanAgainInitial);
} else {
this.scanning = false;
this.onScanFinished();
}
});
for (const itemPath of itemPaths) {
fs.lstat(itemPath, (err2, stats) => {
if (this.closed) return;
if (err2) {
if (
err2.code === "ENOENT" ||
err2.code === "EPERM" ||
err2.code === "EBUSY"
) {
this.setMissing(itemPath, initial, "scan (" + err2.code + ")");
} else {
this.onScanError(err2);
}
itemFinished();
return;
}
this.setFileTime(
itemPath,
+stats.mtime || +stats.ctime || 1,
initial,
true,
"scan (file)"
);
} else if (stats.isDirectory()) {
if (!initial || !this.directories.has(itemPath))
this.setDirectory(
if (stats.isFile() || stats.isSymbolicLink()) {
if (stats.mtime) {
ensureFsAccuracy(stats.mtime);
}
this.setFileTime(
itemPath,
+stats.mtime || +stats.ctime || 1,
initial,
"scan (dir)"
true,
"scan (file)"
);
}
itemFinished();
});
}
itemFinished();
} else if (stats.isDirectory()) {
if (!initial || !this.directories.has(itemPath))
this.setDirectory(
itemPath,
+stats.mtime || +stats.ctime || 1,
initial,
"scan (dir)"
);
}
itemFinished();
});
}
itemFinished();
});
});

@@ -662,0 +682,0 @@ }

@@ -41,2 +41,6 @@ /*

const watcherManagers = new WeakMap();
/**
* @param {object} options options
* @returns {WatcherManager} the watcher manager
*/
module.exports = options => {

@@ -43,0 +47,0 @@ const watcherManager = watcherManagers.get(options);

@@ -11,2 +11,3 @@ /*

const globToRegExp = require("glob-to-regexp");
const watchEventSource = require("./watchEventSource");

@@ -16,2 +17,3 @@ let EXISTANCE_ONLY_TIME_ENTRY; // lazy required

const EMPTY_ARRAY = [];
const EMPTY_OPTIONS = {};

@@ -68,14 +70,17 @@ function addWatchersToSet(watchers, set) {

super();
if (!options) options = {};
if (typeof options.aggregateTimeout !== "number") {
options.aggregateTimeout = 200;
}
if (!options) options = EMPTY_OPTIONS;
this.options = options;
this.aggregateTimeout =
typeof options.aggregateTimeout === "number"
? options.aggregateTimeout
: 200;
this.watcherOptions = cachedNormalizeOptions(options);
this.watcherManager = getWatcherManager(this.watcherOptions);
this.watchers = [];
this.fileWatchers = new Map();
this.directoryWatchers = new Map();
this.startTime = undefined;
this.paused = false;
this.aggregatedChanges = new Set();
this.aggregatedRemovals = new Set();
this.aggregateTimeout = 0;
this.aggregateTimer = undefined;
this._onTimeout = this._onTimeout.bind(this);

@@ -100,3 +105,4 @@ }

this.paused = false;
const oldWatchers = this.watchers;
const oldFileWatchers = this.fileWatchers;
const oldDirectoryWatchers = this.directoryWatchers;
const ignored = this.watcherOptions.ignored;

@@ -106,3 +112,13 @@ const filter = ignored

: () => true;
this.watchers = [];
const addToMap = (map, key, item) => {
const list = map.get(key);
if (list === undefined) {
map.set(key, [item]);
} else {
list.push(item);
}
};
const fileWatchersNeeded = new Map();
const directoryWatchersNeeded = new Map();
const missingFiles = new Set();
if (this.watcherOptions.followSymlinks) {

@@ -114,7 +130,3 @@ const resolver = new LinkResolver();

if (file === innerFile || filter(innerFile)) {
const watcher = this._fileWatcher(
file,
this.watcherManager.watchFile(innerFile, startTime)
);
if (watcher) this.watchers.push(watcher);
addToMap(fileWatchersNeeded, innerFile, file);
}

@@ -128,7 +140,4 @@ }

if (file === innerFile || filter(innerFile)) {
const watcher = this._missingWatcher(
file,
this.watcherManager.watchFile(innerFile, startTime)
);
if (watcher) this.watchers.push(watcher);
missingFiles.add(file);
addToMap(fileWatchersNeeded, innerFile, file);
}

@@ -143,9 +152,7 @@ }

if (filter(innerItem)) {
const watcher = this._dirWatcher(
dir,
first
? this.watcherManager.watchDirectory(innerItem, startTime)
: this.watcherManager.watchFile(innerItem, startTime)
addToMap(
first ? directoryWatchersNeeded : fileWatchersNeeded,
innerItem,
dir
);
if (watcher) this.watchers.push(watcher);
}

@@ -159,7 +166,3 @@ first = false;

if (filter(file)) {
const watcher = this._fileWatcher(
file,
this.watcherManager.watchFile(file, startTime)
);
if (watcher) this.watchers.push(watcher);
addToMap(fileWatchersNeeded, file, file);
}

@@ -169,7 +172,4 @@ }

if (filter(file)) {
const watcher = this._missingWatcher(
file,
this.watcherManager.watchFile(file, startTime)
);
if (watcher) this.watchers.push(watcher);
missingFiles.add(file);
addToMap(fileWatchersNeeded, file, file);
}

@@ -179,11 +179,83 @@ }

if (filter(dir)) {
const watcher = this._dirWatcher(
dir,
this.watcherManager.watchDirectory(dir, startTime)
);
if (watcher) this.watchers.push(watcher);
addToMap(directoryWatchersNeeded, dir, dir);
}
}
}
for (const w of oldWatchers) w.close();
const newFileWatchers = new Map();
const newDirectoryWatchers = new Map();
const setupFileWatcher = (watcher, key, files) => {
watcher.on("initial-missing", type => {
for (const file of files) {
if (!missingFiles.has(file)) this._onRemove(file, file, type);
}
});
watcher.on("change", (mtime, type) => {
for (const file of files) {
this._onChange(file, mtime, file, type);
}
});
watcher.on("remove", type => {
for (const file of files) {
this._onRemove(file, file, type);
}
});
newFileWatchers.set(key, watcher);
};
const setupDirectoryWatcher = (watcher, key, directories) => {
watcher.on("initial-missing", type => {
for (const item of directories) {
this._onRemove(item, item, type);
}
});
watcher.on("change", (file, mtime, type) => {
for (const item of directories) {
this._onChange(item, mtime, file, type);
}
});
watcher.on("remove", type => {
for (const item of directories) {
this._onRemove(item, item, type);
}
});
newDirectoryWatchers.set(key, watcher);
};
// Close unneeded old watchers
const fileWatchersToClose = [];
const directoryWatchersToClose = [];
for (const [key, w] of oldFileWatchers) {
if (!fileWatchersNeeded.has(key)) {
w.close();
} else {
fileWatchersToClose.push(w);
}
}
for (const [key, w] of oldDirectoryWatchers) {
if (!directoryWatchersNeeded.has(key)) {
w.close();
} else {
directoryWatchersToClose.push(w);
}
}
// Create new watchers and install handlers on these watchers
watchEventSource.batch(() => {
for (const [key, files] of fileWatchersNeeded) {
const watcher = this.watcherManager.watchFile(key, startTime);
if (watcher) {
setupFileWatcher(watcher, key, files);
}
}
for (const [key, directories] of directoryWatchersNeeded) {
const watcher = this.watcherManager.watchDirectory(key, startTime);
if (watcher) {
setupDirectoryWatcher(watcher, key, directories);
}
}
});
// Close old watchers
for (const w of fileWatchersToClose) w.close();
for (const w of directoryWatchersToClose) w.close();
// Store watchers
this.fileWatchers = newFileWatchers;
this.directoryWatchers = newDirectoryWatchers;
this.startTime = startTime;
}

@@ -193,5 +265,7 @@

this.paused = true;
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
for (const w of this.watchers) w.close();
this.watchers.length = 0;
if (this.aggregateTimer) clearTimeout(this.aggregateTimer);
for (const w of this.fileWatchers.values()) w.close();
for (const w of this.directoryWatchers.values()) w.close();
this.fileWatchers.clear();
this.directoryWatchers.clear();
}

@@ -201,3 +275,3 @@

this.paused = true;
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
if (this.aggregateTimer) clearTimeout(this.aggregateTimer);
}

@@ -207,3 +281,4 @@

const directoryWatchers = new Set();
addWatchersToSet(this.watchers, directoryWatchers);
addWatchersToSet(this.fileWatchers.values(), directoryWatchers);
addWatchersToSet(this.directoryWatchers.values(), directoryWatchers);
const obj = Object.create(null);

@@ -223,3 +298,4 @@ for (const w of directoryWatchers) {

const directoryWatchers = new Set();
addWatchersToSet(this.watchers, directoryWatchers);
addWatchersToSet(this.fileWatchers.values(), directoryWatchers);
addWatchersToSet(this.directoryWatchers.values(), directoryWatchers);
const map = new Map();

@@ -288,9 +364,6 @@ for (const w of directoryWatchers) {

this.emit("change", file, mtime, type);
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
if (this.aggregateTimer) clearTimeout(this.aggregateTimer);
this.aggregatedRemovals.delete(item);
this.aggregatedChanges.add(item);
this.aggregateTimeout = setTimeout(
this._onTimeout,
this.options.aggregateTimeout
);
this.aggregateTimer = setTimeout(this._onTimeout, this.aggregateTimeout);
}

@@ -302,13 +375,10 @@

this.emit("remove", file, type);
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
if (this.aggregateTimer) clearTimeout(this.aggregateTimer);
this.aggregatedChanges.delete(item);
this.aggregatedRemovals.add(item);
this.aggregateTimeout = setTimeout(
this._onTimeout,
this.options.aggregateTimeout
);
this.aggregateTimer = setTimeout(this._onTimeout, this.aggregateTimeout);
}
_onTimeout() {
this.aggregateTimeout = 0;
this.aggregateTimer = undefined;
const changes = this.aggregatedChanges;

@@ -315,0 +385,0 @@ const removals = this.aggregatedRemovals;

{
"name": "watchpack",
"version": "2.0.0-beta.13",
"version": "2.0.0-beta.14",
"description": "",

@@ -5,0 +5,0 @@ "main": "./lib/watchpack.js",

@@ -69,11 +69,11 @@ # watchpack

// calling this again will override the files and directories
// files: can be files or directories, for files: content and existance changes are tracked
// for directories: only existance and timestamp changes are tracked
// files: can be files or directories, for files: content and existence changes are tracked
// for directories: only existence and timestamp changes are tracked
// directories: only directories, directory content (and content of children, ...) and
// existance changes are tracked.
// assumed to exist, when directory is not found without futher information a remove event is emitted
// missing: can be files or directores,
// only existance changes are tracked
// existence changes are tracked.
// assumed to exist, when directory is not found without further information a remove event is emitted
// missing: can be files or directorees,
// only existence changes are tracked
// expected to not exist, no remove event is emitted when not found initially
// files and directories are assumed to exist, when they are not found without futher information a remove event is emitted
// files and directories are assumed to exist, when they are not found without further information a remove event is emitted
// missing is assumed to not exist and no remove event is emitted

@@ -80,0 +80,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc