diff --git a/declarations.d.ts b/declarations.d.ts index 025ebc7b34f..d261284c4df 100644 --- a/declarations.d.ts +++ b/declarations.d.ts @@ -408,25 +408,6 @@ declare module "webpack-sources" { } } -declare module "browserslist" { - function browserslist(query: string): string[] | undefined; - namespace browserslist { - export function loadConfig( - options: - | { - config: string; - env?: string; - } - | { - path: string; - env?: string; - } - ): string | undefined; - export function findConfig(path: string): Record; - } - export = browserslist; -} - declare module "json-parse-even-better-errors" { function parseJson( text: string, @@ -436,13 +417,6 @@ declare module "json-parse-even-better-errors" { export = parseJson; } -// TODO remove that when @types/estree is updated -interface ImportAttributeNode { - type: "ImportAttribute"; - key: import("estree").Identifier | import("estree").Literal; - value: import("estree").Literal; -} - type RecursiveArrayOrRecord = | { [index: string]: RecursiveArrayOrRecord } | Array> diff --git a/lib/Compilation.js b/lib/Compilation.js index dfc3c71c972..05f56d59e12 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -102,6 +102,7 @@ const { isSourceEqual } = require("./util/source"); /** @typedef {import("./Compiler").MemCache} MemCache */ /** @typedef {import("./Compiler").WeakReferences} WeakReferences */ /** @typedef {import("./Compiler").ModuleMemCachesItem} ModuleMemCachesItem */ +/** @typedef {import("./Compiler").Records} Records */ /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ /** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */ @@ -391,8 +392,6 @@ const { isSourceEqual } = require("./util/source"); /** @typedef {Set} NotCodeGeneratedModules */ -/** @typedef {Record} Records */ - /** @type {AssetInfo} */ const EMPTY_ASSET_INFO = Object.freeze({}); @@ -4089,7 +4088,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o /** * @param {Module} module module relationship for removal - * @param {DependenciesBlockLike} block //TODO: good description + * @param {DependenciesBlockLike} block dependencies block * @returns {void} */ removeReasonsOfDependencyBlock(module, block) { diff --git a/lib/Compiler.js b/lib/Compiler.js index b09e240d687..8211a867bae 100644 --- a/lib/Compiler.js +++ b/lib/Compiler.js @@ -42,10 +42,19 @@ const { isSourceEqual } = require("./util/source"); /** @typedef {import("./Chunk")} Chunk */ /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */ /** @typedef {import("./Dependency")} Dependency */ +/** @typedef {import("./HotModuleReplacementPlugin").ChunkHashes} ChunkHashes */ +/** @typedef {import("./HotModuleReplacementPlugin").ChunkModuleHashes} ChunkModuleHashes */ +/** @typedef {import("./HotModuleReplacementPlugin").ChunkModuleIds} ChunkModuleIds */ +/** @typedef {import("./HotModuleReplacementPlugin").ChunkRuntime} ChunkRuntime */ +/** @typedef {import("./HotModuleReplacementPlugin").FullHashChunkModuleHashes} FullHashChunkModuleHashes */ +/** @typedef {import("./HotModuleReplacementPlugin").HotIndex} HotIndex */ /** @typedef {import("./Module")} Module */ /** @typedef {import("./Module").BuildInfo} BuildInfo */ +/** @typedef {import("./RecordIdsPlugin").RecordsChunks} RecordsChunks */ +/** @typedef {import("./RecordIdsPlugin").RecordsModules} RecordsModules */ /** @typedef {import("./config/target").PlatformTargetProperties} PlatformTargetProperties */ /** @typedef {import("./logging/createConsoleLogger").LoggingFunction} LoggingFunction */ +/** @typedef {import("./optimize/AggressiveSplittingPlugin").SplitData} SplitData */ /** @typedef {import("./util/fs").IStats} IStats */ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ /** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */ @@ -80,6 +89,22 @@ const { isSourceEqual } = require("./util/source"); * @param {Compilation=} compilation */ +/** + * @typedef {object} KnownRecords + * @property {SplitData[]=} aggressiveSplits + * @property {RecordsChunks=} chunks + * @property {RecordsModules=} modules + * @property {string=} hash + * @property {HotIndex=} hotIndex + * @property {FullHashChunkModuleHashes=} fullHashChunkModuleHashes + * @property {ChunkModuleHashes=} chunkModuleHashes + * @property {ChunkHashes=} chunkHashes + * @property {ChunkRuntime=} chunkRuntime + * @property {ChunkModuleIds=} chunkModuleIds + */ + +/** @typedef {KnownRecords & Record & Record} Records */ + /** * @typedef {object} AssetEmittedInfo * @property {Buffer} content @@ -238,11 +263,11 @@ class Compiler { /** @type {WatchFileSystem | null} */ this.watchFileSystem = null; - /** @type {string|null} */ + /** @type {string | null} */ this.recordsInputPath = null; - /** @type {string|null} */ + /** @type {string | null} */ this.recordsOutputPath = null; - /** @type {Record} */ + /** @type {Records} */ this.records = {}; /** @type {Set} */ this.managedPaths = new Set(); @@ -1075,8 +1100,10 @@ ${other}`); }; const recordsOutputPathDirectory = dirname( - /** @type {OutputFileSystem} */ (this.outputFileSystem), - /** @type {string} */ (this.recordsOutputPath) + /** @type {OutputFileSystem} */ + (this.outputFileSystem), + /** @type {string} */ + (this.recordsOutputPath) ); if (!recordsOutputPathDirectory) { return writeFile(); @@ -1201,7 +1228,9 @@ ${other}`); this.records[relativeCompilerName] = []; } if (this.records[relativeCompilerName][compilerIndex]) { - childCompiler.records = this.records[relativeCompilerName][compilerIndex]; + childCompiler.records = + /** @type {Records} */ + (this.records[relativeCompilerName][compilerIndex]); } else { this.records[relativeCompilerName].push((childCompiler.records = {})); } diff --git a/lib/ContextReplacementPlugin.js b/lib/ContextReplacementPlugin.js index eda49603362..828b8192ed8 100644 --- a/lib/ContextReplacementPlugin.js +++ b/lib/ContextReplacementPlugin.js @@ -131,7 +131,8 @@ class ContextReplacementPlugin { result.resource = newContentResource; } else { result.resource = join( - /** @type {InputFileSystem} */ (compiler.inputFileSystem), + /** @type {InputFileSystem} */ + (compiler.inputFileSystem), result.resource, newContentResource ); @@ -159,7 +160,8 @@ class ContextReplacementPlugin { ) { // When the function changed it to an relative path result.resource = join( - /** @type {InputFileSystem} */ (compiler.inputFileSystem), + /** @type {InputFileSystem} */ + (compiler.inputFileSystem), origResource, result.resource ); diff --git a/lib/CssModule.js b/lib/CssModule.js index 1112cea9ec1..90095c505a1 100644 --- a/lib/CssModule.js +++ b/lib/CssModule.js @@ -18,9 +18,9 @@ const makeSerializable = require("./util/makeSerializable"); /** @typedef {string | undefined} Supports */ /** @typedef {string | undefined} Media */ /** @typedef {[CssLayer, Supports, Media]} InheritanceItem */ -/** @typedef {Array} Inheritance */ +/** @typedef {InheritanceItem[]} Inheritance */ -/** @typedef {NormalModuleCreateData & { cssLayer: CssLayer, supports: Supports, media: Media, inheritance: Inheritance }} CSSModuleCreateData */ +/** @typedef {NormalModuleCreateData & { cssLayer: CssLayer, supports: Supports, media: Media, inheritance?: Inheritance }} CSSModuleCreateData */ class CssModule extends NormalModule { /** diff --git a/lib/HotModuleReplacementPlugin.js b/lib/HotModuleReplacementPlugin.js index 4672e2fc9fd..8c84f3a1a3c 100644 --- a/lib/HotModuleReplacementPlugin.js +++ b/lib/HotModuleReplacementPlugin.js @@ -66,6 +66,13 @@ const { * @property {SyncBailHook<[CallExpression, string[]], void>} hotAcceptWithoutCallback */ +/** @typedef {number} HotIndex */ +/** @typedef {Record} FullHashChunkModuleHashes */ +/** @typedef {Record} ChunkModuleHashes */ +/** @typedef {Record} ChunkHashes */ +/** @typedef {Record} ChunkRuntime */ +/** @typedef {Record} ChunkModuleIds */ + /** @typedef {{ updatedChunkIds: Set, removedChunkIds: Set, removedModules: Set, filename: string, assetInfo: AssetInfo }} HotUpdateMainContentByRuntimeItem */ /** @typedef {Map} HotUpdateMainContentByRuntime */ @@ -344,10 +351,11 @@ class HotModuleReplacementPlugin { ); // #endregion + /** @type {HotIndex} */ let hotIndex = 0; - /** @type {Record} */ + /** @type {FullHashChunkModuleHashes} */ const fullHashChunkModuleHashes = {}; - /** @type {Record} */ + /** @type {ChunkModuleHashes} */ const chunkModuleHashes = {}; compilation.hooks.record.tap(PLUGIN_NAME, (compilation, records) => { @@ -361,19 +369,20 @@ class HotModuleReplacementPlugin { records.chunkRuntime = {}; for (const chunk of compilation.chunks) { const chunkId = /** @type {ChunkId} */ (chunk.id); - records.chunkHashes[chunkId] = chunk.hash; + records.chunkHashes[chunkId] = /** @type {string} */ (chunk.hash); records.chunkRuntime[chunkId] = getRuntimeKey(chunk.runtime); } records.chunkModuleIds = {}; for (const chunk of compilation.chunks) { - records.chunkModuleIds[/** @type {ChunkId} */ (chunk.id)] = - Array.from( - chunkGraph.getOrderedChunkModulesIterable( - chunk, - compareModulesById(chunkGraph) - ), - m => chunkGraph.getModuleId(m) - ); + const chunkId = /** @type {ChunkId} */ (chunk.id); + + records.chunkModuleIds[chunkId] = Array.from( + chunkGraph.getOrderedChunkModulesIterable( + chunk, + compareModulesById(chunkGraph) + ), + m => /** @type {ModuleId} */ (chunkGraph.getModuleId(m)) + ); } }); /** @type {TupleSet} */ @@ -418,10 +427,14 @@ class HotModuleReplacementPlugin { const hash = getModuleHash(module); if ( fullHashModulesInThisChunk.has( - /** @type {RuntimeModule} */ (module) + /** @type {RuntimeModule} */ + (module) ) ) { - if (records.fullHashChunkModuleHashes[key] !== hash) { + if ( + /** @type {FullHashChunkModuleHashes} */ + (records.fullHashChunkModuleHashes)[key] !== hash + ) { updatedModules.add(module, chunk); } fullHashChunkModuleHashes[key] = hash; @@ -504,8 +517,11 @@ class HotModuleReplacementPlugin { /** @type {HotUpdateMainContentByRuntime} */ const hotUpdateMainContentByRuntime = new Map(); let allOldRuntime; - for (const key of Object.keys(records.chunkRuntime)) { - const runtime = keyToRuntime(records.chunkRuntime[key]); + const chunkRuntime = + /** @type {ChunkRuntime} */ + (records.chunkRuntime); + for (const key of Object.keys(chunkRuntime)) { + const runtime = keyToRuntime(chunkRuntime[key]); allOldRuntime = mergeRuntimeOwned(allOldRuntime, runtime); } forEachRuntime(allOldRuntime, runtime => { @@ -532,7 +548,7 @@ class HotModuleReplacementPlugin { if (hotUpdateMainContentByRuntime.size === 0) return; // Create a list of all active modules to verify which modules are removed completely - /** @type {Map} */ + /** @type {Map} */ const allModules = new Map(); for (const module of compilation.modules) { const id = @@ -546,7 +562,10 @@ class HotModuleReplacementPlugin { const completelyRemovedModules = new Set(); for (const key of Object.keys(records.chunkHashes)) { - const oldRuntime = keyToRuntime(records.chunkRuntime[key]); + const oldRuntime = keyToRuntime( + /** @type {ChunkRuntime} */ + (records.chunkRuntime)[key] + ); /** @type {Module[]} */ const remainingModules = []; // Check which modules are removed @@ -706,8 +725,8 @@ class HotModuleReplacementPlugin { } const renderManifest = compilation.getRenderManifest({ chunk: hotUpdateChunk, - hash: records.hash, - fullHash: records.hash, + hash: /** @type {string} */ (records.hash), + fullHash: /** @type {string} */ (records.hash), outputOptions: compilation.outputOptions, moduleTemplates: compilation.moduleTemplates, dependencyTemplates: compilation.dependencyTemplates, diff --git a/lib/NormalModuleFactory.js b/lib/NormalModuleFactory.js index 47bedac3172..004d4630b69 100644 --- a/lib/NormalModuleFactory.js +++ b/lib/NormalModuleFactory.js @@ -635,12 +635,10 @@ class NormalModuleFactory extends ModuleFactory { settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null ) { const type = /** @type {keyof ModuleSettings} */ (r.type); - /** @type {TODO} */ - (settings)[type] = cachedCleverMerge(settings[type], r.value); + settings[type] = cachedCleverMerge(settings[type], r.value); } else { const type = /** @type {keyof ModuleSettings} */ (r.type); - /** @type {TODO} */ - (settings)[type] = r.value; + settings[type] = r.value; } } } diff --git a/lib/RecordIdsPlugin.js b/lib/RecordIdsPlugin.js index d76f1c42882..de52ea04a8c 100644 --- a/lib/RecordIdsPlugin.js +++ b/lib/RecordIdsPlugin.js @@ -22,7 +22,6 @@ const identifierUtils = require("./util/identifier"); /** * @typedef {object} RecordsModules * @property {Record=} byIdentifier - * @property {Record=} bySource * @property {number[]=} usedIds */ diff --git a/lib/dependencies/AMDPlugin.js b/lib/dependencies/AMDPlugin.js index 03137d843a5..be8ab4ee641 100644 --- a/lib/dependencies/AMDPlugin.js +++ b/lib/dependencies/AMDPlugin.js @@ -42,7 +42,7 @@ const UnsupportedDependency = require("./UnsupportedDependency"); const PLUGIN_NAME = "AMDPlugin"; -/** @typedef {Record} AmdOptions */ +/** @typedef {Exclude} AmdOptions */ class AMDPlugin { /** @@ -143,7 +143,7 @@ class AMDPlugin { /** * @param {string} optionExpr option expression * @param {string} rootName root name - * @param {() => TODO} getMembers callback + * @param {() => string[]} getMembers callback */ const tapOptionsHooks = (optionExpr, rootName, getMembers) => { parser.hooks.expression @@ -156,10 +156,14 @@ class AMDPlugin { ); parser.hooks.evaluateIdentifier .for(optionExpr) - .tap( - PLUGIN_NAME, - evaluateToIdentifier(optionExpr, rootName, getMembers, true) - ); + .tap(PLUGIN_NAME, function (expr) { + return evaluateToIdentifier( + optionExpr, + rootName, + getMembers, + true + )(expr); + }); parser.hooks.evaluateTypeof .for(optionExpr) .tap(PLUGIN_NAME, evaluateToString("object")); @@ -176,7 +180,7 @@ class AMDPlugin { ); new AMDDefineDependencyParserPlugin(parserOptions).apply(parser); - tapOptionsHooks("define.amd", "define", () => "amd"); + tapOptionsHooks("define.amd", "define", () => ["amd"]); tapOptionsHooks("require.amd", "require", () => ["amd"]); tapOptionsHooks( "__webpack_amd_options__", diff --git a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js index b65b4e7bc71..1ee651cd8c3 100644 --- a/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +++ b/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js @@ -126,7 +126,8 @@ class AMDRequireDependenciesBlockParserPlugin { } const dep = this.newRequireArrayDependency( deps, - /** @type {Range} */ (param.range) + /** @type {Range} */ + (param.range) ); dep.loc = /** @type {DependencyLocation} */ (expr.loc); dep.optional = Boolean(parser.scope.inTry); @@ -158,41 +159,37 @@ class AMDRequireDependenciesBlockParserPlugin { if (param.string === "require") { dep = new ConstDependency( RuntimeGlobals.require, - /** @type {TODO} */ - (param.string), + /** @type {Range} */ + (param.range), [RuntimeGlobals.require] ); } else if (param.string === "module") { dep = new ConstDependency( - /** @type {string} */ - ( - /** @type {BuildInfo} */ - (parser.state.module.buildInfo).moduleArgument - ), - /** @type {Range} */ (param.range), + parser.state.module.moduleArgument, + /** @type {Range} */ + (param.range), [RuntimeGlobals.module] ); } else if (param.string === "exports") { dep = new ConstDependency( - /** @type {string} */ - ( - /** @type {BuildInfo} */ - (parser.state.module.buildInfo).exportsArgument - ), - /** @type {Range} */ (param.range), + parser.state.module.exportsArgument, + /** @type {Range} */ + (param.range), [RuntimeGlobals.exports] ); } else if ( (localModule = getLocalModule( parser.state, - /** @type {string} */ (param.string) + /** @type {string} */ + (param.string) )) ) { localModule.flagUsed(); dep = new LocalModuleDependency(localModule, param.range, false); } else { dep = this.newRequireItemDependency( - /** @type {string} */ (param.string), + /** @type {string} */ + (param.string), param.range ); dep.loc = /** @type {DependencyLocation} */ (expr.loc); @@ -308,13 +305,15 @@ class AMDRequireDependenciesBlockParserPlugin { result = this.processArray( parser, expr, - /** @type {BasicEvaluatedExpression} */ (param) + /** @type {BasicEvaluatedExpression} */ + (param) ); }); parser.state.current = old; if (!result) return; parser.state.current.addBlock( - /** @type {AMDRequireDependenciesBlock} */ (depBlock) + /** @type {AMDRequireDependenciesBlock} */ + (depBlock) ); return true; } @@ -325,13 +324,15 @@ class AMDRequireDependenciesBlockParserPlugin { result = this.processArray( parser, expr, - /** @type {BasicEvaluatedExpression} */ (param) + /** @type {BasicEvaluatedExpression} */ + (param) ); }); if (!result) { const dep = new UnsupportedDependency( "unsupported", - /** @type {Range} */ (expr.range) + /** @type {Range} */ + (expr.range) ); old.addPresentationalDependency(dep); if (parser.state.module) { @@ -340,7 +341,8 @@ class AMDRequireDependenciesBlockParserPlugin { `Cannot statically analyse 'require(…, …)' in line ${ /** @type {SourceLocation} */ (expr.loc).start.line }`, - /** @type {DependencyLocation} */ (expr.loc) + /** @type {DependencyLocation} */ + (expr.loc) ) ); } diff --git a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js index aca20541628..c76c4509d41 100644 --- a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +++ b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js @@ -121,7 +121,7 @@ class ExportMode { /** * @param {ModuleGraph} moduleGraph module graph - * @param {HarmonyExportImportedSpecifierDependency[]} dependencies dependencies + * @param {ReadonlyArray} dependencies dependencies * @param {TODO=} additionalDependency additional dependency * @returns {{ names: Names, dependencyIndices: DependencyIndices }} result */ @@ -166,7 +166,7 @@ const determineExportAssignments = ( * @param {Names} options.names names * @param {DependencyIndices} options.dependencyIndices dependency indices * @param {string} name name - * @param {Iterable} dependencies dependencies + * @param {ReadonlyArray} dependencies dependencies * @returns {HarmonyExportImportedSpecifierDependency | undefined} found dependency or nothing */ const findDependencyForName = ( @@ -302,7 +302,6 @@ const getMode = (moduleGraph, dep, runtimeKey) => { } // Star reexporting - const { ignoredExports, exports, checked, hidden } = dep.getStarReexports( moduleGraph, runtime, @@ -371,7 +370,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { * @param {Ids} ids the requested export name of the imported module * @param {string | null} name the export name of for this module * @param {Set} activeExports other named exports in the module - * @param {ReadonlyArray | Iterable | null} otherStarExports other star exports in the module before this import + * @param {ReadonlyArray | null} otherStarExports other star exports in the module before this import * @param {ExportPresenceMode} exportPresenceMode mode of checking export names * @param {HarmonyStarExportsList | null} allStarExports all star exports in the module * @param {ImportAttributes=} attributes import attributes @@ -658,7 +657,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { const { names, dependencyIndices } = moduleGraph.cached( determineExportAssignments, - this.otherStarExports, + /** @type {HarmonyExportImportedSpecifierDependency[]} */ + (this.otherStarExports), this ); @@ -884,7 +884,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { this.allStarExports ? this.allStarExports.dependencies : [ - .../** @type {Iterable} */ + .../** @type {ReadonlyArray} */ (this.otherStarExports), this ] diff --git a/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/lib/dependencies/HarmonyImportDependencyParserPlugin.js index 7fc43c6b228..48df8dafe3e 100644 --- a/lib/dependencies/HarmonyImportDependencyParserPlugin.js +++ b/lib/dependencies/HarmonyImportDependencyParserPlugin.js @@ -86,12 +86,12 @@ module.exports = class HarmonyImportDependencyParserPlugin { } /** - * @param {TODO} node member expression + * @param {MemberExpression} node member expression * @param {number} count count * @returns {Expression} member expression */ function getNonOptionalMemberChain(node, count) { - while (count--) node = node.object; + while (count--) node = /** @type {MemberExpression} */ (node.object); return node; } @@ -270,7 +270,8 @@ module.exports = class HarmonyImportDependencyParserPlugin { .tap( "HarmonyImportDependencyParserPlugin", (expression, members, membersOptionals, memberRanges) => { - const { arguments: args, callee } = expression; + const { arguments: args } = expression; + const callee = /** @type {MemberExpression} */ (expression.callee); const settings = /** @type {HarmonySettings} */ ( parser.currentTagData ); diff --git a/lib/javascript/JavascriptParser.js b/lib/javascript/JavascriptParser.js index 48272aad6dd..c6d6816ced8 100644 --- a/lib/javascript/JavascriptParser.js +++ b/lib/javascript/JavascriptParser.js @@ -120,7 +120,7 @@ const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert"); const importAssertions = Parser => class extends Parser { /** - * @this {TODO} + * @this {InstanceType} * @returns {ImportAttribute[]} import attributes */ parseWithClause() { @@ -484,13 +484,13 @@ class JavascriptParser extends Parser { preDeclarator: new SyncBailHook(["declarator", "statement"]), /** @type {SyncBailHook<[VariableDeclarator, Statement], boolean | void>} */ declarator: new SyncBailHook(["declarator", "statement"]), - /** @type {HookMap>} */ + /** @type {HookMap>} */ varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])), - /** @type {HookMap>} */ + /** @type {HookMap>} */ varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])), - /** @type {HookMap>} */ + /** @type {HookMap>} */ varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])), - /** @type {HookMap>} */ + /** @type {HookMap>} */ varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])), /** @type {HookMap>} */ pattern: new HookMap(() => new SyncBailHook(["pattern"])), @@ -1373,6 +1373,7 @@ class JavascriptParser extends Parser { name => { cachedExpression = expression; cachedInfo = info; + return undefined; }, name => { const hook = this.hooks.evaluateDefinedIdentifier.get(name); @@ -1879,13 +1880,20 @@ class JavascriptParser extends Parser { scopeParams.push(classy.id); } this.inClassScope(true, scopeParams, () => { - for (const classElement of /** @type {TODO} */ (classy.body.body)) { + for (const classElement of classy.body.body) { if (!this.hooks.classBodyElement.call(classElement, classy)) { - if (classElement.computed && classElement.key) { - this.walkExpression(classElement.key); - } - if (classElement.value) { + if (classElement.type === "StaticBlock") { + const wasTopLevel = this.scope.topLevelScope; + this.scope.topLevelScope = false; + this.walkBlockStatement(classElement); + this.scope.topLevelScope = wasTopLevel; + } else { + if (classElement.computed && classElement.key) { + this.walkExpression(classElement.key); + } + if ( + classElement.value && !this.hooks.classBodyValue.call( classElement.value, classElement, @@ -1897,11 +1905,6 @@ class JavascriptParser extends Parser { this.walkExpression(classElement.value); this.scope.topLevelScope = wasTopLevel; } - } else if (classElement.type === "StaticBlock") { - const wasTopLevel = this.scope.topLevelScope; - this.scope.topLevelScope = false; - this.walkBlockStatement(classElement); - this.scope.topLevelScope = wasTopLevel; } } } @@ -2151,7 +2154,7 @@ class JavascriptParser extends Parser { } /** - * @param {BlockStatement} statement block statement + * @param {BlockStatement | StaticBlock} statement block statement */ walkBlockStatement(statement) { this.inBlockScope(() => { @@ -2824,7 +2827,7 @@ class JavascriptParser extends Parser { /** * @param {VariableDeclaration} statement variable declaration - * @param {TODO} hookMap map of hooks + * @param {HookMap>} hookMap map of hooks */ _preWalkVariableDeclaration(statement, hookMap) { for (const declarator of statement.declarations) { @@ -2832,11 +2835,11 @@ class JavascriptParser extends Parser { case "VariableDeclarator": { this.preWalkVariableDeclarator(declarator); if (!this.hooks.preDeclarator.call(declarator, statement)) { - this.enterPattern(declarator.id, (name, decl) => { + this.enterPattern(declarator.id, (name, ident) => { let hook = hookMap.get(name); - if (hook === undefined || !hook.call(decl)) { + if (hook === undefined || !hook.call(ident)) { hook = this.hooks.varDeclaration.get(name); - if (hook === undefined || !hook.call(decl)) { + if (hook === undefined || !hook.call(ident)) { this.defineVariable(name); } } @@ -3928,7 +3931,7 @@ class JavascriptParser extends Parser { * @template R * @param {HookMap>} hookMap hooks the should be called * @param {Expression | Super} expr expression info - * @param {((name: string, rootInfo: string | ScopeInfo | VariableInfo, getMembers: () => string[]) => TODO) | undefined} fallback callback when variable in not handled by hooks + * @param {((name: string, rootInfo: string | ScopeInfo | VariableInfo, getMembers: () => string[]) => R) | undefined} fallback callback when variable in not handled by hooks * @param {((result?: string) => R | undefined) | undefined} defined callback when variable is defined * @param {AsArray} args args for the hook * @returns {R | undefined} result of hook @@ -3998,7 +4001,7 @@ class JavascriptParser extends Parser { * @template R * @param {HookMap>} hookMap hooks the should be called * @param {ExportedVariableInfo} info variable info - * @param {((name: string) => TODO) | undefined} fallback callback when variable in not handled by hooks + * @param {((name: string) => R | undefined) | undefined} fallback callback when variable in not handled by hooks * @param {((result?: string) => TODO) | undefined} defined callback when variable is defined * @param {AsArray} args args for the hook * @returns {R | undefined} result of hook @@ -4365,9 +4368,11 @@ class JavascriptParser extends Parser { ); } + /** @typedef {{ range?: Range, value: string, code: boolean, conditional: false | CalculatedStringResult[] }} CalculatedStringResult */ + /** * @param {Expression} expression expression - * @returns {{ range?: Range, value: string, code: boolean, conditional: boolean | TODO }} result + * @returns {CalculatedStringResult} result */ parseCalculatedString(expression) { switch (expression.type) { @@ -4415,6 +4420,7 @@ class JavascriptParser extends Parser { case "ConditionalExpression": { const consequent = this.parseCalculatedString(expression.consequent); const alternate = this.parseCalculatedString(expression.alternate); + /** @type {CalculatedStringResult[]} */ const items = []; if (consequent.conditional) { items.push(...consequent.conditional); @@ -4566,14 +4572,20 @@ class JavascriptParser extends Parser { ) { return false; } - const items = - /** @type {TODO[]} */ - (expr.body.body); + const items = expr.body.body; return items.every(item => { + if (item.type === "StaticBlock") { + return false; + } + if ( item.computed && item.key && - !this.isPure(item.key, item.range[0]) + !this.isPure( + item.key, + /** @type {Range} */ + (item.range)[0] + ) ) { return false; } @@ -4583,16 +4595,14 @@ class JavascriptParser extends Parser { item.value && !this.isPure( item.value, - item.key ? item.key.range[1] : item.range[0] + item.key + ? /** @type {Range} */ (item.key.range)[1] + : /** @type {Range} */ (item.range)[0] ) ) { return false; } - if (item.type === "StaticBlock") { - return false; - } - if ( expr.superClass && item.type === "MethodDefinition" && diff --git a/lib/optimize/AggressiveSplittingPlugin.js b/lib/optimize/AggressiveSplittingPlugin.js index e2a85c7e7ad..0b29c1365c8 100644 --- a/lib/optimize/AggressiveSplittingPlugin.js +++ b/lib/optimize/AggressiveSplittingPlugin.js @@ -49,6 +49,8 @@ const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => module => { const isNotAEntryModule = (chunkGraph, chunk) => module => !chunkGraph.isEntryModuleInChunk(module, chunk); +/** @typedef {{ id?: NonNullable, hash?: NonNullable, modules: Module[], size: number }} SplitData */ + /** @type {WeakSet} */ const recordedChunks = new WeakSet(); @@ -92,7 +94,6 @@ class AggressiveSplittingPlugin { apply(compiler) { compiler.hooks.thisCompilation.tap(PLUGIN_NAME, compilation => { let needAdditionalSeal = false; - /** @typedef {{ id?: NonNullable, hash?: NonNullable, modules: Module[], size: number }} SplitData */ /** @type {SplitData[]} */ let newSplits; /** @type {Set} */ diff --git a/test/JavascriptParser.unittest.js b/test/JavascriptParser.unittest.js index 9cf8e5d3a14..21982807af7 100644 --- a/test/JavascriptParser.unittest.js +++ b/test/JavascriptParser.unittest.js @@ -711,16 +711,120 @@ describe("JavascriptParser", () => { }); }); - describe("optional catch binding support", () => { - describe("should accept", () => { + describe("parse calculated string", () => { + describe("should work", () => { const cases = { - "optional binding": "try {} catch {}" + 123: { + code: "123", + result: { + code: false, + conditional: false, + range: [0, 3], + value: "123" + } + }, + "'test'": { + code: "'test'", + result: { + code: false, + conditional: false, + range: [0, 6], + value: "test" + } + }, + "'test' + 'test'": { + code: "'test' + 'test'", + result: { + code: false, + conditional: false, + range: [0, 15], + value: "testtest" + } + }, + "myVar + 'test'": { + code: "myVar + 'test'", + result: { + code: true, + conditional: false, + range: undefined, + value: "" + } + }, + "'test' + myVar": { + code: "'test' + myVar", + result: { + code: true, + conditional: false, + range: [0, 6], + value: "test" + } + }, + "true ? 'one' : 'two'": { + code: "true ? 'one' : 'two'", + result: { + code: true, + conditional: [ + { + code: false, + conditional: false, + range: [7, 12], + value: "one" + }, + { + code: false, + conditional: false, + range: [15, 20], + value: "two" + } + ], + range: undefined, + value: "" + } + }, + "true ? true ? 'one' : 'two' : true ? 'three': 'four'": { + code: "true ? true ? 'one' : 'two' : true ? 'three': 'four'", + result: { + code: true, + conditional: [ + { + code: false, + conditional: false, + range: [14, 19], + value: "one" + }, + { + code: false, + conditional: false, + range: [22, 27], + value: "two" + }, + { + code: false, + conditional: false, + range: [37, 44], + value: "three" + }, + { + code: false, + conditional: false, + range: [46, 52], + value: "four" + } + ], + range: undefined, + value: "" + } + } }; for (const name of Object.keys(cases)) { const expr = cases[name]; it(name, () => { - const actual = JavascriptParser._parse(expr); + const parser = new JavascriptParser(); + const actual = JavascriptParser._parse(expr.code); expect(typeof actual).toBe("object"); + expect( + parser.parseCalculatedString(actual.body[0].expression) + ).toEqual(expr.result); }); } }); diff --git a/test/cases/amd/define-amd/index.js b/test/cases/amd/define-amd/index.js new file mode 100644 index 00000000000..13eac3d953b --- /dev/null +++ b/test/cases/amd/define-amd/index.js @@ -0,0 +1,13 @@ +if (typeof define === "function" && define.amd && require.amd) { + define("my-module", [], function () { + return 'my-module'; + }); +} + + +it("should work with `define.amd`", function(done) { + require(["my-module"], function (myModule) { + expect(myModule).toBe("my-module"); + done(); + }); +}); diff --git a/test/cases/amd/require-module-keywords/index.js b/test/cases/amd/require-module-keywords/index.js new file mode 100644 index 00000000000..8552820d742 --- /dev/null +++ b/test/cases/amd/require-module-keywords/index.js @@ -0,0 +1,10 @@ +it("should work when require module keywords", (done) => { + require(['require', 'module', 'exports'], function (webpackRequire, webpackModule, webpackExports) { + expect(require("./module")).toBe(42); + expect(webpackRequire).toBeDefined(); + expect(webpackModule).toBeDefined(); + expect(webpackExports).toBeDefined(); + + done(); + }); +}); diff --git a/test/cases/amd/require-module-keywords/module.js b/test/cases/amd/require-module-keywords/module.js new file mode 100644 index 00000000000..d83845079f6 --- /dev/null +++ b/test/cases/amd/require-module-keywords/module.js @@ -0,0 +1,3 @@ +define([], function () { + return 42; +}); diff --git a/types.d.ts b/types.d.ts index 47265a9e4dd..3188bdfe1c3 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1021,6 +1021,12 @@ declare class CachedSource extends Source { originalLazy(): Source | (() => Source); getCachedData(): any; } +declare interface CalculatedStringResult { + range?: [number, number]; + value: string; + code: boolean; + conditional: false | CalculatedStringResult[]; +} type CallExpression = SimpleCallExpression | NewExpression; declare interface CallExpressionInfo { type: "call"; @@ -1444,12 +1450,19 @@ declare interface ChunkHashContext { */ chunkGraph: ChunkGraph; } +declare interface ChunkHashes { + [index: number]: string; + [index: string]: string; +} type ChunkId = string | number; declare interface ChunkMaps { hash: Record; contentHash: Record>; name: Record; } +declare interface ChunkModuleHashes { + [index: string]: string; +} declare class ChunkModuleIdRangePlugin { constructor(options: ChunkModuleIdRangePluginOptions); options: ChunkModuleIdRangePluginOptions; @@ -1480,6 +1493,10 @@ declare interface ChunkModuleIdRangePluginOptions { */ end?: number; } +declare interface ChunkModuleIds { + [index: number]: ModuleId[]; + [index: string]: ModuleId[]; +} declare interface ChunkModuleMaps { id: Record; hash: Record; @@ -1564,6 +1581,10 @@ declare interface ChunkRenderContextJavascriptModulesPlugin { */ strictMode?: boolean; } +declare interface ChunkRuntime { + [index: number]: string; + [index: string]: string; +} declare interface ChunkSizeOptions { /** * constant overhead for a chunk @@ -2461,7 +2482,7 @@ declare class Compiler { watchFileSystem: null | WatchFileSystem; recordsInputPath: null | string; recordsOutputPath: null | string; - records: Record; + records: Records; managedPaths: Set; unmanagedPaths: Set; immutablePaths: Set; @@ -3293,7 +3314,7 @@ declare abstract class CssModule extends NormalModule { cssLayer: CssLayer; supports: Supports; media: Media; - inheritance: [CssLayer, Supports, Media][]; + inheritance?: [CssLayer, Supports, Media][]; } /** @@ -5294,6 +5315,9 @@ type FilterItemTypes = string | RegExp | ((value: string) => boolean); declare interface Flags { [index: string]: Argument; } +declare interface FullHashChunkModuleHashes { + [index: string]: string; +} declare interface GenerateContext { /** * mapping from dependencies to templates @@ -6403,10 +6427,10 @@ declare class JavascriptParser extends Parser { boolean | void >; declarator: SyncBailHook<[VariableDeclarator, Statement], boolean | void>; - varDeclaration: HookMap>; - varDeclarationLet: HookMap>; - varDeclarationConst: HookMap>; - varDeclarationVar: HookMap>; + varDeclaration: HookMap>; + varDeclarationLet: HookMap>; + varDeclarationConst: HookMap>; + varDeclarationVar: HookMap>; pattern: HookMap>; canRename: HookMap>; rename: HookMap>; @@ -6815,7 +6839,7 @@ declare class JavascriptParser extends Parser { */ walkNestedStatement(statement: Statement): void; preWalkBlockStatement(statement: BlockStatement): void; - walkBlockStatement(statement: BlockStatement): void; + walkBlockStatement(statement: BlockStatement | StaticBlock): void; walkExpressionStatement(statement: ExpressionStatement): void; preWalkIfStatement(statement: IfStatement): void; walkIfStatement(statement: IfStatement): void; @@ -7059,7 +7083,7 @@ declare class JavascriptParser extends Parser { name: string, rootInfo: string | VariableInfo | ScopeInfo, getMembers: () => string[] - ) => any), + ) => R), defined: undefined | ((result?: string) => undefined | R), ...args: AsArray ): undefined | R; @@ -7076,7 +7100,7 @@ declare class JavascriptParser extends Parser { callHooksForInfoWithFallback( hookMap: HookMap>, info: ExportedVariableInfo, - fallback: undefined | ((name: string) => any), + fallback: undefined | ((name: string) => undefined | R), defined: undefined | ((result?: string) => any), ...args: AsArray ): undefined | R; @@ -7224,12 +7248,7 @@ declare class JavascriptParser extends Parser { | Super ): BasicEvaluatedExpression; parseString(expression: Expression): string; - parseCalculatedString(expression: Expression): { - range?: [number, number]; - value: string; - code: boolean; - conditional: any; - }; + parseCalculatedString(expression: Expression): CalculatedStringResult; evaluate(source: string): BasicEvaluatedExpression; isPure( expr: @@ -7939,6 +7958,18 @@ declare interface KnownNormalizedStatsOptions { loggingDebug: ((value: string) => boolean)[]; loggingTrace: boolean; } +declare interface KnownRecords { + aggressiveSplits?: SplitData[]; + chunks?: RecordsChunks; + modules?: RecordsModules; + hash?: string; + hotIndex?: number; + fullHashChunkModuleHashes?: FullHashChunkModuleHashes; + chunkModuleHashes?: ChunkModuleHashes; + chunkHashes?: ChunkHashes; + chunkRuntime?: ChunkRuntime; + chunkModuleIds?: ChunkModuleIds; +} declare interface KnownStatsAsset { type: string; name: string; @@ -12800,8 +12831,17 @@ declare interface RealPathTypes { callback: (arg0: null | NodeJS.ErrnoException, arg1?: string) => void ): void; } -declare interface Records { - [index: string]: any; +type Records = KnownRecords & + Record & + Record; +declare interface RecordsChunks { + byName?: Record; + bySource?: Record; + usedIds?: number[]; +} +declare interface RecordsModules { + byIdentifier?: Record; + usedIds?: number[]; } type RecursiveArrayOrRecord = | { [index: string]: RecursiveArrayOrRecord } @@ -15037,6 +15077,12 @@ declare class SplitChunksPlugin { declare interface SplitChunksSizes { [index: string]: number; } +declare interface SplitData { + id?: string | number; + hash?: string; + modules: Module[]; + size: number; +} declare abstract class StackedMap { map: Map>; stack: Map>[];