diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2024-08-30 17:21:18 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2024-08-30 17:21:18 +0800 |
| commit | efbc2ffe6a1ee5ec38a4396305561d6515d0943e (patch) | |
| tree | 2b4c94f18f2c792dfda813050755d5c0273fae22 /node_modules/webpack/lib/ResolverFactory.js | |
| parent | 43acceb75957c880a5ba5a31aae221394a36d5f6 (diff) | |
node fixes, updates
Diffstat (limited to 'node_modules/webpack/lib/ResolverFactory.js')
| -rw-r--r-- | node_modules/webpack/lib/ResolverFactory.js | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/ResolverFactory.js b/node_modules/webpack/lib/ResolverFactory.js new file mode 100644 index 00000000..9651c6a7 --- /dev/null +++ b/node_modules/webpack/lib/ResolverFactory.js @@ -0,0 +1,155 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const Factory = require("enhanced-resolve").ResolverFactory; +const { HookMap, SyncHook, SyncWaterfallHook } = require("tapable"); +const { + cachedCleverMerge, + removeOperations, + resolveByProperty +} = require("./util/cleverMerge"); + +/** @typedef {import("enhanced-resolve").ResolveContext} ResolveContext */ +/** @typedef {import("enhanced-resolve").ResolveOptions} ResolveOptions */ +/** @typedef {import("enhanced-resolve").ResolveRequest} ResolveRequest */ +/** @typedef {import("enhanced-resolve").Resolver} Resolver */ +/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} WebpackResolveOptions */ +/** @typedef {import("../declarations/WebpackOptions").ResolvePluginInstance} ResolvePluginInstance */ + +/** @typedef {WebpackResolveOptions & {dependencyType?: string, resolveToContext?: boolean }} ResolveOptionsWithDependencyType */ +/** + * @typedef {object} WithOptions + * @property {function(Partial<ResolveOptionsWithDependencyType>): ResolverWithOptions} withOptions create a resolver with additional/different options + */ + +/** @typedef {Resolver & WithOptions} ResolverWithOptions */ + +// need to be hoisted on module level for caching identity +const EMPTY_RESOLVE_OPTIONS = {}; + +/** + * @param {ResolveOptionsWithDependencyType} resolveOptionsWithDepType enhanced options + * @returns {ResolveOptions} merged options + */ +const convertToResolveOptions = resolveOptionsWithDepType => { + const { dependencyType, plugins, ...remaining } = resolveOptionsWithDepType; + + // check type compat + /** @type {Partial<ResolveOptions>} */ + const partialOptions = { + ...remaining, + plugins: + plugins && + /** @type {ResolvePluginInstance[]} */ ( + plugins.filter(item => item !== "...") + ) + }; + + if (!partialOptions.fileSystem) { + throw new Error( + "fileSystem is missing in resolveOptions, but it's required for enhanced-resolve" + ); + } + // These weird types validate that we checked all non-optional properties + const options = + /** @type {Partial<ResolveOptions> & Pick<ResolveOptions, "fileSystem">} */ ( + partialOptions + ); + + return removeOperations( + resolveByProperty(options, "byDependency", dependencyType), + // Keep the `unsafeCache` because it can be a `Proxy` + ["unsafeCache"] + ); +}; + +/** + * @typedef {object} ResolverCache + * @property {WeakMap<object, ResolverWithOptions>} direct + * @property {Map<string, ResolverWithOptions>} stringified + */ + +module.exports = class ResolverFactory { + constructor() { + this.hooks = Object.freeze({ + /** @type {HookMap<SyncWaterfallHook<[ResolveOptionsWithDependencyType]>>} */ + resolveOptions: new HookMap( + () => new SyncWaterfallHook(["resolveOptions"]) + ), + /** @type {HookMap<SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>>} */ + resolver: new HookMap( + () => new SyncHook(["resolver", "resolveOptions", "userResolveOptions"]) + ) + }); + /** @type {Map<string, ResolverCache>} */ + this.cache = new Map(); + } + + /** + * @param {string} type type of resolver + * @param {ResolveOptionsWithDependencyType=} resolveOptions options + * @returns {ResolverWithOptions} the resolver + */ + get(type, resolveOptions = EMPTY_RESOLVE_OPTIONS) { + let typedCaches = this.cache.get(type); + if (!typedCaches) { + typedCaches = { + direct: new WeakMap(), + stringified: new Map() + }; + this.cache.set(type, typedCaches); + } + const cachedResolver = typedCaches.direct.get(resolveOptions); + if (cachedResolver) { + return cachedResolver; + } + const ident = JSON.stringify(resolveOptions); + const resolver = typedCaches.stringified.get(ident); + if (resolver) { + typedCaches.direct.set(resolveOptions, resolver); + return resolver; + } + const newResolver = this._create(type, resolveOptions); + typedCaches.direct.set(resolveOptions, newResolver); + typedCaches.stringified.set(ident, newResolver); + return newResolver; + } + + /** + * @param {string} type type of resolver + * @param {ResolveOptionsWithDependencyType} resolveOptionsWithDepType options + * @returns {ResolverWithOptions} the resolver + */ + _create(type, resolveOptionsWithDepType) { + /** @type {ResolveOptionsWithDependencyType} */ + const originalResolveOptions = { ...resolveOptionsWithDepType }; + + const resolveOptions = convertToResolveOptions( + this.hooks.resolveOptions.for(type).call(resolveOptionsWithDepType) + ); + const resolver = /** @type {ResolverWithOptions} */ ( + Factory.createResolver(resolveOptions) + ); + if (!resolver) { + throw new Error("No resolver created"); + } + /** @type {WeakMap<Partial<ResolveOptionsWithDependencyType>, ResolverWithOptions>} */ + const childCache = new WeakMap(); + resolver.withOptions = options => { + const cacheEntry = childCache.get(options); + if (cacheEntry !== undefined) return cacheEntry; + const mergedOptions = cachedCleverMerge(originalResolveOptions, options); + const resolver = this.get(type, mergedOptions); + childCache.set(options, resolver); + return resolver; + }; + this.hooks.resolver + .for(type) + .call(resolver, resolveOptions, originalResolveOptions); + return resolver; + } +}; |
