mirror of https://github.com/webpack/webpack.git
				
				
				
			Move Watching to its own file
This commit is contained in:
		
							parent
							
								
									7ed2bd2e9b
								
							
						
					
					
						commit
						0014042c53
					
				
							
								
								
									
										158
									
								
								lib/Compiler.js
								
								
								
								
							
							
						
						
									
										158
									
								
								lib/Compiler.js
								
								
								
								
							| 
						 | 
				
			
			@ -14,6 +14,7 @@ const AsyncSeriesHook = require("tapable").AsyncSeriesHook;
 | 
			
		|||
 | 
			
		||||
const Compilation = require("./Compilation");
 | 
			
		||||
const Stats = require("./Stats");
 | 
			
		||||
const Watching = require("./Watching");
 | 
			
		||||
const NormalModuleFactory = require("./NormalModuleFactory");
 | 
			
		||||
const ContextModuleFactory = require("./ContextModuleFactory");
 | 
			
		||||
const ResolverFactory = require("./ResolverFactory");
 | 
			
		||||
| 
						 | 
				
			
			@ -21,159 +22,6 @@ const ResolverFactory = require("./ResolverFactory");
 | 
			
		|||
const RequestShortener = require("./RequestShortener");
 | 
			
		||||
const makePathsRelative = require("./util/identifier").makePathsRelative;
 | 
			
		||||
 | 
			
		||||
class Watching {
 | 
			
		||||
	constructor(compiler, watchOptions, handler) {
 | 
			
		||||
		this.startTime = null;
 | 
			
		||||
		this.invalid = false;
 | 
			
		||||
		this.handler = handler;
 | 
			
		||||
		this.callbacks = [];
 | 
			
		||||
		this.closed = false;
 | 
			
		||||
		if(typeof watchOptions === "number") {
 | 
			
		||||
			this.watchOptions = {
 | 
			
		||||
				aggregateTimeout: watchOptions
 | 
			
		||||
			};
 | 
			
		||||
		} else if(watchOptions && typeof watchOptions === "object") {
 | 
			
		||||
			this.watchOptions = Object.assign({}, watchOptions);
 | 
			
		||||
		} else {
 | 
			
		||||
			this.watchOptions = {};
 | 
			
		||||
		}
 | 
			
		||||
		this.watchOptions.aggregateTimeout = this.watchOptions.aggregateTimeout || 200;
 | 
			
		||||
		this.compiler = compiler;
 | 
			
		||||
		this.running = true;
 | 
			
		||||
		this.compiler.readRecords(err => {
 | 
			
		||||
			if(err) return this._done(err);
 | 
			
		||||
 | 
			
		||||
			this._go();
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_go() {
 | 
			
		||||
		this.startTime = Date.now();
 | 
			
		||||
		this.running = true;
 | 
			
		||||
		this.invalid = false;
 | 
			
		||||
		this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
 | 
			
		||||
			if(err) return this._done(err);
 | 
			
		||||
			const onCompiled = (err, compilation) => {
 | 
			
		||||
				if(err) return this._done(err);
 | 
			
		||||
				if(this.invalid) return this._done();
 | 
			
		||||
 | 
			
		||||
				if(this.compiler.hooks.shouldEmit.call(compilation) === false) {
 | 
			
		||||
					return this._done(null, compilation);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				this.compiler.emitAssets(compilation, err => {
 | 
			
		||||
					if(err) return this._done(err);
 | 
			
		||||
					if(this.invalid) return this._done();
 | 
			
		||||
 | 
			
		||||
					this.compiler.emitRecords(err => {
 | 
			
		||||
						if(err) return this._done(err);
 | 
			
		||||
 | 
			
		||||
						if(compilation.hooks.needAdditionalPass.call()) {
 | 
			
		||||
							compilation.needAdditionalPass = true;
 | 
			
		||||
 | 
			
		||||
							const stats = new Stats(compilation);
 | 
			
		||||
							stats.startTime = this.startTime;
 | 
			
		||||
							stats.endTime = Date.now();
 | 
			
		||||
							this.compiler.hooks.done.call(stats);
 | 
			
		||||
 | 
			
		||||
							this.compiler.hooks.additionalPass.callAsync(err => {
 | 
			
		||||
								if(err) return this._done(err);
 | 
			
		||||
								this.compiler.compile(onCompiled);
 | 
			
		||||
							});
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
						return this._done(null, compilation);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			};
 | 
			
		||||
			this.compiler.compile(onCompiled);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_getStats(compilation) {
 | 
			
		||||
		const stats = new Stats(compilation);
 | 
			
		||||
		stats.startTime = this.startTime;
 | 
			
		||||
		stats.endTime = Date.now();
 | 
			
		||||
		return stats;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_done(err, compilation) {
 | 
			
		||||
		this.running = false;
 | 
			
		||||
		if(this.invalid) return this._go();
 | 
			
		||||
 | 
			
		||||
		const stats = compilation ? this._getStats(compilation) : null;
 | 
			
		||||
		if(err) {
 | 
			
		||||
			this.compiler.hooks.failed.call(err);
 | 
			
		||||
			this.handler(err, stats);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.compiler.hooks.done.call(stats);
 | 
			
		||||
		this.handler(null, stats);
 | 
			
		||||
		if(!this.closed) {
 | 
			
		||||
			this.watch(Array.from(compilation.fileDependencies), Array.from(compilation.contextDependencies), Array.from(compilation.missingDependencies));
 | 
			
		||||
		}
 | 
			
		||||
		this.callbacks.forEach(cb => cb());
 | 
			
		||||
		this.callbacks.length = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	watch(files, dirs, missing) {
 | 
			
		||||
		this.pausedWatcher = null;
 | 
			
		||||
		this.watcher = this.compiler.watchFileSystem.watch(files, dirs, missing, this.startTime, this.watchOptions, (err, filesModified, contextModified, missingModified, fileTimestamps, contextTimestamps) => {
 | 
			
		||||
			this.pausedWatcher = this.watcher;
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
			if(err) return this.handler(err);
 | 
			
		||||
 | 
			
		||||
			this.compiler.fileTimestamps = fileTimestamps;
 | 
			
		||||
			this.compiler.contextTimestamps = contextTimestamps;
 | 
			
		||||
			this.invalidate();
 | 
			
		||||
		}, (fileName, changeTime) => {
 | 
			
		||||
			this.compiler.hooks.invalid.call(fileName, changeTime);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	invalidate(callback) {
 | 
			
		||||
		if(callback) {
 | 
			
		||||
			this.callbacks.push(callback);
 | 
			
		||||
		}
 | 
			
		||||
		if(this.watcher) {
 | 
			
		||||
			this.pausedWatcher = this.watcher;
 | 
			
		||||
			this.watcher.pause();
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.running) {
 | 
			
		||||
			this.invalid = true;
 | 
			
		||||
			return false;
 | 
			
		||||
		} else {
 | 
			
		||||
			this._go();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(callback) {
 | 
			
		||||
		if(callback === undefined) callback = () => {};
 | 
			
		||||
 | 
			
		||||
		this.closed = true;
 | 
			
		||||
		if(this.watcher) {
 | 
			
		||||
			this.watcher.close();
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.pausedWatcher) {
 | 
			
		||||
			this.pausedWatcher.close();
 | 
			
		||||
			this.pausedWatcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.running) {
 | 
			
		||||
			this.invalid = true;
 | 
			
		||||
			this._done = () => {
 | 
			
		||||
				this.compiler.hooks.watchClose.call();
 | 
			
		||||
				callback();
 | 
			
		||||
			};
 | 
			
		||||
		} else {
 | 
			
		||||
			this.compiler.hooks.watchClose.call();
 | 
			
		||||
			callback();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Compiler extends Tapable {
 | 
			
		||||
	constructor(context) {
 | 
			
		||||
		super();
 | 
			
		||||
| 
						 | 
				
			
			@ -331,8 +179,7 @@ class Compiler extends Tapable {
 | 
			
		|||
	watch(watchOptions, handler) {
 | 
			
		||||
		this.fileTimestamps = {};
 | 
			
		||||
		this.contextTimestamps = {};
 | 
			
		||||
		const watching = new Watching(this, watchOptions, handler);
 | 
			
		||||
		return watching;
 | 
			
		||||
		return new Watching(this, watchOptions, handler);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	run(callback) {
 | 
			
		||||
| 
						 | 
				
			
			@ -626,5 +473,4 @@ class Compiler extends Tapable {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Compiler.Watching = Watching;
 | 
			
		||||
module.exports = Compiler;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
/*
 | 
			
		||||
	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
			
		||||
	Author Tobias Koppers @sokra
 | 
			
		||||
*/
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const Stats = require("./Stats");
 | 
			
		||||
 | 
			
		||||
class Watching {
 | 
			
		||||
	constructor(compiler, watchOptions, handler) {
 | 
			
		||||
		this.startTime = null;
 | 
			
		||||
		this.invalid = false;
 | 
			
		||||
		this.handler = handler;
 | 
			
		||||
		this.callbacks = [];
 | 
			
		||||
		this.closed = false;
 | 
			
		||||
		if(typeof watchOptions === "number") {
 | 
			
		||||
			this.watchOptions = {
 | 
			
		||||
				aggregateTimeout: watchOptions
 | 
			
		||||
			};
 | 
			
		||||
		} else if(watchOptions && typeof watchOptions === "object") {
 | 
			
		||||
			this.watchOptions = Object.assign({}, watchOptions);
 | 
			
		||||
		} else {
 | 
			
		||||
			this.watchOptions = {};
 | 
			
		||||
		}
 | 
			
		||||
		this.watchOptions.aggregateTimeout = this.watchOptions.aggregateTimeout || 200;
 | 
			
		||||
		this.compiler = compiler;
 | 
			
		||||
		this.running = true;
 | 
			
		||||
		this.compiler.readRecords(err => {
 | 
			
		||||
			if(err) return this._done(err);
 | 
			
		||||
 | 
			
		||||
			this._go();
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_go() {
 | 
			
		||||
		this.startTime = Date.now();
 | 
			
		||||
		this.running = true;
 | 
			
		||||
		this.invalid = false;
 | 
			
		||||
		this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
 | 
			
		||||
			if(err) return this._done(err);
 | 
			
		||||
			const onCompiled = (err, compilation) => {
 | 
			
		||||
				if(err) return this._done(err);
 | 
			
		||||
				if(this.invalid) return this._done();
 | 
			
		||||
 | 
			
		||||
				if(this.compiler.hooks.shouldEmit.call(compilation) === false) {
 | 
			
		||||
					return this._done(null, compilation);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				this.compiler.emitAssets(compilation, err => {
 | 
			
		||||
					if(err) return this._done(err);
 | 
			
		||||
					if(this.invalid) return this._done();
 | 
			
		||||
 | 
			
		||||
					this.compiler.emitRecords(err => {
 | 
			
		||||
						if(err) return this._done(err);
 | 
			
		||||
 | 
			
		||||
						if(compilation.hooks.needAdditionalPass.call()) {
 | 
			
		||||
							compilation.needAdditionalPass = true;
 | 
			
		||||
 | 
			
		||||
							const stats = new Stats(compilation);
 | 
			
		||||
							stats.startTime = this.startTime;
 | 
			
		||||
							stats.endTime = Date.now();
 | 
			
		||||
							this.compiler.hooks.done.call(stats);
 | 
			
		||||
 | 
			
		||||
							this.compiler.hooks.additionalPass.callAsync(err => {
 | 
			
		||||
								if(err) return this._done(err);
 | 
			
		||||
								this.compiler.compile(onCompiled);
 | 
			
		||||
							});
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
						return this._done(null, compilation);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
			};
 | 
			
		||||
			this.compiler.compile(onCompiled);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_getStats(compilation) {
 | 
			
		||||
		const stats = new Stats(compilation);
 | 
			
		||||
		stats.startTime = this.startTime;
 | 
			
		||||
		stats.endTime = Date.now();
 | 
			
		||||
		return stats;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_done(err, compilation) {
 | 
			
		||||
		this.running = false;
 | 
			
		||||
		if(this.invalid) return this._go();
 | 
			
		||||
 | 
			
		||||
		const stats = compilation ? this._getStats(compilation) : null;
 | 
			
		||||
		if(err) {
 | 
			
		||||
			this.compiler.hooks.failed.call(err);
 | 
			
		||||
			this.handler(err, stats);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.compiler.hooks.done.call(stats);
 | 
			
		||||
		this.handler(null, stats);
 | 
			
		||||
		if(!this.closed) {
 | 
			
		||||
			this.watch(Array.from(compilation.fileDependencies), Array.from(compilation.contextDependencies), Array.from(compilation.missingDependencies));
 | 
			
		||||
		}
 | 
			
		||||
		this.callbacks.forEach(cb => cb());
 | 
			
		||||
		this.callbacks.length = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	watch(files, dirs, missing) {
 | 
			
		||||
		this.pausedWatcher = null;
 | 
			
		||||
		this.watcher = this.compiler.watchFileSystem.watch(files, dirs, missing, this.startTime, this.watchOptions, (err, filesModified, contextModified, missingModified, fileTimestamps, contextTimestamps) => {
 | 
			
		||||
			this.pausedWatcher = this.watcher;
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
			if(err) return this.handler(err);
 | 
			
		||||
 | 
			
		||||
			this.compiler.fileTimestamps = fileTimestamps;
 | 
			
		||||
			this.compiler.contextTimestamps = contextTimestamps;
 | 
			
		||||
			this.invalidate();
 | 
			
		||||
		}, (fileName, changeTime) => {
 | 
			
		||||
			this.compiler.hooks.invalid.call(fileName, changeTime);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	invalidate(callback) {
 | 
			
		||||
		if(callback) {
 | 
			
		||||
			this.callbacks.push(callback);
 | 
			
		||||
		}
 | 
			
		||||
		if(this.watcher) {
 | 
			
		||||
			this.pausedWatcher = this.watcher;
 | 
			
		||||
			this.watcher.pause();
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.running) {
 | 
			
		||||
			this.invalid = true;
 | 
			
		||||
			return false;
 | 
			
		||||
		} else {
 | 
			
		||||
			this._go();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(callback) {
 | 
			
		||||
		if(callback === undefined) callback = () => {};
 | 
			
		||||
 | 
			
		||||
		this.closed = true;
 | 
			
		||||
		if(this.watcher) {
 | 
			
		||||
			this.watcher.close();
 | 
			
		||||
			this.watcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.pausedWatcher) {
 | 
			
		||||
			this.pausedWatcher.close();
 | 
			
		||||
			this.pausedWatcher = null;
 | 
			
		||||
		}
 | 
			
		||||
		if(this.running) {
 | 
			
		||||
			this.invalid = true;
 | 
			
		||||
			this._done = () => {
 | 
			
		||||
				this.compiler.hooks.watchClose.call();
 | 
			
		||||
				callback();
 | 
			
		||||
			};
 | 
			
		||||
		} else {
 | 
			
		||||
			this.compiler.hooks.watchClose.call();
 | 
			
		||||
			callback();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Watching;
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ const sinon = require("sinon");
 | 
			
		|||
 | 
			
		||||
const webpack = require("../");
 | 
			
		||||
const WebpackOptionsDefaulter = require("../lib/WebpackOptionsDefaulter");
 | 
			
		||||
const Compiler = require("../lib/Compiler");
 | 
			
		||||
const MemoryFs = require("memory-fs");
 | 
			
		||||
 | 
			
		||||
describe("Compiler", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -273,14 +272,6 @@ describe("Compiler", () => {
 | 
			
		|||
				}
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
		describe("static method", () => {
 | 
			
		||||
			it("should have an method, Watching", (done) => {
 | 
			
		||||
				const actual = new Compiler.Watching(compiler, 1000, err => err);
 | 
			
		||||
				actual.running.should.be.exactly(true);
 | 
			
		||||
				actual.constructor.name.should.be.exactly("Watching");
 | 
			
		||||
				done();
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
		describe("constructor", () => {
 | 
			
		||||
			it("constructs Watching.watchOptions correctly when passed a number, string, or object for watchOptions", (done) => {
 | 
			
		||||
				const Watching1 = compiler.watch(1000, err => err);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue