| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | /** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ | 
					
						
							|  |  |  | /** @typedef {import("./RuleSetCompiler").Effect} Effect */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UseEffectRulePlugin { | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	apply(ruleSetCompiler) { | 
					
						
							|  |  |  | 		ruleSetCompiler.hooks.rule.tap( | 
					
						
							|  |  |  | 			"UseEffectRulePlugin", | 
					
						
							|  |  |  | 			(path, rule, unhandledProperties, result, references) => { | 
					
						
							|  |  |  | 				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"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					const use = rule.use; | 
					
						
							|  |  |  | 					const enforce = rule.enforce; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					const type = enforce ? `use-${enforce}` : "use"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 					 * @param {object} item user provided use value | 
					
						
							|  |  |  | 					 * @returns {Effect|function(any): Effect[]} effect | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											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") { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 							return data => useToEffectsWithoutIdent(path, item(data)); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +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 | 
					
						
							|  |  |  | 					 * @param {object} item user provided use value | 
					
						
							|  |  |  | 					 * @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 | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							}; | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							const loader = item.loader; | 
					
						
							|  |  |  | 							const options = item.options; | 
					
						
							|  |  |  | 							let ident = item.ident; | 
					
						
							|  |  |  | 							if (options && typeof options === "object") { | 
					
						
							|  |  |  | 								if (!ident) ident = defaultIdent; | 
					
						
							|  |  |  | 								references.set(ident, options); | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2019-12-16 18:40:04 +08:00
										 |  |  | 							if (typeof options === "string") { | 
					
						
							| 
									
										
										
										
											2019-12-17 23:33:06 +08:00
										 |  |  | 								util.deprecate( | 
					
						
							|  |  |  | 									() => {}, | 
					
						
							|  |  |  | 									`Using a string as loader options is deprecated (${path}.options)`, | 
					
						
							|  |  |  | 									"DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING" | 
					
						
							|  |  |  | 								)(); | 
					
						
							| 
									
										
										
										
											2019-12-16 18:40:04 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 							return { | 
					
						
							|  |  |  | 								type: enforce ? `use-${enforce}` : "use", | 
					
						
							|  |  |  | 								value: { | 
					
						
							|  |  |  | 									loader, | 
					
						
							|  |  |  | 									options, | 
					
						
							|  |  |  | 									ident | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							}; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 					 * @param {string} path options path | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					 * @param {any} items user provided use value | 
					
						
							|  |  |  | 					 * @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)) { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 							return items.map((item, idx) => | 
					
						
							|  |  |  | 								useToEffectRaw(`${path}[${idx}]`, "[[missing ident]]", item) | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 							); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 						return [useToEffectRaw(path, "[[missing ident]]", items)]; | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * @param {string} path current path | 
					
						
							|  |  |  | 					 * @param {any} items user provided use value | 
					
						
							|  |  |  | 					 * @returns {(Effect|function(any): Effect[])[]} effects | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					const useToEffects = (path, items) => { | 
					
						
							|  |  |  | 						if (Array.isArray(items)) { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 							return items.map((item, idx) => { | 
					
						
							|  |  |  | 								const subPath = `${path}[${idx}]`; | 
					
						
							|  |  |  | 								return useToEffect(subPath, subPath, item); | 
					
						
							|  |  |  | 							}); | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 						return [useToEffect(path, path, items)]; | 
					
						
							| 
									
										
										
										
											2019-05-16 17:31:41 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (typeof use === "function") { | 
					
						
							| 
									
										
										
										
											2019-12-18 00:15:49 +08:00
										 |  |  | 						result.effects.push(data => | 
					
						
							|  |  |  | 							useToEffectsWithoutIdent(`${path}.use`, use(data)) | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											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"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					const loader = rule.loader; | 
					
						
							|  |  |  | 					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; | 
					
						
							|  |  |  | 					references.set(ident, 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
										 |  |  | 						} | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	useItemToEffects(path, item) {} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = UseEffectRulePlugin; |