| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  |  Author Tobias Koppers @sokra | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 19:05:58 +08:00
										 |  |  | const { Tapable, HookMap, SyncHook, SyncWaterfallHook } = require("tapable"); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | const Factory = require("enhanced-resolve").ResolverFactory; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:08:51 +08:00
										 |  |  | const { cachedCleverMerge } = require("./util/cleverMerge"); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 19:42:28 +08:00
										 |  |  | /** @typedef {import("enhanced-resolve").Resolver} Resolver */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 21:38:07 +08:00
										 |  |  | const EMTPY_RESOLVE_OPTIONS = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | module.exports = class ResolverFactory extends Tapable { | 
					
						
							|  |  |  | 	constructor() { | 
					
						
							|  |  |  | 		super(); | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 		this.hooks = { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			resolveOptions: new HookMap( | 
					
						
							|  |  |  | 				() => new SyncWaterfallHook(["resolveOptions"]) | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"])) | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 		this._pluginCompat.tap("ResolverFactory", options => { | 
					
						
							|  |  |  | 			let match; | 
					
						
							|  |  |  | 			match = /^resolve-options (.+)$/.exec(options.name); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (match) { | 
					
						
							| 
									
										
										
										
											2019-07-23 15:35:25 +08:00
										 |  |  | 				this.hooks.resolveOptions | 
					
						
							|  |  |  | 					.for(match[1]) | 
					
						
							|  |  |  | 					.tap(options.fn.name || "unnamed compat plugin", options.fn); | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			match = /^resolver (.+)$/.exec(options.name); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (match) { | 
					
						
							| 
									
										
										
										
											2019-07-23 15:35:25 +08:00
										 |  |  | 				this.hooks.resolver | 
					
						
							|  |  |  | 					.for(match[1]) | 
					
						
							|  |  |  | 					.tap(options.fn.name || "unnamed compat plugin", options.fn); | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 				return true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		this.cache2 = new Map(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get(type, resolveOptions) { | 
					
						
							| 
									
										
										
										
											2019-07-17 21:38:07 +08:00
										 |  |  | 		resolveOptions = resolveOptions || EMTPY_RESOLVE_OPTIONS; | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		const ident = `${type}|${JSON.stringify(resolveOptions)}`; | 
					
						
							|  |  |  | 		const resolver = this.cache2.get(ident); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (resolver) return resolver; | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		const newResolver = this._create(type, resolveOptions); | 
					
						
							|  |  |  | 		this.cache2.set(ident, newResolver); | 
					
						
							|  |  |  | 		return newResolver; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_create(type, resolveOptions) { | 
					
						
							| 
									
										
										
										
											2018-12-03 19:42:28 +08:00
										 |  |  | 		const originalResolveOptions = Object.assign({}, resolveOptions); | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 		resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		const resolver = Factory.createResolver(resolveOptions); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (!resolver) { | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 			throw new Error("No resolver created"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-12-03 19:42:28 +08:00
										 |  |  | 		/** @type {Map<Object, Resolver>} */ | 
					
						
							|  |  |  | 		const childCache = new Map(); | 
					
						
							|  |  |  | 		resolver.withOptions = options => { | 
					
						
							|  |  |  | 			const cacheEntry = childCache.get(options); | 
					
						
							|  |  |  | 			if (cacheEntry !== undefined) return cacheEntry; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:08:51 +08:00
										 |  |  | 			const mergedOptions = cachedCleverMerge(originalResolveOptions, options); | 
					
						
							| 
									
										
										
										
											2018-12-03 19:42:28 +08:00
										 |  |  | 			const resolver = this.get(type, mergedOptions); | 
					
						
							|  |  |  | 			childCache.set(options, resolver); | 
					
						
							|  |  |  | 			return resolver; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2017-11-28 23:45:27 +08:00
										 |  |  | 		this.hooks.resolver.for(type).call(resolver, resolveOptions); | 
					
						
							| 
									
										
										
										
											2017-11-17 21:26:23 +08:00
										 |  |  | 		return resolver; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; |