UNPKG

2.35 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4 */
5"use strict";
6
7const { Tapable, HookMap, SyncHook, SyncWaterfallHook } = require("tapable");
8const Factory = require("enhanced-resolve").ResolverFactory;
9const { cachedCleverMerge } = require("./util/cleverMerge");
10
11/** @typedef {import("enhanced-resolve").Resolver} Resolver */
12
13const EMTPY_RESOLVE_OPTIONS = {};
14
15module.exports = class ResolverFactory extends Tapable {
16 constructor() {
17 super();
18 this.hooks = {
19 resolveOptions: new HookMap(
20 () => new SyncWaterfallHook(["resolveOptions"])
21 ),
22 resolver: new HookMap(() => new SyncHook(["resolver", "resolveOptions"]))
23 };
24 this._pluginCompat.tap("ResolverFactory", options => {
25 let match;
26 match = /^resolve-options (.+)$/.exec(options.name);
27 if (match) {
28 this.hooks.resolveOptions
29 .for(match[1])
30 .tap(options.fn.name || "unnamed compat plugin", options.fn);
31 return true;
32 }
33 match = /^resolver (.+)$/.exec(options.name);
34 if (match) {
35 this.hooks.resolver
36 .for(match[1])
37 .tap(options.fn.name || "unnamed compat plugin", options.fn);
38 return true;
39 }
40 });
41 this.cache2 = new Map();
42 }
43
44 get(type, resolveOptions) {
45 resolveOptions = resolveOptions || EMTPY_RESOLVE_OPTIONS;
46 const ident = `${type}|${JSON.stringify(resolveOptions)}`;
47 const resolver = this.cache2.get(ident);
48 if (resolver) return resolver;
49 const newResolver = this._create(type, resolveOptions);
50 this.cache2.set(ident, newResolver);
51 return newResolver;
52 }
53
54 _create(type, resolveOptions) {
55 const originalResolveOptions = Object.assign({}, resolveOptions);
56 resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions);
57 const resolver = Factory.createResolver(resolveOptions);
58 if (!resolver) {
59 throw new Error("No resolver created");
60 }
61 /** @type {Map<Object, Resolver>} */
62 const childCache = new Map();
63 resolver.withOptions = options => {
64 const cacheEntry = childCache.get(options);
65 if (cacheEntry !== undefined) return cacheEntry;
66 const mergedOptions = cachedCleverMerge(originalResolveOptions, options);
67 const resolver = this.get(type, mergedOptions);
68 childCache.set(options, resolver);
69 return resolver;
70 };
71 this.hooks.resolver.for(type).call(resolver, resolveOptions);
72 return resolver;
73 }
74};