diff --git a/lib/Compilation.js b/lib/Compilation.js index a231637be..a3467c9db 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -2227,7 +2227,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si ? /** @type {string} */ (originModule.nameForCondition()) : "", issuerLayer: originModule ? originModule.layer : null, - compiler: /** @type {string} */ (this.compiler.name), + compiler: this.compiler.name, ...contextInfo }, resolveOptions: originModule ? originModule.resolveOptions : undefined, @@ -2235,7 +2235,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si context || (originModule ? /** @type {string} */ (originModule.context) - : /** @type {string} */ (this.compiler.context)), + : this.compiler.context), dependencies }, (err, result) => { diff --git a/lib/ContextModule.js b/lib/ContextModule.js index 73ab9cc2e..7dd2e1cac 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -68,17 +68,17 @@ const makeSerializable = require("./util/makeSerializable"); * @typedef {object} ContextOptions * @property {ContextMode} mode * @property {boolean} recursive - * @property {RegExp} regExp - * @property {("strict" | boolean)=} namespaceObject + * @property {RegExp | false | null} regExp + * @property {"strict" | boolean=} namespaceObject * @property {string=} addon - * @property {(string | null)=} chunkName - * @property {(RegExp | null)=} include - * @property {(RegExp | null)=} exclude + * @property {string | null=} chunkName + * @property {RegExp | null=} include + * @property {RegExp | null=} exclude * @property {RawChunkGroupOptions=} groupOptions * @property {string=} typePrefix * @property {string=} category - * @property {(string[][] | null)=} referencedExports exports referenced from modules (won't be mangled) - * @property {string=} layer + * @property {string[][] | null=} referencedExports exports referenced from modules (won't be mangled) + * @property {string | null=} layer * @property {ImportAttributes=} attributes */ diff --git a/lib/ContextModuleFactory.js b/lib/ContextModuleFactory.js index 03e9b3e3a..4111eed30 100644 --- a/lib/ContextModuleFactory.js +++ b/lib/ContextModuleFactory.js @@ -21,7 +21,9 @@ const { join } = require("./util/fs"); /** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */ /** @typedef {import("./ModuleFactory").ModuleFactoryCallback} ModuleFactoryCallback */ /** @typedef {import("./ResolverFactory")} ResolverFactory */ +/** @typedef {import("./NormalModuleFactory").ResolveData} ResolveData */ /** @typedef {import("./dependencies/ContextDependency")} ContextDependency */ +/** @typedef {import("./dependencies/ContextDependency").ContextOptions} ContextOptions */ /** @typedef {import("enhanced-resolve").ResolveRequest} ResolveRequest */ /** * @template T @@ -31,9 +33,23 @@ const { join } = require("./util/fs"); /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ /** @typedef {{ context: string, request: string }} ContextAlternativeRequest */ +/** + * @typedef {object} ContextResolveData + * @property {string} context + * @property {string} request + * @property {ModuleFactoryCreateData["resolveOptions"]} resolveOptions + * @property {LazySet} fileDependencies + * @property {LazySet} missingDependencies + * @property {LazySet} contextDependencies + * @property {ContextDependency[]} dependencies + */ + +/** @typedef {ContextResolveData & ContextOptions} BeforeContextResolveData */ +/** @typedef {BeforeContextResolveData & { resource: TODO, resourceQuery: string | undefined, resourceFragment: string | undefined, resolveDependencies: ContextModuleFactory["resolveDependencies"] }} AfterContextResolveData */ + const EMPTY_RESOLVE_OPTIONS = {}; -module.exports = class ContextModuleFactory extends ModuleFactory { +class ContextModuleFactory extends ModuleFactory { /** * @param {ResolverFactory} resolverFactory resolverFactory */ @@ -45,9 +61,9 @@ module.exports = class ContextModuleFactory extends ModuleFactory { "options" ]); this.hooks = Object.freeze({ - /** @type {AsyncSeriesWaterfallHook<[TODO]>} */ + /** @type {AsyncSeriesWaterfallHook<[BeforeContextResolveData]>} */ beforeResolve: new AsyncSeriesWaterfallHook(["data"]), - /** @type {AsyncSeriesWaterfallHook<[TODO]>} */ + /** @type {AsyncSeriesWaterfallHook<[AfterContextResolveData]>} */ afterResolve: new AsyncSeriesWaterfallHook(["data"]), /** @type {SyncWaterfallHook<[string[]]>} */ contextModuleFiles: new SyncWaterfallHook(["files"]), @@ -91,9 +107,9 @@ module.exports = class ContextModuleFactory extends ModuleFactory { */ create(data, callback) { const context = data.context; - const dependencies = data.dependencies; + const dependencies = /** @type {ContextDependency[]} */ (data.dependencies); const resolveOptions = data.resolveOptions; - const dependency = /** @type {ContextDependency} */ (dependencies[0]); + const dependency = dependencies[0]; const fileDependencies = new LazySet(); const missingDependencies = new LazySet(); const contextDependencies = new LazySet(); @@ -130,7 +146,9 @@ module.exports = class ContextModuleFactory extends ModuleFactory { const request = beforeResolveResult.request; const resolveOptions = beforeResolveResult.resolveOptions; + /** @type {undefined | string[]} */ let loaders; + /** @type {undefined | string} */ let resource; let loadersPrefix = ""; const idx = request.lastIndexOf("!"); @@ -241,8 +259,8 @@ module.exports = class ContextModuleFactory extends ModuleFactory { (loaderResult.length > 0 ? "!" : ""), resource: contextResult.length > 1 - ? contextResult.map((r) => r.path) - : contextResult[0].path, + ? /** @type {string[]} */ (contextResult.map((r) => r.path)) + : /** @type {string} */ (contextResult[0].path), resolveDependencies: this.resolveDependencies.bind(this), resourceQuery: contextResult[0].query, resourceFragment: contextResult[0].fragment, @@ -478,4 +496,6 @@ module.exports = class ContextModuleFactory extends ModuleFactory { }); } } -}; +} + +module.exports = ContextModuleFactory; diff --git a/lib/ContextReplacementPlugin.js b/lib/ContextReplacementPlugin.js index 76188c29c..92794b70a 100644 --- a/lib/ContextReplacementPlugin.js +++ b/lib/ContextReplacementPlugin.js @@ -98,6 +98,7 @@ class ContextReplacementPlugin { const newContentCreateContextMap = this.newContentCreateContextMap; compiler.hooks.contextModuleFactory.tap(PLUGIN_NAME, (cmf) => { + // @ts-expect-error TODO fix types for AsyncSeriesWaterfallHook cmf.hooks.beforeResolve.tap(PLUGIN_NAME, (result) => { if (!result) return; if (resourceRegExp.test(result.request)) { @@ -120,6 +121,7 @@ class ContextReplacementPlugin { } return result; }); + // @ts-expect-error TODO fix types for AsyncSeriesWaterfallHook cmf.hooks.afterResolve.tap(PLUGIN_NAME, (result) => { if (!result) return; if (resourceRegExp.test(result.resource)) { diff --git a/lib/IgnorePlugin.js b/lib/IgnorePlugin.js index 310af5ee2..b62cc0045 100644 --- a/lib/IgnorePlugin.js +++ b/lib/IgnorePlugin.js @@ -12,6 +12,7 @@ const createSchemaValidation = require("./util/create-schema-validation"); /** @typedef {import("../declarations/plugins/IgnorePlugin").IgnorePluginOptions} IgnorePluginOptions */ /** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./NormalModuleFactory").ResolveData} ResolveData */ +/** @typedef {import("./ContextModuleFactory").BeforeContextResolveData} BeforeContextResolveData */ const validate = createSchemaValidation( require("../schemas/plugins/IgnorePlugin.check"), @@ -36,8 +37,8 @@ class IgnorePlugin { /** * Note that if "contextRegExp" is given, both the "resourceRegExp" and "contextRegExp" have to match. - * @param {ResolveData} resolveData resolve data - * @returns {false|undefined} returns false when the request should be ignored, otherwise undefined + * @param {ResolveData | BeforeContextResolveData} resolveData resolve data + * @returns {false | undefined} returns false when the request should be ignored, otherwise undefined */ checkIgnore(resolveData) { if ( @@ -94,6 +95,7 @@ class IgnorePlugin { }); }); compiler.hooks.contextModuleFactory.tap(PLUGIN_NAME, (cmf) => { + // @ts-expect-error TODO fix types for AsyncSeriesWaterfallHook cmf.hooks.beforeResolve.tap(PLUGIN_NAME, this.checkIgnore); }); } diff --git a/lib/ModuleFactory.js b/lib/ModuleFactory.js index a38ae2a67..76ece8815 100644 --- a/lib/ModuleFactory.js +++ b/lib/ModuleFactory.js @@ -23,7 +23,7 @@ /** * @typedef {object} ModuleFactoryCreateDataContextInfo * @property {string} issuer - * @property {IssuerLayer=} issuerLayer + * @property {IssuerLayer} issuerLayer * @property {string=} compiler */ diff --git a/lib/dependencies/ContextDependency.js b/lib/dependencies/ContextDependency.js index bcec13d18..d72c4faed 100644 --- a/lib/dependencies/ContextDependency.js +++ b/lib/dependencies/ContextDependency.js @@ -24,7 +24,7 @@ const getCriticalDependencyWarning = memoize(() => /** @typedef {ContextOptions & { request: string }} ContextDependencyOptions */ /** - * @param {RegExp | null | undefined} r regexp + * @param {RegExp | false | null | undefined} r regexp * @returns {string} stringified regexp */ const regExpToString = (r) => (r ? String(r) : ""); @@ -45,6 +45,7 @@ class ContextDependency extends Dependency { if ( this.options && + this.options.regExp && (this.options.regExp.global || this.options.regExp.sticky) ) { this.options = { ...this.options, regExp: null }; diff --git a/test/configCases/loaders/resolve/loader.js b/test/configCases/loaders/resolve/loader.js index 3fd66d98e..36d89e8c3 100644 --- a/test/configCases/loaders/resolve/loader.js +++ b/test/configCases/loaders/resolve/loader.js @@ -4,7 +4,7 @@ const path = require("path"); module.exports = function () { const callback = this.async(); - this.resolve(this.context, "./b.js", (err, result, request) => { - callback(err, `module.exports = ${JSON.stringify(path.basename(result))};`) + this.resolve(this.context, "./b.js", (err, result) => { + callback(err, `module.exports = ${JSON.stringify(path.basename(/** @type {string} */ (result)))};`) }); }; diff --git a/types.d.ts b/types.d.ts index f190ebe19..af9310ef5 100644 --- a/types.d.ts +++ b/types.d.ts @@ -189,6 +189,20 @@ declare interface AdditionalData { [index: string]: any; webpackAST: object; } +type AfterContextResolveData = ContextResolveData & + ContextOptions & { + resource: any; + resourceQuery?: string; + resourceFragment?: string; + resolveDependencies: ( + fs: InputFileSystem, + options: ContextModuleOptions, + callback: ( + err: null | Error, + dependencies?: ContextElementDependency[] + ) => any + ) => void; + }; declare class AggressiveMergingPlugin { constructor(options?: AggressiveMergingPluginOptions); options: AggressiveMergingPluginOptions; @@ -910,6 +924,7 @@ declare abstract class BasicEvaluatedExpression { | TemplateElement ): BasicEvaluatedExpression; } +type BeforeContextResolveData = ContextResolveData & ContextOptions; declare interface Bootstrap { header: string[]; beforeStartup: string[]; @@ -3263,6 +3278,19 @@ declare interface ContextAlternativeRequest { context: string; request: string; } +declare abstract class ContextDependency extends Dependency { + options: ContextDependencyOptions; + userRequest: string; + critical?: string | false; + hadGlobalOrStickyRegExp: boolean; + request: any; + range: any; + valueRange: any; + inShorthand?: string | boolean; + replaces: any; + prepend: any; +} +type ContextDependencyOptions = ContextOptions & { request: string }; declare abstract class ContextElementDependency extends ModuleDependency { referencedExports?: null | string[][]; } @@ -3295,8 +3323,8 @@ type ContextMode = | "async-weak"; declare abstract class ContextModuleFactory extends ModuleFactory { hooks: Readonly<{ - beforeResolve: AsyncSeriesWaterfallHook<[any]>; - afterResolve: AsyncSeriesWaterfallHook<[any]>; + beforeResolve: AsyncSeriesWaterfallHook<[BeforeContextResolveData]>; + afterResolve: AsyncSeriesWaterfallHook<[AfterContextResolveData]>; contextModuleFiles: SyncWaterfallHook<[string[]]>; alternatives: FakeHook< Pick< @@ -3318,11 +3346,17 @@ declare abstract class ContextModuleFactory extends ModuleFactory { ) => any ): void; } - -declare interface ContextModuleOptions { +type ContextModuleOptions = ContextOptions & ContextModuleOptionsExtras; +declare interface ContextModuleOptionsExtras { + resource: string | false | string[]; + resourceQuery?: string; + resourceFragment?: string; + resolveOptions?: ResolveOptions; +} +declare interface ContextOptions { mode: ContextMode; recursive: boolean; - regExp: RegExp; + regExp: null | false | RegExp; namespaceObject?: boolean | "strict"; addon?: string; chunkName?: null | string; @@ -3336,12 +3370,8 @@ declare interface ContextModuleOptions { * exports referenced from modules (won't be mangled) */ referencedExports?: null | string[][]; - layer?: string; + layer?: null | string; attributes?: ImportAttributes; - resource: string | false | string[]; - resourceQuery?: string; - resourceFragment?: string; - resolveOptions?: ResolveOptions; } declare class ContextReplacementPlugin { constructor( @@ -3368,6 +3398,15 @@ declare class ContextReplacementPlugin { */ apply(compiler: Compiler): void; } +declare interface ContextResolveData { + context: string; + request: string; + resolveOptions?: ResolveOptions; + fileDependencies: LazySet; + missingDependencies: LazySet; + contextDependencies: LazySet; + dependencies: ContextDependency[]; +} type ContextTimestamp = null | ContextFileSystemInfoEntry | "ignore"; declare interface ContextTimestampAndHash { safeTime: number; @@ -6225,7 +6264,9 @@ declare class IgnorePlugin { /** * Note that if "contextRegExp" is given, both the "resourceRegExp" and "contextRegExp" have to match. */ - checkIgnore(resolveData: ResolveData): undefined | false; + checkIgnore( + resolveData: ResolveData | BeforeContextResolveData + ): undefined | false; /** * Apply the plugin @@ -6481,6 +6522,7 @@ declare interface InterpolatedPathAndAssetInfo { path: string; info: AssetInfo; } +type IssuerLayer = null | string; declare interface Item { [index: string]: string | string[] | T; } @@ -10015,7 +10057,7 @@ declare interface ModuleFactoryCreateData { } declare interface ModuleFactoryCreateDataContextInfo { issuer: string; - issuerLayer?: null | string; + issuerLayer: IssuerLayer; compiler?: string; } declare interface ModuleFactoryResult { @@ -17993,6 +18035,7 @@ declare interface WriteStreamOptions { start?: number; signal?: null | AbortSignal; fs?: null | CreateWriteStreamFSImplementation; + flush?: boolean; } declare function exports( options: Configuration,