| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 00:36:14 +08:00
										 |  |  | const mm = require("micromatch"); | 
					
						
							| 
									
										
										
										
											2018-07-31 04:30:27 +08:00
										 |  |  | const { STAGE_DEFAULT } = require("../OptimizationStages"); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency"); | 
					
						
							|  |  |  | const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 22:24:35 +08:00
										 |  |  | /** @typedef {import("../Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  | /** @typedef {import("../Dependency")} Dependency */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} ExportInModule | 
					
						
							|  |  |  |  * @property {Module} module the module | 
					
						
							|  |  |  |  * @property {string} exportName the name of the export | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 19:35:25 +08:00
										 |  |  | class SideEffectsFlagPlugin { | 
					
						
							| 
									
										
										
										
											2018-07-20 22:24:35 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {Compiler} compiler webpack compiler | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		compiler.hooks.normalModuleFactory.tap("SideEffectsFlagPlugin", nmf => { | 
					
						
							| 
									
										
										
										
											2017-12-14 04:35:39 +08:00
										 |  |  | 			nmf.hooks.module.tap("SideEffectsFlagPlugin", (module, data) => { | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 				const resolveData = data.resourceResolveData; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if ( | 
					
						
							|  |  |  | 					resolveData && | 
					
						
							|  |  |  | 					resolveData.descriptionFileData && | 
					
						
							|  |  |  | 					resolveData.relativePath | 
					
						
							|  |  |  | 				) { | 
					
						
							| 
									
										
										
										
											2017-10-12 23:32:41 +08:00
										 |  |  | 					const sideEffects = resolveData.descriptionFileData.sideEffects; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects( | 
					
						
							|  |  |  | 						resolveData.relativePath, | 
					
						
							|  |  |  | 						sideEffects | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 					if (!hasSideEffects) { | 
					
						
							| 
									
										
										
										
											2017-12-06 19:09:17 +08:00
										 |  |  | 						module.factoryMeta.sideEffectFree = true; | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return module; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-12-06 19:09:34 +08:00
										 |  |  | 			nmf.hooks.module.tap("SideEffectsFlagPlugin", (module, data) => { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 				if (data.settings.sideEffects === false) { | 
					
						
							| 
									
										
										
										
											2017-12-06 19:09:34 +08:00
										 |  |  | 					module.factoryMeta.sideEffectFree = true; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 				} else if (data.settings.sideEffects === true) { | 
					
						
							| 
									
										
										
										
											2017-12-06 19:09:34 +08:00
										 |  |  | 					module.factoryMeta.sideEffectFree = false; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-01-05 02:17:37 +08:00
										 |  |  | 				return module; | 
					
						
							| 
									
										
										
										
											2017-12-06 19:09:34 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 			const moduleGraph = compilation.moduleGraph; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			compilation.hooks.optimizeDependencies.tap( | 
					
						
							| 
									
										
										
										
											2018-07-31 04:30:27 +08:00
										 |  |  | 				/** @type {TODO} */ ({ | 
					
						
							|  |  |  | 					name: "SideEffectsFlagPlugin", | 
					
						
							|  |  |  | 					stage: STAGE_DEFAULT | 
					
						
							|  |  |  | 				}), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				modules => { | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  | 					/** @type {Map<Module, Map<string, ExportInModule>>} */ | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					const reexportMaps = new Map(); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Capture reexports of sideEffectFree modules
 | 
					
						
							|  |  |  | 					for (const module of modules) { | 
					
						
							|  |  |  | 						for (const dep of module.dependencies) { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:11 +08:00
										 |  |  | 							if (dep instanceof HarmonyExportImportedSpecifierDependency) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								if (module.factoryMeta.sideEffectFree) { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 									const mode = dep.getMode(moduleGraph, true); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									if (mode.type === "safe-reexport") { | 
					
						
							|  |  |  | 										let map = reexportMaps.get(module); | 
					
						
							|  |  |  | 										if (!map) { | 
					
						
							|  |  |  | 											reexportMaps.set(module, (map = new Map())); | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										for (const pair of mode.map) { | 
					
						
							|  |  |  | 											map.set(pair[0], { | 
					
						
							| 
									
										
										
										
											2018-07-17 20:04:26 +08:00
										 |  |  | 												module: mode.getModule(), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 												exportName: pair[1] | 
					
						
							|  |  |  | 											}); | 
					
						
							|  |  |  | 										} | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Flatten reexports
 | 
					
						
							|  |  |  | 					for (const map of reexportMaps.values()) { | 
					
						
							|  |  |  | 						for (const pair of map) { | 
					
						
							|  |  |  | 							let mapping = pair[1]; | 
					
						
							|  |  |  | 							while (mapping) { | 
					
						
							|  |  |  | 								const innerMap = reexportMaps.get(mapping.module); | 
					
						
							|  |  |  | 								if (!innerMap) break; | 
					
						
							|  |  |  | 								const newMapping = innerMap.get(mapping.exportName); | 
					
						
							|  |  |  | 								if (newMapping) { | 
					
						
							|  |  |  | 									map.set(pair[0], newMapping); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								mapping = newMapping; | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Update imports along the reexports from sideEffectFree modules
 | 
					
						
							|  |  |  | 					for (const pair of reexportMaps) { | 
					
						
							|  |  |  | 						const module = pair[0]; | 
					
						
							|  |  |  | 						const map = pair[1]; | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 						for (const connection of moduleGraph.getIncomingConnections( | 
					
						
							|  |  |  | 							module | 
					
						
							|  |  |  | 						)) { | 
					
						
							|  |  |  | 							const dep = connection.dependency; | 
					
						
							| 
									
										
										
										
											2018-05-28 03:47:58 +08:00
										 |  |  | 							if ( | 
					
						
							|  |  |  | 								dep instanceof HarmonyImportSpecifierDependency && | 
					
						
							|  |  |  | 								!dep.namespaceObjectAsContext | 
					
						
							|  |  |  | 							) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								const mapping = map.get(dep.id); | 
					
						
							|  |  |  | 								if (mapping) { | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 									moduleGraph.updateModule(dep, mapping.module); | 
					
						
							|  |  |  | 									moduleGraph.addExplanation( | 
					
						
							| 
									
										
										
										
											2018-05-29 19:45:32 +08:00
										 |  |  | 										dep, | 
					
						
							| 
									
										
										
										
											2018-07-24 21:30:37 +08:00
										 |  |  | 										"(skipped side-effect-free modules)" | 
					
						
							| 
									
										
										
										
											2018-05-29 19:45:32 +08:00
										 |  |  | 									); | 
					
						
							| 
									
										
										
										
											2018-08-16 20:07:34 +08:00
										 |  |  | 									dep.setId(moduleGraph, mapping.exportName); | 
					
						
							| 
									
										
										
										
											2018-05-30 00:14:16 +08:00
										 |  |  | 									continue; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	static moduleHasSideEffects(moduleName, flagValue) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		switch (typeof flagValue) { | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 			case "undefined": | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 			case "boolean": | 
					
						
							|  |  |  | 				return flagValue; | 
					
						
							|  |  |  | 			case "string": | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (process.platform === "win32") { | 
					
						
							| 
									
										
										
										
											2018-02-21 00:36:14 +08:00
										 |  |  | 					flagValue = flagValue.replace(/\\/g, "/"); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return mm.isMatch(moduleName, flagValue, { | 
					
						
							|  |  |  | 					matchBase: true | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 			case "object": | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				return flagValue.some(glob => | 
					
						
							|  |  |  | 					SideEffectsFlagPlugin.moduleHasSideEffects(moduleName, glob) | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-14 19:35:25 +08:00
										 |  |  | module.exports = SideEffectsFlagPlugin; |