| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError"); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | const { connectChunkGroupParentAndChild } = require("./GraphHelpers"); | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | const ModuleGraphConnection = require("./ModuleGraphConnection"); | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | const { getEntryRuntime, mergeRuntime } = require("./util/runtime"); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ | 
					
						
							|  |  |  | /** @typedef {import("./Chunk")} Chunk */ | 
					
						
							|  |  |  | /** @typedef {import("./ChunkGroup")} ChunkGroup */ | 
					
						
							|  |  |  | /** @typedef {import("./Compilation")} Compilation */ | 
					
						
							|  |  |  | /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | 
					
						
							|  |  |  | /** @typedef {import("./Dependency")} Dependency */ | 
					
						
							|  |  |  | /** @typedef {import("./Entrypoint")} Entrypoint */ | 
					
						
							|  |  |  | /** @typedef {import("./Module")} Module */ | 
					
						
							|  |  |  | /** @typedef {import("./ModuleGraph")} ModuleGraph */ | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */ | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | /** @typedef {import("./logging/Logger").Logger} Logger */ | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} QueueItem | 
					
						
							|  |  |  |  * @property {number} action | 
					
						
							|  |  |  |  * @property {DependenciesBlock} block | 
					
						
							|  |  |  |  * @property {Module} module | 
					
						
							|  |  |  |  * @property {Chunk} chunk | 
					
						
							|  |  |  |  * @property {ChunkGroup} chunkGroup | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  |  * @property {ChunkGroupInfo} chunkGroupInfo | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | /** @typedef {Set<Module> & { plus: Set<Module> }} ModuleSetPlus */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} ChunkGroupInfo | 
					
						
							| 
									
										
										
										
											2019-08-27 18:25:02 +08:00
										 |  |  |  * @property {ChunkGroup} chunkGroup the chunk group | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  |  * @property {RuntimeSpec} runtime the runtimes | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  |  * @property {ModuleSetPlus} minAvailableModules current minimal set of modules available at this point | 
					
						
							| 
									
										
										
										
											2019-07-25 21:39:54 +08:00
										 |  |  |  * @property {boolean} minAvailableModulesOwned true, if minAvailableModules is owned and can be modified | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  |  * @property {ModuleSetPlus[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules | 
					
						
							| 
									
										
										
										
											2020-01-29 01:28:53 +08:00
										 |  |  |  * @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking) | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  |  * @property {Set<[Module, ModuleGraphConnection[]]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  |  * @property {ModuleSetPlus} resultingAvailableModules set of modules available including modules from this chunk group | 
					
						
							| 
									
										
										
										
											2020-01-28 22:55:51 +08:00
										 |  |  |  * @property {Set<ChunkGroupInfo>} children set of children chunk groups, that will be revisited when availableModules shrink | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  |  * @property {Set<ChunkGroupInfo>} availableSources set of chunk groups that are the source for minAvailableModules | 
					
						
							|  |  |  |  * @property {Set<ChunkGroupInfo>} availableChildren set of chunk groups which depend on the this chunk group as availableSource | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  |  * @property {number} preOrderIndex next pre order index | 
					
						
							|  |  |  |  * @property {number} postOrderIndex next post order index | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  |  * @typedef {Object} BlockChunkGroupConnection | 
					
						
							|  |  |  |  * @property {ChunkGroupInfo} originChunkGroupInfo origin chunk group | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * @property {ChunkGroup} chunkGroup referenced chunk group | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | const EMPTY_SET = /** @type {ModuleSetPlus} */ (new Set()); | 
					
						
							|  |  |  | EMPTY_SET.plus = EMPTY_SET; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  |  * @param {ModuleSetPlus} a first set | 
					
						
							|  |  |  |  * @param {ModuleSetPlus} b second set | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  |  * @returns {number} cmp | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const bySetSize = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 	return b.size + b.plus.size - a.size - a.plus.size; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param {ModuleGraphConnection[]} connections list of connections | 
					
						
							|  |  |  |  * @param {RuntimeSpec} runtime for which runtime | 
					
						
							|  |  |  |  * @returns {ConnectionState} connection state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const getActiveStateOfConnections = (connections, runtime) => { | 
					
						
							|  |  |  | 	let merged = connections[0].getActiveState(runtime); | 
					
						
							|  |  |  | 	if (merged === true) return true; | 
					
						
							|  |  |  | 	for (let i = 1; i < connections.length; i++) { | 
					
						
							|  |  |  | 		const c = connections[i]; | 
					
						
							|  |  |  | 		merged = ModuleGraphConnection.addConnectionStates( | 
					
						
							|  |  |  | 			merged, | 
					
						
							|  |  |  | 			c.getActiveState(runtime) | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		if (merged === true) return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return merged; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  |  * Extracts block to modules mapping from all modules | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  |  * @returns {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} the mapping block to modules | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-01-31 23:54:42 +08:00
										 |  |  | const extractBlockModulesMap = compilation => { | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 	const { moduleGraph } = compilation; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 	/** @type {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} */ | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 	const blockModulesMap = new Map(); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 	const blockQueue = new Set(); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (const module of compilation.modules) { | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 		/** @type {WeakMap<Dependency, ModuleGraphConnection>} */ | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 		let moduleMap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (const connection of moduleGraph.getOutgoingConnections(module)) { | 
					
						
							|  |  |  | 			const d = connection.dependency; | 
					
						
							|  |  |  | 			// We skip connections without dependency
 | 
					
						
							|  |  |  | 			if (!d) continue; | 
					
						
							|  |  |  | 			const m = connection.module; | 
					
						
							|  |  |  | 			// We skip connections without Module pointer
 | 
					
						
							|  |  |  | 			if (!m) continue; | 
					
						
							|  |  |  | 			// We skip weak connections
 | 
					
						
							|  |  |  | 			if (connection.weak) continue; | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 			const state = connection.getActiveState(undefined); | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 			// We skip inactive connections
 | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 			if (state === false) continue; | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 			// Store Dependency to Module mapping in local map
 | 
					
						
							|  |  |  | 			// to allow to access it faster compared to
 | 
					
						
							|  |  |  | 			// moduleGraph.getConnection()
 | 
					
						
							|  |  |  | 			if (moduleMap === undefined) { | 
					
						
							|  |  |  | 				moduleMap = new WeakMap(); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			moduleMap.set(connection.dependency, connection); | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 		blockQueue.clear(); | 
					
						
							|  |  |  | 		blockQueue.add(module); | 
					
						
							|  |  |  | 		for (const block of blockQueue) { | 
					
						
							|  |  |  | 			let modules; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (moduleMap !== undefined && block.dependencies) { | 
					
						
							|  |  |  | 				for (const dep of block.dependencies) { | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 					const connection = moduleMap.get(dep); | 
					
						
							|  |  |  | 					if (connection !== undefined) { | 
					
						
							|  |  |  | 						const { module } = connection; | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 						if (modules === undefined) { | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 							modules = new Map(); | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 							blockModulesMap.set(block, modules); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 						const old = modules.get(module); | 
					
						
							|  |  |  | 						if (old !== undefined) { | 
					
						
							|  |  |  | 							old.push(connection); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							modules.set(module, [connection]); | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 			if (block.blocks) { | 
					
						
							|  |  |  | 				for (const b of block.blocks) { | 
					
						
							|  |  |  | 					blockQueue.add(b); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 07:09:51 +08:00
										 |  |  | 	return blockModulesMap; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  |  * @param {Logger} logger a logger | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  |  * @param {Map<Entrypoint, Module[]>} inputEntrypointsAndModules chunk groups which are processed with the modules | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  |  * @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks | 
					
						
							|  |  |  |  * @param {Set<ChunkGroup>} allCreatedChunkGroups filled with all chunk groups that are created here | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | const visitModules = ( | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	compilation, | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 	inputEntrypointsAndModules, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	chunkGroupInfoMap, | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 	blockConnections, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	blocksWithNestedBlocks, | 
					
						
							|  |  |  | 	allCreatedChunkGroups | 
					
						
							|  |  |  | ) => { | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 	const { moduleGraph, chunkGraph } = compilation; | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.time("visitModules: prepare"); | 
					
						
							| 
									
										
										
										
											2020-01-31 23:54:42 +08:00
										 |  |  | 	const blockModulesMap = extractBlockModulesMap(compilation); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 	let statProcessedQueueItems = 0; | 
					
						
							|  |  |  | 	let statProcessedBlocks = 0; | 
					
						
							|  |  |  | 	let statConnectedChunkGroups = 0; | 
					
						
							|  |  |  | 	let statProcessedChunkGroupsForMerging = 0; | 
					
						
							|  |  |  | 	let statMergedAvailableModuleSets = 0; | 
					
						
							|  |  |  | 	let statForkedAvailableModules = 0; | 
					
						
							|  |  |  | 	let statForkedAvailableModulesCount = 0; | 
					
						
							|  |  |  | 	let statForkedAvailableModulesCountPlus = 0; | 
					
						
							|  |  |  | 	let statForkedMergedModulesCount = 0; | 
					
						
							|  |  |  | 	let statForkedMergedModulesCountPlus = 0; | 
					
						
							|  |  |  | 	let statForkedResultModulesCount = 0; | 
					
						
							|  |  |  | 	let statChunkGroupInfoUpdated = 0; | 
					
						
							|  |  |  | 	let statChildChunkGroupsReconnected = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-26 21:51:40 +08:00
										 |  |  | 	let nextChunkGroupIndex = 0; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	let nextFreeModulePreOrderIndex = 0; | 
					
						
							|  |  |  | 	let nextFreeModulePostOrderIndex = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 	/** @type {Map<DependenciesBlock, ChunkGroupInfo>} */ | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	const blockChunkGroups = new Map(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 	/** @type {Map<string, ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const namedChunkGroups = new Map(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 	/** @type {Map<string, ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const namedAsyncEntrypoints = new Map(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const ADD_AND_ENTER_ENTRY_MODULE = 0; | 
					
						
							|  |  |  | 	const ADD_AND_ENTER_MODULE = 1; | 
					
						
							|  |  |  | 	const ENTER_MODULE = 2; | 
					
						
							|  |  |  | 	const PROCESS_BLOCK = 3; | 
					
						
							|  |  |  | 	const PROCESS_ENTRY_BLOCK = 4; | 
					
						
							|  |  |  | 	const LEAVE_MODULE = 5; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 04:22:05 +08:00
										 |  |  | 	/** @type {QueueItem[]} */ | 
					
						
							|  |  |  | 	let queue = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	/** @type {Map<ChunkGroupInfo, Set<ChunkGroupInfo>>} */ | 
					
						
							|  |  |  | 	const queueConnect = new Map(); | 
					
						
							|  |  |  | 	/** @type {Set<ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const chunkGroupsForCombining = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Fill queue with entrypoint modules
 | 
					
						
							|  |  |  | 	// Create ChunkGroupInfo for entrypoints
 | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 	for (const [chunkGroup, modules] of inputEntrypointsAndModules) { | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 		const runtime = getEntryRuntime( | 
					
						
							|  |  |  | 			compilation, | 
					
						
							|  |  |  | 			chunkGroup.name, | 
					
						
							|  |  |  | 			chunkGroup.options | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		/** @type {ChunkGroupInfo} */ | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 		const chunkGroupInfo = { | 
					
						
							|  |  |  | 			chunkGroup, | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			runtime, | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			minAvailableModules: undefined, | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 			minAvailableModulesOwned: false, | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 			availableModulesToBeMerged: [], | 
					
						
							| 
									
										
										
										
											2020-01-29 01:28:53 +08:00
										 |  |  | 			skippedItems: undefined, | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 			resultingAvailableModules: undefined, | 
					
						
							|  |  |  | 			children: undefined, | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			availableSources: undefined, | 
					
						
							|  |  |  | 			availableChildren: undefined, | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 			preOrderIndex: 0, | 
					
						
							|  |  |  | 			postOrderIndex: 0 | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2019-09-26 21:51:40 +08:00
										 |  |  | 		chunkGroup.index = nextChunkGroupIndex++; | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		if (chunkGroup.getNumberOfParents() > 0) { | 
					
						
							|  |  |  | 			// minAvailableModules for child entrypoints are unknown yet, set to undefined.
 | 
					
						
							|  |  |  | 			// This means no module is added until other sets are merged into
 | 
					
						
							|  |  |  | 			// this minAvailableModules (by the parent entrypoints)
 | 
					
						
							|  |  |  | 			const skippedItems = new Set(); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 			for (const module of modules) { | 
					
						
							|  |  |  | 				skippedItems.add(module); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			chunkGroupInfo.skippedItems = skippedItems; | 
					
						
							|  |  |  | 			chunkGroupsForCombining.add(chunkGroupInfo); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// The application may start here: We start with an empty list of available modules
 | 
					
						
							|  |  |  | 			chunkGroupInfo.minAvailableModules = EMPTY_SET; | 
					
						
							| 
									
										
										
										
											2020-07-21 16:22:10 +08:00
										 |  |  | 			const chunk = chunkGroup.getEntrypointChunk(); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 			for (const module of modules) { | 
					
						
							|  |  |  | 				queue.push({ | 
					
						
							|  |  |  | 					action: ADD_AND_ENTER_MODULE, | 
					
						
							|  |  |  | 					block: module, | 
					
						
							|  |  |  | 					module, | 
					
						
							|  |  |  | 					chunk, | 
					
						
							|  |  |  | 					chunkGroup, | 
					
						
							|  |  |  | 					chunkGroupInfo | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 		chunkGroupInfoMap.set(chunkGroup, chunkGroupInfo); | 
					
						
							|  |  |  | 		if (chunkGroup.name) { | 
					
						
							|  |  |  | 			namedChunkGroups.set(chunkGroup.name, chunkGroupInfo); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-17 04:22:05 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	// Fill availableSources with parent-child dependencies between entrypoints
 | 
					
						
							|  |  |  | 	for (const chunkGroupInfo of chunkGroupsForCombining) { | 
					
						
							|  |  |  | 		const { chunkGroup } = chunkGroupInfo; | 
					
						
							|  |  |  | 		chunkGroupInfo.availableSources = new Set(); | 
					
						
							|  |  |  | 		for (const parent of chunkGroup.parentsIterable) { | 
					
						
							|  |  |  | 			const parentChunkGroupInfo = chunkGroupInfoMap.get(parent); | 
					
						
							|  |  |  | 			chunkGroupInfo.availableSources.add(parentChunkGroupInfo); | 
					
						
							|  |  |  | 			if (parentChunkGroupInfo.availableChildren === undefined) { | 
					
						
							|  |  |  | 				parentChunkGroupInfo.availableChildren = new Set(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			parentChunkGroupInfo.availableChildren.add(chunkGroupInfo); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-17 04:22:05 +08:00
										 |  |  | 	// pop() is used to read from the queue
 | 
					
						
							|  |  |  | 	// so it need to be reversed to be iterated in
 | 
					
						
							|  |  |  | 	// correct order
 | 
					
						
							|  |  |  | 	queue.reverse(); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 14:05:16 +08:00
										 |  |  | 	/** @type {Set<ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const outdatedChunkGroupInfo = new Set(); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	/** @type {Set<ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const chunkGroupsForMerging = new Set(); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	/** @type {QueueItem[]} */ | 
					
						
							|  |  |  | 	let queueDelayed = []; | 
					
						
							| 
									
										
										
										
											2019-07-26 14:05:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.timeEnd("visitModules: prepare"); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 	/** @type {[Module, ModuleGraphConnection[]][]} */ | 
					
						
							|  |  |  | 	const skipConnectionBuffer = []; | 
					
						
							| 
									
										
										
										
											2020-01-29 01:28:53 +08:00
										 |  |  | 	/** @type {Module[]} */ | 
					
						
							|  |  |  | 	const skipBuffer = []; | 
					
						
							|  |  |  | 	/** @type {QueueItem[]} */ | 
					
						
							|  |  |  | 	const queueBuffer = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	/** @type {Module} */ | 
					
						
							|  |  |  | 	let module; | 
					
						
							|  |  |  | 	/** @type {Chunk} */ | 
					
						
							|  |  |  | 	let chunk; | 
					
						
							|  |  |  | 	/** @type {ChunkGroup} */ | 
					
						
							|  |  |  | 	let chunkGroup; | 
					
						
							|  |  |  | 	/** @type {DependenciesBlock} */ | 
					
						
							|  |  |  | 	let block; | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  | 	/** @type {ChunkGroupInfo} */ | 
					
						
							|  |  |  | 	let chunkGroupInfo; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// For each async Block in graph
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {AsyncDependenciesBlock} b iterating over each Async DepBlock | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	const iteratorBlock = b => { | 
					
						
							| 
									
										
										
										
											2020-03-18 17:13:30 +08:00
										 |  |  | 		// 1. We create a chunk group with single chunk in it for this Block
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		// but only once (blockChunkGroups map)
 | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 		let cgi = blockChunkGroups.get(b); | 
					
						
							|  |  |  | 		/** @type {ChunkGroup} */ | 
					
						
							|  |  |  | 		let c; | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 		/** @type {Entrypoint} */ | 
					
						
							|  |  |  | 		let entrypoint; | 
					
						
							|  |  |  | 		const entryOptions = b.groupOptions && b.groupOptions.entryOptions; | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 		if (cgi === undefined) { | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  | 			const chunkName = (b.groupOptions && b.groupOptions.name) || b.chunkName; | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 			if (entryOptions) { | 
					
						
							|  |  |  | 				cgi = namedAsyncEntrypoints.get(chunkName); | 
					
						
							|  |  |  | 				if (!cgi) { | 
					
						
							|  |  |  | 					entrypoint = compilation.addAsyncEntrypoint( | 
					
						
							|  |  |  | 						entryOptions, | 
					
						
							|  |  |  | 						module, | 
					
						
							|  |  |  | 						b.loc, | 
					
						
							|  |  |  | 						b.request | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 					entrypoint.index = nextChunkGroupIndex++; | 
					
						
							|  |  |  | 					cgi = { | 
					
						
							|  |  |  | 						chunkGroup: entrypoint, | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 						runtime: entrypoint.options.runtime || entrypoint.name, | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 						minAvailableModules: EMPTY_SET, | 
					
						
							|  |  |  | 						minAvailableModulesOwned: false, | 
					
						
							|  |  |  | 						availableModulesToBeMerged: [], | 
					
						
							|  |  |  | 						skippedItems: undefined, | 
					
						
							|  |  |  | 						resultingAvailableModules: undefined, | 
					
						
							|  |  |  | 						children: undefined, | 
					
						
							|  |  |  | 						availableSources: undefined, | 
					
						
							|  |  |  | 						availableChildren: undefined, | 
					
						
							|  |  |  | 						preOrderIndex: 0, | 
					
						
							|  |  |  | 						postOrderIndex: 0 | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 					chunkGroupInfoMap.set(entrypoint, cgi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					chunkGraph.connectBlockAndChunkGroup(b, entrypoint); | 
					
						
							|  |  |  | 					if (chunkName) { | 
					
						
							|  |  |  | 						namedAsyncEntrypoints.set(chunkName, cgi); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup); | 
					
						
							|  |  |  | 					// TODO merge entryOptions
 | 
					
						
							|  |  |  | 					entrypoint.addOrigin(module, b.loc, b.request); | 
					
						
							|  |  |  | 					chunkGraph.connectBlockAndChunkGroup(b, entrypoint); | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// 2. We enqueue the DependenciesBlock for traversal
 | 
					
						
							|  |  |  | 				queueDelayed.push({ | 
					
						
							|  |  |  | 					action: PROCESS_ENTRY_BLOCK, | 
					
						
							|  |  |  | 					block: b, | 
					
						
							|  |  |  | 					module: module, | 
					
						
							|  |  |  | 					chunk: entrypoint.chunks[0], | 
					
						
							|  |  |  | 					chunkGroup: entrypoint, | 
					
						
							|  |  |  | 					chunkGroupInfo: cgi | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 				cgi = namedChunkGroups.get(chunkName); | 
					
						
							|  |  |  | 				if (!cgi) { | 
					
						
							|  |  |  | 					c = compilation.addChunkInGroup( | 
					
						
							|  |  |  | 						b.groupOptions || b.chunkName, | 
					
						
							|  |  |  | 						module, | 
					
						
							|  |  |  | 						b.loc, | 
					
						
							|  |  |  | 						b.request | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  | 					); | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 					c.index = nextChunkGroupIndex++; | 
					
						
							|  |  |  | 					cgi = { | 
					
						
							|  |  |  | 						chunkGroup: c, | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 						runtime: chunkGroupInfo.runtime, | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 						minAvailableModules: undefined, | 
					
						
							|  |  |  | 						minAvailableModulesOwned: undefined, | 
					
						
							|  |  |  | 						availableModulesToBeMerged: [], | 
					
						
							|  |  |  | 						skippedItems: undefined, | 
					
						
							|  |  |  | 						resultingAvailableModules: undefined, | 
					
						
							|  |  |  | 						children: undefined, | 
					
						
							|  |  |  | 						availableSources: undefined, | 
					
						
							|  |  |  | 						availableChildren: undefined, | 
					
						
							|  |  |  | 						preOrderIndex: 0, | 
					
						
							|  |  |  | 						postOrderIndex: 0 | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 					allCreatedChunkGroups.add(c); | 
					
						
							|  |  |  | 					chunkGroupInfoMap.set(c, cgi); | 
					
						
							|  |  |  | 					if (chunkName) { | 
					
						
							|  |  |  | 						namedChunkGroups.set(chunkName, cgi); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					c = cgi.chunkGroup; | 
					
						
							|  |  |  | 					if (c.isInitial()) { | 
					
						
							|  |  |  | 						compilation.errors.push( | 
					
						
							|  |  |  | 							new AsyncDependencyToInitialChunkError(chunkName, module, b.loc) | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 						c = chunkGroup; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					c.addOptions(b.groupOptions); | 
					
						
							|  |  |  | 					c.addOrigin(module, b.loc, b.request); | 
					
						
							| 
									
										
										
										
											2020-01-28 22:13:10 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 				blockConnections.set(b, []); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 			blockChunkGroups.set(b, cgi); | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 		} else if (entryOptions) { | 
					
						
							|  |  |  | 			entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup); | 
					
						
							| 
									
										
										
										
											2020-01-28 22:44:03 +08:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			c = cgi.chunkGroup; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 		if (c !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 			// 2. We store the connection for the block
 | 
					
						
							|  |  |  | 			// to connect it later if needed
 | 
					
						
							|  |  |  | 			blockConnections.get(b).push({ | 
					
						
							|  |  |  | 				originChunkGroupInfo: chunkGroupInfo, | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 				chunkGroup: c | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 3. We enqueue the chunk group info creation/updating
 | 
					
						
							|  |  |  | 			let connectList = queueConnect.get(chunkGroupInfo); | 
					
						
							|  |  |  | 			if (connectList === undefined) { | 
					
						
							|  |  |  | 				connectList = new Set(); | 
					
						
							|  |  |  | 				queueConnect.set(chunkGroupInfo, connectList); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			connectList.add(cgi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// TODO check if this really need to be done for each traversal
 | 
					
						
							|  |  |  | 			// or if it is enough when it's queued when created
 | 
					
						
							|  |  |  | 			// 4. We enqueue the DependenciesBlock for traversal
 | 
					
						
							|  |  |  | 			queueDelayed.push({ | 
					
						
							|  |  |  | 				action: PROCESS_BLOCK, | 
					
						
							|  |  |  | 				block: b, | 
					
						
							|  |  |  | 				module: module, | 
					
						
							|  |  |  | 				chunk: c.chunks[0], | 
					
						
							|  |  |  | 				chunkGroup: c, | 
					
						
							|  |  |  | 				chunkGroupInfo: cgi | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			chunkGroupInfo.chunkGroup.addAsyncEntrypoint(entrypoint); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {DependenciesBlock} block the block | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	const processBlock = block => { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 		statProcessedBlocks++; | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 		// get prepared block info
 | 
					
						
							|  |  |  | 		const blockModules = blockModulesMap.get(block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (blockModules !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			const { minAvailableModules, runtime } = chunkGroupInfo; | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 			// Buffer items because order need to be reversed to get indices correct
 | 
					
						
							|  |  |  | 			// Traverse all referenced modules
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			for (const entry of blockModules) { | 
					
						
							|  |  |  | 				const [refModule, connections] = entry; | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 				if (chunkGraph.isModuleInChunk(refModule, chunk)) { | 
					
						
							|  |  |  | 					// skip early if already connected
 | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 				const activeState = getActiveStateOfConnections(connections, runtime); | 
					
						
							|  |  |  | 				if (activeState !== true) { | 
					
						
							|  |  |  | 					skipConnectionBuffer.push(entry); | 
					
						
							|  |  |  | 					if (activeState === false) continue; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 				if ( | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 					activeState === true && | 
					
						
							|  |  |  | 					(minAvailableModules.has(refModule) || | 
					
						
							|  |  |  | 						minAvailableModules.plus.has(refModule)) | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 				) { | 
					
						
							|  |  |  | 					// already in parent chunks, skip it for now
 | 
					
						
							|  |  |  | 					skipBuffer.push(refModule); | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// enqueue, then add and enter to be in the correct order
 | 
					
						
							|  |  |  | 				// this is relevant with circular dependencies
 | 
					
						
							|  |  |  | 				queueBuffer.push({ | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 					action: activeState === true ? ADD_AND_ENTER_MODULE : PROCESS_BLOCK, | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 					block: refModule, | 
					
						
							|  |  |  | 					module: refModule, | 
					
						
							|  |  |  | 					chunk, | 
					
						
							|  |  |  | 					chunkGroup, | 
					
						
							|  |  |  | 					chunkGroupInfo | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Add buffered items in reverse order
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			if (skipConnectionBuffer.length > 0) { | 
					
						
							|  |  |  | 				let { skippedModuleConnections } = chunkGroupInfo; | 
					
						
							|  |  |  | 				if (skippedModuleConnections === undefined) { | 
					
						
							|  |  |  | 					chunkGroupInfo.skippedModuleConnections = skippedModuleConnections = new Set(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for (let i = skipConnectionBuffer.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 					skippedModuleConnections.add(skipConnectionBuffer[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				skipConnectionBuffer.length = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 			if (skipBuffer.length > 0) { | 
					
						
							|  |  |  | 				let { skippedItems } = chunkGroupInfo; | 
					
						
							|  |  |  | 				if (skippedItems === undefined) { | 
					
						
							|  |  |  | 					chunkGroupInfo.skippedItems = skippedItems = new Set(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for (let i = skipBuffer.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 					skippedItems.add(skipBuffer[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				skipBuffer.length = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (queueBuffer.length > 0) { | 
					
						
							|  |  |  | 				for (let i = queueBuffer.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 					queue.push(queueBuffer[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				queueBuffer.length = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Traverse all Blocks
 | 
					
						
							|  |  |  | 		for (const b of block.blocks) { | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 			iteratorBlock(b); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (block.blocks.length > 0 && module !== block) { | 
					
						
							|  |  |  | 			blocksWithNestedBlocks.add(block); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {DependenciesBlock} block the block | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	const processEntryBlock = block => { | 
					
						
							|  |  |  | 		statProcessedBlocks++; | 
					
						
							|  |  |  | 		// get prepared block info
 | 
					
						
							|  |  |  | 		const blockModules = blockModulesMap.get(block); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (blockModules !== undefined) { | 
					
						
							|  |  |  | 			// Traverse all referenced modules
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			for (const [refModule, connections] of blockModules) { | 
					
						
							|  |  |  | 				const activeState = getActiveStateOfConnections(connections, undefined); | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 				// enqueue, then add and enter to be in the correct order
 | 
					
						
							|  |  |  | 				// this is relevant with circular dependencies
 | 
					
						
							|  |  |  | 				queueBuffer.push({ | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 					action: | 
					
						
							| 
									
										
										
										
											2020-10-07 15:10:29 +08:00
										 |  |  | 						activeState === true ? ADD_AND_ENTER_ENTRY_MODULE : PROCESS_BLOCK, | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 					block: refModule, | 
					
						
							|  |  |  | 					module: refModule, | 
					
						
							|  |  |  | 					chunk, | 
					
						
							|  |  |  | 					chunkGroup, | 
					
						
							|  |  |  | 					chunkGroupInfo | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Add buffered items in reverse order
 | 
					
						
							|  |  |  | 			if (queueBuffer.length > 0) { | 
					
						
							|  |  |  | 				for (let i = queueBuffer.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  | 					queue.push(queueBuffer[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				queueBuffer.length = 0; | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 		// Traverse all Blocks
 | 
					
						
							|  |  |  | 		for (const b of block.blocks) { | 
					
						
							|  |  |  | 			iteratorBlock(b); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 		if (block.blocks.length > 0 && module !== block) { | 
					
						
							|  |  |  | 			blocksWithNestedBlocks.add(block); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	const processQueue = () => { | 
					
						
							|  |  |  | 		while (queue.length) { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 			statProcessedQueueItems++; | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			const queueItem = queue.pop(); | 
					
						
							|  |  |  | 			module = queueItem.module; | 
					
						
							|  |  |  | 			block = queueItem.block; | 
					
						
							|  |  |  | 			chunk = queueItem.chunk; | 
					
						
							|  |  |  | 			chunkGroup = queueItem.chunkGroup; | 
					
						
							|  |  |  | 			chunkGroupInfo = queueItem.chunkGroupInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			switch (queueItem.action) { | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 				case ADD_AND_ENTER_ENTRY_MODULE: | 
					
						
							|  |  |  | 					chunkGraph.connectChunkAndEntryModule( | 
					
						
							|  |  |  | 						chunk, | 
					
						
							|  |  |  | 						module, | 
					
						
							|  |  |  | 						/** @type {Entrypoint} */ (chunkGroup) | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				// fallthrough
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 				case ADD_AND_ENTER_MODULE: { | 
					
						
							|  |  |  | 					if (chunkGraph.isModuleInChunk(module, chunk)) { | 
					
						
							|  |  |  | 						// already connected, skip it
 | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					// We connect Module and Chunk
 | 
					
						
							|  |  |  | 					chunkGraph.connectChunkAndModule(chunk, module); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// fallthrough
 | 
					
						
							|  |  |  | 				case ENTER_MODULE: { | 
					
						
							|  |  |  | 					const index = chunkGroup.getModulePreOrderIndex(module); | 
					
						
							|  |  |  | 					if (index === undefined) { | 
					
						
							|  |  |  | 						chunkGroup.setModulePreOrderIndex( | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							chunkGroupInfo.preOrderIndex++ | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if ( | 
					
						
							|  |  |  | 						moduleGraph.setPreOrderIndexIfUnset( | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							nextFreeModulePreOrderIndex | 
					
						
							|  |  |  | 						) | 
					
						
							|  |  |  | 					) { | 
					
						
							|  |  |  | 						nextFreeModulePreOrderIndex++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// reuse queueItem
 | 
					
						
							|  |  |  | 					queueItem.action = LEAVE_MODULE; | 
					
						
							|  |  |  | 					queue.push(queueItem); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				// fallthrough
 | 
					
						
							|  |  |  | 				case PROCESS_BLOCK: { | 
					
						
							| 
									
										
										
										
											2020-04-30 06:39:36 +08:00
										 |  |  | 					processBlock(block); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-09-08 00:02:14 +08:00
										 |  |  | 				case PROCESS_ENTRY_BLOCK: { | 
					
						
							|  |  |  | 					processEntryBlock(block); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 				case LEAVE_MODULE: { | 
					
						
							|  |  |  | 					const index = chunkGroup.getModulePostOrderIndex(module); | 
					
						
							|  |  |  | 					if (index === undefined) { | 
					
						
							|  |  |  | 						chunkGroup.setModulePostOrderIndex( | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							chunkGroupInfo.postOrderIndex++ | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if ( | 
					
						
							|  |  |  | 						moduleGraph.setPostOrderIndexIfUnset( | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							nextFreeModulePostOrderIndex | 
					
						
							|  |  |  | 						) | 
					
						
							|  |  |  | 					) { | 
					
						
							|  |  |  | 						nextFreeModulePostOrderIndex++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const calculateResultingAvailableModules = chunkGroupInfo => { | 
					
						
							|  |  |  | 		if (chunkGroupInfo.resultingAvailableModules) | 
					
						
							|  |  |  | 			return chunkGroupInfo.resultingAvailableModules; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const minAvailableModules = chunkGroupInfo.minAvailableModules; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Create a new Set of available modules at this point
 | 
					
						
							|  |  |  | 		// We want to be as lazy as possible. There are multiple ways doing this:
 | 
					
						
							|  |  |  | 		// Note that resultingAvailableModules is stored as "(a) + (b)" as it's a ModuleSetPlus
 | 
					
						
							|  |  |  | 		// - resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
 | 
					
						
							|  |  |  | 		// - resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
 | 
					
						
							|  |  |  | 		// We choose one depending on the size of minAvailableModules vs minAvailableModules.plus
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		let resultingAvailableModules; | 
					
						
							|  |  |  | 		if (minAvailableModules.size > minAvailableModules.plus.size) { | 
					
						
							|  |  |  | 			// resultingAvailableModules = (modules of chunk) + (minAvailableModules + minAvailableModules.plus)
 | 
					
						
							|  |  |  | 			resultingAvailableModules = /** @type {Set<Module> & {plus: Set<Module>}} */ (new Set()); | 
					
						
							|  |  |  | 			for (const module of minAvailableModules.plus) | 
					
						
							|  |  |  | 				minAvailableModules.add(module); | 
					
						
							|  |  |  | 			minAvailableModules.plus = EMPTY_SET; | 
					
						
							|  |  |  | 			resultingAvailableModules.plus = minAvailableModules; | 
					
						
							|  |  |  | 			chunkGroupInfo.minAvailableModulesOwned = false; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// resultingAvailableModules = (minAvailableModules + modules of chunk) + (minAvailableModules.plus)
 | 
					
						
							|  |  |  | 			resultingAvailableModules = /** @type {Set<Module> & {plus: Set<Module>}} */ (new Set( | 
					
						
							|  |  |  | 				minAvailableModules | 
					
						
							|  |  |  | 			)); | 
					
						
							|  |  |  | 			resultingAvailableModules.plus = minAvailableModules.plus; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// add the modules from the chunk group to the set
 | 
					
						
							|  |  |  | 		for (const chunk of chunkGroupInfo.chunkGroup.chunks) { | 
					
						
							|  |  |  | 			for (const m of chunkGraph.getChunkModulesIterable(chunk)) { | 
					
						
							|  |  |  | 				resultingAvailableModules.add(m); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return (chunkGroupInfo.resultingAvailableModules = resultingAvailableModules); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 	const processConnectQueue = () => { | 
					
						
							|  |  |  | 		// Figure out new parents for chunk groups
 | 
					
						
							|  |  |  | 		// to get new available modules for these children
 | 
					
						
							|  |  |  | 		for (const [chunkGroupInfo, targets] of queueConnect) { | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			// 1. Add new targets to the list of children
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			if (chunkGroupInfo.children === undefined) { | 
					
						
							|  |  |  | 				chunkGroupInfo.children = targets; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				for (const target of targets) { | 
					
						
							|  |  |  | 					chunkGroupInfo.children.add(target); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			// 2. Calculate resulting available modules
 | 
					
						
							|  |  |  | 			const resultingAvailableModules = calculateResultingAvailableModules( | 
					
						
							|  |  |  | 				chunkGroupInfo | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			const runtime = chunkGroupInfo.runtime; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			// 3. Update chunk group info
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			for (const target of targets) { | 
					
						
							|  |  |  | 				target.availableModulesToBeMerged.push(resultingAvailableModules); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 				chunkGroupsForMerging.add(target); | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 				const oldRuntime = target.runtime; | 
					
						
							|  |  |  | 				const newRuntime = mergeRuntime(oldRuntime, runtime); | 
					
						
							|  |  |  | 				if (oldRuntime !== newRuntime) { | 
					
						
							|  |  |  | 					target.runtime = newRuntime; | 
					
						
							|  |  |  | 					outdatedChunkGroupInfo.add(target); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			statConnectedChunkGroups += targets.size; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		queueConnect.clear(); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	const processChunkGroupsForMerging = () => { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 		statProcessedChunkGroupsForMerging += chunkGroupsForMerging.size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 		// Execute the merge
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		for (const info of chunkGroupsForMerging) { | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			const availableModulesToBeMerged = info.availableModulesToBeMerged; | 
					
						
							|  |  |  | 			let cachedMinAvailableModules = info.minAvailableModules; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 			statMergedAvailableModuleSets += availableModulesToBeMerged.length; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			// 1. Get minimal available modules
 | 
					
						
							|  |  |  | 			// It doesn't make sense to traverse a chunk again with more available modules.
 | 
					
						
							|  |  |  | 			// This step calculates the minimal available modules and skips traversal when
 | 
					
						
							|  |  |  | 			// the list didn't shrink.
 | 
					
						
							|  |  |  | 			if (availableModulesToBeMerged.length > 1) { | 
					
						
							|  |  |  | 				availableModulesToBeMerged.sort(bySetSize); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			let changed = false; | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 			merge: for (const availableModules of availableModulesToBeMerged) { | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 				if (cachedMinAvailableModules === undefined) { | 
					
						
							|  |  |  | 					cachedMinAvailableModules = availableModules; | 
					
						
							|  |  |  | 					info.minAvailableModules = cachedMinAvailableModules; | 
					
						
							|  |  |  | 					info.minAvailableModulesOwned = false; | 
					
						
							|  |  |  | 					changed = true; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if (info.minAvailableModulesOwned) { | 
					
						
							|  |  |  | 						// We own it and can modify it
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 						if (cachedMinAvailableModules.plus === availableModules.plus) { | 
					
						
							|  |  |  | 							for (const m of cachedMinAvailableModules) { | 
					
						
							|  |  |  | 								if (!availableModules.has(m)) { | 
					
						
							|  |  |  | 									cachedMinAvailableModules.delete(m); | 
					
						
							|  |  |  | 									changed = true; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							for (const m of cachedMinAvailableModules) { | 
					
						
							|  |  |  | 								if (!availableModules.has(m) && !availableModules.plus.has(m)) { | 
					
						
							|  |  |  | 									cachedMinAvailableModules.delete(m); | 
					
						
							|  |  |  | 									changed = true; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							for (const m of cachedMinAvailableModules.plus) { | 
					
						
							|  |  |  | 								if (!availableModules.has(m) && !availableModules.plus.has(m)) { | 
					
						
							|  |  |  | 									// We can't remove modules from the plus part
 | 
					
						
							|  |  |  | 									// so we need to merge plus into the normal part to allow modifying it
 | 
					
						
							|  |  |  | 									const iterator = cachedMinAvailableModules.plus[ | 
					
						
							|  |  |  | 										Symbol.iterator | 
					
						
							|  |  |  | 									](); | 
					
						
							|  |  |  | 									// fast forward add all modules until m
 | 
					
						
							|  |  |  | 									/** @type {IteratorResult<Module>} */ | 
					
						
							|  |  |  | 									let it; | 
					
						
							|  |  |  | 									while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 										const module = it.value; | 
					
						
							|  |  |  | 										if (module === m) break; | 
					
						
							|  |  |  | 										cachedMinAvailableModules.add(module); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									// check the remaining modules before adding
 | 
					
						
							|  |  |  | 									while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 										const module = it.value; | 
					
						
							|  |  |  | 										if ( | 
					
						
							|  |  |  | 											availableModules.has(module) || | 
					
						
							|  |  |  | 											availableModules.plus.has(m) | 
					
						
							|  |  |  | 										) { | 
					
						
							|  |  |  | 											cachedMinAvailableModules.add(module); | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									cachedMinAvailableModules.plus = EMPTY_SET; | 
					
						
							|  |  |  | 									changed = true; | 
					
						
							|  |  |  | 									continue merge; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} else if (cachedMinAvailableModules.plus === availableModules.plus) { | 
					
						
							| 
									
										
										
										
											2020-08-13 21:45:24 +08:00
										 |  |  | 						// Common and fast case when the plus part is shared
 | 
					
						
							|  |  |  | 						// We only need to care about the normal part
 | 
					
						
							|  |  |  | 						if (availableModules.size < cachedMinAvailableModules.size) { | 
					
						
							|  |  |  | 							// the new availableModules is smaller so it's faster to
 | 
					
						
							|  |  |  | 							// fork from the new availableModules
 | 
					
						
							|  |  |  | 							statForkedAvailableModules++; | 
					
						
							|  |  |  | 							statForkedAvailableModulesCount += availableModules.size; | 
					
						
							|  |  |  | 							statForkedMergedModulesCount += cachedMinAvailableModules.size; | 
					
						
							|  |  |  | 							// construct a new Set as intersection of cachedMinAvailableModules and availableModules
 | 
					
						
							|  |  |  | 							const newSet = /** @type {ModuleSetPlus} */ (new Set()); | 
					
						
							|  |  |  | 							newSet.plus = availableModules.plus; | 
					
						
							|  |  |  | 							for (const m of availableModules) { | 
					
						
							|  |  |  | 								if (cachedMinAvailableModules.has(m)) { | 
					
						
							|  |  |  | 									newSet.add(m); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							statForkedResultModulesCount += newSet.size; | 
					
						
							|  |  |  | 							cachedMinAvailableModules = newSet; | 
					
						
							|  |  |  | 							info.minAvailableModulesOwned = true; | 
					
						
							|  |  |  | 							info.minAvailableModules = newSet; | 
					
						
							|  |  |  | 							changed = true; | 
					
						
							|  |  |  | 							continue merge; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 						for (const m of cachedMinAvailableModules) { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 							if (!availableModules.has(m)) { | 
					
						
							| 
									
										
										
										
											2020-08-13 21:45:24 +08:00
										 |  |  | 								// cachedMinAvailableModules need to be modified
 | 
					
						
							|  |  |  | 								// but we don't own it
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								statForkedAvailableModules++; | 
					
						
							|  |  |  | 								statForkedAvailableModulesCount += | 
					
						
							|  |  |  | 									cachedMinAvailableModules.size; | 
					
						
							|  |  |  | 								statForkedMergedModulesCount += availableModules.size; | 
					
						
							|  |  |  | 								// construct a new Set as intersection of cachedMinAvailableModules and availableModules
 | 
					
						
							|  |  |  | 								// as the plus part is equal we can just take over this one
 | 
					
						
							|  |  |  | 								const newSet = /** @type {ModuleSetPlus} */ (new Set()); | 
					
						
							|  |  |  | 								newSet.plus = availableModules.plus; | 
					
						
							|  |  |  | 								const iterator = cachedMinAvailableModules[Symbol.iterator](); | 
					
						
							|  |  |  | 								// fast forward add all modules until m
 | 
					
						
							|  |  |  | 								/** @type {IteratorResult<Module>} */ | 
					
						
							|  |  |  | 								let it; | 
					
						
							|  |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if (module === m) break; | 
					
						
							|  |  |  | 									newSet.add(module); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								// check the remaining modules before adding
 | 
					
						
							|  |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if (availableModules.has(module)) { | 
					
						
							|  |  |  | 										newSet.add(module); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								statForkedResultModulesCount += newSet.size; | 
					
						
							|  |  |  | 								cachedMinAvailableModules = newSet; | 
					
						
							|  |  |  | 								info.minAvailableModulesOwned = true; | 
					
						
							|  |  |  | 								info.minAvailableModules = newSet; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								changed = true; | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								continue merge; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						for (const m of cachedMinAvailableModules) { | 
					
						
							|  |  |  | 							if (!availableModules.has(m) && !availableModules.plus.has(m)) { | 
					
						
							| 
									
										
										
										
											2020-08-13 21:45:24 +08:00
										 |  |  | 								// cachedMinAvailableModules need to be modified
 | 
					
						
							|  |  |  | 								// but we don't own it
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								statForkedAvailableModules++; | 
					
						
							|  |  |  | 								statForkedAvailableModulesCount += | 
					
						
							|  |  |  | 									cachedMinAvailableModules.size; | 
					
						
							|  |  |  | 								statForkedAvailableModulesCountPlus += | 
					
						
							|  |  |  | 									cachedMinAvailableModules.plus.size; | 
					
						
							|  |  |  | 								statForkedMergedModulesCount += availableModules.size; | 
					
						
							|  |  |  | 								statForkedMergedModulesCountPlus += availableModules.plus.size; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								// construct a new Set as intersection of cachedMinAvailableModules and availableModules
 | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								const newSet = /** @type {ModuleSetPlus} */ (new Set()); | 
					
						
							|  |  |  | 								newSet.plus = EMPTY_SET; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								const iterator = cachedMinAvailableModules[Symbol.iterator](); | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								// fast forward add all modules until m
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								/** @type {IteratorResult<Module>} */ | 
					
						
							|  |  |  | 								let it; | 
					
						
							|  |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if (module === m) break; | 
					
						
							|  |  |  | 									newSet.add(module); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								// check the remaining modules before adding
 | 
					
						
							|  |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										availableModules.has(module) || | 
					
						
							|  |  |  | 										availableModules.plus.has(module) | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										newSet.add(module); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								// also check all modules in cachedMinAvailableModules.plus
 | 
					
						
							|  |  |  | 								for (const module of cachedMinAvailableModules.plus) { | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										availableModules.has(module) || | 
					
						
							|  |  |  | 										availableModules.plus.has(module) | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										newSet.add(module); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								statForkedResultModulesCount += newSet.size; | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								cachedMinAvailableModules = newSet; | 
					
						
							|  |  |  | 								info.minAvailableModulesOwned = true; | 
					
						
							|  |  |  | 								info.minAvailableModules = newSet; | 
					
						
							|  |  |  | 								changed = true; | 
					
						
							|  |  |  | 								continue merge; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						for (const m of cachedMinAvailableModules.plus) { | 
					
						
							|  |  |  | 							if (!availableModules.has(m) && !availableModules.plus.has(m)) { | 
					
						
							| 
									
										
										
										
											2020-08-13 21:45:24 +08:00
										 |  |  | 								// cachedMinAvailableModules need to be modified
 | 
					
						
							|  |  |  | 								// but we don't own it
 | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								statForkedAvailableModules++; | 
					
						
							|  |  |  | 								statForkedAvailableModulesCount += | 
					
						
							|  |  |  | 									cachedMinAvailableModules.size; | 
					
						
							|  |  |  | 								statForkedAvailableModulesCountPlus += | 
					
						
							|  |  |  | 									cachedMinAvailableModules.plus.size; | 
					
						
							|  |  |  | 								statForkedMergedModulesCount += availableModules.size; | 
					
						
							|  |  |  | 								statForkedMergedModulesCountPlus += availableModules.plus.size; | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								// construct a new Set as intersection of cachedMinAvailableModules and availableModules
 | 
					
						
							|  |  |  | 								// we already know that all modules directly from cachedMinAvailableModules are in availableModules too
 | 
					
						
							|  |  |  | 								const newSet = /** @type {ModuleSetPlus} */ (new Set( | 
					
						
							|  |  |  | 									cachedMinAvailableModules | 
					
						
							|  |  |  | 								)); | 
					
						
							|  |  |  | 								newSet.plus = EMPTY_SET; | 
					
						
							|  |  |  | 								const iterator = cachedMinAvailableModules.plus[ | 
					
						
							|  |  |  | 									Symbol.iterator | 
					
						
							|  |  |  | 								](); | 
					
						
							|  |  |  | 								// fast forward add all modules until m
 | 
					
						
							|  |  |  | 								/** @type {IteratorResult<Module>} */ | 
					
						
							|  |  |  | 								let it; | 
					
						
							|  |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if (module === m) break; | 
					
						
							|  |  |  | 									newSet.add(module); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								// check the remaining modules before adding
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								while (!(it = iterator.next()).done) { | 
					
						
							|  |  |  | 									const module = it.value; | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										availableModules.has(module) || | 
					
						
							|  |  |  | 										availableModules.plus.has(module) | 
					
						
							|  |  |  | 									) { | 
					
						
							|  |  |  | 										newSet.add(module); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 								statForkedResultModulesCount += newSet.size; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 								cachedMinAvailableModules = newSet; | 
					
						
							|  |  |  | 								info.minAvailableModulesOwned = true; | 
					
						
							|  |  |  | 								info.minAvailableModules = newSet; | 
					
						
							|  |  |  | 								changed = true; | 
					
						
							| 
									
										
										
										
											2020-02-01 23:09:43 +08:00
										 |  |  | 								continue merge; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			availableModulesToBeMerged.length = 0; | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			if (changed) { | 
					
						
							|  |  |  | 				info.resultingAvailableModules = undefined; | 
					
						
							|  |  |  | 				outdatedChunkGroupInfo.add(info); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 		chunkGroupsForMerging.clear(); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const processChunkGroupsForCombining = () => { | 
					
						
							|  |  |  | 		loop: for (const info of chunkGroupsForCombining) { | 
					
						
							|  |  |  | 			for (const source of info.availableSources) { | 
					
						
							|  |  |  | 				if (!source.minAvailableModules) continue loop; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			const availableModules = /** @type {ModuleSetPlus} */ (new Set()); | 
					
						
							|  |  |  | 			availableModules.plus = EMPTY_SET; | 
					
						
							|  |  |  | 			const mergeSet = set => { | 
					
						
							|  |  |  | 				if (set.size > availableModules.plus.size) { | 
					
						
							|  |  |  | 					for (const item of availableModules.plus) availableModules.add(item); | 
					
						
							|  |  |  | 					availableModules.plus = set; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					for (const item of set) availableModules.add(item); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			// combine minAvailableModules from all resultingAvailableModules
 | 
					
						
							|  |  |  | 			for (const source of info.availableSources) { | 
					
						
							|  |  |  | 				const resultingAvailableModules = calculateResultingAvailableModules( | 
					
						
							|  |  |  | 					source | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				mergeSet(resultingAvailableModules); | 
					
						
							|  |  |  | 				mergeSet(resultingAvailableModules.plus); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			info.minAvailableModules = availableModules; | 
					
						
							|  |  |  | 			info.minAvailableModulesOwned = false; | 
					
						
							|  |  |  | 			info.resultingAvailableModules = undefined; | 
					
						
							|  |  |  | 			outdatedChunkGroupInfo.add(info); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		chunkGroupsForCombining.clear(); | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	const processOutdatedChunkGroupInfo = () => { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 		statChunkGroupInfoUpdated += outdatedChunkGroupInfo.size; | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		// Revisit skipped elements
 | 
					
						
							|  |  |  | 		for (const info of outdatedChunkGroupInfo) { | 
					
						
							|  |  |  | 			// 1. Reconsider skipped items
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			if (info.skippedItems !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 				const { minAvailableModules } = info; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 				for (const module of info.skippedItems) { | 
					
						
							| 
									
										
										
										
											2020-02-06 18:15:57 +08:00
										 |  |  | 					if ( | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 						!minAvailableModules.has(module) && | 
					
						
							|  |  |  | 						!minAvailableModules.plus.has(module) | 
					
						
							| 
									
										
										
										
											2020-02-06 18:15:57 +08:00
										 |  |  | 					) { | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 						queue.push({ | 
					
						
							|  |  |  | 							action: ADD_AND_ENTER_MODULE, | 
					
						
							|  |  |  | 							block: module, | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							chunk: info.chunkGroup.chunks[0], | 
					
						
							|  |  |  | 							chunkGroup: info.chunkGroup, | 
					
						
							|  |  |  | 							chunkGroupInfo: info | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						info.skippedItems.delete(module); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 			// 2. Reconsider skipped connections
 | 
					
						
							|  |  |  | 			if (info.skippedModuleConnections !== undefined) { | 
					
						
							|  |  |  | 				const { minAvailableModules, runtime } = info; | 
					
						
							|  |  |  | 				for (const entry of info.skippedModuleConnections) { | 
					
						
							|  |  |  | 					const [module, connections] = entry; | 
					
						
							|  |  |  | 					const activeState = getActiveStateOfConnections(connections, runtime); | 
					
						
							|  |  |  | 					if (activeState === false) continue; | 
					
						
							|  |  |  | 					if (activeState === true) { | 
					
						
							|  |  |  | 						info.skippedModuleConnections.delete(entry); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if ( | 
					
						
							|  |  |  | 						activeState === true && | 
					
						
							|  |  |  | 						(minAvailableModules.has(module) || | 
					
						
							|  |  |  | 							minAvailableModules.plus.has(module)) | 
					
						
							|  |  |  | 					) { | 
					
						
							|  |  |  | 						info.skippedItems.add(module); | 
					
						
							|  |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					queue.push({ | 
					
						
							|  |  |  | 						action: activeState === true ? ADD_AND_ENTER_MODULE : PROCESS_BLOCK, | 
					
						
							|  |  |  | 						block: module, | 
					
						
							|  |  |  | 						module, | 
					
						
							|  |  |  | 						chunk: info.chunkGroup.chunks[0], | 
					
						
							|  |  |  | 						chunkGroup: info.chunkGroup, | 
					
						
							|  |  |  | 						chunkGroupInfo: info | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			// 2. Reconsider children chunk groups
 | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			if (info.children !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 				statChildChunkGroupsReconnected += info.children.size; | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 				for (const cgi of info.children) { | 
					
						
							|  |  |  | 					let connectList = queueConnect.get(info); | 
					
						
							|  |  |  | 					if (connectList === undefined) { | 
					
						
							|  |  |  | 						connectList = new Set(); | 
					
						
							|  |  |  | 						queueConnect.set(info, connectList); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					connectList.add(cgi); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// 3. Reconsider chunk groups for combining
 | 
					
						
							|  |  |  | 			if (info.availableChildren !== undefined) { | 
					
						
							|  |  |  | 				for (const cgi of info.availableChildren) { | 
					
						
							|  |  |  | 					chunkGroupsForCombining.add(cgi); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		outdatedChunkGroupInfo.clear(); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	// Iterative traversal of the Module graph
 | 
					
						
							|  |  |  | 	// Recursive would be simpler to write but could result in Stack Overflows
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 	while (queue.length || queueConnect.size) { | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 		logger.time("visitModules: visiting"); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		processQueue(); | 
					
						
							|  |  |  | 		logger.timeEnd("visitModules: visiting"); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		if (chunkGroupsForCombining.size > 0) { | 
					
						
							|  |  |  | 			logger.time("visitModules: combine available modules"); | 
					
						
							|  |  |  | 			processChunkGroupsForCombining(); | 
					
						
							|  |  |  | 			logger.timeEnd("visitModules: combine available modules"); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-26 14:05:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		if (queueConnect.size > 0) { | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 			logger.time("visitModules: calculating available modules"); | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 			processConnectQueue(); | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 			logger.timeEnd("visitModules: calculating available modules"); | 
					
						
							| 
									
										
										
										
											2019-07-26 14:05:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			if (chunkGroupsForMerging.size > 0) { | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 				logger.time("visitModules: merging available modules"); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 				processChunkGroupsForMerging(); | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 				logger.timeEnd("visitModules: merging available modules"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		if (outdatedChunkGroupInfo.size > 0) { | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:26 +08:00
										 |  |  | 			logger.time("visitModules: check modules for revisit"); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 			processOutdatedChunkGroupInfo(); | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:26 +08:00
										 |  |  | 			logger.timeEnd("visitModules: check modules for revisit"); | 
					
						
							| 
									
										
										
										
											2020-02-07 17:05:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		// Run queueDelayed when all items of the queue are processed
 | 
					
						
							| 
									
										
										
										
											2020-01-03 14:21:54 +08:00
										 |  |  | 		// This is important to get the global indexing correct
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		// Async blocks should be processed after all sync blocks are processed
 | 
					
						
							|  |  |  | 		if (queue.length === 0) { | 
					
						
							|  |  |  | 			const tempQueue = queue; | 
					
						
							|  |  |  | 			queue = queueDelayed.reverse(); | 
					
						
							|  |  |  | 			queueDelayed = tempQueue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	logger.log( | 
					
						
							| 
									
										
										
										
											2020-08-14 12:29:10 +08:00
										 |  |  | 		`${statProcessedQueueItems} queue items processed (${statProcessedBlocks} blocks)` | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 	); | 
					
						
							| 
									
										
										
										
											2020-08-14 12:29:10 +08:00
										 |  |  | 	logger.log(`${statConnectedChunkGroups} chunk groups connected`); | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 	logger.log( | 
					
						
							| 
									
										
										
										
											2020-08-14 12:29:10 +08:00
										 |  |  | 		`${statProcessedChunkGroupsForMerging} chunk groups processed for merging (${statMergedAvailableModuleSets} module sets, ${statForkedAvailableModules} forked, ${statForkedAvailableModulesCount} + ${statForkedAvailableModulesCountPlus} modules forked, ${statForkedMergedModulesCount} + ${statForkedMergedModulesCountPlus} modules merged into fork, ${statForkedResultModulesCount} resulting modules)` | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 	); | 
					
						
							|  |  |  | 	logger.log( | 
					
						
							| 
									
										
										
										
											2020-08-14 12:29:10 +08:00
										 |  |  | 		`${statChunkGroupInfoUpdated} chunk group info updated (${statChildChunkGroupsReconnected} already connected chunk groups reconnected)` | 
					
						
							| 
									
										
										
										
											2020-08-13 20:39:55 +08:00
										 |  |  | 	); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							|  |  |  |  * @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  |  * @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const connectChunkGroups = ( | 
					
						
							|  |  |  | 	compilation, | 
					
						
							|  |  |  | 	blocksWithNestedBlocks, | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 	blockConnections, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	chunkGroupInfoMap | 
					
						
							|  |  |  | ) => { | 
					
						
							|  |  |  | 	const { chunkGraph } = compilation; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * Helper function to check if all modules of a chunk are available | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * @param {ChunkGroup} chunkGroup the chunkGroup to scan | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 	 * @param {ModuleSetPlus} availableModules the comparator set | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 	 * @returns {boolean} return true if all modules of a chunk are available | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	const areModulesAvailable = (chunkGroup, availableModules) => { | 
					
						
							|  |  |  | 		for (const chunk of chunkGroup.chunks) { | 
					
						
							|  |  |  | 			for (const module of chunkGraph.getChunkModulesIterable(chunk)) { | 
					
						
							| 
									
										
										
										
											2020-01-31 23:38:04 +08:00
										 |  |  | 				if (!availableModules.has(module) && !availableModules.plus.has(module)) | 
					
						
							|  |  |  | 					return false; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// For each edge in the basic chunk graph
 | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 	for (const [block, connections] of blockConnections) { | 
					
						
							|  |  |  | 		// 1. Check if connection is needed
 | 
					
						
							|  |  |  | 		// When none of the dependencies need to be connected
 | 
					
						
							|  |  |  | 		// we can skip all of them
 | 
					
						
							|  |  |  | 		// It's not possible to filter each item so it doesn't create inconsistent
 | 
					
						
							|  |  |  | 		// connections and modules can only create one version
 | 
					
						
							|  |  |  | 		// TODO maybe decide this per runtime
 | 
					
						
							|  |  |  | 		if ( | 
					
						
							|  |  |  | 			// TODO is this needed?
 | 
					
						
							|  |  |  | 			!blocksWithNestedBlocks.has(block) && | 
					
						
							|  |  |  | 			connections.every(({ chunkGroup, originChunkGroupInfo }) => | 
					
						
							|  |  |  | 				areModulesAvailable( | 
					
						
							|  |  |  | 					chunkGroup, | 
					
						
							|  |  |  | 					originChunkGroupInfo.resultingAvailableModules | 
					
						
							|  |  |  | 				) | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 		) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		// 2. Foreach edge
 | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 		for (let i = 0; i < connections.length; i++) { | 
					
						
							|  |  |  | 			const { chunkGroup, originChunkGroupInfo } = connections[i]; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 			// 3. Connect block with chunk
 | 
					
						
							|  |  |  | 			chunkGraph.connectBlockAndChunkGroup(block, chunkGroup); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 			// 4. Connect chunk with parent
 | 
					
						
							|  |  |  | 			connectChunkGroupParentAndChild( | 
					
						
							|  |  |  | 				originChunkGroupInfo.chunkGroup, | 
					
						
							|  |  |  | 				chunkGroup | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Remove all unconnected chunk groups | 
					
						
							|  |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							|  |  |  |  * @param {Iterable<ChunkGroup>} allCreatedChunkGroups all chunk groups that where created before | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const cleanupUnconnectedGroups = (compilation, allCreatedChunkGroups) => { | 
					
						
							|  |  |  | 	const { chunkGraph } = compilation; | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (const chunkGroup of allCreatedChunkGroups) { | 
					
						
							|  |  |  | 		if (chunkGroup.getNumberOfParents() === 0) { | 
					
						
							|  |  |  | 			for (const chunk of chunkGroup.chunks) { | 
					
						
							|  |  |  | 				compilation.chunks.delete(chunk); | 
					
						
							|  |  |  | 				chunkGraph.disconnectChunk(chunk); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			chunkGraph.disconnectChunkGroup(chunkGroup); | 
					
						
							|  |  |  | 			chunkGroup.remove(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * This method creates the Chunk graph from the Module graph | 
					
						
							|  |  |  |  * @param {Compilation} compilation the compilation | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  |  * @param {Map<Entrypoint, Module[]>} inputEntrypointsAndModules chunk groups which are processed with the modules | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  |  * @returns {void} | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | const buildChunkGraph = (compilation, inputEntrypointsAndModules) => { | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	const logger = compilation.getLogger("webpack.buildChunkGraph"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	// SHARED STATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 	/** @type {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} */ | 
					
						
							|  |  |  | 	const blockConnections = new Map(); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/** @type {Set<ChunkGroup>} */ | 
					
						
							|  |  |  | 	const allCreatedChunkGroups = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** @type {Map<ChunkGroup, ChunkGroupInfo>} */ | 
					
						
							|  |  |  | 	const chunkGroupInfoMap = new Map(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** @type {Set<DependenciesBlock>} */ | 
					
						
							|  |  |  | 	const blocksWithNestedBlocks = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// PART ONE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 00:10:53 +08:00
										 |  |  | 	logger.time("visitModules"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	visitModules( | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 		logger, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		compilation, | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 		inputEntrypointsAndModules, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		chunkGroupInfoMap, | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 		blockConnections, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		blocksWithNestedBlocks, | 
					
						
							|  |  |  | 		allCreatedChunkGroups | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2020-02-01 00:10:53 +08:00
										 |  |  | 	logger.timeEnd("visitModules"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// PART TWO
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.time("connectChunkGroups"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	connectChunkGroups( | 
					
						
							|  |  |  | 		compilation, | 
					
						
							|  |  |  | 		blocksWithNestedBlocks, | 
					
						
							| 
									
										
										
										
											2020-09-17 15:55:42 +08:00
										 |  |  | 		blockConnections, | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 		chunkGroupInfoMap | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.timeEnd("connectChunkGroups"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 17:43:48 +08:00
										 |  |  | 	for (const [chunkGroup, chunkGroupInfo] of chunkGroupInfoMap) { | 
					
						
							|  |  |  | 		for (const chunk of chunkGroup.chunks) | 
					
						
							|  |  |  | 			chunk.runtime = mergeRuntime(chunk.runtime, chunkGroupInfo.runtime); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-13 00:51:26 +08:00
										 |  |  | 	// Cleanup work
 | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.time("cleanup"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | 	cleanupUnconnectedGroups(compilation, allCreatedChunkGroups); | 
					
						
							| 
									
										
										
										
											2019-07-26 15:56:55 +08:00
										 |  |  | 	logger.timeEnd("cleanup"); | 
					
						
							| 
									
										
										
										
											2019-07-25 17:25:29 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 14:07:55 +08:00
										 |  |  | module.exports = buildChunkGraph; |