fix: types and test (#19558)
Github Actions / lint (push) Has been cancelled Details
Github Actions / validate-legacy-node (push) Has been cancelled Details
Github Actions / benchmark (1/4) (push) Has been cancelled Details
Github Actions / benchmark (2/4) (push) Has been cancelled Details
Github Actions / benchmark (3/4) (push) Has been cancelled Details
Github Actions / benchmark (4/4) (push) Has been cancelled Details
Github Actions / basic (push) Has been cancelled Details
Github Actions / unit (push) Has been cancelled Details
Github Actions / integration (10.x, macos-latest, a) (push) Has been cancelled Details
Github Actions / integration (10.x, macos-latest, b) (push) Has been cancelled Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Has been cancelled Details
Github Actions / integration (10.x, windows-latest, a) (push) Has been cancelled Details
Github Actions / integration (10.x, windows-latest, b) (push) Has been cancelled Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (20.x, macos-latest, a) (push) Has been cancelled Details
Github Actions / integration (20.x, macos-latest, b) (push) Has been cancelled Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Has been cancelled Details
Github Actions / integration (20.x, windows-latest, a) (push) Has been cancelled Details
Github Actions / integration (20.x, windows-latest, b) (push) Has been cancelled Details
Github Actions / integration (22.x, macos-latest, a) (push) Has been cancelled Details
Github Actions / integration (22.x, macos-latest, b) (push) Has been cancelled Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Has been cancelled Details
Github Actions / integration (22.x, windows-latest, a) (push) Has been cancelled Details
Github Actions / integration (22.x, windows-latest, b) (push) Has been cancelled Details
Github Actions / integration (24.x, macos-latest, a) (push) Has been cancelled Details
Github Actions / integration (24.x, macos-latest, b) (push) Has been cancelled Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Has been cancelled Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Has been cancelled Details
Github Actions / integration (24.x, windows-latest, a) (push) Has been cancelled Details
Github Actions / integration (24.x, windows-latest, b) (push) Has been cancelled Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Has been cancelled Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Has been cancelled Details
Update examples / examples (push) Has been cancelled Details

This commit is contained in:
Alexander Akait 2025-05-23 16:39:55 +03:00 committed by GitHub
parent c9e25e5d06
commit af1c86da6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 369 additions and 155 deletions

26
declarations.d.ts vendored
View File

@ -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<string, string[]>;
}
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<T> =
| { [index: string]: RecursiveArrayOrRecord<T> }
| Array<RecursiveArrayOrRecord<T>>

View File

@ -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<Module>} NotCodeGeneratedModules */
/** @typedef {Record<string, TODO>} 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) {

View File

@ -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<string, KnownRecords[]> & Record<string, EXPECTED_ANY>} 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<string, TODO>} */
/** @type {Records} */
this.records = {};
/** @type {Set<string | RegExp>} */
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 = {}));
}

View File

@ -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
);

View File

@ -18,9 +18,9 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {string | undefined} Supports */
/** @typedef {string | undefined} Media */
/** @typedef {[CssLayer, Supports, Media]} InheritanceItem */
/** @typedef {Array<InheritanceItem>} 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 {
/**

View File

@ -66,6 +66,13 @@ const {
* @property {SyncBailHook<[CallExpression, string[]], void>} hotAcceptWithoutCallback
*/
/** @typedef {number} HotIndex */
/** @typedef {Record<string, string>} FullHashChunkModuleHashes */
/** @typedef {Record<string, string>} ChunkModuleHashes */
/** @typedef {Record<ChunkId, string>} ChunkHashes */
/** @typedef {Record<ChunkId, string>} ChunkRuntime */
/** @typedef {Record<ChunkId, ModuleId[]>} ChunkModuleIds */
/** @typedef {{ updatedChunkIds: Set<ChunkId>, removedChunkIds: Set<ChunkId>, removedModules: Set<Module>, filename: string, assetInfo: AssetInfo }} HotUpdateMainContentByRuntimeItem */
/** @typedef {Map<string, HotUpdateMainContentByRuntimeItem>} HotUpdateMainContentByRuntime */
@ -344,10 +351,11 @@ class HotModuleReplacementPlugin {
);
// #endregion
/** @type {HotIndex} */
let hotIndex = 0;
/** @type {Record<string, string>} */
/** @type {FullHashChunkModuleHashes} */
const fullHashChunkModuleHashes = {};
/** @type {Record<string, string>} */
/** @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<Module, Chunk>} */
@ -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<number|string, Module>} */
/** @type {Map<number | string, Module>} */
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,

View File

@ -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;
}
}
}

View File

@ -22,7 +22,6 @@ const identifierUtils = require("./util/identifier");
/**
* @typedef {object} RecordsModules
* @property {Record<string, number>=} byIdentifier
* @property {Record<string, number>=} bySource
* @property {number[]=} usedIds
*/

View File

@ -42,7 +42,7 @@ const UnsupportedDependency = require("./UnsupportedDependency");
const PLUGIN_NAME = "AMDPlugin";
/** @typedef {Record<string, TODO>} AmdOptions */
/** @typedef {Exclude<Amd, false>} 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__",

View File

@ -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)
)
);
}

View File

@ -121,7 +121,7 @@ class ExportMode {
/**
* @param {ModuleGraph} moduleGraph module graph
* @param {HarmonyExportImportedSpecifierDependency[]} dependencies dependencies
* @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} 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<HarmonyExportImportedSpecifierDependency>} dependencies dependencies
* @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} 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<string>} activeExports other named exports in the module
* @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency> | Iterable<HarmonyExportImportedSpecifierDependency> | null} otherStarExports other star exports in the module before this import
* @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency> | 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<HarmonyExportImportedSpecifierDependency>} */
.../** @type {ReadonlyArray<HarmonyExportImportedSpecifierDependency>} */
(this.otherStarExports),
this
]

View File

@ -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
);

View File

@ -120,7 +120,7 @@ const LEGACY_ASSERT_ATTRIBUTES = Symbol("assert");
const importAssertions = Parser =>
class extends Parser {
/**
* @this {TODO}
* @this {InstanceType<AcornParser>}
* @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<SyncBailHook<[Declaration], boolean | void>>} */
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
varDeclaration: new HookMap(() => new SyncBailHook(["declaration"])),
/** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
varDeclarationLet: new HookMap(() => new SyncBailHook(["declaration"])),
/** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
varDeclarationConst: new HookMap(() => new SyncBailHook(["declaration"])),
/** @type {HookMap<SyncBailHook<[Declaration], boolean | void>>} */
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
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<SyncBailHook<[Identifier], boolean | void>>} 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<SyncBailHook<T, R>>} 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<T>} args args for the hook
* @returns {R | undefined} result of hook
@ -3998,7 +4001,7 @@ class JavascriptParser extends Parser {
* @template R
* @param {HookMap<SyncBailHook<T, R>>} 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<T>} 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" &&

View File

@ -49,6 +49,8 @@ const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => module => {
const isNotAEntryModule = (chunkGraph, chunk) => module =>
!chunkGraph.isEntryModuleInChunk(module, chunk);
/** @typedef {{ id?: NonNullable<Chunk["id"]>, hash?: NonNullable<Chunk["hash"]>, modules: Module[], size: number }} SplitData */
/** @type {WeakSet<Chunk>} */
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<Chunk["id"]>, hash?: NonNullable<Chunk["hash"]>, modules: Module[], size: number }} SplitData */
/** @type {SplitData[]} */
let newSplits;
/** @type {Set<Chunk>} */

View File

@ -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);
});
}
});

View File

@ -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();
});
});

View File

@ -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();
});
});

View File

@ -0,0 +1,3 @@
define([], function () {
return 42;
});

80
types.d.ts vendored
View File

@ -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<string | number, string>;
contentHash: Record<string | number, Record<string, string>>;
name: Record<string | number, string>;
}
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<string | number, (string | number)[]>;
hash: Record<string | number, string>;
@ -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<string, any>;
records: Records;
managedPaths: Set<string | RegExp>;
unmanagedPaths: Set<string | RegExp>;
immutablePaths: Set<string | RegExp>;
@ -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<SyncBailHook<[Declaration], boolean | void>>;
varDeclarationLet: HookMap<SyncBailHook<[Declaration], boolean | void>>;
varDeclarationConst: HookMap<SyncBailHook<[Declaration], boolean | void>>;
varDeclarationVar: HookMap<SyncBailHook<[Declaration], boolean | void>>;
varDeclaration: HookMap<SyncBailHook<[Identifier], boolean | void>>;
varDeclarationLet: HookMap<SyncBailHook<[Identifier], boolean | void>>;
varDeclarationConst: HookMap<SyncBailHook<[Identifier], boolean | void>>;
varDeclarationVar: HookMap<SyncBailHook<[Identifier], boolean | void>>;
pattern: HookMap<SyncBailHook<[Identifier], boolean | void>>;
canRename: HookMap<SyncBailHook<[Expression], boolean | void>>;
rename: HookMap<SyncBailHook<[Expression], boolean | void>>;
@ -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<T>
): undefined | R;
@ -7076,7 +7100,7 @@ declare class JavascriptParser extends Parser {
callHooksForInfoWithFallback<T, R>(
hookMap: HookMap<SyncBailHook<T, R>>,
info: ExportedVariableInfo,
fallback: undefined | ((name: string) => any),
fallback: undefined | ((name: string) => undefined | R),
defined: undefined | ((result?: string) => any),
...args: AsArray<T>
): 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<string, KnownRecords[]> &
Record<string, any>;
declare interface RecordsChunks {
byName?: Record<string, number>;
bySource?: Record<string, number>;
usedIds?: number[];
}
declare interface RecordsModules {
byIdentifier?: Record<string, number>;
usedIds?: number[];
}
type RecursiveArrayOrRecord<T> =
| { [index: string]: RecursiveArrayOrRecord<T> }
@ -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<K, V> {
map: Map<K, InternalCell<V>>;
stack: Map<K, InternalCell<V>>[];