From d5b4b50c10e10178c81cf91b7970db5f361d6f4f Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Tue, 9 Sep 2025 22:11:22 +0300 Subject: [PATCH] feat: PoC of 17512 --- lib/Compilation.js | 1 + lib/NormalModule.js | 2 + lib/NormalModuleFactory.js | 17 ++++-- lib/ResolverFactory.js | 81 +++++++++++++++++++--------- lib/config/defaults.js | 15 ++++-- lib/dependencies/WorkerDependency.js | 4 ++ 6 files changed, 86 insertions(+), 34 deletions(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index 3efa18994..0d55f2d66 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -1988,6 +1988,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si ? /** @type {string} */ (originModule.nameForCondition()) : "", issuerLayer: originModule ? originModule.layer : null, + issuerDependency: originModule ? originModule.issuerDependencyType : null, compiler: this.compiler.name, ...contextInfo }, diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 63cef025e..347b157bc 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -341,6 +341,7 @@ class NormalModule extends Module { constructor({ layer, type, + issuerDependencyType, request, userRequest, rawRequest, @@ -358,6 +359,7 @@ class NormalModule extends Module { }) { super(type, context || getContext(resource), layer); + this.issuerDependencyType = issuerDependencyType; // Info from Factory /** @type {string} */ this.request = request; diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index 4cb24cfbb..139813f0f 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -443,6 +443,7 @@ class NormalModuleFactory extends ModuleFactory { context, dependencies, dependencyType, + issuerDependencyType, request, assertions, resolveOptions, @@ -705,6 +706,7 @@ class NormalModuleFactory extends ModuleFactory { Object.assign(data.createData, { layer: layer === undefined ? contextInfo.issuerLayer || null : layer, + issuerDependencyType: issuerDependencyType, request: stringifyLoadersAndResource( allLoaders, resourceData.resource @@ -793,7 +795,6 @@ class NormalModuleFactory extends ModuleFactory { }; continueCallback(); } - // resource without scheme and with path else { const normalResolver = this.getResolver( @@ -804,6 +805,13 @@ class NormalModuleFactory extends ModuleFactory { "dependencyType", dependencyType ) + : resolveOptions, + issuerDependencyType + ? cachedSetProperty( + resolveOptions || EMPTY_RESOLVE_OPTIONS, + "issuerDependency", + issuerDependencyType + ) : resolveOptions ); this.resolveResource( @@ -899,6 +907,7 @@ class NormalModuleFactory extends ModuleFactory { const assertions = dependency.assertions; const dependencyType = dependency.category || ""; const contextInfo = data.contextInfo; + const issuerDependencyType = dependency.issuerCategory || contextInfo.issuerDependency || null; const fileDependencies = new LazySet(); const missingDependencies = new LazySet(); const contextDependencies = new LazySet(); @@ -911,6 +920,7 @@ class NormalModuleFactory extends ModuleFactory { assertions, dependencies, dependencyType, + issuerDependencyType, fileDependencies, missingDependencies, contextDependencies, @@ -1359,10 +1369,11 @@ If changing the source code is not an option there is also a resolve options cal /** * @param {Parameters[0]} type type of resolver * @param {Parameters[1]=} resolveOptions options + * @param {Parameters[1]=} issuerResolveOptions options * @returns {ReturnType} the resolver */ - getResolver(type, resolveOptions) { - return this.resolverFactory.get(type, resolveOptions); + getResolver(type, resolveOptions, issuerResolveOptions) { + return this.resolverFactory.get(type, resolveOptions, issuerResolveOptions); } } diff --git a/lib/ResolverFactory.js b/lib/ResolverFactory.js index 697fdee5c..28d129d90 100644 --- a/lib/ResolverFactory.js +++ b/lib/ResolverFactory.js @@ -34,9 +34,13 @@ const EMPTY_RESOLVE_OPTIONS = {}; /** * @param {ResolveOptionsWithDependencyType} resolveOptionsWithDepType enhanced options + * @param {ResolveOptionsWithDependencyType} issuerResolveOptions enhanced options * @returns {ResolveOptions} merged options */ -const convertToResolveOptions = (resolveOptionsWithDepType) => { +const convertToResolveOptions = ( + resolveOptionsWithDepType, + issuerResolveOptions +) => { const { dependencyType, plugins, ...remaining } = resolveOptionsWithDepType; // check type compat @@ -60,10 +64,24 @@ const convertToResolveOptions = (resolveOptionsWithDepType) => { /** @type {Partial & Pick} */ ( partialOptions ); + const { issuerDependency } = issuerResolveOptions; + + const resolvedByDependency = resolveByProperty( + options, + "byDependency", + dependencyType + ); return /** @type {ResolveOptions} */ ( + // byIssuerDependencyType removeOperations( - resolveByProperty(options, "byDependency", dependencyType), + issuerDependency + ? resolveByProperty( + resolvedByDependency, + "byIssuerDependency", + issuerDependency + ) + : resolvedByDependency, // Keep the `unsafeCache` because it can be a `Proxy` ["unsafeCache"] ) @@ -95,44 +113,55 @@ module.exports = class ResolverFactory { /** * @param {string} type type of resolver * @param {ResolveOptionsWithDependencyType=} resolveOptions options + * @param {ResolveOptionsWithDependencyType=} issuerResolveOptions 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); + get( + type, + resolveOptions = EMPTY_RESOLVE_OPTIONS, + issuerResolveOptions = 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, + issuerResolveOptions + ); + // typedCaches.direct.set(resolveOptions, newResolver); + // typedCaches.stringified.set(ident, newResolver); return newResolver; } /** * @param {string} type type of resolver * @param {ResolveOptionsWithDependencyType} resolveOptionsWithDepType options + * @param {ResolveOptionsWithIssuerDependencyType} issuerResolveOptions options * @returns {ResolverWithOptions} the resolver */ - _create(type, resolveOptionsWithDepType) { + _create(type, resolveOptionsWithDepType, issuerResolveOptions) { /** @type {ResolveOptionsWithDependencyType} */ const originalResolveOptions = { ...resolveOptionsWithDepType }; const resolveOptions = convertToResolveOptions( - this.hooks.resolveOptions.for(type).call(resolveOptionsWithDepType) + this.hooks.resolveOptions.for(type).call(resolveOptionsWithDepType), + issuerResolveOptions ); const resolver = /** @type {ResolverWithOptions} */ ( Factory.createResolver(resolveOptions) diff --git a/lib/config/defaults.js b/lib/config/defaults.js index 04f507e3e..796c3e594 100644 --- a/lib/config/defaults.js +++ b/lib/config/defaults.js @@ -1787,12 +1787,17 @@ const getResolveDefaults = ({ conditionNames: ["require", "module", "..."], extensions: [...jsExtensions] }); - /** @type {() => ResolveOptions} */ - const esmDeps = () => ({ + /** @type {(options?: { worker?: boolean }) => ResolveOptions} */ + const esmDeps = ({ worker } = {}) => ({ aliasFields: browserField ? ["browser"] : [], mainFields: browserField ? ["browser", "module", "..."] : ["module", "..."], - conditionNames: ["import", "module", "..."], - extensions: [...jsExtensions] + conditionNames: [...(worker ? ["worker"] : []), "import", "module", "..."], + extensions: [...jsExtensions], + byIssuerDependency: { + worker: { + conditionNames: ["worker", "import", "module", "..."] + } + } }); /** @type {ResolveOptions} */ @@ -1815,7 +1820,7 @@ const getResolveDefaults = ({ preferRelative: true }, worker: { - ...esmDeps(), + ...esmDeps({ worker: true }), preferRelative: true }, commonjs: cjsDeps(), diff --git a/lib/dependencies/WorkerDependency.js b/lib/dependencies/WorkerDependency.js index eafc653d9..e2559438c 100644 --- a/lib/dependencies/WorkerDependency.js +++ b/lib/dependencies/WorkerDependency.js @@ -59,6 +59,10 @@ class WorkerDependency extends ModuleDependency { return "worker"; } + get issuerCategory() { + return "worker"; + } + /** * Update the hash * @param {Hash} hash hash to be updated