diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
| commit | d1d9f00b1bd660842addf5e6b1d1b64c852a9eea (patch) | |
| tree | 60fb37ae73a1109d95301de5ec9b61b5726a4b61 /node_modules/watchpack/lib/watchEventSource.js | |
| parent | 7c85166c4cbdd862fc4252007d2df5befcbc2a58 (diff) | |
added hover prefixer
Diffstat (limited to 'node_modules/watchpack/lib/watchEventSource.js')
| -rw-r--r-- | node_modules/watchpack/lib/watchEventSource.js | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/node_modules/watchpack/lib/watchEventSource.js b/node_modules/watchpack/lib/watchEventSource.js new file mode 100644 index 00000000..3583c2e1 --- /dev/null +++ b/node_modules/watchpack/lib/watchEventSource.js @@ -0,0 +1,335 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const { EventEmitter } = require("events"); +const reducePlan = require("./reducePlan"); + +const IS_OSX = require("os").platform() === "darwin"; +const IS_WIN = require("os").platform() === "win32"; +const SUPPORTS_RECURSIVE_WATCHING = IS_OSX || IS_WIN; + +const watcherLimit = + +process.env.WATCHPACK_WATCHER_LIMIT || (IS_OSX ? 2000 : 10000); + +const recursiveWatcherLogging = !!process.env + .WATCHPACK_RECURSIVE_WATCHER_LOGGING; + +let isBatch = false; +let watcherCount = 0; + +/** @type {Map<Watcher, string>} */ +const pendingWatchers = new Map(); + +/** @type {Map<string, RecursiveWatcher>} */ +const recursiveWatchers = new Map(); + +/** @type {Map<string, DirectWatcher>} */ +const directWatchers = new Map(); + +/** @type {Map<Watcher, RecursiveWatcher | DirectWatcher>} */ +const underlyingWatcher = new Map(); + +class DirectWatcher { + constructor(filePath) { + this.filePath = filePath; + this.watchers = new Set(); + this.watcher = undefined; + try { + const watcher = fs.watch(filePath); + this.watcher = watcher; + watcher.on("change", (type, filename) => { + for (const w of this.watchers) { + w.emit("change", type, filename); + } + }); + watcher.on("error", error => { + for (const w of this.watchers) { + w.emit("error", error); + } + }); + } catch (err) { + process.nextTick(() => { + for (const w of this.watchers) { + w.emit("error", err); + } + }); + } + watcherCount++; + } + + add(watcher) { + underlyingWatcher.set(watcher, this); + this.watchers.add(watcher); + } + + remove(watcher) { + this.watchers.delete(watcher); + if (this.watchers.size === 0) { + directWatchers.delete(this.filePath); + watcherCount--; + if (this.watcher) this.watcher.close(); + } + } + + getWatchers() { + return this.watchers; + } +} + +class RecursiveWatcher { + constructor(rootPath) { + this.rootPath = rootPath; + /** @type {Map<Watcher, string>} */ + this.mapWatcherToPath = new Map(); + /** @type {Map<string, Set<Watcher>>} */ + this.mapPathToWatchers = new Map(); + this.watcher = undefined; + try { + const watcher = fs.watch(rootPath, { + recursive: true + }); + this.watcher = watcher; + watcher.on("change", (type, filename) => { + if (!filename) { + if (recursiveWatcherLogging) { + process.stderr.write( + `[watchpack] dispatch ${type} event in recursive watcher (${ + this.rootPath + }) to all watchers\n` + ); + } + for (const w of this.mapWatcherToPath.keys()) { + w.emit("change", type); + } + } else { + const dir = path.dirname(filename); + const watchers = this.mapPathToWatchers.get(dir); + if (recursiveWatcherLogging) { + process.stderr.write( + `[watchpack] dispatch ${type} event in recursive watcher (${ + this.rootPath + }) for '${filename}' to ${ + watchers ? watchers.size : 0 + } watchers\n` + ); + } + if (watchers === undefined) return; + for (const w of watchers) { + w.emit("change", type, path.basename(filename)); + } + } + }); + watcher.on("error", error => { + for (const w of this.mapWatcherToPath.keys()) { + w.emit("error", error); + } + }); + } catch (err) { + process.nextTick(() => { + for (const w of this.mapWatcherToPath.keys()) { + w.emit("error", err); + } + }); + } + watcherCount++; + if (recursiveWatcherLogging) { + process.stderr.write( + `[watchpack] created recursive watcher at ${rootPath}\n` + ); + } + } + + add(filePath, watcher) { + underlyingWatcher.set(watcher, this); + const subpath = filePath.slice(this.rootPath.length + 1) || "."; + this.mapWatcherToPath.set(watcher, subpath); + const set = this.mapPathToWatchers.get(subpath); + if (set === undefined) { + const newSet = new Set(); + newSet.add(watcher); + this.mapPathToWatchers.set(subpath, newSet); + } else { + set.add(watcher); + } + } + + remove(watcher) { + const subpath = this.mapWatcherToPath.get(watcher); + if (!subpath) return; + this.mapWatcherToPath.delete(watcher); + const set = this.mapPathToWatchers.get(subpath); + set.delete(watcher); + if (set.size === 0) { + this.mapPathToWatchers.delete(subpath); + } + if (this.mapWatcherToPath.size === 0) { + recursiveWatchers.delete(this.rootPath); + watcherCount--; + if (this.watcher) this.watcher.close(); + if (recursiveWatcherLogging) { + process.stderr.write( + `[watchpack] closed recursive watcher at ${this.rootPath}\n` + ); + } + } + } + + getWatchers() { + return this.mapWatcherToPath; + } +} + +class Watcher extends EventEmitter { + close() { + if (pendingWatchers.has(this)) { + pendingWatchers.delete(this); + return; + } + const watcher = underlyingWatcher.get(this); + watcher.remove(this); + underlyingWatcher.delete(this); + } +} + +const createDirectWatcher = filePath => { + const existing = directWatchers.get(filePath); + if (existing !== undefined) return existing; + const w = new DirectWatcher(filePath); + directWatchers.set(filePath, w); + return w; +}; + +const createRecursiveWatcher = rootPath => { + const existing = recursiveWatchers.get(rootPath); + if (existing !== undefined) return existing; + const w = new RecursiveWatcher(rootPath); + recursiveWatchers.set(rootPath, w); + return w; +}; + +const execute = () => { + /** @type {Map<string, Watcher[] | Watcher>} */ + const map = new Map(); + const addWatcher = (watcher, filePath) => { + const entry = map.get(filePath); + if (entry === undefined) { + map.set(filePath, watcher); + } else if (Array.isArray(entry)) { + entry.push(watcher); + } else { + map.set(filePath, [entry, watcher]); + } + }; + for (const [watcher, filePath] of pendingWatchers) { + addWatcher(watcher, filePath); + } + pendingWatchers.clear(); + + // Fast case when we are not reaching the limit + if (!SUPPORTS_RECURSIVE_WATCHING || watcherLimit - watcherCount >= map.size) { + // Create watchers for all entries in the map + for (const [filePath, entry] of map) { + const w = createDirectWatcher(filePath); + if (Array.isArray(entry)) { + for (const item of entry) w.add(item); + } else { + w.add(entry); + } + } + return; + } + + // Reconsider existing watchers to improving watch plan + for (const watcher of recursiveWatchers.values()) { + for (const [w, subpath] of watcher.getWatchers()) { + addWatcher(w, path.join(watcher.rootPath, subpath)); + } + } + for (const watcher of directWatchers.values()) { + for (const w of watcher.getWatchers()) { + addWatcher(w, watcher.filePath); + } + } + + // Merge map entries to keep watcher limit + // Create a 10% buffer to be able to enter fast case more often + const plan = reducePlan(map, watcherLimit * 0.9); + + // Update watchers for all entries in the map + for (const [filePath, entry] of plan) { + if (entry.size === 1) { + for (const [watcher, filePath] of entry) { + const w = createDirectWatcher(filePath); + const old = underlyingWatcher.get(watcher); + if (old === w) continue; + w.add(watcher); + if (old !== undefined) old.remove(watcher); + } + } else { + const filePaths = new Set(entry.values()); + if (filePaths.size > 1) { + const w = createRecursiveWatcher(filePath); + for (const [watcher, watcherPath] of entry) { + const old = underlyingWatcher.get(watcher); + if (old === w) continue; + w.add(watcherPath, watcher); + if (old !== undefined) old.remove(watcher); + } + } else { + for (const filePath of filePaths) { + const w = createDirectWatcher(filePath); + for (const watcher of entry.keys()) { + const old = underlyingWatcher.get(watcher); + if (old === w) continue; + w.add(watcher); + if (old !== undefined) old.remove(watcher); + } + } + } + } + } +}; + +exports.watch = filePath => { + const watcher = new Watcher(); + // Find an existing watcher + const directWatcher = directWatchers.get(filePath); + if (directWatcher !== undefined) { + directWatcher.add(watcher); + return watcher; + } + let current = filePath; + for (;;) { + const recursiveWatcher = recursiveWatchers.get(current); + if (recursiveWatcher !== undefined) { + recursiveWatcher.add(filePath, watcher); + return watcher; + } + const parent = path.dirname(current); + if (parent === current) break; + current = parent; + } + // Queue up watcher for creation + pendingWatchers.set(watcher, filePath); + if (!isBatch) execute(); + return watcher; +}; + +exports.batch = fn => { + isBatch = true; + try { + fn(); + } finally { + isBatch = false; + execute(); + } +}; + +exports.getNumberOfWatchers = () => { + return watcherCount; +}; |
