| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | var Tapable = require("tapable"); | 
					
						
							|  |  |  | var async = require("async"); | 
					
						
							|  |  |  | var Stats = require("./Stats"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function MultiWatching(watchings) { | 
					
						
							|  |  |  | 	this.watchings = watchings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiWatching.prototype.invalidate = function() { | 
					
						
							|  |  |  | 	this.watchings.forEach(function(watching) { | 
					
						
							|  |  |  | 		watching.invalidate(); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiWatching.prototype.close = function(callback) { | 
					
						
							|  |  |  | 	async.forEach(this.watchings, function(watching, callback) { | 
					
						
							|  |  |  | 		watching.close(callback); | 
					
						
							|  |  |  | 	}, callback); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function MultiCompiler(compilers) { | 
					
						
							|  |  |  | 	Tapable.call(this); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 	if(!Array.isArray(compilers)) { | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 		compilers = Object.keys(compilers).map(function(name) { | 
					
						
							|  |  |  | 			compilers[name].name = name; | 
					
						
							|  |  |  | 			return compilers[name]; | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	this.compilers = compilers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function delegateProperty(name) { | 
					
						
							|  |  |  | 		Object.defineProperty(this, name, { | 
					
						
							|  |  |  | 			configurable: false, | 
					
						
							|  |  |  | 			get: function() { | 
					
						
							|  |  |  | 				throw new Error("Cannot read " + name + " of a MultiCompiler"); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			set: function(value) { | 
					
						
							|  |  |  | 				this.compilers.forEach(function(compiler) { | 
					
						
							|  |  |  | 					compiler[name] = value; | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			}.bind(this) | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	delegateProperty.call(this, "outputFileSystem"); | 
					
						
							|  |  |  | 	delegateProperty.call(this, "inputFileSystem"); | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 	Object.defineProperty(this, "outputPath", { | 
					
						
							|  |  |  | 		configurable: false, | 
					
						
							|  |  |  | 		get: function() { | 
					
						
							|  |  |  | 			var commonPath = compilers[0].outputPath; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			for(var i = 1; i < compilers.length; i++) { | 
					
						
							|  |  |  | 				while(compilers[i].outputPath.indexOf(commonPath) !== 0 && /[\/\\]/.test(commonPath)) { | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 					commonPath = commonPath.replace(/[\/\\][^\/\\]*$/, ""); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(!commonPath && compilers[0].outputPath[0] === "/") return "/"; | 
					
						
							| 
									
										
										
										
											2014-06-19 05:02:33 +08:00
										 |  |  | 			return commonPath; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var doneCompilers = 0; | 
					
						
							|  |  |  | 	var compilerStats = []; | 
					
						
							|  |  |  | 	this.compilers.forEach(function(compiler, idx) { | 
					
						
							|  |  |  | 		var compilerDone = false; | 
					
						
							|  |  |  | 		compiler.plugin("done", function(stats) { | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(!compilerDone) { | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 				compilerDone = true; | 
					
						
							|  |  |  | 				doneCompilers++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			compilerStats[idx] = stats; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(doneCompilers === this.compilers.length) { | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 				this.applyPlugins("done", new MultiStats(compilerStats)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}.bind(this)); | 
					
						
							|  |  |  | 		compiler.plugin("invalid", function() { | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(compilerDone) { | 
					
						
							| 
									
										
										
										
											2014-06-12 12:29:39 +08:00
										 |  |  | 				compilerDone = false; | 
					
						
							|  |  |  | 				doneCompilers--; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 			this.applyPlugins("invalid"); | 
					
						
							| 
									
										
										
										
											2014-06-12 12:29:39 +08:00
										 |  |  | 		}.bind(this)); | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 	}, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | module.exports = MultiCompiler; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiCompiler.prototype = Object.create(Tapable.prototype); | 
					
						
							| 
									
										
										
										
											2015-08-18 19:35:57 +08:00
										 |  |  | MultiCompiler.prototype.constructor = MultiCompiler; | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | function runWithDependencies(compilers, fn, callback) { | 
					
						
							|  |  |  | 	var fulfilledNames = {}; | 
					
						
							|  |  |  | 	var remainingCompilers = compilers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function isDependencyFulfilled(d) { | 
					
						
							|  |  |  | 		return fulfilledNames[d]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function getReadyCompilers() { | 
					
						
							|  |  |  | 		var readyCompilers = []; | 
					
						
							|  |  |  | 		var list = remainingCompilers; | 
					
						
							|  |  |  | 		remainingCompilers = []; | 
					
						
							|  |  |  | 		for(var i = 0; i < list.length; i++) { | 
					
						
							|  |  |  | 			var c = list[i]; | 
					
						
							|  |  |  | 			var ready = !c.dependencies || c.dependencies.every(isDependencyFulfilled); | 
					
						
							|  |  |  | 			if(ready) | 
					
						
							|  |  |  | 				readyCompilers.push(c); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				remainingCompilers.push(c); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return readyCompilers; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function runCompilers(callback) { | 
					
						
							|  |  |  | 		if(remainingCompilers.length === 0) return callback(); | 
					
						
							|  |  |  | 		async.map(getReadyCompilers(), function(compiler, callback) { | 
					
						
							|  |  |  | 			fn(compiler, function(err) { | 
					
						
							|  |  |  | 				if(err) return callback(err); | 
					
						
							|  |  |  | 				fulfilledNames[compiler.name] = true; | 
					
						
							|  |  |  | 				runCompilers(callback); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		}, callback); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	runCompilers(callback); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiCompiler.prototype.watch = function(watchOptions, handler) { | 
					
						
							|  |  |  | 	var watchings = []; | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 	var allStats = this.compilers.map(function() { | 
					
						
							|  |  |  | 		return null; | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 	var compilerStatus = this.compilers.map(function() { | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	runWithDependencies(this.compilers, function(compiler, callback) { | 
					
						
							|  |  |  | 		var compilerIdx = this.compilers.indexOf(compiler); | 
					
						
							|  |  |  | 		var firstRun = true; | 
					
						
							|  |  |  | 		var watching = compiler.watch(watchOptions, function(err, stats) { | 
					
						
							|  |  |  | 			if(err) | 
					
						
							|  |  |  | 				handler(err); | 
					
						
							|  |  |  | 			if(stats) { | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 				allStats[compilerIdx] = stats; | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 				compilerStatus[compilerIdx] = true; | 
					
						
							|  |  |  | 				if(compilerStatus.every(Boolean)) { | 
					
						
							|  |  |  | 					var multiStats = new MultiStats(allStats); | 
					
						
							|  |  |  | 					handler(null, multiStats) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(firstRun && !err) { | 
					
						
							|  |  |  | 				firstRun = false; | 
					
						
							|  |  |  | 				callback(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 		watchings.push(watching); | 
					
						
							|  |  |  | 	}.bind(this), function() { | 
					
						
							|  |  |  | 		// ignore
 | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 	return new MultiWatching(watchings); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiCompiler.prototype.run = function(callback) { | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 	var allStats = this.compilers.map(function() { | 
					
						
							|  |  |  | 		return null; | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	runWithDependencies(this.compilers, function(compiler, callback) { | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 		var compilerIdx = this.compilers.indexOf(compiler); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 		compiler.run(function(err, stats) { | 
					
						
							|  |  |  | 			if(err) return callback(err); | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 			allStats[compilerIdx] = stats; | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 			callback(); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2016-09-07 20:57:53 +08:00
										 |  |  | 	}.bind(this), function(err) { | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 		if(err) return callback(err); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 		callback(null, new MultiStats(allStats)); | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 04:52:02 +08:00
										 |  |  | MultiCompiler.prototype.purgeInputFileSystem = function() { | 
					
						
							|  |  |  | 	this.compilers.forEach(function(compiler) { | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 		if(compiler.inputFileSystem && compiler.inputFileSystem.purge) | 
					
						
							| 
									
										
										
										
											2014-06-12 04:52:02 +08:00
										 |  |  | 			compiler.inputFileSystem.purge(); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | function MultiStats(stats) { | 
					
						
							|  |  |  | 	this.stats = stats; | 
					
						
							|  |  |  | 	this.hash = stats.map(function(stat) { | 
					
						
							|  |  |  | 		return stat.hash; | 
					
						
							|  |  |  | 	}).join(""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiStats.prototype.hasErrors = function() { | 
					
						
							|  |  |  | 	return this.stats.map(function(stat) { | 
					
						
							|  |  |  | 		return stat.hasErrors(); | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	}).reduce(function(a, b) { | 
					
						
							|  |  |  | 		return a || b; | 
					
						
							|  |  |  | 	}, false); | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiStats.prototype.hasWarnings = function() { | 
					
						
							|  |  |  | 	return this.stats.map(function(stat) { | 
					
						
							|  |  |  | 		return stat.hasWarnings(); | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	}).reduce(function(a, b) { | 
					
						
							|  |  |  | 		return a || b; | 
					
						
							|  |  |  | 	}, false); | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MultiStats.prototype.toJson = function(options, forToString) { | 
					
						
							|  |  |  | 	var jsons = this.stats.map(function(stat) { | 
					
						
							|  |  |  | 		var obj = stat.toJson(options, forToString); | 
					
						
							|  |  |  | 		obj.name = stat.compilation && stat.compilation.name; | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2015-02-28 08:40:11 +08:00
										 |  |  | 	var obj = { | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 		errors: jsons.reduce(function(arr, j) { | 
					
						
							|  |  |  | 			return arr.concat(j.errors.map(function(msg) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 				return "(" + j.name + ") " + msg; | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 			})); | 
					
						
							|  |  |  | 		}, []), | 
					
						
							|  |  |  | 		warnings: jsons.reduce(function(arr, j) { | 
					
						
							|  |  |  | 			return arr.concat(j.warnings.map(function(msg) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 				return "(" + j.name + ") " + msg; | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 			})); | 
					
						
							| 
									
										
										
										
											2015-02-28 08:40:11 +08:00
										 |  |  | 		}, []) | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 	if(!options || options.version !== false) | 
					
						
							| 
									
										
										
										
											2015-02-28 08:40:11 +08:00
										 |  |  | 		obj.version = require("../package.json").version; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 	if(!options || options.hash !== false) | 
					
						
							| 
									
										
										
										
											2015-02-28 08:40:11 +08:00
										 |  |  | 		obj.hash = this.hash; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 	if(!options || options.children !== false) | 
					
						
							| 
									
										
										
										
											2015-02-28 08:40:11 +08:00
										 |  |  | 		obj.children = jsons; | 
					
						
							|  |  |  | 	return obj; | 
					
						
							| 
									
										
										
										
											2014-06-12 04:26:50 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-08 20:39:02 +08:00
										 |  |  | MultiStats.prototype.toString = Stats.prototype.toString; |