| 
									
										
										
										
											2013-05-31 18:22:40 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | "use strict"; | 
					
						
							| 
									
										
										
										
											2015-04-04 08:09:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | function makeRelative(compiler, identifier) { | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 	const context = compiler.context; | 
					
						
							|  |  |  | 	return identifier.split("|").map(str => str.split("!").map(str => path.relative(context, str)).join("!")).join("|"); | 
					
						
							| 
									
										
										
										
											2015-04-04 08:09:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | const path = require("path"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RecordIdsPlugin { | 
					
						
							|  |  |  | 	apply(compiler) { | 
					
						
							|  |  |  | 		compiler.plugin("compilation", compilation => { | 
					
						
							|  |  |  | 			compilation.plugin("record-modules", (modules, records) => { | 
					
						
							|  |  |  | 				if(!records.modules) records.modules = {}; | 
					
						
							|  |  |  | 				if(!records.modules.byIdentifier) records.modules.byIdentifier = {}; | 
					
						
							|  |  |  | 				if(!records.modules.usedIds) records.modules.usedIds = {}; | 
					
						
							| 
									
										
										
										
											2016-07-18 06:41:26 +08:00
										 |  |  | 				modules.forEach(function(module) { | 
					
						
							| 
									
										
										
										
											2016-09-29 23:01:26 +08:00
										 |  |  | 					if(!module.portableId) module.portableId = makeRelative(compiler, module.identifier()); | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 					const identifier = module.portableId; | 
					
						
							|  |  |  | 					records.modules.byIdentifier[identifier] = module.id; | 
					
						
							|  |  |  | 					records.modules.usedIds[module.id] = module.id; | 
					
						
							| 
									
										
										
										
											2016-07-18 06:41:26 +08:00
										 |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 			compilation.plugin("revive-modules", (modules, records) => { | 
					
						
							|  |  |  | 				if(!records.modules) return; | 
					
						
							|  |  |  | 				if(records.modules.byIdentifier) { | 
					
						
							|  |  |  | 					const usedIds = {}; | 
					
						
							|  |  |  | 					modules.forEach(function(module) { | 
					
						
							|  |  |  | 						if(module.id !== null) return; | 
					
						
							|  |  |  | 						if(!module.portableId) module.portableId = makeRelative(compiler, module.identifier()); | 
					
						
							|  |  |  | 						const identifier = module.portableId; | 
					
						
							|  |  |  | 						const id = records.modules.byIdentifier[identifier]; | 
					
						
							|  |  |  | 						if(id === undefined) return; | 
					
						
							|  |  |  | 						if(usedIds[id]) return; | 
					
						
							|  |  |  | 						usedIds[id] = true; | 
					
						
							|  |  |  | 						module.id = id; | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				compilation.usedModuleIds = records.modules.usedIds; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 			function getDepBlockIdent(chunk, block) { | 
					
						
							|  |  |  | 				const ident = []; | 
					
						
							|  |  |  | 				if(block.chunks.length > 1) | 
					
						
							|  |  |  | 					ident.push(block.chunks.indexOf(chunk)); | 
					
						
							|  |  |  | 				while(block.parent) { | 
					
						
							|  |  |  | 					const p = block.parent; | 
					
						
							|  |  |  | 					const idx = p.blocks.indexOf(block); | 
					
						
							|  |  |  | 					const l = p.blocks.length - 1; | 
					
						
							|  |  |  | 					ident.unshift(`${idx}/${l}`); | 
					
						
							|  |  |  | 					block = block.parent; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(!block.identifier) return null; | 
					
						
							|  |  |  | 				ident.unshift(makeRelative(compiler, block.identifier())); | 
					
						
							|  |  |  | 				return ident.join(":"); | 
					
						
							| 
									
										
										
										
											2013-05-31 18:22:40 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 			compilation.plugin("record-chunks", (chunks, records) => { | 
					
						
							|  |  |  | 				records.nextFreeChunkId = compilation.nextFreeChunkId; | 
					
						
							|  |  |  | 				if(!records.chunks) records.chunks = {}; | 
					
						
							|  |  |  | 				if(!records.chunks.byName) records.chunks.byName = {}; | 
					
						
							|  |  |  | 				if(!records.chunks.byBlocks) records.chunks.byBlocks = {}; | 
					
						
							|  |  |  | 				records.chunks.usedIds = {}; | 
					
						
							|  |  |  | 				chunks.forEach(chunk => { | 
					
						
							|  |  |  | 					const name = chunk.name; | 
					
						
							|  |  |  | 					const blockIdents = chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean); | 
					
						
							|  |  |  | 					if(name) records.chunks.byName[name] = chunk.id; | 
					
						
							|  |  |  | 					blockIdents.forEach((blockIdent) => { | 
					
						
							|  |  |  | 						records.chunks.byBlocks[blockIdent] = chunk.id; | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 					records.chunks.usedIds[chunk.id] = chunk.id; | 
					
						
							| 
									
										
										
										
											2013-05-31 18:22:40 +08:00
										 |  |  | 				}); | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 			compilation.plugin("revive-chunks", (chunks, records) => { | 
					
						
							|  |  |  | 				if(!records.chunks) return; | 
					
						
							|  |  |  | 				const usedIds = {}; | 
					
						
							|  |  |  | 				if(records.chunks.byName) { | 
					
						
							|  |  |  | 					chunks.forEach(function(chunk) { | 
					
						
							|  |  |  | 						if(chunk.id !== null) return; | 
					
						
							|  |  |  | 						if(!chunk.name) return; | 
					
						
							|  |  |  | 						const id = records.chunks.byName[chunk.name]; | 
					
						
							|  |  |  | 						if(id === undefined) return; | 
					
						
							|  |  |  | 						if(usedIds[id]) return; | 
					
						
							|  |  |  | 						usedIds[id] = true; | 
					
						
							|  |  |  | 						chunk.id = id; | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(records.chunks.byBlocks) { | 
					
						
							|  |  |  | 					const argumentedChunks = chunks.filter(chunk => chunk.id === null).map(chunk => ({ | 
					
						
							|  |  |  | 						chunk, | 
					
						
							| 
									
										
										
										
											2015-04-21 14:35:34 +08:00
										 |  |  | 						blockIdents: chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean) | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 					})).filter(arg => arg.blockIdents.length > 0); | 
					
						
							|  |  |  | 					let blockIdentsCount = {}; | 
					
						
							|  |  |  | 					argumentedChunks.forEach((arg, idx) => { | 
					
						
							|  |  |  | 						arg.blockIdents.forEach(blockIdent => { | 
					
						
							|  |  |  | 							const id = records.chunks.byBlocks[blockIdent]; | 
					
						
							|  |  |  | 							if(typeof id !== "number") return; | 
					
						
							|  |  |  | 							const accessor = `${id}:${idx}`; | 
					
						
							|  |  |  | 							blockIdentsCount[accessor] = (blockIdentsCount[accessor] || 0) + 1; | 
					
						
							|  |  |  | 						}); | 
					
						
							| 
									
										
										
										
											2013-05-31 18:22:40 +08:00
										 |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 					blockIdentsCount = Object.keys(blockIdentsCount).map(accessor => [blockIdentsCount[accessor]].concat(accessor.split(":").map(Number))).sort((a, b) => b[0] - a[0]); | 
					
						
							|  |  |  | 					blockIdentsCount.forEach(function(arg) { | 
					
						
							|  |  |  | 						const id = arg[1]; | 
					
						
							|  |  |  | 						if(usedIds[id]) return; | 
					
						
							|  |  |  | 						const idx = arg[2]; | 
					
						
							|  |  |  | 						const chunk = argumentedChunks[idx].chunk; | 
					
						
							|  |  |  | 						if(chunk.id !== null) return; | 
					
						
							|  |  |  | 						usedIds[id] = true; | 
					
						
							|  |  |  | 						chunk.id = id; | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				compilation.usedChunkIds = records.chunks.usedIds; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2013-05-31 18:22:40 +08:00
										 |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-02-21 22:13:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | module.exports = RecordIdsPlugin; |