| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 23:33:06 +08:00
										 |  |  | const util = require("util"); | 
					
						
							| 
									
										
										
										
											2019-12-16 18:40:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | /** @typedef {import("../../declarations/WebpackOptions").Falsy} Falsy */ | 
					
						
							| 
									
										
										
										
											2024-08-06 11:08:48 +08:00
										 |  |  | /** @typedef {import("../../declarations/WebpackOptions").RuleSetLoader} RuleSetLoader */ | 
					
						
							|  |  |  | /** @typedef {import("../../declarations/WebpackOptions").RuleSetLoaderOptions} RuleSetLoaderOptions */ | 
					
						
							|  |  |  | /** @typedef {import("../../declarations/WebpackOptions").RuleSetRule} RuleSetRule */ | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | /** @typedef {import("../../declarations/WebpackOptions").RuleSetUse} RuleSetUse */ | 
					
						
							|  |  |  | /** @typedef {import("../../declarations/WebpackOptions").RuleSetUseItem} RuleSetUseItem */ | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | /** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ | 
					
						
							|  |  |  | /** @typedef {import("./RuleSetCompiler").Effect} Effect */ | 
					
						
							| 
									
										
										
										
											2025-05-01 22:36:51 +08:00
										 |  |  | /** @typedef {import("./RuleSetCompiler").EffectData} EffectData */ | 
					
						
							| 
									
										
										
										
											2025-07-10 21:30:16 +08:00
										 |  |  | /** @typedef {import("./RuleSetCompiler").EffectUseType} EffectUseType */ | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-04 02:20:37 +08:00
										 |  |  | const PLUGIN_NAME = "UseEffectRulePlugin"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | class UseEffectRulePlugin { | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	apply(ruleSetCompiler) { | 
					
						
							|  |  |  | 		ruleSetCompiler.hooks.rule.tap( | 
					
						
							| 
									
										
										
										
											2025-06-04 02:20:37 +08:00
										 |  |  | 			PLUGIN_NAME, | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 			(path, rule, unhandledProperties, result, references) => { | 
					
						
							| 
									
										
										
										
											2024-08-06 11:08:48 +08:00
										 |  |  | 				/** | 
					
						
							|  |  |  | 				 * @param {keyof RuleSetRule} property property | 
					
						
							|  |  |  | 				 * @param {string} correctProperty correct property | 
					
						
							|  |  |  | 				 */ | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 				const conflictWith = (property, correctProperty) => { | 
					
						
							|  |  |  | 					if (unhandledProperties.has(property)) { | 
					
						
							|  |  |  | 						throw ruleSetCompiler.error( | 
					
						
							|  |  |  | 							`${path}.${property}`, | 
					
						
							|  |  |  | 							rule[property], | 
					
						
							|  |  |  | 							`A Rule must not have a '${property}' property when it has a '${correctProperty}' property` | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (unhandledProperties.has("use")) { | 
					
						
							|  |  |  | 					unhandledProperties.delete("use"); | 
					
						
							|  |  |  | 					unhandledProperties.delete("enforce"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					conflictWith("loader", "use"); | 
					
						
							|  |  |  | 					conflictWith("options", "use"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 					const use = /** @type {RuleSetUse} */ (rule.use); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					const enforce = rule.enforce; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-10 21:30:16 +08:00
										 |  |  | 					const type = | 
					
						
							|  |  |  | 						/** @type {EffectUseType} */ | 
					
						
							|  |  |  | 						(enforce ? `use-${enforce}` : "use"); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					 * @param {string} path options path | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 * @param {string} defaultIdent default ident when none is provided | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 					 * @param {RuleSetUseItem} item user provided use value | 
					
						
							| 
									
										
										
										
											2025-05-01 22:36:51 +08:00
										 |  |  | 					 * @returns {(Effect | ((effectData: EffectData) => Effect[]))} effect | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					const useToEffect = (path, defaultIdent, item) => { | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						if (typeof item === "function") { | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 							return (data) => | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 								useToEffectsWithoutIdent( | 
					
						
							|  |  |  | 									path, | 
					
						
							|  |  |  | 									/** @type {RuleSetUseItem | RuleSetUseItem[]} */ | 
					
						
							|  |  |  | 									(item(data)) | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 						return useToEffectRaw(path, defaultIdent, item); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					 * @param {string} path options path | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 * @param {string} defaultIdent default ident when none is provided | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 					 * @param {Exclude<NonNullable<RuleSetUseItem>, EXPECTED_FUNCTION>} item user provided use value | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 * @returns {Effect} effect | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					const useToEffectRaw = (path, defaultIdent, item) => { | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						if (typeof item === "string") { | 
					
						
							|  |  |  | 							return { | 
					
						
							|  |  |  | 								type, | 
					
						
							|  |  |  | 								value: { | 
					
						
							|  |  |  | 									loader: item, | 
					
						
							|  |  |  | 									options: undefined, | 
					
						
							|  |  |  | 									ident: undefined | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							}; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2025-07-10 21:30:16 +08:00
										 |  |  | 						const loader = /** @type {string} */ (item.loader); | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 						const options = item.options; | 
					
						
							|  |  |  | 						let ident = item.ident; | 
					
						
							|  |  |  | 						if (options && typeof options === "object") { | 
					
						
							|  |  |  | 							if (!ident) ident = defaultIdent; | 
					
						
							|  |  |  | 							references.set(ident, options); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (typeof options === "string") { | 
					
						
							|  |  |  | 							util.deprecate( | 
					
						
							|  |  |  | 								() => {}, | 
					
						
							|  |  |  | 								`Using a string as loader options is deprecated (${path}.options)`, | 
					
						
							|  |  |  | 								"DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING" | 
					
						
							|  |  |  | 							)(); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return { | 
					
						
							|  |  |  | 							type: enforce ? `use-${enforce}` : "use", | 
					
						
							|  |  |  | 							value: { | 
					
						
							|  |  |  | 								loader, | 
					
						
							|  |  |  | 								options, | 
					
						
							|  |  |  | 								ident | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}; | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					 * @param {string} path options path | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 					 * @param {RuleSetUseItem | (Falsy | RuleSetUseItem)[]} items user provided use value | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 * @returns {Effect[]} effects | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					const useToEffectsWithoutIdent = (path, items) => { | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						if (Array.isArray(items)) { | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 							return items.filter(Boolean).map((item, idx) => | 
					
						
							|  |  |  | 								useToEffectRaw( | 
					
						
							|  |  |  | 									`${path}[${idx}]`, | 
					
						
							|  |  |  | 									"[[missing ident]]", | 
					
						
							|  |  |  | 									/** @type {Exclude<RuleSetUseItem, EXPECTED_FUNCTION>} */ | 
					
						
							|  |  |  | 									(item) | 
					
						
							|  |  |  | 								) | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 						return [ | 
					
						
							|  |  |  | 							useToEffectRaw( | 
					
						
							|  |  |  | 								path, | 
					
						
							|  |  |  | 								"[[missing ident]]", | 
					
						
							|  |  |  | 								/** @type {Exclude<RuleSetUseItem, EXPECTED_FUNCTION>} */ | 
					
						
							|  |  |  | 								(items) | 
					
						
							|  |  |  | 							) | 
					
						
							|  |  |  | 						]; | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * @param {string} path current path | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 					 * @param {RuleSetUse} items user provided use value | 
					
						
							| 
									
										
										
										
											2025-05-01 22:36:51 +08:00
										 |  |  | 					 * @returns {(Effect | ((effectData: EffectData) => Effect[]))[]} effects | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 */ | 
					
						
							|  |  |  | 					const useToEffects = (path, items) => { | 
					
						
							|  |  |  | 						if (Array.isArray(items)) { | 
					
						
							| 
									
										
										
										
											2023-06-07 09:07:31 +08:00
										 |  |  | 							return items.filter(Boolean).map((item, idx) => { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 								const subPath = `${path}[${idx}]`; | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 								return useToEffect( | 
					
						
							|  |  |  | 									subPath, | 
					
						
							|  |  |  | 									subPath, | 
					
						
							|  |  |  | 									/** @type {RuleSetUseItem} */ | 
					
						
							|  |  |  | 									(item) | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 							}); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2025-03-27 08:07:25 +08:00
										 |  |  | 						return [ | 
					
						
							|  |  |  | 							useToEffect(path, path, /** @type {RuleSetUseItem} */ (items)) | 
					
						
							|  |  |  | 						]; | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (typeof use === "function") { | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 						result.effects.push((data) => | 
					
						
							| 
									
										
										
										
											2025-05-01 22:36:51 +08:00
										 |  |  | 							useToEffectsWithoutIdent(`${path}.use`, use(data)) | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 						); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					} else { | 
					
						
							|  |  |  | 						for (const effect of useToEffects(`${path}.use`, use)) { | 
					
						
							|  |  |  | 							result.effects.push(effect); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (unhandledProperties.has("loader")) { | 
					
						
							|  |  |  | 					unhandledProperties.delete("loader"); | 
					
						
							|  |  |  | 					unhandledProperties.delete("options"); | 
					
						
							|  |  |  | 					unhandledProperties.delete("enforce"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-06 11:08:48 +08:00
										 |  |  | 					const loader = /** @type {RuleSetLoader} */ (rule.loader); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					const options = rule.options; | 
					
						
							|  |  |  | 					const enforce = rule.enforce; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (loader.includes("!")) { | 
					
						
							|  |  |  | 						throw ruleSetCompiler.error( | 
					
						
							|  |  |  | 							`${path}.loader`, | 
					
						
							|  |  |  | 							loader, | 
					
						
							|  |  |  | 							"Exclamation mark separated loader lists has been removed in favor of the 'use' property with arrays" | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (loader.includes("?")) { | 
					
						
							|  |  |  | 						throw ruleSetCompiler.error( | 
					
						
							|  |  |  | 							`${path}.loader`, | 
					
						
							|  |  |  | 							loader, | 
					
						
							|  |  |  | 							"Query arguments on 'loader' has been removed in favor of the 'options' property" | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 23:33:06 +08:00
										 |  |  | 					if (typeof options === "string") { | 
					
						
							|  |  |  | 						util.deprecate( | 
					
						
							|  |  |  | 							() => {}, | 
					
						
							|  |  |  | 							`Using a string as loader options is deprecated (${path}.options)`, | 
					
						
							|  |  |  | 							"DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING" | 
					
						
							|  |  |  | 						)(); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 16:14:10 +08:00
										 |  |  | 					const ident = | 
					
						
							|  |  |  | 						options && typeof options === "object" ? path : undefined; | 
					
						
							| 
									
										
										
										
											2025-07-10 21:30:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					if (ident) { | 
					
						
							|  |  |  | 						references.set( | 
					
						
							|  |  |  | 							ident, | 
					
						
							|  |  |  | 							/** @type {RuleSetLoaderOptions} */ | 
					
						
							|  |  |  | 							(options) | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					result.effects.push({ | 
					
						
							|  |  |  | 						type: enforce ? `use-${enforce}` : "use", | 
					
						
							|  |  |  | 						value: { | 
					
						
							|  |  |  | 							loader, | 
					
						
							|  |  |  | 							options, | 
					
						
							| 
									
										
										
										
											2020-01-16 16:14:10 +08:00
										 |  |  | 							ident | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = UseEffectRulePlugin; |