| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  |  MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  |  Author Tobias Koppers @sokra | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | const path = require("path"); | 
					
						
							| 
									
										
										
										
											2018-02-11 12:27:09 +08:00
										 |  |  | const asyncLib = require("neo-async"); | 
					
						
							| 
									
										
										
										
											2018-03-22 19:05:58 +08:00
										 |  |  | const { | 
					
						
							|  |  |  | 	Tapable, | 
					
						
							|  |  |  | 	AsyncSeriesWaterfallHook, | 
					
						
							|  |  |  | 	SyncWaterfallHook, | 
					
						
							|  |  |  | 	SyncBailHook, | 
					
						
							|  |  |  | 	SyncHook, | 
					
						
							|  |  |  | 	HookMap | 
					
						
							|  |  |  | } = require("tapable"); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | const NormalModule = require("./NormalModule"); | 
					
						
							|  |  |  | const RawModule = require("./RawModule"); | 
					
						
							|  |  |  | const RuleSet = require("./RuleSet"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:08:51 +08:00
										 |  |  | const { cachedCleverMerge } = require("./util/cleverMerge"); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const EMPTY_RESOLVE_OPTIONS = {}; | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | const loaderToIdent = data => { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 	if (!data.options) { | 
					
						
							|  |  |  | 		return data.loader; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof data.options === "string") { | 
					
						
							|  |  |  | 		return data.loader + "?" + data.options; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (typeof data.options !== "object") { | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 		throw new Error("loader options must be string or object"); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (data.ident) { | 
					
						
							|  |  |  | 		return data.loader + "??" + data.ident; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 	return data.loader + "?" + JSON.stringify(data.options); | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | const identToLoaderRequest = resultString => { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:26:16 +08:00
										 |  |  | 	const idx = resultString.indexOf("?"); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	if (idx >= 0) { | 
					
						
							| 
									
										
										
										
											2018-04-04 19:42:37 +08:00
										 |  |  | 		const loader = resultString.substr(0, idx); | 
					
						
							|  |  |  | 		const options = resultString.substr(idx + 1); | 
					
						
							| 
									
										
										
										
											2016-12-08 23:57:47 +08:00
										 |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2018-04-04 19:42:37 +08:00
										 |  |  | 			loader, | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 			options | 
					
						
							| 
									
										
										
										
											2016-12-08 23:57:47 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2018-04-04 19:41:56 +08:00
										 |  |  | 			loader: resultString, | 
					
						
							| 
									
										
										
										
											2018-04-04 19:42:37 +08:00
										 |  |  | 			options: undefined | 
					
						
							| 
									
										
										
										
											2017-01-11 17:51:58 +08:00
										 |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2016-12-08 23:57:47 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-12-08 23:57:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-19 19:42:18 +08:00
										 |  |  | const dependencyCache = new WeakMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | class NormalModuleFactory extends Tapable { | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 	constructor(context, resolverFactory, options) { | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 		super(); | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 		this.hooks = { | 
					
						
							|  |  |  | 			resolver: new SyncWaterfallHook(["resolver"]), | 
					
						
							|  |  |  | 			factory: new SyncWaterfallHook(["factory"]), | 
					
						
							|  |  |  | 			beforeResolve: new AsyncSeriesWaterfallHook(["data"]), | 
					
						
							|  |  |  | 			afterResolve: new AsyncSeriesWaterfallHook(["data"]), | 
					
						
							|  |  |  | 			createModule: new SyncBailHook(["data"]), | 
					
						
							|  |  |  | 			module: new SyncWaterfallHook(["module", "data"]), | 
					
						
							|  |  |  | 			createParser: new HookMap(() => new SyncBailHook(["parserOptions"])), | 
					
						
							|  |  |  | 			parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			createGenerator: new HookMap( | 
					
						
							|  |  |  | 				() => new SyncBailHook(["generatorOptions"]) | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			generator: new HookMap( | 
					
						
							|  |  |  | 				() => new SyncHook(["generator", "generatorOptions"]) | 
					
						
							|  |  |  | 			) | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 		this._pluginCompat.tap("NormalModuleFactory", options => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			switch (options.name) { | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 				case "before-resolve": | 
					
						
							|  |  |  | 				case "after-resolve": | 
					
						
							|  |  |  | 					options.async = true; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case "parser": | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					this.hooks.parser | 
					
						
							|  |  |  | 						.for("javascript/auto") | 
					
						
							|  |  |  | 						.tap(options.fn.name || "unnamed compat plugin", options.fn); | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 					return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			let match; | 
					
						
							|  |  |  | 			match = /^parser (.+)$/.exec(options.name); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (match) { | 
					
						
							|  |  |  | 				this.hooks.parser | 
					
						
							|  |  |  | 					.for(match[1]) | 
					
						
							|  |  |  | 					.tap( | 
					
						
							|  |  |  | 						options.fn.name || "unnamed compat plugin", | 
					
						
							|  |  |  | 						options.fn.bind(this) | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			match = /^create-parser (.+)$/.exec(options.name); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (match) { | 
					
						
							|  |  |  | 				this.hooks.createParser | 
					
						
							|  |  |  | 					.for(match[1]) | 
					
						
							|  |  |  | 					.tap( | 
					
						
							|  |  |  | 						options.fn.name || "unnamed compat plugin", | 
					
						
							|  |  |  | 						options.fn.bind(this) | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		this.resolverFactory = resolverFactory; | 
					
						
							|  |  |  | 		this.ruleSet = new RuleSet(options.defaultRules.concat(options.rules)); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		this.cachePredicate = | 
					
						
							|  |  |  | 			typeof options.unsafeCache === "function" | 
					
						
							|  |  |  | 				? options.unsafeCache | 
					
						
							|  |  |  | 				: Boolean.bind(null, options.unsafeCache); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 		this.context = context || ""; | 
					
						
							| 
									
										
										
										
											2018-01-22 05:35:30 +08:00
										 |  |  | 		this.parserCache = Object.create(null); | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 		this.generatorCache = Object.create(null); | 
					
						
							| 
									
										
										
										
											2017-12-14 04:35:39 +08:00
										 |  |  | 		this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => { | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 			let resolver = this.hooks.resolver.call(null); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 			// Ignored
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (!resolver) return callback(); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 			resolver(result, (err, data) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (err) return callback(err); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 				// Ignored
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (!data) return callback(); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 				// direct module
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (typeof data.source === "function") return callback(null, data); | 
					
						
							| 
									
										
										
										
											2016-02-10 02:32:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 				this.hooks.afterResolve.callAsync(data, (err, result) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (err) return callback(err); | 
					
						
							| 
									
										
										
										
											2015-05-17 00:27:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 					// Ignored
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (!result) return callback(); | 
					
						
							| 
									
										
										
										
											2015-05-17 00:27:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 					let createdModule = this.hooks.createModule.call(result); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (!createdModule) { | 
					
						
							|  |  |  | 						if (!result.request) { | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 							return callback(new Error("Empty dependency (no request)")); | 
					
						
							| 
									
										
										
										
											2016-11-23 00:58:24 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 						createdModule = new NormalModule(result); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 					createdModule = this.hooks.module.call(createdModule, result); | 
					
						
							| 
									
										
										
										
											2015-05-16 20:59:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 					return callback(null, createdModule); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-12-14 04:35:39 +08:00
										 |  |  | 		this.hooks.resolver.tap("NormalModuleFactory", () => (data, callback) => { | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 			const contextInfo = data.contextInfo; | 
					
						
							|  |  |  | 			const context = data.context; | 
					
						
							|  |  |  | 			const request = data.request; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | 			const loaderResolver = this.getResolver("loader"); | 
					
						
							|  |  |  | 			const normalResolver = this.getResolver("normal", data.resolveOptions); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			let matchResource = undefined; | 
					
						
							|  |  |  | 			let requestWithoutMatchResource = request; | 
					
						
							|  |  |  | 			const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request); | 
					
						
							|  |  |  | 			if (matchResourceMatch) { | 
					
						
							|  |  |  | 				matchResource = matchResourceMatch[1]; | 
					
						
							|  |  |  | 				if (/^\.\.?\//.test(matchResource)) { | 
					
						
							|  |  |  | 					matchResource = path.join(context, matchResource); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				requestWithoutMatchResource = request.substr( | 
					
						
							|  |  |  | 					matchResourceMatch[0].length | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!"); | 
					
						
							|  |  |  | 			const noAutoLoaders = | 
					
						
							|  |  |  | 				noPreAutoLoaders || requestWithoutMatchResource.startsWith("!"); | 
					
						
							|  |  |  | 			const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!"); | 
					
						
							|  |  |  | 			let elements = requestWithoutMatchResource | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				.replace(/^-?!+/, "") | 
					
						
							|  |  |  | 				.replace(/!!+/g, "!") | 
					
						
							|  |  |  | 				.split("!"); | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 			let resource = elements.pop(); | 
					
						
							|  |  |  | 			elements = elements.map(identToLoaderRequest); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			asyncLib.parallel( | 
					
						
							|  |  |  | 				[ | 
					
						
							|  |  |  | 					callback => | 
					
						
							|  |  |  | 						this.resolveRequestArray( | 
					
						
							|  |  |  | 							contextInfo, | 
					
						
							|  |  |  | 							context, | 
					
						
							|  |  |  | 							elements, | 
					
						
							|  |  |  | 							loaderResolver, | 
					
						
							|  |  |  | 							callback | 
					
						
							|  |  |  | 						), | 
					
						
							|  |  |  | 					callback => { | 
					
						
							|  |  |  | 						if (resource === "" || resource[0] === "?") { | 
					
						
							|  |  |  | 							return callback(null, { | 
					
						
							|  |  |  | 								resource | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						normalResolver.resolve( | 
					
						
							|  |  |  | 							contextInfo, | 
					
						
							|  |  |  | 							context, | 
					
						
							|  |  |  | 							resource, | 
					
						
							|  |  |  | 							{}, | 
					
						
							|  |  |  | 							(err, resource, resourceResolveData) => { | 
					
						
							|  |  |  | 								if (err) return callback(err); | 
					
						
							|  |  |  | 								callback(null, { | 
					
						
							|  |  |  | 									resourceResolveData, | 
					
						
							|  |  |  | 									resource | 
					
						
							|  |  |  | 								}); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				], | 
					
						
							|  |  |  | 				(err, results) => { | 
					
						
							|  |  |  | 					if (err) return callback(err); | 
					
						
							|  |  |  | 					let loaders = results[0]; | 
					
						
							|  |  |  | 					const resourceResolveData = results[1].resourceResolveData; | 
					
						
							|  |  |  | 					resource = results[1].resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// translate option idents
 | 
					
						
							|  |  |  | 					try { | 
					
						
							|  |  |  | 						for (const item of loaders) { | 
					
						
							|  |  |  | 							if (typeof item.options === "string" && item.options[0] === "?") { | 
					
						
							|  |  |  | 								const ident = item.options.substr(1); | 
					
						
							|  |  |  | 								item.options = this.ruleSet.findOptionsByIdent(ident); | 
					
						
							|  |  |  | 								item.ident = ident; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} catch (e) { | 
					
						
							|  |  |  | 						return callback(e); | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (resource === false) { | 
					
						
							|  |  |  | 						// ignored
 | 
					
						
							|  |  |  | 						return callback( | 
					
						
							|  |  |  | 							null, | 
					
						
							|  |  |  | 							new RawModule( | 
					
						
							|  |  |  | 								"/* (ignored) */", | 
					
						
							|  |  |  | 								`ignored ${context} ${request}`, | 
					
						
							|  |  |  | 								`${request} (ignored)` | 
					
						
							|  |  |  | 							) | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | 					const userRequest = | 
					
						
							|  |  |  | 						(matchResource !== undefined ? `${matchResource}!=!` : "") + | 
					
						
							|  |  |  | 						loaders | 
					
						
							|  |  |  | 							.map(loaderToIdent) | 
					
						
							|  |  |  | 							.concat([resource]) | 
					
						
							|  |  |  | 							.join("!"); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | 					let resourcePath = | 
					
						
							|  |  |  | 						matchResource !== undefined ? matchResource : resource; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					let resourceQuery = ""; | 
					
						
							|  |  |  | 					const queryIndex = resourcePath.indexOf("?"); | 
					
						
							|  |  |  | 					if (queryIndex >= 0) { | 
					
						
							|  |  |  | 						resourceQuery = resourcePath.substr(queryIndex); | 
					
						
							|  |  |  | 						resourcePath = resourcePath.substr(0, queryIndex); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					const result = this.ruleSet.exec({ | 
					
						
							|  |  |  | 						resource: resourcePath, | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | 						realResource: | 
					
						
							|  |  |  | 							matchResource !== undefined | 
					
						
							|  |  |  | 								? resource.replace(/\?.*/, "") | 
					
						
							|  |  |  | 								: resourcePath, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						resourceQuery, | 
					
						
							|  |  |  | 						issuer: contextInfo.issuer, | 
					
						
							|  |  |  | 						compiler: contextInfo.compiler | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 					const settings = {}; | 
					
						
							|  |  |  | 					const useLoadersPost = []; | 
					
						
							|  |  |  | 					const useLoaders = []; | 
					
						
							|  |  |  | 					const useLoadersPre = []; | 
					
						
							|  |  |  | 					for (const r of result) { | 
					
						
							|  |  |  | 						if (r.type === "use") { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 							if (r.enforce === "post" && !noPrePostAutoLoaders) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								useLoadersPost.push(r.value); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 							} else if ( | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								r.enforce === "pre" && | 
					
						
							|  |  |  | 								!noPreAutoLoaders && | 
					
						
							|  |  |  | 								!noPrePostAutoLoaders | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 							) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								useLoadersPre.push(r.value); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 							} else if ( | 
					
						
							|  |  |  | 								!r.enforce && | 
					
						
							|  |  |  | 								!noAutoLoaders && | 
					
						
							|  |  |  | 								!noPrePostAutoLoaders | 
					
						
							|  |  |  | 							) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								useLoaders.push(r.value); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						} else if ( | 
					
						
							|  |  |  | 							typeof r.value === "object" && | 
					
						
							|  |  |  | 							r.value !== null && | 
					
						
							|  |  |  | 							typeof settings[r.type] === "object" && | 
					
						
							|  |  |  | 							settings[r.type] !== null | 
					
						
							|  |  |  | 						) { | 
					
						
							| 
									
										
										
										
											2019-07-17 19:08:51 +08:00
										 |  |  | 							settings[r.type] = cachedCleverMerge(settings[r.type], r.value); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 							settings[r.type] = r.value; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-07-24 17:54:58 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					asyncLib.parallel( | 
					
						
							|  |  |  | 						[ | 
					
						
							|  |  |  | 							this.resolveRequestArray.bind( | 
					
						
							|  |  |  | 								this, | 
					
						
							|  |  |  | 								contextInfo, | 
					
						
							|  |  |  | 								this.context, | 
					
						
							|  |  |  | 								useLoadersPost, | 
					
						
							|  |  |  | 								loaderResolver | 
					
						
							|  |  |  | 							), | 
					
						
							|  |  |  | 							this.resolveRequestArray.bind( | 
					
						
							|  |  |  | 								this, | 
					
						
							|  |  |  | 								contextInfo, | 
					
						
							|  |  |  | 								this.context, | 
					
						
							|  |  |  | 								useLoaders, | 
					
						
							|  |  |  | 								loaderResolver | 
					
						
							|  |  |  | 							), | 
					
						
							|  |  |  | 							this.resolveRequestArray.bind( | 
					
						
							|  |  |  | 								this, | 
					
						
							|  |  |  | 								contextInfo, | 
					
						
							|  |  |  | 								this.context, | 
					
						
							|  |  |  | 								useLoadersPre, | 
					
						
							|  |  |  | 								loaderResolver | 
					
						
							|  |  |  | 							) | 
					
						
							|  |  |  | 						], | 
					
						
							|  |  |  | 						(err, results) => { | 
					
						
							|  |  |  | 							if (err) return callback(err); | 
					
						
							| 
									
										
										
										
											2019-07-01 15:37:35 +08:00
										 |  |  | 							if (matchResource === undefined) { | 
					
						
							|  |  |  | 								loaders = results[0].concat(loaders, results[1], results[2]); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								loaders = results[0].concat(results[1], loaders, results[2]); | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							process.nextTick(() => { | 
					
						
							|  |  |  | 								const type = settings.type; | 
					
						
							|  |  |  | 								const resolveOptions = settings.resolve; | 
					
						
							|  |  |  | 								callback(null, { | 
					
						
							|  |  |  | 									context: context, | 
					
						
							|  |  |  | 									request: loaders | 
					
						
							|  |  |  | 										.map(loaderToIdent) | 
					
						
							|  |  |  | 										.concat([resource]) | 
					
						
							|  |  |  | 										.join("!"), | 
					
						
							|  |  |  | 									dependencies: data.dependencies, | 
					
						
							|  |  |  | 									userRequest, | 
					
						
							|  |  |  | 									rawRequest: request, | 
					
						
							|  |  |  | 									loaders, | 
					
						
							|  |  |  | 									resource, | 
					
						
							| 
									
										
										
										
											2018-06-01 20:54:54 +08:00
										 |  |  | 									matchResource, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									resourceResolveData, | 
					
						
							|  |  |  | 									settings, | 
					
						
							|  |  |  | 									type, | 
					
						
							|  |  |  | 									parser: this.getParser(type, settings.parser), | 
					
						
							|  |  |  | 									generator: this.getGenerator(type, settings.generator), | 
					
						
							|  |  |  | 									resolveOptions | 
					
						
							|  |  |  | 								}); | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 	create(data, callback) { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:26:16 +08:00
										 |  |  | 		const dependencies = data.dependencies; | 
					
						
							| 
									
										
										
										
											2018-05-19 19:42:18 +08:00
										 |  |  | 		const cacheEntry = dependencyCache.get(dependencies[0]); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (cacheEntry) return callback(null, cacheEntry); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:26:16 +08:00
										 |  |  | 		const context = data.context || this.context; | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:26:16 +08:00
										 |  |  | 		const request = dependencies[0].request; | 
					
						
							|  |  |  | 		const contextInfo = data.contextInfo || {}; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		this.hooks.beforeResolve.callAsync( | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				contextInfo, | 
					
						
							|  |  |  | 				resolveOptions, | 
					
						
							|  |  |  | 				context, | 
					
						
							|  |  |  | 				request, | 
					
						
							|  |  |  | 				dependencies | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			(err, result) => { | 
					
						
							|  |  |  | 				if (err) return callback(err); | 
					
						
							| 
									
										
										
										
											2016-12-05 06:47:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				// Ignored
 | 
					
						
							|  |  |  | 				if (!result) return callback(); | 
					
						
							| 
									
										
										
										
											2016-12-05 06:47:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				const factory = this.hooks.factory.call(null); | 
					
						
							| 
									
										
										
										
											2013-11-06 01:19:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				// Ignored
 | 
					
						
							|  |  |  | 				if (!factory) return callback(); | 
					
						
							| 
									
										
										
										
											2016-12-08 16:39:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				factory(result, (err, module) => { | 
					
						
							|  |  |  | 					if (err) return callback(err); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (module && this.cachePredicate(module)) { | 
					
						
							|  |  |  | 						for (const d of dependencies) { | 
					
						
							| 
									
										
										
										
											2018-05-19 19:42:18 +08:00
										 |  |  | 							dependencyCache.set(d, module); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					callback(null, module); | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	resolveRequestArray(contextInfo, context, array, resolver, callback) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (array.length === 0) return callback(null, []); | 
					
						
							|  |  |  | 		asyncLib.map( | 
					
						
							|  |  |  | 			array, | 
					
						
							|  |  |  | 			(item, callback) => { | 
					
						
							|  |  |  | 				resolver.resolve( | 
					
						
							|  |  |  | 					contextInfo, | 
					
						
							|  |  |  | 					context, | 
					
						
							|  |  |  | 					item.loader, | 
					
						
							|  |  |  | 					{}, | 
					
						
							|  |  |  | 					(err, result) => { | 
					
						
							|  |  |  | 						if ( | 
					
						
							|  |  |  | 							err && | 
					
						
							|  |  |  | 							/^[^/]*$/.test(item.loader) && | 
					
						
							|  |  |  | 							!/-loader$/.test(item.loader) | 
					
						
							|  |  |  | 						) { | 
					
						
							|  |  |  | 							return resolver.resolve( | 
					
						
							|  |  |  | 								contextInfo, | 
					
						
							|  |  |  | 								context, | 
					
						
							|  |  |  | 								item.loader + "-loader", | 
					
						
							|  |  |  | 								{}, | 
					
						
							|  |  |  | 								err2 => { | 
					
						
							|  |  |  | 									if (!err2) { | 
					
						
							|  |  |  | 										err.message = | 
					
						
							|  |  |  | 											err.message + | 
					
						
							|  |  |  | 											"\n" + | 
					
						
							|  |  |  | 											"BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" + | 
					
						
							| 
									
										
										
										
											2019-06-09 17:23:42 +08:00
										 |  |  | 											`                 You need to specify '${item.loader}-loader' instead of '${item.loader}',\n` + | 
					
						
							| 
									
										
										
										
											2018-05-24 22:05:56 +08:00
										 |  |  | 											"                 see https://webpack.js.org/migrate/3/#automatic-loader-module-name-extension-removed"; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									} | 
					
						
							|  |  |  | 									callback(err); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						if (err) return callback(err); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						const optionsOnly = item.options | 
					
						
							|  |  |  | 							? { | 
					
						
							|  |  |  | 									options: item.options | 
					
						
							| 
									
										
										
										
											2018-03-26 22:56:10 +08:00
										 |  |  | 							  } | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							: undefined; | 
					
						
							|  |  |  | 						return callback( | 
					
						
							|  |  |  | 							null, | 
					
						
							|  |  |  | 							Object.assign({}, item, identToLoaderRequest(result), optionsOnly) | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			callback | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | 	getParser(type, parserOptions) { | 
					
						
							|  |  |  | 		let ident = type; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (parserOptions) { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 			if (parserOptions.ident) { | 
					
						
							|  |  |  | 				ident = `${type}|${parserOptions.ident}`; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ident = JSON.stringify([type, parserOptions]); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (ident in this.parserCache) { | 
					
						
							| 
									
										
										
										
											2018-01-22 05:35:30 +08:00
										 |  |  | 			return this.parserCache[ident]; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		return (this.parserCache[ident] = this.createParser(type, parserOptions)); | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 05:35:30 +08:00
										 |  |  | 	createParser(type, parserOptions = {}) { | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 		const parser = this.hooks.createParser.for(type).call(parserOptions); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (!parser) { | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | 			throw new Error(`No parser registered for ${type}`); | 
					
						
							| 
									
										
										
										
											2017-10-30 20:56:57 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-28 16:54:24 +08:00
										 |  |  | 		this.hooks.parser.for(type).call(parser, parserOptions); | 
					
						
							| 
									
										
										
										
											2016-09-14 18:04:42 +08:00
										 |  |  | 		return parser; | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 	getGenerator(type, generatorOptions) { | 
					
						
							|  |  |  | 		let ident = type; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (generatorOptions) { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 			if (generatorOptions.ident) { | 
					
						
							|  |  |  | 				ident = `${type}|${generatorOptions.ident}`; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ident = JSON.stringify([type, generatorOptions]); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (ident in this.generatorCache) { | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 			return this.generatorCache[ident]; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		return (this.generatorCache[ident] = this.createGenerator( | 
					
						
							|  |  |  | 			type, | 
					
						
							|  |  |  | 			generatorOptions | 
					
						
							|  |  |  | 		)); | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	createGenerator(type, generatorOptions = {}) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		const generator = this.hooks.createGenerator | 
					
						
							|  |  |  | 			.for(type) | 
					
						
							|  |  |  | 			.call(generatorOptions); | 
					
						
							|  |  |  | 		if (!generator) { | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | 			throw new Error(`No generator registered for ${type}`); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		this.hooks.generator.for(type).call(generator, generatorOptions); | 
					
						
							|  |  |  | 		return generator; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 	getResolver(type, resolveOptions) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		return this.resolverFactory.get( | 
					
						
							|  |  |  | 			type, | 
					
						
							|  |  |  | 			resolveOptions || EMPTY_RESOLVE_OPTIONS | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 05:28:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = NormalModuleFactory; |