| 
									
										
										
										
											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"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | const glob2regexp = require("glob-to-regexp"); | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | const { | 
					
						
							|  |  |  | 	JAVASCRIPT_MODULE_TYPE_AUTO, | 
					
						
							|  |  |  | 	JAVASCRIPT_MODULE_TYPE_ESM, | 
					
						
							|  |  |  | 	JAVASCRIPT_MODULE_TYPE_DYNAMIC | 
					
						
							|  |  |  | } = require("../ModuleTypeConstants"); | 
					
						
							| 
									
										
										
										
											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"); | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | const formatLocation = require("../formatLocation"); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 01:52:25 +08:00
										 |  |  | /** @typedef {import("estree").ModuleDeclaration} ModuleDeclaration */ | 
					
						
							|  |  |  | /** @typedef {import("estree").Statement} Statement */ | 
					
						
							| 
									
										
										
										
											2018-07-20 22:24:35 +08:00
										 |  |  | /** @typedef {import("../Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  | /** @typedef {import("../Dependency")} Dependency */ | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** @typedef {import("../Module").BuildMeta} BuildMeta */ | 
					
						
							| 
									
										
										
										
											2024-08-09 23:42:37 +08:00
										 |  |  | /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */ | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */ | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** @typedef {import("../javascript/JavascriptParser").Range} Range */ | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2024-06-11 21:09:50 +08:00
										 |  |  |  * @typedef {object} ExportInModule | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  |  * @property {Module} module the module | 
					
						
							|  |  |  |  * @property {string} exportName the name of the export | 
					
						
							| 
									
										
										
										
											2020-05-19 06:25:41 +08:00
										 |  |  |  * @property {boolean} checked if the export is conditional | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2024-06-11 21:09:50 +08:00
										 |  |  |  * @typedef {object} ReexportInfo | 
					
						
							| 
									
										
										
										
											2020-05-19 06:25:41 +08:00
										 |  |  |  * @property {Map<string, ExportInModule[]>} static | 
					
						
							|  |  |  |  * @property {Map<Module, Set<string>>} dynamic | 
					
						
							| 
									
										
										
										
											2018-05-27 05:07:02 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | /** @typedef {Map<string, RegExp>} CacheItem */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @type {WeakMap<any, CacheItem>} */ | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | const globToRegexpCache = new WeakMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {string} glob the pattern | 
					
						
							|  |  |  |  * @param {Map<string, RegExp>} cache the glob to RegExp cache | 
					
						
							|  |  |  |  * @returns {RegExp} a regular expression | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const globToRegexp = (glob, cache) => { | 
					
						
							|  |  |  | 	const cacheEntry = cache.get(glob); | 
					
						
							|  |  |  | 	if (cacheEntry !== undefined) return cacheEntry; | 
					
						
							|  |  |  | 	if (!glob.includes("/")) { | 
					
						
							|  |  |  | 		glob = `**/${glob}`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	const baseRegexp = glob2regexp(glob, { globstar: true, extended: true }); | 
					
						
							|  |  |  | 	const regexpSource = baseRegexp.source; | 
					
						
							| 
									
										
										
										
											2024-07-31 10:39:30 +08:00
										 |  |  | 	const regexp = new RegExp(`^(\\./)?${regexpSource.slice(1)}`); | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | 	cache.set(glob, regexp); | 
					
						
							|  |  |  | 	return regexp; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | const PLUGIN_NAME = "SideEffectsFlagPlugin"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 19:35:25 +08:00
										 |  |  | class SideEffectsFlagPlugin { | 
					
						
							| 
									
										
										
										
											2020-10-26 22:32:34 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {boolean} analyseSource analyse source code for side effects | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	constructor(analyseSource = true) { | 
					
						
							|  |  |  | 		this._analyseSource = analyseSource; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-31 12:23:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 22:24:35 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-04-23 16:48:36 +08:00
										 |  |  | 	 * Apply the plugin | 
					
						
							|  |  |  | 	 * @param {Compiler} compiler the compiler instance | 
					
						
							| 
									
										
										
										
											2018-07-20 22:24:35 +08:00
										 |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | 		let cache = globToRegexpCache.get(compiler.root); | 
					
						
							|  |  |  | 		if (cache === undefined) { | 
					
						
							|  |  |  | 			cache = new Map(); | 
					
						
							|  |  |  | 			globToRegexpCache.set(compiler.root, cache); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 		compiler.hooks.compilation.tap( | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 			PLUGIN_NAME, | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 			(compilation, { normalModuleFactory }) => { | 
					
						
							|  |  |  | 				const moduleGraph = compilation.moduleGraph; | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 				normalModuleFactory.hooks.module.tap(PLUGIN_NAME, (module, data) => { | 
					
						
							|  |  |  | 					const resolveData = data.resourceResolveData; | 
					
						
							|  |  |  | 					if ( | 
					
						
							|  |  |  | 						resolveData && | 
					
						
							|  |  |  | 						resolveData.descriptionFileData && | 
					
						
							|  |  |  | 						resolveData.relativePath | 
					
						
							|  |  |  | 					) { | 
					
						
							|  |  |  | 						const sideEffects = resolveData.descriptionFileData.sideEffects; | 
					
						
							|  |  |  | 						if (sideEffects !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							if (module.factoryMeta === undefined) { | 
					
						
							|  |  |  | 								module.factoryMeta = {}; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 							const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects( | 
					
						
							|  |  |  | 								resolveData.relativePath, | 
					
						
							|  |  |  | 								sideEffects, | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 								/** @type {CacheItem} */ (cache) | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 							); | 
					
						
							|  |  |  | 							module.factoryMeta.sideEffectFree = !hasSideEffects; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return module; | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.module.tap(PLUGIN_NAME, (module, data) => { | 
					
						
							|  |  |  | 					if (typeof data.settings.sideEffects === "boolean") { | 
					
						
							|  |  |  | 						if (module.factoryMeta === undefined) { | 
					
						
							|  |  |  | 							module.factoryMeta = {}; | 
					
						
							| 
									
										
										
										
											2020-10-05 22:57:31 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 						module.factoryMeta.sideEffectFree = !data.settings.sideEffects; | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 					return module; | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 				if (this._analyseSource) { | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * @param {JavascriptParser} parser the parser | 
					
						
							|  |  |  | 					 * @returns {void} | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					const parserHandler = parser => { | 
					
						
							| 
									
										
										
										
											2023-06-04 01:52:25 +08:00
										 |  |  | 						/** @type {undefined | Statement | ModuleDeclaration} */ | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 						let sideEffectsStatement; | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 						parser.hooks.program.tap(PLUGIN_NAME, () => { | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							sideEffectsStatement = undefined; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						parser.hooks.statement.tap( | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 							{ name: PLUGIN_NAME, stage: -100 }, | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							statement => { | 
					
						
							|  |  |  | 								if (sideEffectsStatement) return; | 
					
						
							|  |  |  | 								if (parser.scope.topLevelScope !== true) return; | 
					
						
							|  |  |  | 								switch (statement.type) { | 
					
						
							|  |  |  | 									case "ExpressionStatement": | 
					
						
							|  |  |  | 										if ( | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.expression, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 										) { | 
					
						
							|  |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "IfStatement": | 
					
						
							|  |  |  | 									case "WhileStatement": | 
					
						
							|  |  |  | 									case "DoWhileStatement": | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 										if ( | 
					
						
							|  |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.test, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) | 
					
						
							|  |  |  | 										) { | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										// statement hook will be called for child statements too
 | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "ForStatement": | 
					
						
							|  |  |  | 										if ( | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.init, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) || | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.test, | 
					
						
							|  |  |  | 												statement.init | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 													? /** @type {Range} */ (statement.init.range)[1] | 
					
						
							|  |  |  | 													: /** @type {Range} */ (statement.range)[0] | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											) || | 
					
						
							|  |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.update, | 
					
						
							|  |  |  | 												statement.test | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 													? /** @type {Range} */ (statement.test.range)[1] | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 													: statement.init | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 														? /** @type {Range} */ (statement.init.range)[1] | 
					
						
							|  |  |  | 														: /** @type {Range} */ (statement.range)[0] | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											) | 
					
						
							|  |  |  | 										) { | 
					
						
							|  |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										// statement hook will be called for child statements too
 | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "SwitchStatement": | 
					
						
							|  |  |  | 										if ( | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.discriminant, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 										) { | 
					
						
							|  |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										// statement hook will be called for child statements too
 | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "VariableDeclaration": | 
					
						
							|  |  |  | 									case "ClassDeclaration": | 
					
						
							|  |  |  | 									case "FunctionDeclaration": | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 										if ( | 
					
						
							|  |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) | 
					
						
							|  |  |  | 										) { | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "ExportNamedDeclaration": | 
					
						
							|  |  |  | 									case "ExportDefaultDeclaration": | 
					
						
							|  |  |  | 										if ( | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 											!parser.isPure( | 
					
						
							|  |  |  | 												statement.declaration, | 
					
						
							|  |  |  | 												/** @type {Range} */ (statement.range)[0] | 
					
						
							|  |  |  | 											) | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 										) { | 
					
						
							|  |  |  | 											sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "LabeledStatement": | 
					
						
							|  |  |  | 									case "BlockStatement": | 
					
						
							|  |  |  | 										// statement hook will be called for child statements too
 | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "EmptyStatement": | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									case "ExportAllDeclaration": | 
					
						
							|  |  |  | 									case "ImportDeclaration": | 
					
						
							|  |  |  | 										// imports will be handled by the dependencies
 | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 									default: | 
					
						
							|  |  |  | 										sideEffectsStatement = statement; | 
					
						
							|  |  |  | 										break; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 						parser.hooks.finish.tap(PLUGIN_NAME, () => { | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							if (sideEffectsStatement === undefined) { | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 								/** @type {BuildMeta} */ | 
					
						
							|  |  |  | 								(parser.state.module.buildMeta).sideEffectFree = true; | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							} else { | 
					
						
							|  |  |  | 								const { loc, type } = sideEffectsStatement; | 
					
						
							|  |  |  | 								moduleGraph | 
					
						
							|  |  |  | 									.getOptimizationBailout(parser.state.module) | 
					
						
							|  |  |  | 									.push( | 
					
						
							|  |  |  | 										() => | 
					
						
							|  |  |  | 											`Statement (${type}) with side effects in source code at ${formatLocation( | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 												/** @type {DependencyLocation} */ (loc) | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											)}`
 | 
					
						
							|  |  |  | 									); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 					for (const key of [ | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 						JAVASCRIPT_MODULE_TYPE_AUTO, | 
					
						
							|  |  |  | 						JAVASCRIPT_MODULE_TYPE_ESM, | 
					
						
							|  |  |  | 						JAVASCRIPT_MODULE_TYPE_DYNAMIC | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 					]) { | 
					
						
							|  |  |  | 						normalModuleFactory.hooks.parser | 
					
						
							|  |  |  | 							.for(key) | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 							.tap(PLUGIN_NAME, parserHandler); | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-10-26 22:32:34 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 				compilation.hooks.optimizeDependencies.tap( | 
					
						
							|  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2023-04-01 01:56:32 +08:00
										 |  |  | 						name: PLUGIN_NAME, | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 						stage: STAGE_DEFAULT | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					modules => { | 
					
						
							|  |  |  | 						const logger = compilation.getLogger( | 
					
						
							|  |  |  | 							"webpack.SideEffectsFlagPlugin" | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2020-01-30 18:34:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 						logger.time("update dependencies"); | 
					
						
							| 
									
										
										
										
											2023-08-13 17:13:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						const optimizedModules = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 22:20:17 +08:00
										 |  |  | 						/** | 
					
						
							|  |  |  | 						 * @param {Module} module module | 
					
						
							|  |  |  | 						 */ | 
					
						
							| 
									
										
										
										
											2023-08-13 17:13:14 +08:00
										 |  |  | 						const optimizeIncomingConnections = module => { | 
					
						
							| 
									
										
										
										
											2023-08-13 18:03:11 +08:00
										 |  |  | 							if (optimizedModules.has(module)) return; | 
					
						
							| 
									
										
										
										
											2023-08-13 17:13:14 +08:00
										 |  |  | 							optimizedModules.add(module); | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 							if (module.getSideEffectsConnectionState(moduleGraph) === false) { | 
					
						
							|  |  |  | 								const exportsInfo = moduleGraph.getExportsInfo(module); | 
					
						
							|  |  |  | 								for (const connection of moduleGraph.getIncomingConnections( | 
					
						
							|  |  |  | 									module | 
					
						
							|  |  |  | 								)) { | 
					
						
							|  |  |  | 									const dep = connection.dependency; | 
					
						
							|  |  |  | 									let isReexport; | 
					
						
							|  |  |  | 									if ( | 
					
						
							|  |  |  | 										(isReexport = | 
					
						
							|  |  |  | 											dep instanceof | 
					
						
							|  |  |  | 											HarmonyExportImportedSpecifierDependency) || | 
					
						
							|  |  |  | 										(dep instanceof HarmonyImportSpecifierDependency && | 
					
						
							|  |  |  | 											!dep.namespaceObjectAsContext) | 
					
						
							|  |  |  | 									) { | 
					
						
							| 
									
										
										
										
											2023-08-17 11:58:19 +08:00
										 |  |  | 										if (connection.originModule !== null) { | 
					
						
							|  |  |  | 											optimizeIncomingConnections(connection.originModule); | 
					
						
							|  |  |  | 										} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 										// TODO improve for export *
 | 
					
						
							|  |  |  | 										if (isReexport && dep.name) { | 
					
						
							|  |  |  | 											const exportInfo = moduleGraph.getExportInfo( | 
					
						
							| 
									
										
										
										
											2023-06-04 01:52:25 +08:00
										 |  |  | 												/** @type {Module} */ (connection.originModule), | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 												dep.name | 
					
						
							|  |  |  | 											); | 
					
						
							|  |  |  | 											exportInfo.moveTarget( | 
					
						
							|  |  |  | 												moduleGraph, | 
					
						
							|  |  |  | 												({ module }) => | 
					
						
							|  |  |  | 													module.getSideEffectsConnectionState(moduleGraph) === | 
					
						
							| 
									
										
										
										
											2021-02-06 05:02:24 +08:00
										 |  |  | 													false, | 
					
						
							|  |  |  | 												({ module: newModule, export: exportName }) => { | 
					
						
							|  |  |  | 													moduleGraph.updateModule(dep, newModule); | 
					
						
							|  |  |  | 													moduleGraph.addExplanation( | 
					
						
							|  |  |  | 														dep, | 
					
						
							|  |  |  | 														"(skipped side-effect-free modules)" | 
					
						
							|  |  |  | 													); | 
					
						
							|  |  |  | 													const ids = dep.getIds(moduleGraph); | 
					
						
							|  |  |  | 													dep.setIds( | 
					
						
							|  |  |  | 														moduleGraph, | 
					
						
							|  |  |  | 														exportName | 
					
						
							|  |  |  | 															? [...exportName, ...ids.slice(1)] | 
					
						
							|  |  |  | 															: ids.slice(1) | 
					
						
							|  |  |  | 													); | 
					
						
							| 
									
										
										
										
											2024-08-09 23:42:37 +08:00
										 |  |  | 													return /** @type {ModuleGraphConnection} */ ( | 
					
						
							|  |  |  | 														moduleGraph.getConnection(dep) | 
					
						
							|  |  |  | 													); | 
					
						
							| 
									
										
										
										
											2021-02-06 05:02:24 +08:00
										 |  |  | 												} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											); | 
					
						
							| 
									
										
										
										
											2021-02-06 05:02:24 +08:00
										 |  |  | 											continue; | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 										} | 
					
						
							|  |  |  | 										// TODO improve for nested imports
 | 
					
						
							|  |  |  | 										const ids = dep.getIds(moduleGraph); | 
					
						
							|  |  |  | 										if (ids.length > 0) { | 
					
						
							|  |  |  | 											const exportInfo = exportsInfo.getExportInfo(ids[0]); | 
					
						
							| 
									
										
										
										
											2020-11-30 17:18:38 +08:00
										 |  |  | 											const target = exportInfo.getTarget( | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 												moduleGraph, | 
					
						
							|  |  |  | 												({ module }) => | 
					
						
							|  |  |  | 													module.getSideEffectsConnectionState(moduleGraph) === | 
					
						
							|  |  |  | 													false | 
					
						
							|  |  |  | 											); | 
					
						
							|  |  |  | 											if (!target) continue; | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 											moduleGraph.updateModule(dep, target.module); | 
					
						
							|  |  |  | 											moduleGraph.addExplanation( | 
					
						
							|  |  |  | 												dep, | 
					
						
							|  |  |  | 												"(skipped side-effect-free modules)" | 
					
						
							|  |  |  | 											); | 
					
						
							|  |  |  | 											dep.setIds( | 
					
						
							|  |  |  | 												moduleGraph, | 
					
						
							|  |  |  | 												target.export | 
					
						
							|  |  |  | 													? [...target.export, ...ids.slice(1)] | 
					
						
							|  |  |  | 													: ids.slice(1) | 
					
						
							|  |  |  | 											); | 
					
						
							|  |  |  | 										} | 
					
						
							| 
									
										
										
										
											2019-03-14 19:06:59 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2023-08-13 17:13:14 +08:00
										 |  |  | 						}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						for (const module of modules) { | 
					
						
							|  |  |  | 							optimizeIncomingConnections(module); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 						logger.timeEnd("update dependencies"); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-11-29 00:30:32 +08:00
										 |  |  | 				); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2017-08-08 15:40:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 01:52:25 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {string} moduleName the module name | 
					
						
							|  |  |  | 	 * @param {undefined | boolean | string | string[]} flagValue the flag value | 
					
						
							|  |  |  | 	 * @param {Map<string, RegExp>} cache cache for glob to regexp | 
					
						
							|  |  |  | 	 * @returns {boolean | undefined} true, when the module has side effects, undefined or false when not | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | 	static moduleHasSideEffects(moduleName, flagValue, cache) { | 
					
						
							| 
									
										
										
										
											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": | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | 				return globToRegexp(flagValue, cache).test(moduleName); | 
					
						
							| 
									
										
										
										
											2018-01-19 00:14:19 +08:00
										 |  |  | 			case "object": | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				return flagValue.some(glob => | 
					
						
							| 
									
										
										
										
											2019-05-17 03:12:59 +08:00
										 |  |  | 					SideEffectsFlagPlugin.moduleHasSideEffects(moduleName, glob, cache) | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				); | 
					
						
							| 
									
										
										
										
											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; |