feat: refactoring project

This commit is contained in:
Carlos
2024-11-23 14:56:07 -05:00
parent f0c2a50c18
commit 1c6db5818d
2351 changed files with 39323 additions and 60326 deletions

View File

@@ -51,7 +51,7 @@ class AggressiveMergingPlugin {
chunks => {
const chunkGraph = compilation.chunkGraph;
/** @type {{a: Chunk, b: Chunk, improvement: number}[]} */
let combinations = [];
const combinations = [];
for (const a of chunks) {
if (a.canBeInitial()) continue;
for (const b of chunks) {
@@ -78,9 +78,7 @@ class AggressiveMergingPlugin {
}
}
combinations.sort((a, b) => {
return b.improvement - a.improvement;
});
combinations.sort((a, b) => b.improvement - a.improvement);
const pair = combinations[0];

View File

@@ -36,11 +36,9 @@ const validate = createSchemaValidation(
* @param {Chunk} newChunk the new chunk
* @returns {(module: Module) => void} function to move module between chunks
*/
const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => {
return module => {
chunkGraph.disconnectChunkAndModule(oldChunk, module);
chunkGraph.connectChunkAndModule(newChunk, module);
};
const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => module => {
chunkGraph.disconnectChunkAndModule(oldChunk, module);
chunkGraph.connectChunkAndModule(newChunk, module);
};
/**
@@ -48,11 +46,8 @@ const moveModuleBetween = (chunkGraph, oldChunk, newChunk) => {
* @param {Chunk} chunk the chunk
* @returns {function(Module): boolean} filter for entry module
*/
const isNotAEntryModule = (chunkGraph, chunk) => {
return module => {
return !chunkGraph.isEntryModuleInChunk(module, chunk);
};
};
const isNotAEntryModule = (chunkGraph, chunk) => module =>
!chunkGraph.isEntryModuleInChunk(module, chunk);
/** @type {WeakSet<Chunk>} */
const recordedChunks = new WeakSet();
@@ -97,10 +92,12 @@ class AggressiveSplittingPlugin {
"AggressiveSplittingPlugin",
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>} */
let fromAggressiveSplittingSet;
/** @type {Map<Chunk, TODO>} */
/** @type {Map<Chunk, SplitData>} */
let chunkSplitDataMap;
compilation.hooks.optimize.tap("AggressiveSplittingPlugin", () => {
newSplits = [];
@@ -144,6 +141,10 @@ class AggressiveSplittingPlugin {
const minSize = /** @type {number} */ (this.options.minSize);
const maxSize = /** @type {number} */ (this.options.maxSize);
/**
* @param {SplitData} splitData split data
* @returns {boolean} true when applied, otherwise false
*/
const applySplit = splitData => {
// Cannot split if id is already taken
if (splitData.id !== undefined && usedIds.has(splitData.id)) {
@@ -191,11 +192,11 @@ class AggressiveSplittingPlugin {
const newChunk = compilation.addChunk();
newChunk.chunkReason = "aggressive splitted";
for (const chunk of selectedChunks) {
selectedModules.forEach(
moveModuleBetween(chunkGraph, chunk, newChunk)
);
for (const module of selectedModules) {
moveModuleBetween(chunkGraph, chunk, newChunk)(module);
}
chunk.split(newChunk);
chunk.name = null;
chunk.name = /** @type {TODO} */ (null);
}
fromAggressiveSplittingSet.add(newChunk);
chunkSplitDataMap.set(newChunk, splitData);
@@ -250,6 +251,7 @@ class AggressiveSplittingPlugin {
selectedModules.push(module);
}
if (selectedModules.length === 0) continue;
/** @type {SplitData} */
const splitData = {
modules: selectedModules
.map(m => moduleToNameMap.get(m))
@@ -271,33 +273,42 @@ class AggressiveSplittingPlugin {
records => {
// 4. save made splittings to records
const allSplits = new Set();
/** @type {Set<SplitData>} */
const invalidSplits = new Set();
// Check if some splittings are invalid
// We remove invalid splittings and try again
for (const chunk of compilation.chunks) {
const splitData = chunkSplitDataMap.get(chunk);
if (splitData !== undefined) {
if (splitData.hash && chunk.hash !== splitData.hash) {
// Split was successful, but hash doesn't equal
// We can throw away the split since it's useless now
invalidSplits.add(splitData);
}
if (
splitData !== undefined &&
splitData.hash &&
chunk.hash !== splitData.hash
) {
// Split was successful, but hash doesn't equal
// We can throw away the split since it's useless now
invalidSplits.add(splitData);
}
}
if (invalidSplits.size > 0) {
records.aggressiveSplits = records.aggressiveSplits.filter(
splitData => !invalidSplits.has(splitData)
);
records.aggressiveSplits =
/** @type {SplitData[]} */
(records.aggressiveSplits).filter(
splitData => !invalidSplits.has(splitData)
);
needAdditionalSeal = true;
} else {
// set hash and id values on all (new) splittings
for (const chunk of compilation.chunks) {
const splitData = chunkSplitDataMap.get(chunk);
if (splitData !== undefined) {
splitData.hash = chunk.hash;
splitData.id = chunk.id;
splitData.hash =
/** @type {NonNullable<Chunk["hash"]>} */
(chunk.hash);
splitData.id =
/** @type {NonNullable<Chunk["id"]>} */
(chunk.id);
allSplits.add(splitData);
// set flag for stats
recordedChunks.add(chunk);

View File

@@ -16,6 +16,7 @@ const {
const ConcatenationScope = require("../ConcatenationScope");
const { UsageState } = require("../ExportsInfo");
const Module = require("../Module");
const { JS_TYPES } = require("../ModuleSourceTypesConstants");
const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
@@ -24,10 +25,17 @@ const JavascriptParser = require("../javascript/JavascriptParser");
const { equals } = require("../util/ArrayHelpers");
const LazySet = require("../util/LazySet");
const { concatComparators } = require("../util/comparators");
const {
RESERVED_NAMES,
findNewName,
addScopeSymbols,
getAllReferences,
getPathInAst,
getUsedNamesInScopeInfo
} = require("../util/concatenate");
const createHash = require("../util/createHash");
const { makePathsRelative } = require("../util/identifier");
const makeSerializable = require("../util/makeSerializable");
const { getAllReferences, getPathInAst } = require("../util/mergeScope");
const propertyAccess = require("../util/propertyAccess");
const { propertyName } = require("../util/propertyName");
const {
@@ -58,10 +66,12 @@ const {
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
/** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
/** @typedef {import("../ModuleParseError")} ModuleParseError */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
@@ -72,6 +82,7 @@ const {
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {typeof import("../util/Hash")} HashConstructor */
/** @typedef {import("../util/concatenate").UsedNames} UsedNames */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
@@ -128,12 +139,12 @@ if (!ReferencerClass.prototype.PropertyDefinition) {
* @property {Module} module
* @property {number} index
* @property {Program | undefined} ast
* @property {Source} internalSource
* @property {ReplaceSource} source
* @property {Source | undefined} internalSource
* @property {ReplaceSource | undefined} source
* @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
* @property {ReadOnlyRuntimeRequirements} runtimeRequirements
* @property {Scope} globalScope
* @property {Scope} moduleScope
* @property {ReadOnlyRuntimeRequirements | undefined} runtimeRequirements
* @property {Scope | undefined} globalScope
* @property {Scope | undefined} moduleScope
* @property {Map<string, string>} internalNames
* @property {Map<string, string> | undefined} exportMap
* @property {Map<string, string> | undefined} rawExportMap
@@ -153,64 +164,34 @@ if (!ReferencerClass.prototype.PropertyDefinition) {
* @property {Module} module
* @property {RuntimeSpec | boolean} runtimeCondition
* @property {number} index
* @property {string} name
* @property {string | undefined} name
* @property {boolean} interopNamespaceObjectUsed
* @property {string} interopNamespaceObjectName
* @property {string | undefined} interopNamespaceObjectName
* @property {boolean} interopNamespaceObject2Used
* @property {string} interopNamespaceObject2Name
* @property {string | undefined} interopNamespaceObject2Name
* @property {boolean} interopDefaultAccessUsed
* @property {string} interopDefaultAccessName
* @property {string | undefined} interopDefaultAccessName
*/
/**
* @typedef {object} ReferenceToModuleInfo
* @property {"reference"} type
* @property {RuntimeSpec | boolean} runtimeCondition
* @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
* @property {ModuleInfo} target
*/
/** @typedef {Set<string>} UsedNames */
const RESERVED_NAMES = new Set(
[
// internal names (should always be renamed)
ConcatenationScope.DEFAULT_EXPORT,
ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
// keywords
"abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
"debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
"for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
"package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
"throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
// commonjs/amd
"module,__dirname,__filename,exports,require,define",
// js globals
"Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
"NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
// browser globals
"alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
"clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
"defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
"event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
"mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
"open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
"parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
"secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
"untaint,window",
// window events
"onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
]
.join(",")
.split(",")
);
/**
* @template T
* @param {string} property property
* @param {function(T[keyof T], T[keyof T]): 0 | 1 | -1} comparator comparator
* @returns {Comparator<T>} comparator
*/
const createComparator = (property, comparator) => (a, b) =>
comparator(a[property], b[property]);
comparator(
a[/** @type {keyof T} */ (property)],
b[/** @type {keyof T} */ (property)]
);
/**
* @param {number} a a
@@ -218,12 +199,12 @@ const createComparator = (property, comparator) => (a, b) =>
* @returns {0 | 1 | -1} result
*/
const compareNumbers = (a, b) => {
if (isNaN(a)) {
if (!isNaN(b)) {
if (Number.isNaN(a)) {
if (!Number.isNaN(b)) {
return 1;
}
} else {
if (isNaN(b)) {
if (Number.isNaN(b)) {
return -1;
}
if (a !== b) {
@@ -397,12 +378,21 @@ const getFinalBinding = (
neededNamespaceObjects.add(info);
return {
info,
rawName: /** @type {string} */ (info.namespaceObjectName),
rawName:
/** @type {NonNullable<ConcatenatedModuleInfo["namespaceObjectName"]>} */
(info.namespaceObjectName),
ids: exportName,
exportName
};
case "external":
return { info, rawName: info.name, ids: exportName, exportName };
return {
info,
rawName:
/** @type {NonNullable<ExternalModuleInfo["name"]>} */
(info.name),
ids: exportName,
exportName
};
}
}
const exportsInfo = moduleGraph.getExportsInfo(info.module);
@@ -608,30 +598,9 @@ const getFinalName = (
}
};
/**
* @param {Scope | null} s scope
* @param {UsedNames} nameSet name set
* @param {TODO} scopeSet1 scope set 1
* @param {TODO} scopeSet2 scope set 2
*/
const addScopeSymbols = (s, nameSet, scopeSet1, scopeSet2) => {
let scope = s;
while (scope) {
if (scopeSet1.has(scope)) break;
if (scopeSet2.has(scope)) break;
scopeSet1.add(scope);
for (const variable of scope.variables) {
nameSet.add(variable.name);
}
scope = scope.upper;
}
};
const TYPES = new Set(["javascript"]);
/**
* @typedef {object} ConcatenateModuleHooks
* @property {SyncBailHook<[Record<string, string>]>} exportsDefinitions
* @property {SyncBailHook<[Record<string, string>], boolean | void>} exportsDefinitions
*/
/** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
@@ -688,9 +657,9 @@ class ConcatenatedModule extends Module {
/**
* @param {object} options options
* @param {string} options.identifier the identifier of the module
* @param {Module=} options.rootModule the root module of the concatenation
* @param {Module} options.rootModule the root module of the concatenation
* @param {RuntimeSpec} options.runtime the selected runtime
* @param {Set<Module>=} options.modules all concatenated modules
* @param {Set<Module>} options.modules all concatenated modules
* @param {Compilation} options.compilation the compilation
*/
constructor({ identifier, rootModule, modules, runtime, compilation }) {
@@ -724,7 +693,7 @@ class ConcatenatedModule extends Module {
* @returns {SourceTypes} types available (do not mutate)
*/
getSourceTypes() {
return TYPES;
return JS_TYPES;
}
get modules() {
@@ -743,10 +712,9 @@ class ConcatenatedModule extends Module {
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
return (
this.rootModule.readableIdentifier(requestShortener) +
` + ${this._modules.size - 1} modules`
);
return `${this.rootModule.readableIdentifier(
requestShortener
)} + ${this._modules.size - 1} modules`;
}
/**
@@ -857,7 +825,14 @@ class ConcatenatedModule extends Module {
if (this.buildInfo.assets === undefined) {
this.buildInfo.assets = Object.create(null);
}
Object.assign(/** @type {BuildInfo} */ (this.buildInfo).assets, assets);
Object.assign(
/** @type {NonNullable<BuildInfo["assets"]>} */
(
/** @type {BuildInfo} */
(this.buildInfo).assets
),
assets
);
}
if (assetsInfo) {
if (this.buildInfo.assetsInfo === undefined) {
@@ -903,7 +878,9 @@ class ConcatenatedModule extends Module {
* @returns {Iterable<{ connection: ModuleGraphConnection, runtimeCondition: RuntimeSpec | true }>} imported modules in order
*/
const getConcatenatedImports = module => {
let connections = Array.from(moduleGraph.getOutgoingConnections(module));
const connections = Array.from(
moduleGraph.getOutgoingConnections(module)
);
if (module === rootModule) {
for (const c of moduleGraph.getOutgoingConnections(this))
connections.push(c);
@@ -1077,14 +1054,14 @@ class ConcatenatedModule extends Module {
/** @type {string} */ (rootModule.context),
associatedObjectForCache
);
let identifiers = [];
const identifiers = [];
for (const module of modules) {
identifiers.push(cachedMakePathsRelative(module.identifier()));
}
identifiers.sort();
const hash = createHash(hashFunction);
hash.update(identifiers.join(" "));
return rootModule.identifier() + "|" + hash.digest("hex");
return `${rootModule.identifier()}|${hash.digest("hex")}`;
}
/**
@@ -1121,7 +1098,7 @@ class ConcatenatedModule extends Module {
runtime: generationRuntime,
codeGenerationResults
}) {
/** @type {Set<string>} */
/** @type {RuntimeRequirements} */
const runtimeRequirements = new Set();
const runtime = intersectRuntime(generationRuntime, this._runtime);
@@ -1147,7 +1124,8 @@ class ConcatenatedModule extends Module {
moduleGraph,
chunkGraph,
runtime,
codeGenerationResults
/** @type {CodeGenerationResults} */
(codeGenerationResults)
);
}
@@ -1164,18 +1142,6 @@ class ConcatenatedModule extends Module {
* @param {string} id export id
* @returns {{ usedNames: UsedNames, alreadyCheckedScopes: Set<TODO> }} info
*/
const getUsedNamesInScopeInfo = (module, id) => {
const key = `${module}-${id}`;
let info = usedNamesInScopeInfo.get(key);
if (info === undefined) {
info = {
usedNames: new Set(),
alreadyCheckedScopes: new Set()
};
usedNamesInScopeInfo.set(key, info);
}
return info;
};
// Set of already checked scopes
const ignoredScopes = new Set();
@@ -1245,6 +1211,7 @@ class ConcatenatedModule extends Module {
if (!binding.ids) continue;
const { usedNames, alreadyCheckedScopes } =
getUsedNamesInScopeInfo(
usedNamesInScopeInfo,
binding.info.module.identifier(),
"name" in binding ? binding.name : ""
);
@@ -1277,14 +1244,17 @@ class ConcatenatedModule extends Module {
// generate names for symbols
for (const info of moduleToInfoMap.values()) {
const { usedNames: namespaceObjectUsedNames } = getUsedNamesInScopeInfo(
usedNamesInScopeInfo,
info.module.identifier(),
""
);
switch (info.type) {
case "concatenated": {
for (const variable of info.moduleScope.variables) {
const variables = /** @type {Scope} */ (info.moduleScope).variables;
for (const variable of variables) {
const name = variable.name;
const { usedNames, alreadyCheckedScopes } = getUsedNamesInScopeInfo(
usedNamesInScopeInfo,
info.module.identifier(),
name
);
@@ -1298,7 +1268,7 @@ class ConcatenatedModule extends Module {
ignoredScopes
);
}
const newName = this.findNewName(
const newName = findNewName(
name,
allUsedNames,
usedNames,
@@ -1307,13 +1277,17 @@ class ConcatenatedModule extends Module {
allUsedNames.add(newName);
info.internalNames.set(name, newName);
topLevelDeclarations.add(newName);
const source = info.source;
const source = /** @type {ReplaceSource} */ (info.source);
const allIdentifiers = new Set(
references.map(r => r.identifier).concat(variable.identifiers)
);
for (const identifier of allIdentifiers) {
const r = /** @type {Range} */ (identifier.range);
const path = getPathInAst(info.ast, identifier);
const path = getPathInAst(
/** @type {NonNullable<ConcatenatedModuleInfo["ast"]>} */
(info.ast),
identifier
);
if (path && path.length > 1) {
const maybeProperty =
path[1].type === "AssignmentPattern" &&
@@ -1342,7 +1316,7 @@ class ConcatenatedModule extends Module {
info.namespaceExportSymbol
);
} else {
namespaceObjectName = this.findNewName(
namespaceObjectName = findNewName(
"namespaceObject",
allUsedNames,
namespaceObjectUsedNames,
@@ -1357,7 +1331,7 @@ class ConcatenatedModule extends Module {
break;
}
case "external": {
const externalName = this.findNewName(
const externalName = findNewName(
"",
allUsedNames,
namespaceObjectUsedNames,
@@ -1371,7 +1345,7 @@ class ConcatenatedModule extends Module {
}
const buildMeta = /** @type {BuildMeta} */ (info.module.buildMeta);
if (buildMeta.exportsType !== "namespace") {
const externalNameInterop = this.findNewName(
const externalNameInterop = findNewName(
"namespaceObject",
allUsedNames,
namespaceObjectUsedNames,
@@ -1385,7 +1359,7 @@ class ConcatenatedModule extends Module {
buildMeta.exportsType === "default" &&
buildMeta.defaultObject !== "redirect"
) {
const externalNameInterop = this.findNewName(
const externalNameInterop = findNewName(
"namespaceObject2",
allUsedNames,
namespaceObjectUsedNames,
@@ -1396,7 +1370,7 @@ class ConcatenatedModule extends Module {
topLevelDeclarations.add(externalNameInterop);
}
if (buildMeta.exportsType === "dynamic" || !buildMeta.exportsType) {
const externalNameInterop = this.findNewName(
const externalNameInterop = findNewName(
"default",
allUsedNames,
namespaceObjectUsedNames,
@@ -1411,7 +1385,8 @@ class ConcatenatedModule extends Module {
// Find and replace references to modules
for (const info of moduleToInfoMap.values()) {
if (info.type === "concatenated") {
for (const reference of info.globalScope.through) {
const globalScope = /** @type {Scope} */ (info.globalScope);
for (const reference of globalScope.through) {
const name = reference.identifier.name;
const match = ConcatenationScope.matchModuleReference(name);
if (match) {
@@ -1434,7 +1409,7 @@ class ConcatenatedModule extends Module {
match.asiSafe
);
const r = /** @type {Range} */ (reference.identifier.range);
const source = info.source;
const source = /** @type {ReplaceSource} */ (info.source);
// range is extended by 2 chars to cover the appended "._"
source.replace(r[0], r[1] + 1, finalName);
}
@@ -1487,11 +1462,11 @@ class ConcatenatedModule extends Module {
return `/* ${
exportInfo.isReexport() ? "reexport" : "binding"
} */ ${finalName}`;
} catch (e) {
} catch (err) {
/** @type {Error} */
(e).message +=
(err).message +=
`\nwhile generating the root export '${name}' (used name: '${used}')`;
throw e;
throw err;
}
});
}
@@ -1510,7 +1485,7 @@ class ConcatenatedModule extends Module {
// define exports
if (exportsMap.size > 0) {
const { exportsDefinitions } = ConcatenatedModule.getCompilationHooks(
this.compilation
/** @type {Compilation} */ (this.compilation)
);
const definitions = [];
@@ -1529,7 +1504,7 @@ class ConcatenatedModule extends Module {
runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
if (shouldAddHarmonyFlag) {
result.add(`// ESM COMPAT FLAG\n`);
result.add("// ESM COMPAT FLAG\n");
result.add(
runtimeTemplate.defineEsModuleFlagStatement({
exportsArgument: this.exportsArgument,
@@ -1538,14 +1513,15 @@ class ConcatenatedModule extends Module {
);
}
result.add(`\n// EXPORTS\n`);
result.add("\n// EXPORTS\n");
result.add(
`${RuntimeGlobals.definePropertyGetters}(${
this.exportsArgument
}, {${definitions.join(",")}\n});\n`
);
} else {
this.buildMeta.exportsFinalName = exportsFinalName;
/** @type {BuildMeta} */
(this.buildMeta).exportsFinalName = exportsFinalName;
}
}
@@ -1627,11 +1603,9 @@ ${defineGetters}`
switch (info.type) {
case "concatenated": {
result.add(
`\n;// CONCATENATED MODULE: ${info.module.readableIdentifier(
requestShortener
)}\n`
`\n;// ${info.module.readableIdentifier(requestShortener)}\n`
);
result.add(info.source);
result.add(/** @type {ReplaceSource} */ (info.source));
if (info.chunkInitFragments) {
for (const f of info.chunkInitFragments) chunkInitFragments.push(f);
}
@@ -1747,7 +1721,7 @@ ${defineGetters}`
runtime,
concatenationScope,
codeGenerationResults,
sourceTypes: TYPES
sourceTypes: JS_TYPES
});
const source = /** @type {Source} */ (
codeGenResult.sources.get("javascript")
@@ -1760,7 +1734,8 @@ ${defineGetters}`
ast = JavascriptParser._parse(code, {
sourceType: "module"
});
} catch (err) {
} catch (_err) {
const err = /** @type {TODO} */ (_err);
if (
err.loc &&
typeof err.loc === "object" &&
@@ -1768,11 +1743,9 @@ ${defineGetters}`
) {
const lineNumber = err.loc.line;
const lines = code.split("\n");
err.message +=
"\n| " +
lines
.slice(Math.max(0, lineNumber - 3), lineNumber + 2)
.join("\n| ");
err.message += `\n| ${lines
.slice(Math.max(0, lineNumber - 3), lineNumber + 2)
.join("\n| ")}`;
}
throw err;
}
@@ -1786,7 +1759,9 @@ ${defineGetters}`
const globalScope = /** @type {Scope} */ (scopeManager.acquire(ast));
const moduleScope = globalScope.childScopes[0];
const resultSource = new ReplaceSource(source);
info.runtimeRequirements = codeGenResult.runtimeRequirements;
info.runtimeRequirements =
/** @type {ReadOnlyRuntimeRequirements} */
(codeGenResult.runtimeRequirements);
info.ast = ast;
info.internalSource = source;
info.source = resultSource;
@@ -1868,66 +1843,19 @@ ${defineGetters}`
/** @type {ModuleInfo} */ (item).module,
/** @type {ModuleInfo} */ (item)
);
return item;
} else {
/** @type {ReferenceToModuleInfo} */
const ref = {
type: "reference",
runtimeCondition: info.runtimeCondition,
target: item
};
return ref;
return /** @type {ModuleInfo} */ (item);
}
/** @type {ReferenceToModuleInfo} */
const ref = {
type: "reference",
runtimeCondition: info.runtimeCondition,
target: item
};
return ref;
});
return [list, map];
}
/**
* @param {string} oldName old name
* @param {UsedNames} usedNamed1 used named 1
* @param {UsedNames} usedNamed2 used named 2
* @param {string} extraInfo extra info
* @returns {string} found new name
*/
findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
let name = oldName;
if (name === ConcatenationScope.DEFAULT_EXPORT) {
name = "";
}
if (name === ConcatenationScope.NAMESPACE_OBJECT_EXPORT) {
name = "namespaceObject";
}
// Remove uncool stuff
extraInfo = extraInfo.replace(
/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g,
""
);
const splittedInfo = extraInfo.split("/");
while (splittedInfo.length) {
name = splittedInfo.pop() + (name ? "_" + name : "");
const nameIdent = Template.toIdentifier(name);
if (
!usedNamed1.has(nameIdent) &&
(!usedNamed2 || !usedNamed2.has(nameIdent))
)
return nameIdent;
}
let i = 0;
let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
while (
usedNamed1.has(nameWithNumber) ||
(usedNamed2 && usedNamed2.has(nameWithNumber))
) {
i++;
nameWithNumber = Template.toIdentifier(`${name}_${i}`);
}
return nameWithNumber;
}
/**
* @param {Hash} hash the hash used to track dependencies
* @param {UpdateHashContext} context context
@@ -1960,11 +1888,11 @@ ${defineGetters}`
*/
static deserialize(context) {
const obj = new ConcatenatedModule({
identifier: undefined,
rootModule: undefined,
modules: undefined,
identifier: /** @type {EXPECTED_ANY} */ (undefined),
rootModule: /** @type {EXPECTED_ANY} */ (undefined),
modules: /** @type {EXPECTED_ANY} */ (undefined),
runtime: undefined,
compilation: undefined
compilation: /** @type {EXPECTED_ANY} */ (undefined)
});
obj.deserialize(context);
return obj;

View File

@@ -56,7 +56,7 @@ class EnsureChunkConditionsPlugin {
// We reached the entrypoint: fail
if (chunkGroup.isInitial()) {
throw new Error(
"Cannot fulfil chunk condition of " + module.identifier()
`Cannot fulfil chunk condition of ${module.identifier()}`
);
}
// Try placing in all parents

View File

@@ -5,6 +5,8 @@
"use strict";
const { compareIds } = require("../util/comparators");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Chunk").ChunkId} ChunkId */
/** @typedef {import("../Compiler")} Compiler */
@@ -39,10 +41,10 @@ class FlagIncludedChunksPlugin {
const modulesCount = compilation.modules.size;
// precalculate the modulo values for each bit
const modulo = 1 / Math.pow(1 / modulesCount, 1 / 31);
const modulo = 1 / (1 / modulesCount) ** (1 / 31);
const modulos = Array.from(
{ length: 31 },
(x, i) => Math.pow(modulo, i) | 0
(x, i) => (modulo ** i) | 0
);
// iterate all modules to generate bit values
@@ -74,7 +76,7 @@ class FlagIncludedChunksPlugin {
const chunkAModulesCount =
chunkGraph.getNumberOfChunkModules(chunkA);
if (chunkAModulesCount === 0) continue;
let bestModule = undefined;
let bestModule;
for (const module of chunkGraph.getChunkModulesIterable(chunkA)) {
if (
bestModule === undefined ||
@@ -112,8 +114,12 @@ class FlagIncludedChunksPlugin {
for (const m of chunkGraph.getChunkModulesIterable(chunkA)) {
if (!chunkGraph.isModuleInChunk(m, chunkB)) continue loopB;
}
/** @type {ChunkId[]} */
(chunkB.ids).push(/** @type {ChunkId} */ (chunkA.id));
// https://github.com/webpack/webpack/issues/18837
/** @type {ChunkId[]} */
(chunkB.ids).sort(compareIds);
}
}
}

View File

@@ -45,7 +45,7 @@ function getState(parserState) {
* @param {ParserState} parserState parser state
* @returns {void}
*/
exports.bailout = parserState => {
module.exports.bailout = parserState => {
parserStateMap.set(parserState, false);
};
@@ -53,7 +53,7 @@ exports.bailout = parserState => {
* @param {ParserState} parserState parser state
* @returns {void}
*/
exports.enable = parserState => {
module.exports.enable = parserState => {
const state = parserStateMap.get(parserState);
if (state === false) {
return;
@@ -69,9 +69,9 @@ exports.enable = parserState => {
* @param {ParserState} parserState parser state
* @returns {boolean} true, when enabled
*/
exports.isEnabled = parserState => {
module.exports.isEnabled = parserState => {
const state = parserStateMap.get(parserState);
return !!state;
return Boolean(state);
};
/**
@@ -80,7 +80,7 @@ exports.isEnabled = parserState => {
* @param {string | TopLevelSymbol | true} usage usage data
* @returns {void}
*/
exports.addUsage = (state, symbol, usage) => {
module.exports.addUsage = (state, symbol, usage) => {
const innerGraphState = getState(state);
if (innerGraphState) {
@@ -102,13 +102,13 @@ exports.addUsage = (state, symbol, usage) => {
* @param {string | TopLevelSymbol | true} usage usage data
* @returns {void}
*/
exports.addVariableUsage = (parser, name, usage) => {
module.exports.addVariableUsage = (parser, name, usage) => {
const symbol =
/** @type {TopLevelSymbol} */ (
parser.getTagData(name, topLevelSymbolTag)
) || exports.tagTopLevelSymbol(parser, name);
) || module.exports.tagTopLevelSymbol(parser, name);
if (symbol) {
exports.addUsage(parser.state, symbol, usage);
module.exports.addUsage(parser.state, symbol, usage);
}
};
@@ -116,7 +116,7 @@ exports.addVariableUsage = (parser, name, usage) => {
* @param {ParserState} state parser state
* @returns {void}
*/
exports.inferDependencyUsage = state => {
module.exports.inferDependencyUsage = state => {
const innerGraphState = getState(state);
if (!innerGraphState) {
@@ -212,7 +212,7 @@ exports.inferDependencyUsage = state => {
* @param {ParserState} state parser state
* @param {UsageCallback} onUsageCallback on usage callback
*/
exports.onUsage = (state, onUsageCallback) => {
module.exports.onUsage = (state, onUsageCallback) => {
const innerGraphState = getState(state);
if (innerGraphState) {
@@ -238,7 +238,7 @@ exports.onUsage = (state, onUsageCallback) => {
* @param {ParserState} state parser state
* @param {TopLevelSymbol | undefined} symbol the symbol
*/
exports.setTopLevelSymbol = (state, symbol) => {
module.exports.setTopLevelSymbol = (state, symbol) => {
const innerGraphState = getState(state);
if (innerGraphState) {
@@ -250,7 +250,7 @@ exports.setTopLevelSymbol = (state, symbol) => {
* @param {ParserState} state parser state
* @returns {TopLevelSymbol|void} usage data
*/
exports.getTopLevelSymbol = state => {
module.exports.getTopLevelSymbol = state => {
const innerGraphState = getState(state);
if (innerGraphState) {
@@ -263,7 +263,7 @@ exports.getTopLevelSymbol = state => {
* @param {string} name name of variable
* @returns {TopLevelSymbol | undefined} symbol
*/
exports.tagTopLevelSymbol = (parser, name) => {
module.exports.tagTopLevelSymbol = (parser, name) => {
const innerGraphState = getState(parser.state);
if (!innerGraphState) return;
@@ -288,7 +288,7 @@ exports.tagTopLevelSymbol = (parser, name) => {
* @param {RuntimeSpec} runtime runtime
* @returns {boolean} false, when unused. Otherwise true
*/
exports.isDependencyUsedByExports = (
module.exports.isDependencyUsedByExports = (
dependency,
usedByExports,
moduleGraph,
@@ -316,7 +316,7 @@ exports.isDependencyUsedByExports = (
* @param {ModuleGraph} moduleGraph moduleGraph
* @returns {null | false | function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
*/
exports.getDependencyUsedByExportsCondition = (
module.exports.getDependencyUsedByExportsCondition = (
dependency,
usedByExports,
moduleGraph
@@ -347,5 +347,5 @@ class TopLevelSymbol {
}
}
exports.TopLevelSymbol = TopLevelSymbol;
exports.topLevelSymbolTag = topLevelSymbolTag;
module.exports.TopLevelSymbol = TopLevelSymbol;
module.exports.topLevelSymbolTag = topLevelSymbolTag;

View File

@@ -12,8 +12,9 @@ const {
const PureExpressionDependency = require("../dependencies/PureExpressionDependency");
const InnerGraph = require("./InnerGraph");
/** @typedef {import("estree").ClassDeclaration} ClassDeclarationNode */
/** @typedef {import("estree").ClassExpression} ClassExpressionNode */
/** @typedef {import("estree").ClassDeclaration} ClassDeclaration */
/** @typedef {import("estree").ClassExpression} ClassExpression */
/** @typedef {import("estree").Expression} Expression */
/** @typedef {import("estree").Node} Node */
/** @typedef {import("estree").VariableDeclarator} VariableDeclaratorNode */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
@@ -53,6 +54,9 @@ class InnerGraphPlugin {
* @returns {void}
*/
const handler = (parser, parserOptions) => {
/**
* @param {Expression} sup sup
*/
const onUsageSuper = sup => {
InnerGraph.onUsage(parser.state, usedByExports => {
switch (usedByExports) {
@@ -60,8 +64,11 @@ class InnerGraphPlugin {
case true:
return;
default: {
const dep = new PureExpressionDependency(sup.range);
dep.loc = sup.loc;
const dep = new PureExpressionDependency(
/** @type {Range} */
(sup.range)
);
dep.loc = /** @type {DependencyLocation} */ (sup.loc);
dep.usedByExports = usedByExports;
parser.state.module.addDependency(dep);
break;
@@ -96,7 +103,7 @@ class InnerGraphPlugin {
/** @type {WeakMap<Node, Node>} */
const statementPurePart = new WeakMap();
/** @type {WeakMap<ClassExpressionNode | ClassDeclarationNode, TopLevelSymbol>} */
/** @type {WeakMap<ClassExpression | ClassDeclaration, TopLevelSymbol>} */
const classWithTopLevelSymbol = new WeakMap();
/** @type {WeakMap<VariableDeclaratorNode, TopLevelSymbol>} */
@@ -109,13 +116,16 @@ class InnerGraphPlugin {
parser.hooks.preStatement.tap(PLUGIN_NAME, statement => {
if (!InnerGraph.isEnabled(parser.state)) return;
if (parser.scope.topLevelScope === true) {
if (statement.type === "FunctionDeclaration") {
const name = statement.id ? statement.id.name : "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
statementWithTopLevelSymbol.set(statement, fn);
return true;
}
if (
parser.scope.topLevelScope === true &&
statement.type === "FunctionDeclaration"
) {
const name = statement.id ? statement.id.name : "*default*";
const fn =
/** @type {TopLevelSymbol} */
(InnerGraph.tagTopLevelSymbol(parser, name));
statementWithTopLevelSymbol.set(statement, fn);
return true;
}
});
@@ -131,22 +141,40 @@ class InnerGraphPlugin {
)
) {
const name = statement.id ? statement.id.name : "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
const fn = /** @type {TopLevelSymbol} */ (
InnerGraph.tagTopLevelSymbol(parser, name)
);
classWithTopLevelSymbol.set(statement, fn);
return true;
}
if (statement.type === "ExportDefaultDeclaration") {
const name = "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
const fn =
/** @type {TopLevelSymbol} */
(InnerGraph.tagTopLevelSymbol(parser, name));
const decl = statement.declaration;
if (
(decl.type === "ClassExpression" ||
decl.type === "ClassDeclaration") &&
parser.isPure(decl, /** @type {Range} */ (decl.range)[0])
parser.isPure(
/** @type {ClassExpression | ClassDeclaration} */
(decl),
/** @type {Range} */
(decl.range)[0]
)
) {
classWithTopLevelSymbol.set(decl, fn);
classWithTopLevelSymbol.set(
/** @type {ClassExpression | ClassDeclaration} */
(decl),
fn
);
} else if (
parser.isPure(decl, /** @type {Range} */ (statement.range)[0])
parser.isPure(
/** @type {Expression} */
(decl),
/** @type {Range} */
(statement.range)[0]
)
) {
statementWithTopLevelSymbol.set(statement, fn);
if (
@@ -154,7 +182,11 @@ class InnerGraphPlugin {
!decl.type.endsWith("Declaration") &&
decl.type !== "Literal"
) {
statementPurePart.set(statement, decl);
statementPurePart.set(
statement,
/** @type {Expression} */
(decl)
);
}
}
}
@@ -176,7 +208,9 @@ class InnerGraphPlugin {
/** @type {Range} */ (decl.id.range)[1]
)
) {
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
const fn =
/** @type {TopLevelSymbol} */
(InnerGraph.tagTopLevelSymbol(parser, name));
classWithTopLevelSymbol.set(decl.init, fn);
} else if (
parser.isPure(
@@ -184,7 +218,9 @@ class InnerGraphPlugin {
/** @type {Range} */ (decl.id.range)[1]
)
) {
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
const fn =
/** @type {TopLevelSymbol} */
(InnerGraph.tagTopLevelSymbol(parser, name));
declWithTopLevelSymbol.set(decl, fn);
if (
!decl.init.type.endsWith("FunctionExpression") &&
@@ -332,7 +368,10 @@ class InnerGraphPlugin {
if (fn) {
InnerGraph.setTopLevelSymbol(parser.state, fn);
if (pureDeclarators.has(decl)) {
if (decl.init.type === "ClassExpression") {
if (
/** @type {ClassExpression} */
(decl.init).type === "ClassExpression"
) {
if (decl.init.superClass) {
onUsageSuper(decl.init.superClass);
}
@@ -344,7 +383,10 @@ class InnerGraphPlugin {
return;
default: {
const dep = new PureExpressionDependency(
/** @type {Range} */ (decl.init.range)
/** @type {Range} */ (
/** @type {ClassExpression} */
(decl.init).range
)
);
dep.loc = /** @type {DependencyLocation} */ (decl.loc);
dep.usedByExports = usedByExports;

View File

@@ -57,7 +57,7 @@ class LimitChunkCountPlugin {
*/
constructor(options) {
validate(options);
this.options = options;
this.options = /** @type {LimitChunkCountPluginOptions} */ (options);
}
/**
@@ -74,9 +74,7 @@ class LimitChunkCountPlugin {
},
chunks => {
const chunkGraph = compilation.chunkGraph;
const maxChunks =
/** @type {LimitChunkCountPluginOptions} */
(options).maxChunks;
const maxChunks = options.maxChunks;
if (!maxChunks) return;
if (maxChunks < 1) return;
if (compilation.chunks.size <= maxChunks) return;
@@ -119,7 +117,7 @@ class LimitChunkCountPlugin {
/** @type {Map<Chunk, Set<ChunkCombination>>} */
const combinationsByChunk = new Map();
orderedChunks.forEach((b, bIdx) => {
for (const [bIdx, b] of orderedChunks.entries()) {
// create combination pairs with size and integrated size
for (let aIdx = 0; aIdx < bIdx; aIdx++) {
const a = orderedChunks[aIdx];
@@ -149,8 +147,7 @@ class LimitChunkCountPlugin {
addToSetMap(combinationsByChunk, a, c);
addToSetMap(combinationsByChunk, b, c);
}
return combinations;
});
}
// list of modified chunks during this run
// combinations affected by this change are skipped to allow

View File

@@ -149,6 +149,7 @@ class MangleExportsPlugin {
constructor(deterministic) {
this._deterministic = deterministic;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance

View File

@@ -5,7 +5,7 @@
"use strict";
const { STAGE_BASIC } = require("../OptimizationStages");
const { STAGE_ADVANCED } = require("../OptimizationStages");
const { runtimeEqual } = require("../util/runtime");
/** @typedef {import("../Compiler")} Compiler */
@@ -22,7 +22,7 @@ class MergeDuplicateChunksPlugin {
compilation.hooks.optimizeChunks.tap(
{
name: "MergeDuplicateChunksPlugin",
stage: STAGE_BASIC
stage: STAGE_ADVANCED
},
chunks => {
const { chunkGraph, moduleGraph } = compilation;

View File

@@ -23,7 +23,7 @@ class MinMaxSizeWarning extends WebpackError {
: `Cache group ${keys[0]}`;
}
super(
`SplitChunksPlugin\n` +
"SplitChunksPlugin\n" +
`${keysMessage}\n` +
`Configured minSize (${SizeFormatHelpers.formatSize(minSize)}) is ` +
`bigger than maxSize (${SizeFormatHelpers.formatSize(maxSize)}).\n` +

View File

@@ -45,19 +45,9 @@ const ConcatenatedModule = require("./ConcatenatedModule");
* @param {string} msg message
* @returns {string} formatted message
*/
const formatBailoutReason = msg => {
return "ModuleConcatenation bailout: " + msg;
};
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
@@ -130,15 +120,14 @@ class ModuleConcatenationPlugin {
requestShortener
)}${reasonWithPrefix}`
);
} else {
return formatBailoutReason(
`Cannot concat with ${module.readableIdentifier(
requestShortener
)} because of ${problem.readableIdentifier(
requestShortener
)}${reasonWithPrefix}`
);
}
return formatBailoutReason(
`Cannot concat with ${module.readableIdentifier(
requestShortener
)} because of ${problem.readableIdentifier(
requestShortener
)}${reasonWithPrefix}`
);
};
compilation.hooks.optimizeChunkModules.tapAsync(
@@ -170,13 +159,13 @@ class ModuleConcatenationPlugin {
// Must not be an async module
if (moduleGraph.isAsync(module)) {
setBailoutReason(module, `Module is async`);
setBailoutReason(module, "Module is async");
continue;
}
// Must be in strict mode
if (!(/** @type {BuildInfo} */ (module.buildInfo).strict)) {
setBailoutReason(module, `Module is not in strict mode`);
setBailoutReason(module, "Module is not in strict mode");
continue;
}
@@ -189,11 +178,10 @@ class ModuleConcatenationPlugin {
// Exports must be known (and not dynamic)
const exportsInfo = moduleGraph.getExportsInfo(module);
const relevantExports = exportsInfo.getRelevantExports(undefined);
const unknownReexports = relevantExports.filter(exportInfo => {
return (
const unknownReexports = relevantExports.filter(
exportInfo =>
exportInfo.isReexport() && !exportInfo.getTarget(moduleGraph)
);
});
);
if (unknownReexports.length > 0) {
setBailoutReason(
module,
@@ -210,9 +198,7 @@ class ModuleConcatenationPlugin {
// Root modules must have a static list of exports
const unknownProvidedExports = relevantExports.filter(
exportInfo => {
return exportInfo.provided !== true;
}
exportInfo => exportInfo.provided !== true
);
if (unknownProvidedExports.length > 0) {
setBailoutReason(
@@ -245,12 +231,11 @@ class ModuleConcatenationPlugin {
// modules with lower depth are more likely suited as roots
// this improves performance, because modules already selected as inner are skipped
logger.time("sort relevant modules");
relevantModules.sort((a, b) => {
return (
relevantModules.sort(
(a, b) =>
/** @type {number} */ (moduleGraph.getDepth(a)) -
/** @type {number} */ (moduleGraph.getDepth(b))
);
});
);
logger.timeEnd("sort relevant modules");
/** @type {Statistics} */
@@ -279,7 +264,7 @@ class ModuleConcatenationPlugin {
// TODO reconsider that when it's only used in a different runtime
if (usedAsInner.has(currentRoot)) continue;
let chunkRuntime = undefined;
let chunkRuntime;
for (const r of chunkGraph.getModuleRuntimes(currentRoot)) {
chunkRuntime = mergeRuntimeOwned(chunkRuntime, r);
}
@@ -376,11 +361,9 @@ class ModuleConcatenationPlugin {
// to get the biggest groups possible. Used modules are marked with usedModules
// TODO: Allow to reuse existing configuration while trying to add dependencies.
// This would improve performance. O(n^2) -> O(n)
logger.time(`sort concat configurations`);
concatConfigurations.sort((a, b) => {
return b.modules.size - a.modules.size;
});
logger.timeEnd(`sort concat configurations`);
logger.time("sort concat configurations");
concatConfigurations.sort((a, b) => b.modules.size - a.modules.size);
logger.timeEnd("sort concat configurations");
const usedModules = new Set();
logger.time("create concatenated modules");
@@ -399,7 +382,7 @@ class ModuleConcatenationPlugin {
// Create a new ConcatenatedModule
ConcatenatedModule.getCompilationHooks(compilation);
let newModule = ConcatenatedModule.create(
const newModule = ConcatenatedModule.create(
rootModule,
modules,
concatConfiguration.runtime,
@@ -412,8 +395,10 @@ class ModuleConcatenationPlugin {
newModule.build(
compiler.options,
compilation,
null,
null,
/** @type {TODO} */
(null),
/** @type {TODO} */
(null),
err => {
if (err) {
if (!err.module) {
@@ -448,15 +433,12 @@ class ModuleConcatenationPlugin {
moduleGraph.copyOutgoingModuleConnections(
m,
newModule,
c => {
return (
c.originModule === m &&
!(
c.dependency instanceof HarmonyImportDependency &&
modules.has(c.module)
)
);
}
c =>
c.originModule === m &&
!(
c.dependency instanceof HarmonyImportDependency &&
modules.has(c.module)
)
);
// remove module from chunk
for (const chunk of chunkGraph.getModuleChunksIterable(
@@ -639,11 +621,11 @@ class ModuleConcatenationPlugin {
incomingConnections.get(null) || incomingConnections.get(undefined);
if (incomingConnectionsFromNonModules) {
const activeNonModulesConnections =
incomingConnectionsFromNonModules.filter(connection => {
incomingConnectionsFromNonModules.filter(connection =>
// We are not interested in inactive connections
// or connections without dependency
return connection.isActive(runtime);
});
connection.isActive(runtime)
);
if (activeNonModulesConnections.length > 0) {
/**
* @param {RequestShortener} requestShortener request shortener
@@ -676,7 +658,7 @@ class ModuleConcatenationPlugin {
if (chunkGraph.getNumberOfModuleChunks(originModule) === 0) continue;
// We don't care for connections from other runtimes
let originRuntime = undefined;
let originRuntime;
for (const r of chunkGraph.getModuleRuntimes(originModule)) {
originRuntime = mergeRuntimeOwned(originRuntime, r);
}
@@ -743,19 +725,20 @@ class ModuleConcatenationPlugin {
*/
const problem = requestShortener => {
const names = Array.from(nonHarmonyConnections)
.map(([originModule, connections]) => {
return `${originModule.readableIdentifier(
requestShortener
)} (referenced with ${Array.from(
new Set(
connections
.map(c => c.dependency && c.dependency.type)
.filter(Boolean)
.map(
([originModule, connections]) =>
`${originModule.readableIdentifier(
requestShortener
)} (referenced with ${Array.from(
new Set(
connections
.map(c => c.dependency && c.dependency.type)
.filter(Boolean)
)
)
)
.sort()
.join(", ")})`;
})
.sort()
.join(", ")})`
)
.sort();
return `Module ${module.readableIdentifier(
requestShortener
@@ -779,19 +762,15 @@ class ModuleConcatenationPlugin {
/** @type {false | RuntimeSpec} */
let currentRuntimeCondition = false;
for (const connection of connections) {
const runtimeCondition = filterRuntime(runtime, runtime => {
return connection.isTargetActive(runtime);
});
const runtimeCondition = filterRuntime(runtime, runtime =>
connection.isTargetActive(runtime)
);
if (runtimeCondition === false) continue;
if (runtimeCondition === true) continue outer;
if (currentRuntimeCondition !== false) {
currentRuntimeCondition = mergeRuntime(
currentRuntimeCondition,
runtimeCondition
);
} else {
currentRuntimeCondition = runtimeCondition;
}
currentRuntimeCondition =
currentRuntimeCondition !== false
? mergeRuntime(currentRuntimeCondition, runtimeCondition)
: runtimeCondition;
}
if (currentRuntimeCondition !== false) {
otherRuntimeConnections.push({
@@ -805,8 +784,8 @@ class ModuleConcatenationPlugin {
* @param {RequestShortener} requestShortener request shortener
* @returns {string} problem description
*/
const problem = requestShortener => {
return `Module ${module.readableIdentifier(
const problem = requestShortener =>
`Module ${module.readableIdentifier(
requestShortener
)} is runtime-dependent referenced by these modules: ${Array.from(
otherRuntimeConnections,
@@ -819,7 +798,6 @@ class ModuleConcatenationPlugin {
/** @type {RuntimeSpec} */ (runtimeCondition)
)})`
).join(", ")}`;
};
statistics.incorrectRuntimeCondition++;
failureCache.set(module, problem); // cache failures for performance
return problem;

View File

@@ -61,9 +61,7 @@ const mapAndDeduplicateBuffers = (input, fn) => {
* @param {string} str String to quote
* @returns {string} Escaped string
*/
const quoteMeta = str => {
return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
};
const quoteMeta = str => str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
const cachedSourceMap = new WeakMap();
@@ -103,7 +101,7 @@ const toCachedSource = source => {
/**
* @typedef {object} CompilationHooks
* @property {SyncBailHook<[Buffer[], string], string>} updateHash
* @property {SyncBailHook<[Buffer[], string], string | void>} updateHash
*/
/** @type {WeakMap<Compilation, CompilationHooks>} */
@@ -215,7 +213,7 @@ class RealContentHashPlugin {
[asset.referencedHashes, asset.ownHashes] =
await cacheAnalyse.providePromise(name, etag, () => {
const referencedHashes = new Set();
let ownHashes = new Set();
const ownHashes = new Set();
const inContent = content.match(hashRegExp);
if (inContent) {
for (const hash of inContent) {
@@ -256,7 +254,7 @@ ${referencingAssets
})
.join("\n")}`);
compilation.errors.push(err);
return undefined;
return;
}
const hashes = new Set();
for (const { referencedHashes, ownHashes } of assets) {
@@ -369,7 +367,7 @@ ${referencingAssets
(asset.referencedHashes)
).some(hash => hashToNewHash.get(hash) !== hash)
) {
const identifier = asset.name + "|without-own";
const identifier = `${asset.name}|without-own`;
const etag = getEtag(asset);
asset.newSourceWithoutOwn = await cacheGenerate.providePromise(
identifier,
@@ -410,11 +408,10 @@ ${referencingAssets
return asset.newSourceWithoutOwn
? asset.newSourceWithoutOwn.buffer()
: asset.source.buffer();
} else {
return asset.newSource
? asset.newSource.buffer()
: asset.source.buffer();
}
return asset.newSource
? asset.newSource.buffer()
: asset.source.buffer();
});
let newHash = hooks.updateHash.call(assetsContent, oldHash);
if (!newHash) {

View File

@@ -41,7 +41,7 @@ function* getModulesFromMask(mask, ordinalModules) {
// Consider the last 32 bits, since that's what Math.clz32 can handle
let last32 = Number(BigInt.asUintN(32, mask));
while (last32 > 0) {
let last = Math.clz32(last32);
const last = Math.clz32(last32);
// The number of trailing zeros is the number trimmed off the input mask + 31 - the number of leading zeros
// The 32 is baked into the initial value of offset
const moduleIndex = offset - last;
@@ -148,7 +148,7 @@ class RemoveParentModulesPlugin {
availableModulesMask = parentMask;
changed = true;
} else {
let newMask = availableModulesMask & parentMask;
const newMask = availableModulesMask & parentMask;
if (newMask !== availableModulesMask) {
changed = true;
availableModulesMask = newMask;
@@ -177,7 +177,7 @@ class RemoveParentModulesPlugin {
chunk.groupsIterable,
chunkGroup => availableModulesMap.get(chunkGroup)
);
if (availableModulesSets.some(s => s === undefined)) continue; // No info about this chunk group
if (availableModulesSets.includes(undefined)) continue; // No info about this chunk group
const availableModulesMask = intersectMasks(availableModulesSets);
const toRemoveMask = chunkMask & availableModulesMask;

View File

@@ -23,6 +23,8 @@ const formatLocation = require("../formatLocation");
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("../NormalModuleFactory").ModuleSettings} ModuleSettings */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
@@ -57,7 +59,7 @@ const globToRegexp = (glob, cache) => {
}
const baseRegexp = glob2regexp(glob, { globstar: true, extended: true });
const regexpSource = baseRegexp.source;
const regexp = new RegExp("^(\\./)?" + regexpSource.slice(1));
const regexp = new RegExp(`^(\\./)?${regexpSource.slice(1)}`);
cache.set(glob, regexp);
return regexp;
};
@@ -71,6 +73,7 @@ class SideEffectsFlagPlugin {
constructor(analyseSource = true) {
this._analyseSource = analyseSource;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
@@ -110,11 +113,12 @@ class SideEffectsFlagPlugin {
return module;
});
normalModuleFactory.hooks.module.tap(PLUGIN_NAME, (module, data) => {
if (typeof data.settings.sideEffects === "boolean") {
const settings = /** @type {ModuleSettings} */ (data.settings);
if (typeof settings.sideEffects === "boolean") {
if (module.factoryMeta === undefined) {
module.factoryMeta = {};
}
module.factoryMeta.sideEffectFree = !data.settings.sideEffects;
module.factoryMeta.sideEffectFree = !settings.sideEffects;
}
return module;
});
@@ -210,7 +214,8 @@ class SideEffectsFlagPlugin {
case "ExportDefaultDeclaration":
if (
!parser.isPure(
statement.declaration,
/** @type {TODO} */
(statement.declaration),
/** @type {Range} */ (statement.range)[0]
)
) {
@@ -321,7 +326,9 @@ class SideEffectsFlagPlugin {
? [...exportName, ...ids.slice(1)]
: ids.slice(1)
);
return moduleGraph.getConnection(dep);
return /** @type {ModuleGraphConnection} */ (
moduleGraph.getConnection(dep)
);
}
);
continue;

View File

@@ -28,11 +28,10 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Compilation").AssetInfo} AssetInfo */
/** @typedef {import("../Compilation").PathData} PathData */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
/** @typedef {import("../util/deterministicGrouping").GroupedItems<Module>} DeterministicGroupingGroupedItemsForModule */
/** @typedef {import("../util/deterministicGrouping").Options<Module>} DeterministicGroupingOptionsForModule */
@@ -67,7 +66,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
* @property {number=} minChunks
* @property {number=} maxAsyncRequests
* @property {number=} maxInitialRequests
* @property {(string | function(PathData, AssetInfo=): string)=} filename
* @property {TemplatePath=} filename
* @property {string=} idHint
* @property {string=} automaticNameDelimiter
* @property {boolean=} reuseExistingChunk
@@ -89,7 +88,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
* @property {number=} minChunks
* @property {number=} maxAsyncRequests
* @property {number=} maxInitialRequests
* @property {(string | function(PathData, AssetInfo=): string)=} filename
* @property {TemplatePath=} filename
* @property {string=} idHint
* @property {string} automaticNameDelimiter
* @property {boolean} reuseExistingChunk
@@ -144,7 +143,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
* @property {number} maxAsyncRequests
* @property {number} maxInitialRequests
* @property {boolean} hidePathInfo
* @property {string | function(PathData, AssetInfo=): string} filename
* @property {TemplatePath} filename
* @property {string} automaticNameDelimiter
* @property {GetCacheGroups} getCacheGroups
* @property {GetName} getName
@@ -167,9 +166,8 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
const defaultGetName = /** @type {GetName} */ (() => {});
const deterministicGroupingForModules =
/** @type {function(DeterministicGroupingOptionsForModule): DeterministicGroupingGroupedItemsForModule[]} */ (
deterministicGrouping
);
/** @type {function(DeterministicGroupingOptionsForModule): DeterministicGroupingGroupedItemsForModule[]} */
(deterministicGrouping);
/** @type {WeakMap<Module, string>} */
const getKeyCache = new WeakMap();
@@ -180,11 +178,13 @@ const getKeyCache = new WeakMap();
* @returns {string} hashed filename
*/
const hashFilename = (name, outputOptions) => {
const digest = /** @type {string} */ (
createHash(outputOptions.hashFunction)
.update(name)
.digest(outputOptions.hashDigest)
);
const digest =
/** @type {string} */
(
createHash(outputOptions.hashFunction)
.update(name)
.digest(outputOptions.hashDigest)
);
return digest.slice(0, 8);
};
@@ -200,10 +200,21 @@ const getRequests = chunk => {
return requests;
};
/**
* @template {object} T
* @template {object} R
* @param {T} obj obj an object
* @param {function(T[keyof T], keyof T): T[keyof T]} fn fn
* @returns {T} result
*/
const mapObject = (obj, fn) => {
const newObj = Object.create(null);
for (const key of Object.keys(obj)) {
newObj[key] = fn(obj[key], key);
newObj[key] = fn(
obj[/** @type {keyof T} */ (key)],
/** @type {keyof T} */
(key)
);
}
return newObj;
};
@@ -283,13 +294,12 @@ const normalizeSizes = (value, defaultSizeTypes) => {
return o;
} else if (typeof value === "object" && value !== null) {
return { ...value };
} else {
return {};
}
return {};
};
/**
* @param {...SplitChunksSizes} sizes the sizes
* @param {...(SplitChunksSizes | undefined)} sizes the sizes
* @returns {SplitChunksSizes} the merged sizes
*/
const mergeSizes = (...sizes) => {
@@ -324,11 +334,7 @@ const combineSizes = (a, b, combine) => {
/** @type {SplitChunksSizes} */
const result = {};
for (const key of aKeys) {
if (bKeys.has(key)) {
result[key] = combine(a[key], b[key]);
} else {
result[key] = a[key];
}
result[key] = bKeys.has(key) ? combine(a[key], b[key]) : a[key];
}
for (const key of bKeys) {
if (!aKeys.has(key)) {
@@ -425,9 +431,7 @@ const normalizeChunksFilter = chunks => {
return ALL_CHUNK_FILTER;
}
if (chunks instanceof RegExp) {
return chunk => {
return chunk.name ? chunks.test(chunk.name) : false;
};
return chunk => (chunk.name ? chunks.test(chunk.name) : false);
}
if (typeof chunks === "function") {
return chunks;
@@ -500,7 +504,7 @@ const normalizeCacheGroups = (cacheGroups, defaultSizeTypes) => {
*/
const fn = (module, context) => {
/** @type {CacheGroupSource[]} */
let results = [];
const results = [];
for (const fn of handlers) {
fn(module, context, results);
}
@@ -1210,7 +1214,7 @@ module.exports = class SplitChunksPlugin {
// Walk through all modules
for (const module of compilation.modules) {
// Get cache group
let cacheGroups = this.options.getCacheGroups(module, context);
const cacheGroups = this.options.getCacheGroups(module, context);
if (!Array.isArray(cacheGroups) || cacheGroups.length === 0) {
continue;
}
@@ -1437,7 +1441,7 @@ module.exports = class SplitChunksPlugin {
: item.cacheGroup.maxAsyncRequests
);
if (
isFinite(maxRequests) &&
Number.isFinite(maxRequests) &&
getRequests(chunk) >= maxRequests
) {
usedChunks.delete(chunk);
@@ -1482,7 +1486,7 @@ module.exports = class SplitChunksPlugin {
usedChunks.size === 1
) {
const [chunk] = usedChunks;
let chunkSizes = Object.create(null);
const chunkSizes = Object.create(null);
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
if (!item.modules.has(module)) {
for (const type of module.getSourceTypes()) {
@@ -1522,7 +1526,7 @@ module.exports = class SplitChunksPlugin {
// Add a note to the chunk
newChunk.chunkReason =
(newChunk.chunkReason ? newChunk.chunkReason + ", " : "") +
(newChunk.chunkReason ? `${newChunk.chunkReason}, ` : "") +
(isReusedWithAllModules
? "reused as split chunk"
: "split chunk");