Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

watchpack

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

watchpack - npm Package Compare versions

Comparing version 2.0.0-beta.3 to 2.0.0-beta.4

463

lib/DirectoryWatcher.js

@@ -20,5 +20,6 @@ /*

const WATCHPACK_POLLING = process.env.WATCHPACK_POLLING;
const FORCE_POLLING = `${+WATCHPACK_POLLING}` === WATCHPACK_POLLING ?
+WATCHPACK_POLLING :
!!WATCHPACK_POLLING && WATCHPACK_POLLING !== "false";
const FORCE_POLLING =
`${+WATCHPACK_POLLING}` === WATCHPACK_POLLING
? +WATCHPACK_POLLING
: !!WATCHPACK_POLLING && WATCHPACK_POLLING !== "false";

@@ -39,3 +40,3 @@ function withoutCase(str) {

const startTime = this.startTime;
if(typeof startTime !== "number") return !initial;
if (typeof startTime !== "number") return !initial;
return startTime <= mtime;

@@ -52,3 +53,3 @@ }

super();
if(FORCE_POLLING) {
if (FORCE_POLLING) {
options.poll = FORCE_POLLING;

@@ -65,5 +66,10 @@ }

this.initialScan = true;
this.ignored = options.ignored;
this.nestedWatching = false;
this.polledWatching = typeof options.poll === "number" ? options.poll : options.poll ? 5007 : false;
this.filesWatchListener = new Map();
this.polledWatching =
typeof options.poll === "number"
? options.poll
: options.poll
? 5007
: false;
this.initialScanRemoved = new Set();

@@ -77,2 +83,3 @@ this.watchers = new Map();

this.scanAgain = false;
this.scanAgainInitial = false;

@@ -83,24 +90,22 @@ this.createWatcher();

checkIgnore(path) {
if (!this.ignored) return false;
path = path.replace(/\\/g, "/");
return this.ignored.test(path);
}
createWatcher() {
try {
// TODO options.ignored
if(this.polledWatching) {
const listener = this.onWatchFileEvent.bind(this);
fs.watchFile(this.path, { persistent: true, interval: this.polledWatching }, listener);
// Fallback to caputure too late attached watchers
const timeout = setTimeout(() => {
fs.stat(this.path, (err, stats) => {
if(!err) {
listener(stats);
}
})
}, 1000);
if (this.polledWatching) {
// Poll for changes
const interval = setInterval(() => {
this.doScan(false);
}, this.polledWatching);
this.watcher = {
close: () => {
clearTimeout(timeout);
fs.unwatchFile(this.path, listener);
clearInterval(interval);
}
};
} else {
if(IS_OSX) {
if (IS_OSX) {
this.watchInParentDirectory();

@@ -112,3 +117,3 @@ }

}
} catch(err) {
} catch (err) {
this.onWatcherError(err);

@@ -120,4 +125,4 @@ }

const watchers = this.watchers.get(withoutCase(path));
if(watchers !== undefined) {
for(const w of watchers) {
if (watchers !== undefined) {
for (const w of watchers) {
fn(w);

@@ -129,3 +134,3 @@ }

setMissing(itemPath, initial, type) {
if(this.initialScan) {
if (this.initialScan) {
this.initialScanRemoved.add(itemPath);

@@ -135,10 +140,11 @@ }

const oldDirectory = this.directories.get(itemPath);
if(oldDirectory) {
if(this.nestedWatching)
oldDirectory.close();
if (oldDirectory) {
if (this.nestedWatching) oldDirectory.close();
this.directories.delete(itemPath);
this.forEachWatcher(itemPath, w => w.emit("remove", type));
if(!initial) {
this.forEachWatcher(this.path, w => w.emit("change", itemPath, null, type));
if (!initial) {
this.forEachWatcher(this.path, w =>
w.emit("change", itemPath, null, type)
);
}

@@ -148,18 +154,12 @@ }

const oldFile = this.files.get(itemPath);
if(oldFile) {
if (oldFile) {
this.files.delete(itemPath);
this.forEachWatcher(itemPath, w => w.emit("remove", type));
if(!initial) {
this.forEachWatcher(this.path, w => w.emit("change", itemPath, null, type));
if (!initial) {
this.forEachWatcher(this.path, w =>
w.emit("change", itemPath, null, type)
);
}
}
if(this.polledWatching) {
const oldListener = this.filesWatchListener.get(itemPath);
if(oldListener) {
this.filesWatchListener.delete(itemPath);
fs.unwatchFile(itemPath, oldListener);
}
}
}

@@ -169,6 +169,9 @@

const now = Date.now();
if (this.checkIgnore(filePath)) return;
const old = this.files.get(filePath);
let safeTime, accuracy;
if(initial) {
if (initial) {
safeTime = Math.min(now, mtime) + FS_ACCURACY;

@@ -181,3 +184,3 @@ accuracy = FS_ACCURACY;

if(ignoreWhenEqual && old && old.timestamp === mtime) return;
if (ignoreWhenEqual && old && old.timestamp === mtime) return;

@@ -190,17 +193,13 @@ this.files.set(filePath, {

if(this.polledWatching) {
this._ensureFilePolling(filePath);
}
if(!old) {
if (!old) {
this.forEachWatcher(filePath, w => {
if(!initial || w.checkStartTime(safeTime, initial)) {
if (!initial || w.checkStartTime(safeTime, initial)) {
w.emit("change", mtime, type);
}
});
} else if(!initial) {
} else if (!initial) {
this.forEachWatcher(filePath, w => w.emit("change", mtime, type));
}
this.forEachWatcher(this.path, w => {
if(!initial || w.checkStartTime(safeTime, initial)) {
if (!initial || w.checkStartTime(safeTime, initial)) {
w.emit("change", filePath, safeTime, type);

@@ -212,16 +211,15 @@ }

setDirectory(directoryPath, mtime, initial, type) {
if(directoryPath === this.path) {
if(!initial) {
this.forEachWatcher(this.path, w => w.emit("change", directoryPath, mtime, type));
if (this.checkIgnore(directoryPath)) return;
if (directoryPath === this.path) {
if (!initial) {
this.forEachWatcher(this.path, w =>
w.emit("change", directoryPath, mtime, type)
);
}
} else {
const old = this.directories.get(directoryPath);
if(!old) {
if (!old) {
const now = Date.now();
if(this.polledWatching) {
this._ensureFilePolling(directoryPath);
}
if(this.nestedWatching) {
if (this.nestedWatching) {
this.createNestedWatcher(directoryPath);

@@ -233,3 +231,3 @@ } else {

let safeTime;
if(initial) {
if (initial) {
safeTime = Math.min(now, mtime) + FS_ACCURACY;

@@ -241,3 +239,3 @@ } else {

this.forEachWatcher(directoryPath, w => {
if(!initial || w.checkStartTime(safeTime, false)) {
if (!initial || w.checkStartTime(safeTime, false)) {
w.emit("change", mtime, type);

@@ -247,3 +245,3 @@ }

this.forEachWatcher(this.path, w => {
if(!initial || w.checkStartTime(safeTime, initial)) {
if (!initial || w.checkStartTime(safeTime, initial)) {
w.emit("change", directoryPath, safeTime, type);

@@ -257,6 +255,10 @@ }

createNestedWatcher(directoryPath) {
const watcher = watcherManager.watchDirectory(directoryPath, this.options, 1);
const watcher = watcherManager.watchDirectory(
directoryPath,
this.options,
1
);
watcher.on("change", (filePath, mtime, type) => {
this.forEachWatcher(this.path, w => {
if(w.checkStartTime(mtime, false)) {
if (w.checkStartTime(mtime, false)) {
w.emit("change", filePath, mtime, type);

@@ -269,28 +271,11 @@ }

_ensureFilePolling(path) {
if(!this.filesWatchListener.has(path)) {
const listener = this.onWatchFileChildEvent.bind(this, path);
this.filesWatchListener.set(path, listener);
fs.watchFile(path, { persistent: true, interval: this.polledWatching }, listener);
// It's possible that we miss the first event
// so we have a fallback after 1s
setTimeout(() => {
fs.stat(path, (err, stats) => {
if(!err) {
listener(stats);
}
})
}, 1000);
}
}
setNestedWatching(flag) {
if(this.nestedWatching !== !!flag) {
if (this.nestedWatching !== !!flag) {
this.nestedWatching = !!flag;
if(this.nestedWatching) {
for(const directory of this.directories.keys()) {
if (this.nestedWatching) {
for (const directory of this.directories.keys()) {
this.createNestedWatcher(directory);
}
} else {
for(const [directory, watcher] of this.directories) {
for (const [directory, watcher] of this.directories) {
watcher.close();

@@ -306,3 +291,3 @@ this.directories.set(directory, true);

let watchers = this.watchers.get(key);
if(watchers === undefined) {
if (watchers === undefined) {
watchers = new Set();

@@ -315,23 +300,20 @@ this.watchers.set(key, watchers);

watchers.delete(watcher);
if(watchers.size === 0) {
if (watchers.size === 0) {
this.watchers.delete(key);
if(this.path === filePath)
this.setNestedWatching(false);
if (this.path === filePath) this.setNestedWatching(false);
}
if(--this.refs <= 0)
this.close();
if (--this.refs <= 0) this.close();
});
watchers.add(watcher);
let safeTime;
if(filePath === this.path) {
if (filePath === this.path) {
this.setNestedWatching(true);
safeTime = this.lastWatchEvent;
for(const entry of this.files.values()) {
for (const entry of this.files.values()) {
fixupEntryAccuracy(entry);
safeTime = Math.max(safeTime, entry.safeTime);
}
} else {
const entry = this.files.get(filePath);
if(entry) {
if (entry) {
fixupEntryAccuracy(entry);

@@ -344,7 +326,6 @@ safeTime = entry.safeTime;

process.nextTick(() => {
if(this.closed) return;
if(safeTime) {
if(safeTime >= startTime)
watcher.emit("change", safeTime);
} else if(this.initialScan && this.initialScanRemoved.has(filePath)) {
if (this.closed) return;
if (safeTime) {
if (safeTime >= startTime) watcher.emit("change", safeTime);
} else if (this.initialScan && this.initialScanRemoved.has(filePath)) {
watcher.emit("remove");

@@ -357,4 +338,4 @@ }

onWatchEvent(eventType, filename) {
if(this.closed) return;
if(!filename) {
if (this.closed) return;
if (!filename) {
// In some cases no filename is provided

@@ -367,11 +348,14 @@ // This seem to happen on windows

}
if(this._activeEvents.get(filename) === undefined) {
const filePath = path.join(this.path, filename);
if (this.checkIgnore(filePath)) return;
if (this._activeEvents.get(filename) === undefined) {
this._activeEvents.set(filename, false);
const checkStats = () => {
if(this.closed) return;
if (this.closed) return;
this._activeEvents.set(filename, false);
const filePath = path.join(this.path, filename);
fs.stat(filePath, (err, stats) => {
if(this.closed) return;
if(this._activeEvents.get(filename) === true) {
if (this.closed) return;
if (this._activeEvents.get(filename) === true) {
process.nextTick(checkStats);

@@ -383,9 +367,13 @@ return;

// EPERM happens when the containing directory doesn't exist
if(err) {
if(err.code !== "ENOENT" && err.code !== "EPERM" && err.code !== "EBUSY") {
if (err) {
if (
err.code !== "ENOENT" &&
err.code !== "EPERM" &&
err.code !== "EBUSY"
) {
this.onStatsError(err);
} else {
if(filename === path.basename(this.path)) {
if (filename === path.basename(this.path)) {
// This may indicate that the directory itself was removed
if(!fs.existsSync(this.path)) {
if (!fs.existsSync(this.path)) {
this.onDirectoryRemoved();

@@ -397,11 +385,22 @@ }

this.lastWatchEvent = Date.now();
if(!stats) {
if (!stats) {
this.setMissing(filePath, false, eventType);
} else if(stats.isDirectory()) {
this.setDirectory(filePath, +stats.mtime || +stats.ctime || 1, false, eventType);
} else if (stats.isDirectory()) {
this.setDirectory(
filePath,
+stats.mtime || +stats.ctime || 1,
false,
eventType
);
} else {
if(stats.mtime) {
if (stats.mtime) {
ensureFsAccuracy(stats.mtime);
}
this.setFileTime(filePath, +stats.mtime || +stats.ctime || 1, false, false, eventType);
this.setFileTime(
filePath,
+stats.mtime || +stats.ctime || 1,
false,
false,
eventType
);
}

@@ -416,31 +415,6 @@ });

onWatchFileEvent(current) {
if(this.closed) return;
if(current.isDirectory()) {
this.lastWatchEvent = Date.now();
this.doScan(false);
} else {
this.onDirectoryRemoved();
}
}
onWatchFileChildEvent(path, stats) {
if(this.closed) return;
this.lastWatchEvent = Date.now();
if(stats.isFile()) {
if(stats.mtime) {
ensureFsAccuracy(stats.mtime);
}
this.setFileTime(path, +stats.mtime || +stats.ctime || 1, false, true, "poll");
} else if(stats.isDirectory()) {
this.setDirectory(path, +stats.mtime || +stats.ctime || 1, false, "poll");
} else {
this.setMissing(path, false, "poll");
}
}
onWatcherError(err) {
if(this.closed) return;
if(err) {
if(err.code !== "EPERM" && err.code !== "ENOENT") {
if (this.closed) return;
if (err) {
if (err.code !== "EPERM" && err.code !== "ENOENT") {
console.error("Watchpack Error (watcher): " + err);

@@ -453,3 +427,3 @@ }

onStatsError(err) {
if(err) {
if (err) {
console.error("Watchpack Error (stats): " + err);

@@ -460,3 +434,3 @@ }

onScanError(err) {
if(err) {
if (err) {
console.error("Watchpack Error (initial scan): " + err);

@@ -467,11 +441,10 @@ }

onDirectoryRemoved() {
if(this.watcher) {
this.watcher.close(),
this.watcher = null;
if (this.watcher) {
this.watcher.close(), (this.watcher = null);
}
this.watchInParentDirectory();
for(const directory of this.directories.keys()) {
for (const directory of this.directories.keys()) {
this.setMissing(directory, null, "directory-removed");
}
for(const file of this.files.keys()) {
for (const file of this.files.keys()) {
this.setMissing(file, null, "directory-removed");

@@ -482,15 +455,15 @@ }

watchInParentDirectory() {
if(!this.parentWatcher) {
if (!this.parentWatcher) {
const parentDir = path.dirname(this.path);
// avoid watching in the root directory
// removing directories in the root directory is not supported
if(path.dirname(parentDir) === parentDir) return;
if (path.dirname(parentDir) === parentDir) return;
this.parentWatcher = watcherManager.watchFile(this.path, this.options, 1);
this.parentWatcher.on("change", (mtime, type) => {
if(this.closed) return;
if (this.closed) return;
// On non-osx platforms we don't need this watcher to detect
// directory removal, as a EPERM error indicates that
if(!IS_OSX && this.parentWatcher) {
if ((!IS_OSX || this.polledWatching) && this.parentWatcher) {
this.parentWatcher.close();

@@ -500,3 +473,3 @@ this.parentWatcher = null;

// Try to create the watcher when parent directory is found
if(!this.watcher) {
if (!this.watcher) {
this.createWatcher();

@@ -506,3 +479,5 @@ this.doScan(false);

// directory was created so we emit a event
this.forEachWatcher(this.path, w => w.emit("change", this.path, mtime, type));
this.forEachWatcher(this.path, w =>
w.emit("change", this.path, mtime, type)
);
}

@@ -517,4 +492,9 @@ });

doScan(initial) {
if(this.scanning) {
this.scanAgain = true;
if (this.scanning) {
if (this.scanAgain) {
if (!initial) this.scanAgainInitial = false;
} else {
this.scanAgain = true;
this.scanAgainInitial = initial;
}
return;

@@ -524,6 +504,6 @@ }

fs.readdir(this.path, (err, items) => {
if(this.closed) return;
if(err) {
if(err.code === "ENOENT" || err.code === "EPERM") {
this.watchInParentDirectory();
if (this.closed) return;
if (err) {
if (err.code === "ENOENT" || err.code === "EPERM") {
this.onDirectoryRemoved();
} else {

@@ -533,5 +513,5 @@ this.onScanError(err);

this.initialScan = false;
if(this.scanAgain) {
if (this.scanAgain) {
this.scanAgain = false;
this.doScan(false);
this.doScan(this.scanAgainInitial);
} else {

@@ -543,8 +523,13 @@ this.scanning = false;

const itemPaths = new Set(items.map(item => path.join(this.path, item)));
for(const file of this.files) {
if(!itemPaths.has(file)) {
for (const file of this.files.keys()) {
if (!itemPaths.has(file)) {
this.setMissing(file, initial, "scan (missing)");
}
}
if(this.scanAgain) {
for (const directory of this.directories.keys()) {
if (!itemPaths.has(directory)) {
this.setMissing(directory, initial, "scan (missing)");
}
}
if (this.scanAgain) {
// Early repeat of scan

@@ -555,36 +540,55 @@ this.scanAgain = false;

}
async.forEach(itemPaths, (itemPath, callback) => {
fs.stat(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);
async.forEach(
itemPaths,
(itemPath, callback) => {
fs.stat(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);
}
callback();
return;
}
if (stats.isFile()) {
if (stats.mtime) {
ensureFsAccuracy(stats.mtime);
}
this.setFileTime(
itemPath,
+stats.mtime || +stats.ctime || 1,
initial,
true,
"scan (file)"
);
} else if (stats.isDirectory()) {
if (!initial || !this.directories.has(itemPath))
this.setDirectory(
itemPath,
+stats.mtime || +stats.ctime || 1,
initial,
"scan (dir)"
);
}
callback();
return;
});
},
() => {
if (this.closed) return;
this.initialScan = false;
this.initialScanRemoved = null;
if (this.scanAgain) {
this.scanAgain = false;
this.doScan(this.scanAgainInitial);
} else {
this.scanning = false;
}
if(stats.isFile()) {
if(stats.mtime) {
ensureFsAccuracy(stats.mtime);
}
this.setFileTime(itemPath, +stats.mtime || +stats.ctime || 1, initial, true, "scan (file)");
} else if(stats.isDirectory()) {
if(!initial || !this.directories.has(itemPath))
this.setDirectory(itemPath, +stats.mtime || +stats.ctime || 1, initial, "scan (dir)");
}
callback();
});
}, () => {
if(this.closed) return;
this.initialScan = false;
this.initialScanRemoved = null;
if(this.scanAgain) {
this.scanAgain = false;
this.doScan(false);
} else {
this.scanning = false;
}
});
);
});

@@ -596,3 +600,3 @@ }

let safeTime = this.lastWatchEvent;
for(const [file, entry] of this.files) {
for (const [file, entry] of this.files) {
fixupEntryAccuracy(entry);

@@ -602,4 +606,4 @@ safeTime = Math.max(safeTime, entry.safeTime);

}
if(this.nestedWatching) {
for(const w of this.directories.values()) {
if (this.nestedWatching) {
for (const w of this.directories.values()) {
const times = w.directoryWatcher.getTimes();

@@ -614,7 +618,7 @@ Object.keys(times).forEach(function(file) {

}
if(!this.initialScan) {
for(const watchers of this.watchers.values()) {
for(const watcher of watchers) {
if (!this.initialScan) {
for (const watchers of this.watchers.values()) {
for (const watcher of watchers) {
const path = watcher.path;
if(!Object.prototype.hasOwnProperty.call(obj, path)) {
if (!Object.prototype.hasOwnProperty.call(obj, path)) {
obj[path] = null;

@@ -631,3 +635,3 @@ }

let safeTime = this.lastWatchEvent;
for(const [file, entry] of this.files) {
for (const [file, entry] of this.files) {
fixupEntryAccuracy(entry);

@@ -637,7 +641,7 @@ safeTime = Math.max(safeTime, entry.safeTime);

}
if(this.nestedWatching) {
for(const w of this.directories.values()) {
if (this.nestedWatching) {
for (const w of this.directories.values()) {
const timeInfoEntries = w.directoryWatcher.getTimeInfoEntries();
for(const [file, entry] of timeInfoEntries) {
if(entry) {
for (const [file, entry] of timeInfoEntries) {
if (entry) {
safeTime = Math.max(safeTime, entry.safeTime);

@@ -652,3 +656,3 @@ }

} else {
for(const dir of this.directories.keys()) {
for (const dir of this.directories.keys()) {
// No additional info about this directory

@@ -659,7 +663,7 @@ map.set(dir, EXISTANCE_ONLY_TIME_ENTRY);

}
if(!this.initialScan) {
for(const watchers of this.watchers.values()) {
for(const watcher of watchers) {
if (!this.initialScan) {
for (const watchers of this.watchers.values()) {
for (const watcher of watchers) {
const path = watcher.path;
if(!map.has(path)) {
if (!map.has(path)) {
map.set(path, null);

@@ -676,8 +680,8 @@ }

this.initialScan = false;
if(this.watcher) {
if (this.watcher) {
this.watcher.close();
this.watcher = null;
}
if(this.nestedWatching) {
for(const w of this.directories.values()) {
if (this.nestedWatching) {
for (const w of this.directories.values()) {
w.close();

@@ -687,7 +691,3 @@ }

}
for(const [file, listener] of this.filesWatchListener) {
fs.unwatchFile(file, listener);
}
this.filesWatchListener.clear();
if(this.parentWatcher) {
if (this.parentWatcher) {
this.parentWatcher.close();

@@ -704,3 +704,3 @@ this.parentWatcher = null;

function fixupEntryAccuracy(entry) {
if(entry.accuracy > FS_ACCURACY) {
if (entry.accuracy > FS_ACCURACY) {
entry.safeTime = entry.safeTime - entry.accuracy + FS_ACCURACY;

@@ -712,9 +712,6 @@ entry.accuracy = FS_ACCURACY;

function ensureFsAccuracy(mtime) {
if(!mtime) return;
if(FS_ACCURACY > 1 && mtime % 1 !== 0)
FS_ACCURACY = 1;
else if(FS_ACCURACY > 10 && mtime % 10 !== 0)
FS_ACCURACY = 10;
else if(FS_ACCURACY > 100 && mtime % 100 !== 0)
FS_ACCURACY = 100;
if (!mtime) return;
if (FS_ACCURACY > 1 && mtime % 1 !== 0) FS_ACCURACY = 1;
else if (FS_ACCURACY > 10 && mtime % 10 !== 0) FS_ACCURACY = 10;
else if (FS_ACCURACY > 100 && mtime % 100 !== 0) FS_ACCURACY = 100;
}

@@ -17,3 +17,3 @@ /*

getDirectoryWatcher(directory, options) {
if(DirectoryWatcher === undefined) {
if (DirectoryWatcher === undefined) {
DirectoryWatcher = require("./DirectoryWatcher");

@@ -24,3 +24,3 @@ }

const watcher = this.directoryWatchers.get(key);
if(watcher === undefined) {
if (watcher === undefined) {
const newWatcher = new DirectoryWatcher(directory, options);

@@ -42,3 +42,6 @@ this.directoryWatchers.set(key, newWatcher);

watchDirectory(directory, options, startTime) {
return this.getDirectoryWatcher(directory, options).watch(directory, startTime);
return this.getDirectoryWatcher(directory, options).watch(
directory,
startTime
);
}

@@ -45,0 +48,0 @@ }

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

const EventEmitter = require("events").EventEmitter;
const globToRegExp = require("glob-to-regexp");

@@ -14,4 +15,4 @@ let EXISTANCE_ONLY_TIME_ENTRY; // lazy required

function addWatchersToSet(watchers, set) {
for(const w of watchers) {
if(w !== true && !set.has(w.directoryWatcher)) {
for (const w of watchers) {
if (w !== true && !set.has(w.directoryWatcher)) {
set.add(w.directoryWatcher);

@@ -23,10 +24,29 @@ addWatchersToSet(w.directoryWatcher.directories.values(), set);

const stringToRegexp = ignored => {
const source = globToRegExp(ignored, { globstar: true, extended: true })
.source;
const matchingStart = source.slice(0, source.length - 1) + "(?:$|\\/)";
return matchingStart;
};
const ignoredToRegexp = 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) {
throw new Error(`Invalid option for 'ignored': ${ignored}`);
} else {
return undefined;
}
};
class Watchpack extends EventEmitter {
constructor(options) {
super();
if(!options) options = {};
if(!options.aggregateTimeout) options.aggregateTimeout = 200;
if (!options) options = {};
if (!options.aggregateTimeout) options.aggregateTimeout = 200;
this.options = options;
this.watcherOptions = {
ignored: options.ignored,
ignored: ignoredToRegexp(options.ignored),
poll: options.poll

@@ -47,8 +67,21 @@ };

const oldDirWatchers = this.dirWatchers;
this.fileWatchers = files.map(file =>
this._fileWatcher(file, watcherManager.watchFile(file, this.watcherOptions, startTime))
);
this.dirWatchers = directories.map(dir =>
this._dirWatcher(dir, watcherManager.watchDirectory(dir, this.watcherOptions, startTime))
);
const filter = this.watcherOptions.ignored
? path => !this.watcherOptions.ignored.test(path.replace(/\\/g, "/"))
: () => true;
this.fileWatchers = files
.filter(filter)
.map(file =>
this._fileWatcher(
file,
watcherManager.watchFile(file, this.watcherOptions, startTime)
)
);
this.dirWatchers = directories
.filter(filter)
.map(dir =>
this._dirWatcher(
dir,
watcherManager.watchDirectory(dir, this.watcherOptions, startTime)
)
);
oldFileWatchers.forEach(w => w.close());

@@ -60,4 +93,3 @@ oldDirWatchers.forEach(w => w.close());

this.paused = true;
if(this.aggregateTimeout)
clearTimeout(this.aggregateTimeout);
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
this.fileWatchers.forEach(w => w.close());

@@ -71,4 +103,3 @@ this.dirWatchers.forEach(w => w.close());

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

@@ -81,5 +112,5 @@

const obj = Object.create(null);
for(const w of directoryWatchers) {
for (const w of directoryWatchers) {
const times = w.getTimes();
Object.keys(times).forEach(file => obj[file] = times[file]);
Object.keys(times).forEach(file => (obj[file] = times[file]));
}

@@ -90,4 +121,5 @@ return obj;

getTimeInfoEntries() {
if(EXISTANCE_ONLY_TIME_ENTRY === undefined) {
EXISTANCE_ONLY_TIME_ENTRY = require("./DirectoryWatcher").EXISTANCE_ONLY_TIME_ENTRY;
if (EXISTANCE_ONLY_TIME_ENTRY === undefined) {
EXISTANCE_ONLY_TIME_ENTRY = require("./DirectoryWatcher")
.EXISTANCE_ONLY_TIME_ENTRY;
}

@@ -98,10 +130,10 @@ const directoryWatchers = new Set();

const map = new Map();
for(const w of directoryWatchers) {
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;
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) {
if (value === entry) continue;
if (value !== EXISTANCE_ONLY_TIME_ENTRY) {
map.set(path, Object.assign({}, value, entry));

@@ -121,3 +153,3 @@ continue;

});
watcher.on("remove", (type) => {
watcher.on("remove", type => {
this._onRemove(file, file, type);

@@ -137,8 +169,10 @@ });

file = file || item;
if(this.paused) return;
if (this.paused) return;
this.emit("change", file, mtime, type);
if(this.aggregateTimeout)
clearTimeout(this.aggregateTimeout);
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
this.aggregatedChanges.add(item);
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout);
this.aggregateTimeout = setTimeout(
this._onTimeout,
this.options.aggregateTimeout
);
}

@@ -148,8 +182,10 @@

file = file || item;
if(this.paused) return;
if (this.paused) return;
this.emit("remove", item);
if(this.aggregateTimeout)
clearTimeout(this.aggregateTimeout);
if (this.aggregateTimeout) clearTimeout(this.aggregateTimeout);
this.aggregatedRemovals.add(item);
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout);
this.aggregateTimeout = setTimeout(
this._onTimeout,
this.options.aggregateTimeout
);
}

@@ -156,0 +192,0 @@

{
"name": "watchpack",
"version": "2.0.0-beta.3",
"version": "2.0.0-beta.4",
"description": "",

@@ -17,2 +17,3 @@ "main": "./lib/watchpack.js",

"precover": "yarn lint",
"pretty-files": "prettier \"lib/**.*\" \"test/**/*.js\" --write",
"cover": "istanbul cover node_modules/mocha/bin/_mocha"

@@ -33,4 +34,6 @@ },

"eslint": "^5.11.1",
"eslint-plugin-prettier": "^3.1.0",
"istanbul": "^0.4.3",
"mocha": "^5.0.1",
"prettier": "^1.11.0",
"rimraf": "^2.6.2",

@@ -40,2 +43,4 @@ "should": "^8.3.1"

"dependencies": {
"eslint-config-prettier": "^4.3.0",
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2",

@@ -42,0 +47,0 @@ "neo-async": "^2.5.0"

@@ -36,2 +36,7 @@ # watchpack

// When WATCHPACK_POLLING environment variable is set it will override this option
ignored: "**/.git",
// ignored: "string" - a glob pattern for files or folders that should not be watched
// ignored: ["string", "string"] - multiple glob patterns that should be ignored
// All subdirectories are ignored too
});

@@ -38,0 +43,0 @@

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc