Buckets:
| /* | |
| MIT License http://www.opensource.org/licenses/mit-license.php | |
| Author Tobias Koppers @sokra | |
| */ | |
| ; | |
| const Stats = require("./Stats"); | |
| /** @typedef {import("../declarations/WebpackOptions").WatchOptions} WatchOptions */ | |
| /** @typedef {import("./Compilation")} Compilation */ | |
| /** @typedef {import("./Compiler")} Compiler */ | |
| /** @typedef {import("./Compiler").ErrorCallback} ErrorCallback */ | |
| /** @typedef {import("./WebpackError")} WebpackError */ | |
| /** @typedef {import("./logging/Logger").Logger} Logger */ | |
| /** @typedef {import("./util/fs").TimeInfoEntries} TimeInfoEntries */ | |
| /** @typedef {import("./util/fs").WatchFileSystem} WatchFileSystem */ | |
| /** @typedef {import("./util/fs").Watcher} Watcher */ | |
| /** | |
| * @template T | |
| * @template [R=void] | |
| * @typedef {import("./webpack").Callback<T, R>} Callback | |
| */ | |
| /** @typedef {Set<string>} CollectedFiles */ | |
| class Watching { | |
| /** | |
| * @param {Compiler} compiler the compiler | |
| * @param {WatchOptions} watchOptions options | |
| * @param {Callback<Stats>} handler completion handler | |
| */ | |
| constructor(compiler, watchOptions, handler) { | |
| /** @type {null | number} */ | |
| this.startTime = null; | |
| this.invalid = false; | |
| /** @type {Callback<Stats>} */ | |
| this.handler = handler; | |
| /** @type {ErrorCallback[]} */ | |
| this.callbacks = []; | |
| /** @type {ErrorCallback[] | undefined} */ | |
| this._closeCallbacks = undefined; | |
| this.closed = false; | |
| this.suspended = false; | |
| this.blocked = false; | |
| this._isBlocked = () => false; | |
| this._onChange = () => {}; | |
| this._onInvalid = () => {}; | |
| if (typeof watchOptions === "number") { | |
| /** @type {WatchOptions} */ | |
| this.watchOptions = { | |
| aggregateTimeout: watchOptions | |
| }; | |
| } else if (watchOptions && typeof watchOptions === "object") { | |
| /** @type {WatchOptions} */ | |
| this.watchOptions = { ...watchOptions }; | |
| } else { | |
| /** @type {WatchOptions} */ | |
| this.watchOptions = {}; | |
| } | |
| if (typeof this.watchOptions.aggregateTimeout !== "number") { | |
| this.watchOptions.aggregateTimeout = 20; | |
| } | |
| this.compiler = compiler; | |
| this.running = false; | |
| this._initial = true; | |
| this._invalidReported = true; | |
| this._needRecords = true; | |
| /** @type {undefined | null | Watcher} */ | |
| this.watcher = undefined; | |
| /** @type {undefined | null | Watcher} */ | |
| this.pausedWatcher = undefined; | |
| /** @type {CollectedFiles | undefined} */ | |
| this._collectedChangedFiles = undefined; | |
| /** @type {CollectedFiles | undefined} */ | |
| this._collectedRemovedFiles = undefined; | |
| this._done = this._done.bind(this); | |
| process.nextTick(() => { | |
| if (this._initial) this._invalidate(); | |
| }); | |
| } | |
| /** | |
| * @param {ReadonlySet<string> | undefined | null} changedFiles changed files | |
| * @param {ReadonlySet<string> | undefined | null} removedFiles removed files | |
| */ | |
| _mergeWithCollected(changedFiles, removedFiles) { | |
| if (!changedFiles) return; | |
| if (!this._collectedChangedFiles) { | |
| this._collectedChangedFiles = new Set(changedFiles); | |
| this._collectedRemovedFiles = new Set(removedFiles); | |
| } else { | |
| for (const file of changedFiles) { | |
| this._collectedChangedFiles.add(file); | |
| /** @type {CollectedFiles} */ | |
| (this._collectedRemovedFiles).delete(file); | |
| } | |
| for (const file of /** @type {ReadonlySet<string>} */ (removedFiles)) { | |
| this._collectedChangedFiles.delete(file); | |
| /** @type {CollectedFiles} */ | |
| (this._collectedRemovedFiles).add(file); | |
| } | |
| } | |
| } | |
| /** | |
| * @param {TimeInfoEntries=} fileTimeInfoEntries info for files | |
| * @param {TimeInfoEntries=} contextTimeInfoEntries info for directories | |
| * @param {ReadonlySet<string>=} changedFiles changed files | |
| * @param {ReadonlySet<string>=} removedFiles removed files | |
| * @returns {void} | |
| */ | |
| _go(fileTimeInfoEntries, contextTimeInfoEntries, changedFiles, removedFiles) { | |
| this._initial = false; | |
| if (this.startTime === null) this.startTime = Date.now(); | |
| this.running = true; | |
| if (this.watcher) { | |
| this.pausedWatcher = this.watcher; | |
| this.lastWatcherStartTime = Date.now(); | |
| this.watcher.pause(); | |
| this.watcher = null; | |
| } else if (!this.lastWatcherStartTime) { | |
| this.lastWatcherStartTime = Date.now(); | |
| } | |
| this.compiler.fsStartTime = Date.now(); | |
| if ( | |
| changedFiles && | |
| removedFiles && | |
| fileTimeInfoEntries && | |
| contextTimeInfoEntries | |
| ) { | |
| this._mergeWithCollected(changedFiles, removedFiles); | |
| this.compiler.fileTimestamps = fileTimeInfoEntries; | |
| this.compiler.contextTimestamps = contextTimeInfoEntries; | |
| } else if (this.pausedWatcher) { | |
| if (this.pausedWatcher.getInfo) { | |
| const { | |
| changes, | |
| removals, | |
| fileTimeInfoEntries, | |
| contextTimeInfoEntries | |
| } = this.pausedWatcher.getInfo(); | |
| this._mergeWithCollected(changes, removals); | |
| this.compiler.fileTimestamps = fileTimeInfoEntries; | |
| this.compiler.contextTimestamps = contextTimeInfoEntries; | |
| } else { | |
| this._mergeWithCollected( | |
| this.pausedWatcher.getAggregatedChanges && | |
| this.pausedWatcher.getAggregatedChanges(), | |
| this.pausedWatcher.getAggregatedRemovals && | |
| this.pausedWatcher.getAggregatedRemovals() | |
| ); | |
| this.compiler.fileTimestamps = | |
| this.pausedWatcher.getFileTimeInfoEntries(); | |
| this.compiler.contextTimestamps = | |
| this.pausedWatcher.getContextTimeInfoEntries(); | |
| } | |
| } | |
| this.compiler.modifiedFiles = this._collectedChangedFiles; | |
| this._collectedChangedFiles = undefined; | |
| this.compiler.removedFiles = this._collectedRemovedFiles; | |
| this._collectedRemovedFiles = undefined; | |
| const run = () => { | |
| if (this.compiler.idle) { | |
| return this.compiler.cache.endIdle((err) => { | |
| if (err) return this._done(err); | |
| this.compiler.idle = false; | |
| run(); | |
| }); | |
| } | |
| if (this._needRecords) { | |
| return this.compiler.readRecords((err) => { | |
| if (err) return this._done(err); | |
| this._needRecords = false; | |
| run(); | |
| }); | |
| } | |
| this.invalid = false; | |
| this._invalidReported = false; | |
| this.compiler.hooks.watchRun.callAsync(this.compiler, (err) => { | |
| if (err) return this._done(err); | |
| /** | |
| * @param {Error | null} err error | |
| * @param {Compilation=} _compilation compilation | |
| * @returns {void} | |
| */ | |
| const onCompiled = (err, _compilation) => { | |
| if (err) return this._done(err, _compilation); | |
| const compilation = /** @type {Compilation} */ (_compilation); | |
| if (this.compiler.hooks.shouldEmit.call(compilation) === false) { | |
| return this._done(null, compilation); | |
| } | |
| process.nextTick(() => { | |
| const logger = compilation.getLogger("webpack.Compiler"); | |
| logger.time("emitAssets"); | |
| this.compiler.emitAssets(compilation, (err) => { | |
| logger.timeEnd("emitAssets"); | |
| if (err) return this._done(err, compilation); | |
| if (this.invalid) return this._done(null, compilation); | |
| logger.time("emitRecords"); | |
| this.compiler.emitRecords((err) => { | |
| logger.timeEnd("emitRecords"); | |
| if (err) return this._done(err, compilation); | |
| if (compilation.hooks.needAdditionalPass.call()) { | |
| compilation.needAdditionalPass = true; | |
| compilation.startTime = /** @type {number} */ ( | |
| this.startTime | |
| ); | |
| compilation.endTime = Date.now(); | |
| logger.time("done hook"); | |
| const stats = new Stats(compilation); | |
| this.compiler.hooks.done.callAsync(stats, (err) => { | |
| logger.timeEnd("done hook"); | |
| if (err) return this._done(err, compilation); | |
| this.compiler.hooks.additionalPass.callAsync((err) => { | |
| if (err) return this._done(err, compilation); | |
| this.compiler.compile(onCompiled); | |
| }); | |
| }); | |
| return; | |
| } | |
| return this._done(null, compilation); | |
| }); | |
| }); | |
| }); | |
| }; | |
| this.compiler.compile(onCompiled); | |
| }); | |
| }; | |
| run(); | |
| } | |
| /** | |
| * @param {Compilation} compilation the compilation | |
| * @returns {Stats} the compilation stats | |
| */ | |
| _getStats(compilation) { | |
| const stats = new Stats(compilation); | |
| return stats; | |
| } | |
| /** | |
| * @param {(Error | null)=} err an optional error | |
| * @param {Compilation=} compilation the compilation | |
| * @returns {void} | |
| */ | |
| _done(err, compilation) { | |
| this.running = false; | |
| const logger = | |
| /** @type {Logger} */ | |
| (compilation && compilation.getLogger("webpack.Watching")); | |
| /** @type {Stats | undefined} */ | |
| let stats; | |
| /** | |
| * @param {Error} err error | |
| * @param {ErrorCallback[]=} cbs callbacks | |
| */ | |
| const handleError = (err, cbs) => { | |
| this.compiler.hooks.failed.call(err); | |
| this.compiler.cache.beginIdle(); | |
| this.compiler.idle = true; | |
| this.handler(err, /** @type {Stats} */ (stats)); | |
| if (!cbs) { | |
| cbs = this.callbacks; | |
| this.callbacks = []; | |
| } | |
| for (const cb of cbs) cb(err); | |
| }; | |
| if ( | |
| this.invalid && | |
| !this.suspended && | |
| !this.blocked && | |
| !(this._isBlocked() && (this.blocked = true)) | |
| ) { | |
| if (compilation) { | |
| logger.time("storeBuildDependencies"); | |
| this.compiler.cache.storeBuildDependencies( | |
| compilation.buildDependencies, | |
| (err) => { | |
| logger.timeEnd("storeBuildDependencies"); | |
| if (err) return handleError(err); | |
| this._go(); | |
| } | |
| ); | |
| } else { | |
| this._go(); | |
| } | |
| return; | |
| } | |
| if (compilation) { | |
| compilation.startTime = /** @type {number} */ (this.startTime); | |
| compilation.endTime = Date.now(); | |
| stats = new Stats(compilation); | |
| } | |
| this.startTime = null; | |
| if (err) return handleError(err); | |
| const cbs = this.callbacks; | |
| this.callbacks = []; | |
| logger.time("done hook"); | |
| this.compiler.hooks.done.callAsync(/** @type {Stats} */ (stats), (err) => { | |
| logger.timeEnd("done hook"); | |
| if (err) return handleError(err, cbs); | |
| this.handler(null, stats); | |
| logger.time("storeBuildDependencies"); | |
| this.compiler.cache.storeBuildDependencies( | |
| /** @type {Compilation} */ | |
| (compilation).buildDependencies, | |
| (err) => { | |
| logger.timeEnd("storeBuildDependencies"); | |
| if (err) return handleError(err, cbs); | |
| logger.time("beginIdle"); | |
| this.compiler.cache.beginIdle(); | |
| this.compiler.idle = true; | |
| logger.timeEnd("beginIdle"); | |
| process.nextTick(() => { | |
| if (!this.closed) { | |
| this.watch( | |
| /** @type {Compilation} */ | |
| (compilation).fileDependencies, | |
| /** @type {Compilation} */ | |
| (compilation).contextDependencies, | |
| /** @type {Compilation} */ | |
| (compilation).missingDependencies | |
| ); | |
| } | |
| }); | |
| for (const cb of cbs) cb(null); | |
| this.compiler.hooks.afterDone.call(/** @type {Stats} */ (stats)); | |
| } | |
| ); | |
| }); | |
| } | |
| /** | |
| * @param {Iterable<string>} files watched files | |
| * @param {Iterable<string>} dirs watched directories | |
| * @param {Iterable<string>} missing watched existence entries | |
| * @returns {void} | |
| */ | |
| watch(files, dirs, missing) { | |
| this.pausedWatcher = null; | |
| this.watcher = | |
| /** @type {WatchFileSystem} */ | |
| (this.compiler.watchFileSystem).watch( | |
| files, | |
| dirs, | |
| missing, | |
| /** @type {number} */ (this.lastWatcherStartTime), | |
| this.watchOptions, | |
| ( | |
| err, | |
| fileTimeInfoEntries, | |
| contextTimeInfoEntries, | |
| changedFiles, | |
| removedFiles | |
| ) => { | |
| if (err) { | |
| this.compiler.modifiedFiles = undefined; | |
| this.compiler.removedFiles = undefined; | |
| this.compiler.fileTimestamps = undefined; | |
| this.compiler.contextTimestamps = undefined; | |
| this.compiler.fsStartTime = undefined; | |
| return this.handler(err); | |
| } | |
| this._invalidate( | |
| fileTimeInfoEntries, | |
| contextTimeInfoEntries, | |
| changedFiles, | |
| removedFiles | |
| ); | |
| this._onChange(); | |
| }, | |
| (fileName, changeTime) => { | |
| if (!this._invalidReported) { | |
| this._invalidReported = true; | |
| this.compiler.hooks.invalid.call(fileName, changeTime); | |
| } | |
| this._onInvalid(); | |
| } | |
| ); | |
| } | |
| /** | |
| * @param {ErrorCallback=} callback signals when the build has completed again | |
| * @returns {void} | |
| */ | |
| invalidate(callback) { | |
| if (callback) { | |
| this.callbacks.push(callback); | |
| } | |
| if (!this._invalidReported) { | |
| this._invalidReported = true; | |
| this.compiler.hooks.invalid.call(null, Date.now()); | |
| } | |
| this._onChange(); | |
| this._invalidate(); | |
| } | |
| /** | |
| * @param {TimeInfoEntries=} fileTimeInfoEntries info for files | |
| * @param {TimeInfoEntries=} contextTimeInfoEntries info for directories | |
| * @param {ReadonlySet<string>=} changedFiles changed files | |
| * @param {ReadonlySet<string>=} removedFiles removed files | |
| * @returns {void} | |
| */ | |
| _invalidate( | |
| fileTimeInfoEntries, | |
| contextTimeInfoEntries, | |
| changedFiles, | |
| removedFiles | |
| ) { | |
| if (this.suspended || (this._isBlocked() && (this.blocked = true))) { | |
| this._mergeWithCollected(changedFiles, removedFiles); | |
| return; | |
| } | |
| if (this.running) { | |
| this._mergeWithCollected(changedFiles, removedFiles); | |
| this.invalid = true; | |
| } else { | |
| this._go( | |
| fileTimeInfoEntries, | |
| contextTimeInfoEntries, | |
| changedFiles, | |
| removedFiles | |
| ); | |
| } | |
| } | |
| suspend() { | |
| this.suspended = true; | |
| } | |
| resume() { | |
| if (this.suspended) { | |
| this.suspended = false; | |
| this._invalidate(); | |
| } | |
| } | |
| /** | |
| * @param {ErrorCallback} callback signals when the watcher is closed | |
| * @returns {void} | |
| */ | |
| close(callback) { | |
| if (this._closeCallbacks) { | |
| if (callback) { | |
| this._closeCallbacks.push(callback); | |
| } | |
| return; | |
| } | |
| /** | |
| * @param {WebpackError | null} err error if any | |
| * @param {Compilation=} compilation compilation if any | |
| */ | |
| const finalCallback = (err, compilation) => { | |
| this.running = false; | |
| this.compiler.running = false; | |
| this.compiler.watching = undefined; | |
| this.compiler.watchMode = false; | |
| this.compiler.modifiedFiles = undefined; | |
| this.compiler.removedFiles = undefined; | |
| this.compiler.fileTimestamps = undefined; | |
| this.compiler.contextTimestamps = undefined; | |
| this.compiler.fsStartTime = undefined; | |
| /** | |
| * @param {WebpackError | null} err error if any | |
| */ | |
| const shutdown = (err) => { | |
| this.compiler.hooks.watchClose.call(); | |
| const closeCallbacks = | |
| /** @type {ErrorCallback[]} */ | |
| (this._closeCallbacks); | |
| this._closeCallbacks = undefined; | |
| for (const cb of closeCallbacks) cb(err); | |
| }; | |
| if (compilation) { | |
| const logger = compilation.getLogger("webpack.Watching"); | |
| logger.time("storeBuildDependencies"); | |
| this.compiler.cache.storeBuildDependencies( | |
| compilation.buildDependencies, | |
| (err2) => { | |
| logger.timeEnd("storeBuildDependencies"); | |
| shutdown(err || err2); | |
| } | |
| ); | |
| } else { | |
| shutdown(err); | |
| } | |
| }; | |
| this.closed = true; | |
| if (this.watcher) { | |
| this.watcher.close(); | |
| this.watcher = null; | |
| } | |
| if (this.pausedWatcher) { | |
| this.pausedWatcher.close(); | |
| this.pausedWatcher = null; | |
| } | |
| this._closeCallbacks = []; | |
| if (callback) { | |
| this._closeCallbacks.push(callback); | |
| } | |
| if (this.running) { | |
| this.invalid = true; | |
| this._done = finalCallback; | |
| } else { | |
| finalCallback(null); | |
| } | |
| } | |
| } | |
| module.exports = Watching; | |
Xet Storage Details
- Size:
- 14.8 kB
- Xet hash:
- 71cf2d6fe5999c511f62f661f244b98c46bfcab5dc02dc458650e0eaa33fbfbf
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.