diff --git a/lib/AbstractMethodError.js b/lib/AbstractMethodError.js index d90ddef96..7a9d2f992 100644 --- a/lib/AbstractMethodError.js +++ b/lib/AbstractMethodError.js @@ -20,11 +20,15 @@ function createMessage(method) { * @constructor */ function Message() { - /** @type {string} */ + /** @type {string | undefined} */ this.stack = undefined; Error.captureStackTrace(this); - /** @type {RegExpMatchArray} */ - const match = this.stack.split("\n")[3].match(CURRENT_METHOD_REGEXP); + /** @type {RegExpMatchArray | null} */ + const match = + /** @type {string} */ + (/** @type {unknown} */ (this.stack)) + .split("\n")[3] + .match(CURRENT_METHOD_REGEXP); this.message = match && match[1] ? createMessage(match[1]) : createMessage(); } diff --git a/lib/ChunkGroup.js b/lib/ChunkGroup.js index 01b37ccfc..9b899dd21 100644 --- a/lib/ChunkGroup.js +++ b/lib/ChunkGroup.js @@ -22,7 +22,7 @@ const { /** @typedef {import("./ModuleGraph")} ModuleGraph */ /** @typedef {{id: number}} HasId */ -/** @typedef {{module: Module, loc: DependencyLocation, request: string}} OriginRecord */ +/** @typedef {{module: Module | null, loc: DependencyLocation, request: string}} OriginRecord */ /** * @typedef {object} RawChunkGroupOptions @@ -404,7 +404,7 @@ class ChunkGroup { } /** - * @param {Module} module origin module + * @param {Module | null} module origin module * @param {DependencyLocation} loc location of the reference in the origin module * @param {string} request request name of the reference * @returns {void} diff --git a/lib/Compilation.js b/lib/Compilation.js index 34deb2ed5..018b38dd1 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -153,7 +153,7 @@ const { isSourceEqual } = require("./util/source"); /** * @callback ExecuteModuleCallback - * @param {(WebpackError | null)=} err + * @param {WebpackError | null} err * @param {ExecuteModuleResult=} result * @returns {void} */ @@ -1966,6 +1966,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si callback ) { // Check for cycles when build is trigger inside another build + /** @type {Set | undefined} */ let creatingModuleDuringBuildSet; if (checkCycle && this.buildQueue.isProcessing(originModule)) { // Track build dependency @@ -4963,12 +4964,6 @@ This prevents using hashes of each other and should be avoided.`); processAsyncTree( modules, 10, - /** - * @param {Module} module the module - * @param {function(Module): void} push push more jobs - * @param {Callback} callback callback - * @returns {void} - */ (module, push, callback) => { this.buildQueue.waitFor(module, err => { if (err) return callback(err); diff --git a/lib/Compiler.js b/lib/Compiler.js index dd722cf28..f1472544b 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -201,7 +201,7 @@ class Compiler { /** @type {AsyncSeriesHook<[]>} */ shutdown: new AsyncSeriesHook([]), - /** @type {SyncBailHook<[string, string, any[]], true>} */ + /** @type {SyncBailHook<[string, string, any[] | undefined], true>} */ infrastructureLog: new SyncBailHook(["origin", "type", "args"]), // TODO the following hooks are weirdly located here @@ -1227,9 +1227,16 @@ ${other}`); "done", "thisCompilation" ].includes(name) && - childCompiler.hooks[name] + childCompiler.hooks[/** @type {keyof Compiler["hooks"]} */ (name)] ) { - childCompiler.hooks[name].taps = this.hooks[name].taps.slice(); + childCompiler.hooks[ + /** @type {keyof Compiler["hooks"]} */ + (name) + ].taps = + this.hooks[ + /** @type {keyof Compiler["hooks"]} */ + (name) + ].taps.slice(); } } diff --git a/lib/ContextModule.js b/lib/ContextModule.js index c71881343..91a5b1bf3 100644 --- a/lib/ContextModule.js +++ b/lib/ContextModule.js @@ -30,6 +30,7 @@ const makeSerializable = require("./util/makeSerializable"); /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ /** @typedef {import("./Chunk")} Chunk */ +/** @typedef {import("./Chunk").ChunkId} ChunkId */ /** @typedef {import("./ChunkGraph")} ChunkGraph */ /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */ /** @typedef {import("./ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */ @@ -86,7 +87,7 @@ const makeSerializable = require("./util/makeSerializable"); /** * @callback ResolveDependenciesCallback - * @param {(Error | null)=} err + * @param {Error | null} err * @param {ContextElementDependency[]=} dependencies */ @@ -99,7 +100,7 @@ const makeSerializable = require("./util/makeSerializable"); /** @typedef {1 | 3 | 7 | 9} FakeMapType */ -/** @typedef {Map | FakeMapType} FakeMap */ +/** @typedef {Record} FakeMap */ const SNAPSHOT_OPTIONS = { timestamp: true }; @@ -602,7 +603,7 @@ class ContextModule extends Module { /** * @param {Dependency[]} dependencies all dependencies * @param {ChunkGraph} chunkGraph chunk graph - * @returns {FakeMap} fake map + * @returns {FakeMap | FakeMapType} fake map */ getFakeMap(dependencies, chunkGraph) { if (!this.options.namespaceObject) { @@ -621,13 +622,14 @@ class ContextModule extends Module { ) .filter(Boolean) .sort(comparator); + /** @type {FakeMap} */ const fakeMap = Object.create(null); for (const module of sortedModules) { const exportsType = module.getExportsType( moduleGraph, this.options.namespaceObject === "strict" ); - const id = chunkGraph.getModuleId(module); + const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module)); switch (exportsType) { case "namespace": fakeMap[id] = 9; @@ -668,7 +670,7 @@ class ContextModule extends Module { } /** - * @param {FakeMap} fakeMap fake map + * @param {FakeMap | FakeMapType} fakeMap fake map * @returns {string} fake map init statement */ getFakeMapInitStatement(fakeMap) { @@ -692,7 +694,7 @@ class ContextModule extends Module { } /** - * @param {FakeMap} fakeMap fake map + * @param {FakeMap | FakeMapType} fakeMap fake map * @param {boolean=} asyncModule us async module * @param {string=} fakeMapDataExpression fake map data expression * @returns {string} module object source @@ -944,6 +946,10 @@ module.exports = webpackAsyncContext;`; chunkGraph ); const hasFakeMap = typeof fakeMap === "object"; + /** @typedef {{userRequest: string, dependency: ContextElementDependency, chunks: undefined | Chunk[], module: Module, block: AsyncDependenciesBlock}} Item */ + /** + * @type {Item[]} + */ const items = blocks .map(block => { const dependency = @@ -974,18 +980,23 @@ module.exports = webpackAsyncContext;`; if (a.userRequest === b.userRequest) return 0; return a.userRequest < b.userRequest ? -1 : 1; }); + /** @type {Record} */ const map = Object.create(null); for (const item of sortedItems) { - const moduleId = chunkGraph.getModuleId(item.module); + const moduleId = + /** @type {ModuleId} */ + (chunkGraph.getModuleId(item.module)); if (shortMode) { map[item.userRequest] = moduleId; } else { + /** @type {(ModuleId | ChunkId)[]} */ const arrayStart = [moduleId]; if (hasFakeMap) { arrayStart.push(fakeMap[moduleId]); } map[item.userRequest] = arrayStart.concat( - item.chunks.map(chunk => chunk.id) + /** @type {Chunk[]} */ + (item.chunks).map(chunk => /** @type {ChunkId} */ (chunk.id)) ); } } @@ -1086,7 +1097,7 @@ module.exports = webpackEmptyAsyncContext;`; * @returns {string} the source code */ getSourceString(asyncMode, { runtimeTemplate, chunkGraph }) { - const id = chunkGraph.getModuleId(this); + const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(this)); if (asyncMode === "lazy") { if (this.blocks && this.blocks.length > 0) { return this.getLazySource(this.blocks, id, { diff --git a/lib/ContextModuleFactory.js b/lib/ContextModuleFactory.js index 3744a4a06..4b25f9be0 100644 --- a/lib/ContextModuleFactory.js +++ b/lib/ContextModuleFactory.js @@ -22,8 +22,14 @@ const { join } = require("./util/fs"); /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */ /** @typedef {import("./ResolverFactory")} ResolverFactory */ /** @typedef {import("./dependencies/ContextDependency")} ContextDependency */ -/** @template T @typedef {import("./util/deprecation").FakeHook} FakeHook */ +/** @typedef {import("enhanced-resolve").ResolveRequest} ResolveRequest */ +/** + * @template T + * @typedef {import("./util/deprecation").FakeHook} FakeHook + */ +/** @typedef {import("./util/fs").IStats} IStats */ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ +/** @typedef {{ context: string, request: string }} ContextAlternativeRequest */ const EMPTY_RESOLVE_OPTIONS = {}; @@ -33,7 +39,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory { */ constructor(resolverFactory) { super(); - /** @type {AsyncSeriesWaterfallHook<[TODO[], ContextModuleOptions]>} */ + /** @type {AsyncSeriesWaterfallHook<[ContextAlternativeRequest[], ContextModuleOptions]>} */ const alternativeRequests = new AsyncSeriesWaterfallHook([ "modules", "options" @@ -45,27 +51,27 @@ module.exports = class ContextModuleFactory extends ModuleFactory { afterResolve: new AsyncSeriesWaterfallHook(["data"]), /** @type {SyncWaterfallHook<[string[]]>} */ contextModuleFiles: new SyncWaterfallHook(["files"]), - /** @type {FakeHook, "tap" | "tapAsync" | "tapPromise" | "name">>} */ + /** @type {FakeHook, "tap" | "tapAsync" | "tapPromise" | "name">>} */ alternatives: createFakeHook( { name: "alternatives", - /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["intercept"]} */ + /** @type {AsyncSeriesWaterfallHook<[ContextAlternativeRequest[]]>["intercept"]} */ intercept: interceptor => { throw new Error( "Intercepting fake hook ContextModuleFactory.hooks.alternatives is not possible, use ContextModuleFactory.hooks.alternativeRequests instead" ); }, - /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tap"]} */ + /** @type {AsyncSeriesWaterfallHook<[ContextAlternativeRequest[]]>["tap"]} */ tap: (options, fn) => { alternativeRequests.tap(options, fn); }, - /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tapAsync"]} */ + /** @type {AsyncSeriesWaterfallHook<[ContextAlternativeRequest[]]>["tapAsync"]} */ tapAsync: (options, fn) => { alternativeRequests.tapAsync(options, (items, _options, callback) => fn(items, callback) ); }, - /** @type {AsyncSeriesWaterfallHook<[TODO[]]>["tapPromise"]} */ + /** @type {AsyncSeriesWaterfallHook<[ContextAlternativeRequest[]]>["tapPromise"]} */ tapPromise: (options, fn) => { alternativeRequests.tapPromise(options, fn); } @@ -164,7 +170,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory { asyncLib.parallel( [ callback => { - const results = []; + const results = /** @type ResolveRequest[] */ ([]); const yield_ = obj => results.push(obj); contextResolver.resolve( @@ -198,7 +204,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory { }, (err, result) => { if (err) return callback(err); - callback(null, result); + callback(null, /** @type {string} */ (result)); } ); }, @@ -214,7 +220,8 @@ module.exports = class ContextModuleFactory extends ModuleFactory { contextDependencies }); } - let [contextResult, loaderResult] = result; + let [contextResult, loaderResult] = + /** @type {[ResolveRequest[], string[]]} */ (result); if (contextResult.length > 1) { const first = contextResult[0]; contextResult = contextResult.filter(r => r.path); @@ -290,10 +297,19 @@ module.exports = class ContextModuleFactory extends ModuleFactory { } = options; if (!regExp || !resource) return callback(null, []); + /** + * @param {string} ctx context + * @param {string} directory directory + * @param {Set} visited visited + * @param {ResolveDependenciesCallback} callback callback + */ const addDirectoryChecked = (ctx, directory, visited, callback) => { - fs.realpath(directory, (err, realPath) => { + /** @type {NonNullable} */ + (fs.realpath)(directory, (err, _realPath) => { if (err) return callback(err); + const realPath = /** @type {string} */ (_realPath); if (visited.has(realPath)) return callback(null, []); + /** @type {Set | undefined} */ let recursionStack; addDirectory( ctx, @@ -310,6 +326,12 @@ module.exports = class ContextModuleFactory extends ModuleFactory { }); }; + /** + * @param {string} ctx context + * @param {string} directory directory + * @param {function(string, string, function(): void): void} addSubDirectory addSubDirectoryFn + * @param {ResolveDependenciesCallback} callback callback + */ const addDirectory = (ctx, directory, addSubDirectory, callback) => { fs.readdir(directory, (err, files) => { if (err) return callback(err); @@ -324,7 +346,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory { const subResource = join(fs, directory, segment); if (!exclude || !subResource.match(exclude)) { - fs.stat(subResource, (err, stat) => { + fs.stat(subResource, (err, _stat) => { if (err) { if (err.code === "ENOENT") { // ENOENT is ok here because the file may have been deleted between @@ -334,6 +356,8 @@ module.exports = class ContextModuleFactory extends ModuleFactory { return callback(err); } + const stat = /** @type {IStats} */ (_stat); + if (stat.isDirectory()) { if (!recursive) return callback(); addSubDirectory(ctx, subResource, callback); @@ -341,6 +365,7 @@ module.exports = class ContextModuleFactory extends ModuleFactory { stat.isFile() && (!include || subResource.match(include)) ) { + /** @type {{ context: string, request: string }} */ const obj = { context: ctx, request: `.${subResource.slice(ctx.length).replace(/\\/g, "/")}` @@ -351,22 +376,29 @@ module.exports = class ContextModuleFactory extends ModuleFactory { options, (err, alternatives) => { if (err) return callback(err); - alternatives = alternatives - .filter(obj => regExp.test(obj.request)) - .map(obj => { - const dep = new ContextElementDependency( - `${obj.request}${resourceQuery}${resourceFragment}`, - obj.request, - typePrefix, - category, - referencedExports, - obj.context, - attributes - ); - dep.optional = true; - return dep; - }); - callback(null, alternatives); + callback( + null, + /** @type {ContextAlternativeRequest[]} */ + (alternatives) + .filter(obj => + regExp.test(/** @type {string} */ (obj.request)) + ) + .map(obj => { + const dep = new ContextElementDependency( + `${obj.request}${resourceQuery}${resourceFragment}`, + obj.request, + typePrefix, + /** @type {string} */ + (category), + referencedExports, + /** @type {TODO} */ + (obj.context), + attributes + ); + dep.optional = true; + return dep; + }) + ); } ); } else { @@ -394,9 +426,19 @@ module.exports = class ContextModuleFactory extends ModuleFactory { }); }; + /** + * @param {string} ctx context + * @param {string} dir dir + * @param {ResolveDependenciesCallback} callback callback + * @returns {void} + */ const addSubDirectory = (ctx, dir, callback) => addDirectory(ctx, dir, addSubDirectory, callback); + /** + * @param {string} resource resource + * @param {ResolveDependenciesCallback} callback callback + */ const visitResource = (resource, callback) => { if (typeof fs.realpath === "function") { addDirectoryChecked(resource, resource, new Set(), callback); @@ -408,12 +450,15 @@ module.exports = class ContextModuleFactory extends ModuleFactory { if (typeof resource === "string") { visitResource(resource, callback); } else { - asyncLib.map(resource, visitResource, (err, result) => { + asyncLib.map(resource, visitResource, (err, _result) => { if (err) return callback(err); + const result = /** @type {ContextElementDependency[][]} */ (_result); // result dependencies should have unique userRequest // ordered by resolve result + /** @type {Set} */ const temp = new Set(); + /** @type {ContextElementDependency[]} */ const res = []; for (let i = 0; i < result.length; i++) { const inner = result[i]; diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index 9b1810180..d33929814 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -134,7 +134,9 @@ class HotModuleReplacementPlugin { (module.buildInfo).moduleConcatenationBailout = "Hot Module Replacement"; if (expr.arguments.length >= 1) { - const arg = parser.evaluateExpression(expr.arguments[0]); + const arg = parser.evaluateExpression( + /** @type {Expression} */ (expr.arguments[0]) + ); /** @type {BasicEvaluatedExpression[]} */ let params = []; if (arg.isString()) { diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 34e32a97c..f02e9652a 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -82,6 +82,10 @@ const memoize = require("./util/memoize"); /** @typedef {import("./util/Hash")} Hash */ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ +/** + * @template T + * @typedef {import("./util/deprecation").FakeHook} FakeHook + */ /** @typedef {{[k: string]: any}} ParserOptions */ /** @typedef {{[k: string]: any}} GeneratorOptions */ @@ -217,8 +221,8 @@ makeSerializable( * @property {SyncHook<[LoaderItem[], NormalModule, LoaderContext]>} beforeLoaders * @property {SyncHook<[NormalModule]>} beforeParse * @property {SyncHook<[NormalModule]>} beforeSnapshot - * @property {HookMap>} readResourceForScheme - * @property {HookMap], string | Buffer>>} readResource + * @property {HookMap>>} readResourceForScheme + * @property {HookMap], string | Buffer | null>>} readResource * @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild */ @@ -268,7 +272,7 @@ class NormalModule extends Module { /** @type {NormalModuleCompilationHooks} */ (hooks).readResource.for(scheme); return createFakeHook( - /** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer>} */ ({ + /** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>} */ ({ tap: (options, fn) => hook.tap(options, loaderContext => fn( @@ -1150,7 +1154,7 @@ class NormalModule extends Module { try { hooks.beforeSnapshot.call(this); } catch (err) { - this.markModuleAsErrored(err); + this.markModuleAsErrored(/** @type {WebpackError} */ (err)); return callback(); } @@ -1240,7 +1244,7 @@ class NormalModule extends Module { try { hooks.beforeParse.call(this); } catch (err) { - this.markModuleAsErrored(err); + this.markModuleAsErrored(/** @type {WebpackError} */ (err)); this._initBuildHash(compilation); return callback(); } diff --git a/lib/WebpackOptionsApply.js b/lib/WebpackOptionsApply.js index eb3811bb2..0521b8bfb 100644 --- a/lib/WebpackOptionsApply.js +++ b/lib/WebpackOptionsApply.js @@ -71,7 +71,7 @@ class WebpackOptionsApply extends OptionsApply { * @returns {WebpackOptions} options object */ process(options, compiler) { - compiler.outputPath = options.output.path; + compiler.outputPath = /** @type {string} */ (options.output.path); compiler.recordsInputPath = options.recordsInputPath || null; compiler.recordsOutputPath = options.recordsOutputPath || null; compiler.name = options.name; @@ -200,22 +200,34 @@ class WebpackOptionsApply extends OptionsApply { } } - if (options.output.enabledChunkLoadingTypes.length > 0) { - for (const type of options.output.enabledChunkLoadingTypes) { + const enabledChunkLoadingTypes = + /** @type {NonNullable} */ + (options.output.enabledChunkLoadingTypes); + + if (enabledChunkLoadingTypes.length > 0) { + for (const type of enabledChunkLoadingTypes) { const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin"); new EnableChunkLoadingPlugin(type).apply(compiler); } } - if (options.output.enabledWasmLoadingTypes.length > 0) { - for (const type of options.output.enabledWasmLoadingTypes) { + const enabledWasmLoadingTypes = + /** @type {NonNullable} */ + (options.output.enabledWasmLoadingTypes); + + if (enabledWasmLoadingTypes.length > 0) { + for (const type of enabledWasmLoadingTypes) { const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin"); new EnableWasmLoadingPlugin(type).apply(compiler); } } - if (options.output.enabledLibraryTypes.length > 0) { - for (const type of options.output.enabledLibraryTypes) { + const enabledLibraryTypes = + /** @type {NonNullable} */ + (options.output.enabledLibraryTypes); + + if (enabledLibraryTypes.length > 0) { + for (const type of enabledLibraryTypes) { const EnableLibraryPlugin = require("./library/EnableLibraryPlugin"); new EnableLibraryPlugin(type).apply(compiler); } @@ -320,7 +332,7 @@ class WebpackOptionsApply extends OptionsApply { const lazyOptions = typeof options.experiments.lazyCompilation === "object" ? options.experiments.lazyCompilation - : null; + : {}; new LazyCompilationPlugin({ backend: typeof lazyOptions.backend === "function" @@ -348,7 +360,11 @@ class WebpackOptionsApply extends OptionsApply { } new EntryOptionPlugin().apply(compiler); - compiler.hooks.entryOption.call(options.context, options.entry); + compiler.hooks.entryOption.call( + /** @type {string} */ + (options.context), + options.entry + ); new RuntimePlugin().apply(compiler); @@ -595,9 +611,12 @@ class WebpackOptionsApply extends OptionsApply { const AddManagedPathsPlugin = require("./cache/AddManagedPathsPlugin"); new AddManagedPathsPlugin( - options.snapshot.managedPaths, - options.snapshot.immutablePaths, - options.snapshot.unmanagedPaths + /** @type {NonNullable} */ + (options.snapshot.managedPaths), + /** @type {NonNullable} */ + (options.snapshot.immutablePaths), + /** @type {NonNullable} */ + (options.snapshot.unmanagedPaths) ).apply(compiler); if (options.cache && typeof options.cache === "object") { @@ -608,7 +627,9 @@ class WebpackOptionsApply extends OptionsApply { // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697 const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin"); new MemoryWithGcCachePlugin({ - maxGenerations: cacheOptions.maxGenerations + maxGenerations: + /** @type {number} */ + (cacheOptions.maxGenerations) }).apply(compiler); } else { // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697 @@ -658,17 +679,19 @@ class WebpackOptionsApply extends OptionsApply { new IdleFileCachePlugin( new PackFileCacheStrategy({ compiler, - fs: /** @type {IntermediateFileSystem} */ ( - compiler.intermediateFileSystem - ), - context: options.context, - cacheLocation: cacheOptions.cacheLocation, + fs: + /** @type {IntermediateFileSystem} */ + (compiler.intermediateFileSystem), + context: /** @type {string} */ (options.context), + cacheLocation: + /** @type {string} */ + (cacheOptions.cacheLocation), version: cacheOptions.version, logger: compiler.getInfrastructureLogger( "webpack.cache.PackFileCacheStrategy" ), snapshot: options.snapshot, - maxAge: cacheOptions.maxAge, + maxAge: /** @type {number} */ (cacheOptions.maxAge), profile: cacheOptions.profile, allowCollectingMemory: cacheOptions.allowCollectingMemory, compression: cacheOptions.compression, diff --git a/lib/cache/PackFileCacheStrategy.js b/lib/cache/PackFileCacheStrategy.js index ebf418fd8..3f340dbcb 100644 --- a/lib/cache/PackFileCacheStrategy.js +++ b/lib/cache/PackFileCacheStrategy.js @@ -816,6 +816,7 @@ class PackContent { return this.content.get(identifier); } + const logger = /** @type {Logger} */ (this.logger); // We are in state B const { lazyName } = this; /** @type {string | undefined} */ @@ -826,19 +827,19 @@ class PackContent { timeMessage = `restore cache content ${lazyName} (${formatSize( this.getSize() )})`; - this.logger.log( + logger.log( `starting to restore cache content ${lazyName} (${formatSize( this.getSize() )}) because of request to: ${identifier}` ); - this.logger.time(timeMessage); + logger.time(timeMessage); } const value = this.lazy(); if ("then" in value) { return value.then(data => { const map = data.map; if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } // Move to state C this.content = map; @@ -849,7 +850,7 @@ class PackContent { const map = value.map; if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } // Move to state C this.content = map; @@ -864,6 +865,7 @@ class PackContent { unpack(reason) { if (this.content) return; + const logger = /** @type {Logger} */ (this.logger); // Move from state B to C if (this.lazy) { const { lazyName } = this; @@ -875,24 +877,24 @@ class PackContent { timeMessage = `unpack cache content ${lazyName} (${formatSize( this.getSize() )})`; - this.logger.log( + logger.log( `starting to unpack cache content ${lazyName} (${formatSize( this.getSize() )}) because ${reason}` ); - this.logger.time(timeMessage); + logger.time(timeMessage); } const value = this.lazy(); if ("then" in value) { return value.then(data => { if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } this.content = data.map; }); } if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } this.content = value.map; } @@ -955,6 +957,7 @@ class PackContent { ); return; } + const logger = /** @type {Logger} */ (this.logger); // State B2 const { lazyName } = this; /** @type {string | undefined} */ @@ -965,12 +968,12 @@ class PackContent { timeMessage = `unpack cache content ${lazyName} (${formatSize( this.getSize() )})`; - this.logger.log( + logger.log( `starting to unpack cache content ${lazyName} (${formatSize( this.getSize() )}) because it's outdated and need to be serialized` ); - this.logger.time(timeMessage); + logger.time(timeMessage); } const value = this.lazy(); this.outdated = false; @@ -979,7 +982,7 @@ class PackContent { this.lazy = write(() => value.then(data => { if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } const oldMap = data.map; /** @type {Map} */ @@ -997,7 +1000,7 @@ class PackContent { } else { // Move to state C1 if (timeMessage) { - this.logger.timeEnd(timeMessage); + logger.timeEnd(timeMessage); } const oldMap = value.map; /** @type {Map} */ diff --git a/lib/container/ContainerPlugin.js b/lib/container/ContainerPlugin.js index 9b6c471fe..953e7c392 100644 --- a/lib/container/ContainerPlugin.js +++ b/lib/container/ContainerPlugin.js @@ -76,7 +76,7 @@ class ContainerPlugin { const dep = new ContainerEntryDependency(name, exposes, shareScope); dep.loc = { name }; compilation.addEntry( - compilation.options.context, + /** @type {string} */ (compilation.options.context), dep, { name, diff --git a/lib/container/RemoteRuntimeModule.js b/lib/container/RemoteRuntimeModule.js index 7d91462c8..21370e304 100644 --- a/lib/container/RemoteRuntimeModule.js +++ b/lib/container/RemoteRuntimeModule.js @@ -12,6 +12,7 @@ const Template = require("../Template"); /** @typedef {import("../Chunk")} Chunk */ /** @typedef {import("../Chunk").ChunkId} ChunkId */ /** @typedef {import("../ChunkGraph")} ChunkGraph */ +/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */ /** @typedef {import("../Compilation")} Compilation */ /** @typedef {import("./RemoteModule")} RemoteModule */ @@ -29,7 +30,7 @@ class RemoteRuntimeModule extends RuntimeModule { const { runtimeTemplate, moduleGraph } = compilation; /** @type {Record} */ const chunkToRemotesMapping = {}; - /** @type {Record} */ + /** @type {Record} */ const idToExternalAndNameMapping = {}; for (const chunk of /** @type {Chunk} */ (this.chunk).getAllAsyncChunks()) { const modules = chunkGraph.getChunkModulesIterableBySourceType( @@ -37,19 +38,21 @@ class RemoteRuntimeModule extends RuntimeModule { "remote" ); if (!modules) continue; - /** @type {(string | number)[]} */ + /** @type {ModuleId[]} */ const remotes = (chunkToRemotesMapping[ - /** @type {ChunkId} */ (chunk.id) + /** @type {ChunkId} */ + (chunk.id) ] = []); for (const m of modules) { const module = /** @type {RemoteModule} */ (m); const name = module.internalRequest; - const id = chunkGraph.getModuleId(module); + const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module)); const shareScope = module.shareScope; const dep = module.dependencies[0]; const externalModule = moduleGraph.getModule(dep); const externalModuleId = - externalModule && chunkGraph.getModuleId(externalModule); + /** @type {ModuleId} */ + (externalModule && chunkGraph.getModuleId(externalModule)); remotes.push(id); idToExternalAndNameMapping[id] = [shareScope, name, externalModuleId]; } diff --git a/lib/container/options.js b/lib/container/options.js index 2088e3abe..cb7df0d55 100644 --- a/lib/container/options.js +++ b/lib/container/options.js @@ -5,7 +5,15 @@ "use strict"; -/** @template T @typedef {(string | Record)[] | Record} ContainerOptionsFormat */ +/** + * @template T + * @typedef {Record} Item + */ + +/** + * @template T + * @typedef {(string | Item)[] | Item} ContainerOptionsFormat + */ /** * @template T @@ -17,6 +25,9 @@ * @returns {void} */ const process = (options, normalizeSimple, normalizeOptions, fn) => { + /** + * @param {(string | Item)[]} items items + */ const array = items => { for (const item of items) { if (typeof item === "string") { @@ -28,6 +39,9 @@ const process = (options, normalizeSimple, normalizeOptions, fn) => { } } }; + /** + * @param {Item} obj an object + */ const object = obj => { for (const [key, value] of Object.entries(obj)) { if (typeof value === "string" || Array.isArray(value)) { diff --git a/lib/dependencies/AMDDefineDependency.js b/lib/dependencies/AMDDefineDependency.js index 9f58ad084..4acb15252 100644 --- a/lib/dependencies/AMDDefineDependency.js +++ b/lib/dependencies/AMDDefineDependency.js @@ -111,7 +111,7 @@ class AMDDefineDependency extends NullDependency { * @param {Range | null} arrayRange array range * @param {Range | null} functionRange function range * @param {Range | null} objectRange object range - * @param {boolean | null} namedModule true, when define is called with a name + * @param {string | null} namedModule true, when define is called with a name */ constructor(range, arrayRange, functionRange, objectRange, namedModule) { super(); diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js index f8a696d17..14fbe4af2 100644 --- a/lib/dependencies/AMDDefineDependencyParserPlugin.js +++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js @@ -20,7 +20,11 @@ const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers"); /** @typedef {import("estree").CallExpression} CallExpression */ /** @typedef {import("estree").Expression} Expression */ /** @typedef {import("estree").FunctionExpression} FunctionExpression */ +/** @typedef {import("estree").Identifier} Identifier */ /** @typedef {import("estree").Literal} Literal */ +/** @typedef {import("estree").MemberExpression} MemberExpression */ +/** @typedef {import("estree").ObjectExpression} ObjectExpression */ +/** @typedef {import("estree").SimpleCallExpression} SimpleCallExpression */ /** @typedef {import("estree").SpreadElement} SpreadElement */ /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */ /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */ @@ -30,7 +34,7 @@ const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers"); /** * @param {Expression | SpreadElement} expr expression - * @returns {boolean} true if it's a bound function expression + * @returns {expr is CallExpression} true if it's a bound function expression */ const isBoundFunctionExpression = expr => { if (expr.type !== "CallExpression") return false; @@ -46,7 +50,7 @@ const isBoundFunctionExpression = expr => { /** * @param {Expression | SpreadElement} expr expression - * @returns {boolean} true when unbound function expression + * @returns {expr is FunctionExpression | ArrowFunctionExpression} true when unbound function expression */ const isUnboundFunctionExpression = expr => { if (expr.type === "FunctionExpression") return true; @@ -56,7 +60,7 @@ const isUnboundFunctionExpression = expr => { /** * @param {Expression | SpreadElement} expr expression - * @returns {boolean} true when callable + * @returns {expr is FunctionExpression | ArrowFunctionExpression | CallExpression} true when callable */ const isCallable = expr => { if (isUnboundFunctionExpression(expr)) return true; @@ -103,7 +107,9 @@ class AMDDefineDependencyParserPlugin { /** @type {string} */ (item.string) ) ) - identifiers[/** @type {number} */ (idx)] = item.string; + identifiers[/** @type {number} */ (idx)] = /** @type {string} */ ( + item.string + ); const result = this.processItem(parser, expr, item, namedModule); if (result === undefined) { this.processContext(parser, expr, item); @@ -113,8 +119,8 @@ class AMDDefineDependencyParserPlugin { } else if (param.isConstArray()) { /** @type {(string | LocalModuleDependency | AMDRequireItemDependency)[]} */ const deps = []; - /** @type {string[]} */ - for (const [idx, request] of param.array.entries()) { + const array = /** @type {string[]} */ (param.array); + for (const [idx, request] of array.entries()) { let dep; let localModule; if (request === "require") { @@ -242,9 +248,13 @@ class AMDDefineDependencyParserPlugin { * @returns {boolean | undefined} result */ processCallDefine(parser, expr) { + /** @type {TODO} */ let array; + /** @type {FunctionExpression | ArrowFunctionExpression | CallExpression | Identifier | undefined} */ let fn; + /** @type {ObjectExpression | Identifier | undefined} */ let obj; + /** @type {string | undefined} */ let namedModule; switch (expr.arguments.length) { case 1: @@ -257,12 +267,12 @@ class AMDDefineDependencyParserPlugin { } else { // define(expr) // unclear if function or object - obj = fn = expr.arguments[0]; + obj = fn = /** @type {Identifier} */ (expr.arguments[0]); } break; case 2: if (expr.arguments[0].type === "Literal") { - namedModule = expr.arguments[0].value; + namedModule = /** @type {string} */ (expr.arguments[0].value); // define("…", …) if (isCallable(expr.arguments[1])) { // define("…", f() {…}) @@ -273,7 +283,7 @@ class AMDDefineDependencyParserPlugin { } else { // define("…", expr) // unclear if function or object - obj = fn = expr.arguments[1]; + obj = fn = /** @type {Identifier} */ (expr.arguments[1]); } } else { array = expr.arguments[0]; @@ -286,13 +296,18 @@ class AMDDefineDependencyParserPlugin { } else { // define([…], expr) // unclear if function or object - obj = fn = expr.arguments[1]; + obj = fn = /** @type {Identifier} */ (expr.arguments[1]); } } break; case 3: // define("…", […], f() {…}) - namedModule = /** @type {TODO} */ (expr).arguments[0].value; + namedModule = + /** @type {string} */ + ( + /** @type {Literal} */ + (expr.arguments[0]).value + ); array = expr.arguments[1]; if (isCallable(expr.arguments[2])) { // define("…", […], f() {}) @@ -303,21 +318,30 @@ class AMDDefineDependencyParserPlugin { } else { // define("…", […], expr) // unclear if function or object - obj = fn = expr.arguments[2]; + obj = fn = /** @type {Identifier} */ (expr.arguments[2]); } break; default: return; } DynamicExports.bailout(parser.state); + /** @type {Identifier[] | null} */ let fnParams = null; let fnParamsOffset = 0; if (fn) { if (isUnboundFunctionExpression(fn)) { - fnParams = /** @type {UnboundFunctionExpression} */ (fn).params; + fnParams = + /** @type {Identifier[]} */ + (fn.params); } else if (isBoundFunctionExpression(fn)) { - fnParams = /** @type {TODO} */ (fn).callee.object.params; - fnParamsOffset = /** @type {TODO} */ (fn).arguments.length - 1; + const object = + /** @type {FunctionExpression} */ + (/** @type {MemberExpression} */ (fn.callee).object); + + fnParams = + /** @type {Identifier[]} */ + (object.params); + fnParamsOffset = fn.arguments.length - 1; if (fnParamsOffset < 0) { fnParamsOffset = 0; } @@ -378,9 +402,14 @@ class AMDDefineDependencyParserPlugin { }); } else if (fn && isBoundFunctionExpression(fn)) { inTry = parser.scope.inTry; + + const object = + /** @type {FunctionExpression} */ + (/** @type {MemberExpression} */ (fn.callee).object); + parser.inScope( - /** @type {TODO} */ - (fn).callee.object.params.filter( + /** @type {Identifier[]} */ + (object.params).filter( i => !["require", "module", "exports"].includes(i.name) ), () => { @@ -388,19 +417,20 @@ class AMDDefineDependencyParserPlugin { parser.setVariable(name, varInfo); } parser.scope.inTry = /** @type {boolean} */ (inTry); - if (fn.callee.object.body.type === "BlockStatement") { - parser.detectMode(fn.callee.object.body.body); + + if (object.body.type === "BlockStatement") { + parser.detectMode(object.body.body); const prev = parser.prevStatement; - parser.preWalkStatement(fn.callee.object.body); + parser.preWalkStatement(object.body); parser.prevStatement = prev; - parser.walkStatement(fn.callee.object.body); + parser.walkStatement(object.body); } else { - parser.walkExpression(fn.callee.object.body); + parser.walkExpression(object.body); } } ); - if (/** @type {TODO} */ (fn).arguments) { - parser.walkExpressions(/** @type {TODO} */ (fn).arguments); + if (fn.arguments) { + parser.walkExpressions(fn.arguments); } } else if (fn || obj) { parser.walkExpression(fn || obj); @@ -426,7 +456,7 @@ class AMDDefineDependencyParserPlugin { * @param {Range | null} arrayRange array range * @param {Range | null} functionRange function range * @param {Range | null} objectRange object range - * @param {boolean | null} namedModule true, when define is called with a name + * @param {string | null} namedModule true, when define is called with a name * @returns {AMDDefineDependency} AMDDefineDependency */ newDefineDependency( @@ -446,7 +476,7 @@ class AMDDefineDependencyParserPlugin { } /** - * @param {TODO[]} depsArray deps array + * @param {(string | LocalModuleDependency | AMDRequireItemDependency)[]} depsArray deps array * @param {Range} range range * @returns {AMDRequireArrayDependency} AMDRequireArrayDependency */ diff --git a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index 8335422f4..803ce398b 100644 --- a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -272,10 +272,12 @@ class AMDRequireDependenciesBlockParserPlugin { const old = parser.state.current; if (expr.arguments.length >= 1) { - param = parser.evaluateExpression(expr.arguments[0]); + param = parser.evaluateExpression( + /** @type {Expression} */ (expr.arguments[0]) + ); depBlock = this.newRequireDependenciesBlock( /** @type {DependencyLocation} */ (expr.loc), - /** @type {string} */ (this.processArrayForRequestString(param)) + this.processArrayForRequestString(param) ); dep = this.newRequireDependency( /** @type {Range} */ (expr.range), @@ -359,7 +361,7 @@ class AMDRequireDependenciesBlockParserPlugin { /** * @param {DependencyLocation} loc location - * @param {string} request request + * @param {string=} request request * @returns {AMDRequireDependenciesBlock} AMDRequireDependenciesBlock */ newRequireDependenciesBlock(loc, request) { diff --git a/lib/dependencies/ContextElementDependency.js b/lib/dependencies/ContextElementDependency.js index 071998f5b..448ef7c21 100644 --- a/lib/dependencies/ContextElementDependency.js +++ b/lib/dependencies/ContextElementDependency.js @@ -20,9 +20,9 @@ class ContextElementDependency extends ModuleDependency { /** * @param {string} request request * @param {string|undefined} userRequest user request - * @param {string} typePrefix type prefix + * @param {string | undefined} typePrefix type prefix * @param {string} category category - * @param {string[][]=} referencedExports referenced exports + * @param {(string[][] | null)=} referencedExports referenced exports * @param {string=} context context * @param {ImportAttributes=} attributes import assertions */ diff --git a/lib/dependencies/CssExportDependency.js b/lib/dependencies/CssExportDependency.js index 1d82bfc99..a7cf6dbb8 100644 --- a/lib/dependencies/CssExportDependency.js +++ b/lib/dependencies/CssExportDependency.js @@ -58,9 +58,9 @@ class CssExportDependency extends NullDependency { */ getExports(moduleGraph) { const module = /** @type {CssModule} */ (moduleGraph.getParentModule(this)); - const convention = /** @type {CssGenerator | CssExportsGenerator} */ ( - module.generator - ).convention; + const convention = + /** @type {CssGenerator | CssExportsGenerator} */ + (module.generator).convention; const names = this.getExportsConventionNames(this.name, convention); return { exports: names.map(name => ({ @@ -81,9 +81,9 @@ class CssExportDependency extends NullDependency { const module = /** @type {CssModule} */ ( chunkGraph.moduleGraph.getParentModule(this) ); - const generator = /** @type {CssGenerator | CssExportsGenerator} */ ( - module.generator - ); + const generator = + /** @type {CssGenerator | CssExportsGenerator} */ + (module.generator); const names = this.getExportsConventionNames( this.name, generator.convention diff --git a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js index 75ae3108b..17c7ff45b 100644 --- a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +++ b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js @@ -1178,6 +1178,15 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS } } + /** + * @param {Module} module the current module + * @param {string} comment comment + * @param {string | string[] | false} key key + * @param {string} name name + * @param {string | string[] | false} valueKey value key + * @param {RuntimeRequirements} runtimeRequirements runtime requirements + * @returns {HarmonyExportInitFragment} harmony export init fragment + */ getReexportFragment( module, comment, diff --git a/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/lib/dependencies/HarmonyImportDependencyParserPlugin.js index c94feb1f8..f1e1d4c4a 100644 --- a/lib/dependencies/HarmonyImportDependencyParserPlugin.js +++ b/lib/dependencies/HarmonyImportDependencyParserPlugin.js @@ -50,7 +50,7 @@ const harmonySpecifierTag = Symbol("harmony import"); /** * @param {ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | (ImportExpression & { arguments?: ObjectExpression[] })} node node with assertions - * @returns {ImportAttributes} import attributes + * @returns {ImportAttributes | undefined} import attributes */ function getAttributes(node) { if ( @@ -138,12 +138,22 @@ module.exports = class HarmonyImportDependencyParserPlugin { apply(parser) { const { exportPresenceMode } = this; + /** + * @param {string[]} members members + * @param {boolean[]} membersOptionals members Optionals + * @returns {string[]} a non optional part + */ function getNonOptionalPart(members, membersOptionals) { let i = 0; while (i < members.length && membersOptionals[i] === false) i++; return i !== members.length ? members.slice(0, i) : members; } + /** + * @param {TODO} node member expression + * @param {number} count count + * @returns {TODO} member expression + */ function getNonOptionalMemberChain(node, count) { while (count--) node = node.object; return node; @@ -221,7 +231,9 @@ module.exports = class HarmonyImportDependencyParserPlugin { ) return; const settings = rootInfo.tagInfo.data; - const members = rightPart.getMembers(); + const members = + /** @type {(() => string[])} */ + (rightPart.getMembers)(); const dep = new HarmonyEvaluatedImportSpecifierDependency( settings.source, settings.sourceOrder, @@ -280,6 +292,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { members, membersOptionals ); + /** @type {Range[]} */ const ranges = memberRanges.slice( 0, memberRanges.length - (members.length - nonOptionalMembers.length) @@ -326,6 +339,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { members, membersOptionals ); + /** @type {Range[]} */ const ranges = memberRanges.slice( 0, memberRanges.length - (members.length - nonOptionalMembers.length) diff --git a/lib/hmr/LazyCompilationPlugin.js b/lib/hmr/LazyCompilationPlugin.js index 125ec835b..0fca65f0b 100644 --- a/lib/hmr/LazyCompilationPlugin.js +++ b/lib/hmr/LazyCompilationPlugin.js @@ -39,7 +39,7 @@ const { registerNotSerializable } = require("../util/serialization"); /** * @typedef {object} BackendApi - * @property {function(Error=): void} dispose + * @property {function(function((Error | null)=) : void): void} dispose * @property {function(Module): { client: string, data: string, active: boolean }} module */ @@ -320,10 +320,10 @@ class LazyCompilationDependencyFactory extends ModuleFactory { class LazyCompilationPlugin { /** * @param {object} options options - * @param {(function(Compiler, function(Error?, BackendApi?): void): void) | function(Compiler): Promise} options.backend the backend + * @param {(function(Compiler, function(Error=, BackendApi?): void): void) | function(Compiler): Promise} options.backend the backend * @param {boolean} options.entries true, when entries are lazy compiled * @param {boolean} options.imports true, when import() modules are lazy compiled - * @param {RegExp | string | (function(Module): boolean)} options.test additional filter for lazy compiled entrypoint modules + * @param {RegExp | string | (function(Module): boolean) | undefined} options.test additional filter for lazy compiled entrypoint modules */ constructor({ backend, entries, imports, test }) { this.backend = backend; @@ -338,6 +338,7 @@ class LazyCompilationPlugin { * @returns {void} */ apply(compiler) { + /** @type {BackendApi} */ let backend; compiler.hooks.beforeCompile.tapAsync( "LazyCompilationPlugin", diff --git a/lib/hmr/lazyCompilationBackend.js b/lib/hmr/lazyCompilationBackend.js index dcc0130d1..9e21e6c6e 100644 --- a/lib/hmr/lazyCompilationBackend.js +++ b/lib/hmr/lazyCompilationBackend.js @@ -5,15 +5,22 @@ "use strict"; +/** @typedef {import("http").IncomingMessage} IncomingMessage */ +/** @typedef {import("http").RequestListener} RequestListener */ /** @typedef {import("http").ServerOptions} HttpServerOptions */ +/** @typedef {import("http").ServerResponse} ServerResponse */ /** @typedef {import("https").ServerOptions} HttpsServerOptions */ +/** @typedef {import("net").AddressInfo} AddressInfo */ +/** @typedef {import("net").Server} Server */ /** @typedef {import("../../declarations/WebpackOptions").LazyCompilationDefaultBackendOptions} LazyCompilationDefaultBackendOptions */ /** @typedef {import("../Compiler")} Compiler */ +/** @typedef {import("../Module")} Module */ +/** @typedef {import("./LazyCompilationPlugin").BackendApi} BackendApi */ /** * @callback BackendHandler * @param {Compiler} compiler compiler - * @param {function((Error | null)=, any=): void} callback callback + * @param {function(Error | null, BackendApi=): void} callback callback * @returns {void} */ @@ -36,8 +43,13 @@ module.exports = options => (compiler, callback) => { ? options.server : (() => { const http = isHttps ? require("https") : require("http"); - return http.createServer.bind(http, options.server); + return http.createServer.bind( + http, + /** @type {HttpServerOptions | HttpsServerOptions} */ + (options.server) + ); })(); + /** @type {function(Server): void} */ const listen = typeof options.listen === "function" ? options.listen @@ -50,7 +62,9 @@ module.exports = options => (compiler, callback) => { const protocol = options.protocol || (isHttps ? "https" : "http"); + /** @type {RequestListener} */ const requestListener = (req, res) => { + if (req.url === undefined) return; const keys = req.url.slice(prefix.length).split("@"); req.socket.on("close", () => { setTimeout(() => { @@ -85,7 +99,7 @@ module.exports = options => (compiler, callback) => { if (moduleActivated && compiler.watching) compiler.watching.invalidate(); }; - const server = /** @type {import("net").Server} */ (createServer()); + const server = /** @type {Server} */ (createServer()); server.on("request", requestListener); let isClosing = false; @@ -101,43 +115,53 @@ module.exports = options => (compiler, callback) => { server.on("clientError", e => { if (e.message !== "Server is disposing") logger.warn(e); }); - server.on("listening", err => { - if (err) return callback(err); - const addr = server.address(); - if (typeof addr === "string") throw new Error("addr must not be a string"); - const urlBase = - addr.address === "::" || addr.address === "0.0.0.0" - ? `${protocol}://localhost:${addr.port}` - : addr.family === "IPv6" - ? `${protocol}://[${addr.address}]:${addr.port}` - : `${protocol}://${addr.address}:${addr.port}`; - logger.log( - `Server-Sent-Events server for lazy compilation open at ${urlBase}.` - ); - callback(null, { - dispose(callback) { - isClosing = true; - // Removing the listener is a workaround for a memory leak in node.js - server.off("request", requestListener); - server.close(err => { - callback(err); - }); - for (const socket of sockets) { - socket.destroy(new Error("Server is disposing")); + + server.on( + "listening", + /** + * @param {Error} err error + * @returns {void} + */ + err => { + if (err) return callback(err); + const _addr = server.address(); + if (typeof _addr === "string") + throw new Error("addr must not be a string"); + const addr = /** @type {AddressInfo} */ (_addr); + const urlBase = + addr.address === "::" || addr.address === "0.0.0.0" + ? `${protocol}://localhost:${addr.port}` + : addr.family === "IPv6" + ? `${protocol}://[${addr.address}]:${addr.port}` + : `${protocol}://${addr.address}:${addr.port}`; + logger.log( + `Server-Sent-Events server for lazy compilation open at ${urlBase}.` + ); + callback(null, { + dispose(callback) { + isClosing = true; + // Removing the listener is a workaround for a memory leak in node.js + server.off("request", requestListener); + server.close(err => { + callback(err); + }); + for (const socket of sockets) { + socket.destroy(new Error("Server is disposing")); + } + }, + module(originalModule) { + const key = `${encodeURIComponent( + originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_") + ).replace(/%(2F|3A|24|26|2B|2C|3B|3D)/g, decodeURIComponent)}`; + const active = activeModules.get(key) > 0; + return { + client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`, + data: key, + active + }; } - }, - module(originalModule) { - const key = `${encodeURIComponent( - originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_") - ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`; - const active = activeModules.get(key) > 0; - return { - client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`, - data: key, - active - }; - } - }); - }); + }); + } + ); listen(server); }; diff --git a/lib/javascript/JavascriptParser.js b/lib/javascript/JavascriptParser.js index ed0a81df9..214e66374 100644 --- a/lib/javascript/JavascriptParser.js +++ b/lib/javascript/JavascriptParser.js @@ -204,7 +204,7 @@ const objectAndMembersToName = (object, membersReversed) => { * [ThisExpressions](https://github.com/estree/estree/blob/master/es5.md#identifier), and * [MetaProperties](https://github.com/estree/estree/blob/master/es2015.md#metaproperty) which is * specifically for handling the `new.target` meta property. - * @param {Expression | Super} expression expression + * @param {Expression | SpreadElement | Super} expression expression * @returns {string | "this" | undefined} name or variable info */ const getRootName = expression => { @@ -248,7 +248,7 @@ class JavascriptParser extends Parser { this.hooks = Object.freeze({ /** @type {HookMap>} */ evaluateTypeof: new HookMap(() => new SyncBailHook(["expression"])), - /** @type {HookMap>} */ + /** @type {HookMap>} */ evaluate: new HookMap(() => new SyncBailHook(["expression"])), /** @type {HookMap>} */ evaluateIdentifier: new HookMap(() => new SyncBailHook(["expression"])), @@ -1212,7 +1212,7 @@ class JavascriptParser extends Parser { }); /** * @param {string} exprType expression type name - * @param {function(Expression): GetInfoResult | undefined} getInfo get info + * @param {function(Expression | SpreadElement): GetInfoResult | undefined} getInfo get info * @returns {void} */ const tapEvaluateWithVariableInfo = (exprType, getInfo) => { @@ -4031,7 +4031,7 @@ class JavascriptParser extends Parser { } /** - * @param {TODO} expression expression node + * @param {Expression | SpreadElement} expression expression node * @returns {BasicEvaluatedExpression} evaluation result */ evaluateExpression(expression) { diff --git a/lib/logging/Logger.js b/lib/logging/Logger.js index 38de6191e..a19297d88 100644 --- a/lib/logging/Logger.js +++ b/lib/logging/Logger.js @@ -45,26 +45,45 @@ class WebpackLogger { this.getChildLogger = getChildLogger; } + /** + * @param {...any} args args + */ error(...args) { this[LOG_SYMBOL](LogType.error, args); } + /** + * @param {...any} args args + */ warn(...args) { this[LOG_SYMBOL](LogType.warn, args); } + /** + * @param {...any} args args + */ info(...args) { this[LOG_SYMBOL](LogType.info, args); } + /** + * @param {...any} args args + */ log(...args) { this[LOG_SYMBOL](LogType.log, args); } + /** + * @param {...any} args args + */ debug(...args) { this[LOG_SYMBOL](LogType.debug, args); } + /** + * @param {any} assertion assertion + * @param {...any} args args + */ assert(assertion, ...args) { if (!assertion) { this[LOG_SYMBOL](LogType.error, args); @@ -79,20 +98,29 @@ class WebpackLogger { this[LOG_SYMBOL](LogType.clear); } + /** + * @param {...any} args args + */ status(...args) { this[LOG_SYMBOL](LogType.status, args); } + /** + * @param {...any} args args + */ group(...args) { this[LOG_SYMBOL](LogType.group, args); } + /** + * @param {...any} args args + */ groupCollapsed(...args) { this[LOG_SYMBOL](LogType.groupCollapsed, args); } - groupEnd(...args) { - this[LOG_SYMBOL](LogType.groupEnd, args); + groupEnd() { + this[LOG_SYMBOL](LogType.groupEnd); } /** diff --git a/lib/logging/createConsoleLogger.js b/lib/logging/createConsoleLogger.js index dd76d5ebf..068e80572 100644 --- a/lib/logging/createConsoleLogger.js +++ b/lib/logging/createConsoleLogger.js @@ -12,7 +12,7 @@ const { LogType } = require("./Logger"); /** @typedef {import("./Logger").LogTypeEnum} LogTypeEnum */ /** @typedef {function(string): boolean} FilterFunction */ -/** @typedef {function(string, LogTypeEnum, any[]): void} LoggingFunction */ +/** @typedef {function(string, LogTypeEnum, any[]=): void} LoggingFunction */ /** * @typedef {object} LoggerConsole @@ -95,7 +95,7 @@ module.exports = ({ level = "info", debug = false, console }) => { /** * @param {string} name name of the logger * @param {LogTypeEnum} type type of the log entry - * @param {any[]} args arguments of the log entry + * @param {any[]=} args arguments of the log entry * @returns {void} */ const logger = (name, type, args) => { @@ -165,8 +165,11 @@ module.exports = ({ level = "info", debug = false, console }) => { break; case LogType.time: { if (!debug && loglevel > LogLevel.log) return; - const ms = args[1] * 1000 + args[2] / 1000000; - const msg = `[${name}] ${args[0]}: ${ms} ms`; + const [label, start, end] = + /** @type {[string, number, number]} */ + (args); + const ms = start * 1000 + end / 1000000; + const msg = `[${name}] ${label}: ${ms} ms`; if (typeof console.logTime === "function") { console.logTime(msg); } else { @@ -193,12 +196,12 @@ module.exports = ({ level = "info", debug = false, console }) => { case LogType.status: if (!debug && loglevel > LogLevel.info) return; if (typeof console.status === "function") { - if (args.length === 0) { + if (!args || args.length === 0) { console.status(); } else { console.status(...labeledArgs()); } - } else if (args.length !== 0) { + } else if (args && args.length !== 0) { console.info(...labeledArgs()); } break; diff --git a/lib/optimize/ModuleConcatenationPlugin.js b/lib/optimize/ModuleConcatenationPlugin.js index 3b10f4ba5..49c145c6e 100644 --- a/lib/optimize/ModuleConcatenationPlugin.js +++ b/lib/optimize/ModuleConcatenationPlugin.js @@ -48,14 +48,6 @@ const ConcatenatedModule = require("./ConcatenatedModule"); const formatBailoutReason = msg => `ModuleConcatenation bailout: ${msg}`; class ModuleConcatenationPlugin { - /** - * @param {TODO} options options - */ - constructor(options) { - if (typeof options !== "object") options = {}; - this.options = options; - } - /** * Apply the plugin * @param {Compiler} compiler the compiler instance diff --git a/lib/schemes/DataUriPlugin.js b/lib/schemes/DataUriPlugin.js index 659fee93d..f5db88dc4 100644 --- a/lib/schemes/DataUriPlugin.js +++ b/lib/schemes/DataUriPlugin.js @@ -15,7 +15,7 @@ const URIRegEx = /^data:([^;,]+)?((?:;[^;,]+)*?)(?:;(base64))?,(.*)$/i; /** * @param {string} uri data URI - * @returns {Buffer|null} decoded data + * @returns {Buffer | null} decoded data */ const decodeDataURI = uri => { const match = URIRegEx.exec(uri); diff --git a/lib/util/TupleSet.js b/lib/util/TupleSet.js index eae29083f..803ae194e 100644 --- a/lib/util/TupleSet.js +++ b/lib/util/TupleSet.js @@ -9,7 +9,11 @@ * @template {any[]} T */ class TupleSet { + /** + * @param {Iterable=} init init + */ constructor(init) { + /** @type {Map} */ this._map = new Map(); this.size = 0; if (init) { @@ -101,10 +105,17 @@ class TupleSet { * @returns {Iterator} iterator */ [Symbol.iterator]() { + /** @type {TODO[]} */ const iteratorStack = []; + /** @type {T[]} */ const tuple = []; + /** @type {Iterator | undefined} */ let currentSetIterator; + /** + * @param {TODO} it iterator + * @returns {boolean} result + */ const next = it => { const result = it.next(); if (result.done) { diff --git a/lib/util/deprecation.js b/lib/util/deprecation.js index e821393c1..35d694adc 100644 --- a/lib/util/deprecation.js +++ b/lib/util/deprecation.js @@ -15,7 +15,10 @@ const deprecationCache = new Map(); * @property {true} _fakeHook it's a fake hook */ -/** @template T @typedef {T & FakeHookMarker} FakeHook */ +/** + * @template T + * @typedef {T & FakeHookMarker} FakeHook + */ /** * @param {string} message deprecation message @@ -84,8 +87,11 @@ module.exports.arrayToSetDeprecation = (set, name) => { set[method] = function () { d(); const array = Array.from(this); - // eslint-disable-next-line prefer-rest-params - return Array.prototype[method].apply(array, arguments); + return Array.prototype[/** @type {keyof COPY_METHODS} */ (method)].apply( + array, + // eslint-disable-next-line prefer-rest-params + arguments + ); }; } const dPush = createDeprecation( @@ -191,12 +197,11 @@ module.exports.createArrayToSetDeprecationSet = name => { }; /** - * @template T * @param {object} obj object * @param {string} name property name * @param {string} code deprecation code * @param {string} note additional note - * @returns {object} frozen object with deprecation when modifying + * @returns {Proxy} frozen object with deprecation when modifying */ module.exports.soonFrozenObjectDeprecation = (obj, name, code, note = "") => { const message = `${name} will be frozen in future, all modifications are deprecated.${ diff --git a/types.d.ts b/types.d.ts index 074e691fe..b3b9fecd4 100644 --- a/types.d.ts +++ b/types.d.ts @@ -452,7 +452,7 @@ declare class AutomaticPrefetchPlugin { } type AuxiliaryComment = string | LibraryCustomUmdCommentObject; declare interface BackendApi { - dispose: (arg0?: Error) => void; + dispose: (arg0: (arg0?: null | Error) => void) => void; module: (arg0: Module) => { client: string; data: string; active: boolean }; } declare class BannerPlugin { @@ -578,6 +578,7 @@ declare abstract class BasicEvaluatedExpression { | ThisExpression | UpdateExpression | YieldExpression + | SpreadElement | FunctionDeclaration | VariableDeclaration | ClassDeclaration @@ -615,7 +616,6 @@ declare abstract class BasicEvaluatedExpression { | ArrayPattern | RestElement | AssignmentPattern - | SpreadElement | Property | AssignmentProperty | ClassBody @@ -801,6 +801,7 @@ declare abstract class BasicEvaluatedExpression { | ThisExpression | UpdateExpression | YieldExpression + | SpreadElement | FunctionDeclaration | VariableDeclaration | ClassDeclaration @@ -838,7 +839,6 @@ declare abstract class BasicEvaluatedExpression { | ArrayPattern | RestElement | AssignmentPattern - | SpreadElement | Property | AssignmentProperty | ClassBody @@ -1334,7 +1334,11 @@ declare abstract class ChunkGroup { hasBlock(block: AsyncDependenciesBlock): boolean; get blocksIterable(): Iterable; addBlock(block: AsyncDependenciesBlock): boolean; - addOrigin(module: Module, loc: DependencyLocation, request: string): void; + addOrigin( + module: null | Module, + loc: DependencyLocation, + request: string + ): void; getFiles(): string[]; remove(): void; sortItems(): void; @@ -2118,7 +2122,7 @@ declare class Compilation { executeModule( module: Module, options: ExecuteModuleOptions, - callback: (err?: null | WebpackError, result?: ExecuteModuleResult) => void + callback: (err: null | WebpackError, result?: ExecuteModuleResult) => void ): void; checkConstraints(): void; factorizeModule: { @@ -2281,7 +2285,7 @@ declare class Compiler { invalid: SyncHook<[null | string, number]>; watchClose: SyncHook<[]>; shutdown: AsyncSeriesHook<[]>; - infrastructureLog: SyncBailHook<[string, string, any[]], true>; + infrastructureLog: SyncBailHook<[string, string, undefined | any[]], true>; environment: SyncHook<[]>; afterEnvironment: SyncHook<[]>; afterPlugins: SyncHook<[Compiler]>; @@ -2313,7 +2317,11 @@ declare class Compiler { >; fsStartTime?: number; resolverFactory: ResolverFactory; - infrastructureLogger?: (arg0: string, arg1: LogTypeEnum, arg2: any[]) => void; + infrastructureLogger?: ( + arg0: string, + arg1: LogTypeEnum, + arg2?: any[] + ) => void; platform: Readonly; options: WebpackOptionsNormalized; context: string; @@ -2773,9 +2781,7 @@ declare interface ConsumesConfig { declare interface ConsumesObject { [index: string]: string | ConsumesConfig; } -type ContainerOptionsFormat = - | Record - | (string | Record)[]; +type ContainerOptionsFormat = Item | (string | Item)[]; declare class ContainerPlugin { constructor(options: ContainerPluginOptions); @@ -2839,8 +2845,12 @@ declare interface ContainerReferencePluginOptions { */ shareScope?: string; } +declare interface ContextAlternativeRequest { + context: string; + request: string; +} declare abstract class ContextElementDependency extends ModuleDependency { - referencedExports?: string[][]; + referencedExports?: null | string[][]; } declare class ContextExclusionPlugin { constructor(negativeMatcher: RegExp); @@ -2876,12 +2886,12 @@ declare abstract class ContextModuleFactory extends ModuleFactory { contextModuleFiles: SyncWaterfallHook<[string[]]>; alternatives: FakeHook< Pick< - AsyncSeriesWaterfallHook<[any[]]>, + AsyncSeriesWaterfallHook<[ContextAlternativeRequest[]]>, "name" | "tap" | "tapAsync" | "tapPromise" > >; alternativeRequests: AsyncSeriesWaterfallHook< - [any[], ContextModuleOptions] + [ContextAlternativeRequest[], ContextModuleOptions] >; }>; resolverFactory: ResolverFactory; @@ -2889,7 +2899,7 @@ declare abstract class ContextModuleFactory extends ModuleFactory { fs: InputFileSystem, options: ContextModuleOptions, callback: ( - err?: null | Error, + err: null | Error, dependencies?: ContextElementDependency[] ) => any ): void; @@ -5509,6 +5519,9 @@ declare interface IntermediateFileSystemExtras { ) => void; } type InternalCell = T | typeof TOMBSTONE | typeof UNDEFINED_MARKER; +declare interface Item { + [index: string]: string | string[] | T; +} declare abstract class ItemCacheFacade { get(callback: CallbackCacheCacheFacade): void; getPromise(): Promise; @@ -5590,7 +5603,39 @@ declare class JavascriptParser extends Parser { > >; evaluate: HookMap< - SyncBailHook<[Expression], undefined | null | BasicEvaluatedExpression> + SyncBailHook< + [ + | UnaryExpression + | ArrayExpression + | ArrowFunctionExpression + | AssignmentExpression + | AwaitExpression + | BinaryExpression + | SimpleCallExpression + | NewExpression + | ChainExpression + | ClassExpression + | ConditionalExpression + | FunctionExpression + | Identifier + | ImportExpression + | SimpleLiteral + | RegExpLiteral + | BigIntLiteral + | LogicalExpression + | MemberExpression + | MetaProperty + | ObjectExpression + | SequenceExpression + | TaggedTemplateExpression + | TemplateLiteral + | ThisExpression + | UpdateExpression + | YieldExpression + | SpreadElement + ], + undefined | null | BasicEvaluatedExpression + > >; evaluateIdentifier: HookMap< SyncBailHook< @@ -6426,7 +6471,37 @@ declare class JavascriptParser extends Parser { enterArrayPattern(pattern: ArrayPattern, onIdent?: any): void; enterRestElement(pattern: RestElement, onIdent?: any): void; enterAssignmentPattern(pattern: AssignmentPattern, onIdent?: any): void; - evaluateExpression(expression?: any): BasicEvaluatedExpression; + evaluateExpression( + expression: + | UnaryExpression + | ArrayExpression + | ArrowFunctionExpression + | AssignmentExpression + | AwaitExpression + | BinaryExpression + | SimpleCallExpression + | NewExpression + | ChainExpression + | ClassExpression + | ConditionalExpression + | FunctionExpression + | Identifier + | ImportExpression + | SimpleLiteral + | RegExpLiteral + | BigIntLiteral + | LogicalExpression + | MemberExpression + | MetaProperty + | ObjectExpression + | SequenceExpression + | TaggedTemplateExpression + | TemplateLiteral + | ThisExpression + | UpdateExpression + | YieldExpression + | SpreadElement + ): BasicEvaluatedExpression; parseString(expression: Expression): string; parseCalculatedString(expression: Expression): any; evaluate(source: string): BasicEvaluatedExpression; @@ -8178,8 +8253,7 @@ declare class Module extends DependenciesBlock { used: any; } declare class ModuleConcatenationPlugin { - constructor(options?: any); - options: any; + constructor(); /** * Apply the plugin @@ -8948,10 +9022,15 @@ declare interface NormalModuleCompilationHooks { beforeParse: SyncHook<[NormalModule]>; beforeSnapshot: SyncHook<[NormalModule]>; readResourceForScheme: HookMap< - AsyncSeriesBailHook<[string, NormalModule], null | string | Buffer> + FakeHook< + AsyncSeriesBailHook<[string, NormalModule], null | string | Buffer> + > >; readResource: HookMap< - AsyncSeriesBailHook<[LoaderContextNormalModule], string | Buffer> + AsyncSeriesBailHook< + [LoaderContextNormalModule], + null | string | Buffer + > >; needBuild: AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>; } @@ -9743,7 +9822,7 @@ declare abstract class OptionsApply { process(options?: any, compiler?: any): void; } declare interface OriginRecord { - module: Module; + module: null | Module; loc: DependencyLocation; request: string; } @@ -14667,7 +14746,7 @@ declare abstract class WebpackLogger { status(...args: any[]): void; group(...args: any[]): void; groupCollapsed(...args: any[]): void; - groupEnd(...args: any[]): void; + groupEnd(): void; profile(label?: string): void; profileEnd(label?: string): void; time(label: string): void;