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

@@ -71,9 +71,12 @@ makeSerializable(
"RestoreProvidedData"
);
/** @typedef {Map<string, ExportInfo>} Exports */
/** @typedef {string | string[] | false} UsedName */
class ExportsInfo {
constructor() {
/** @type {Map<string, ExportInfo>} */
/** @type {Exports} */
this._exports = new Map();
this._otherExportsInfo = new ExportInfo(null);
this._sideEffectsOnlyInfo = new ExportInfo("*side effects only*");
@@ -144,6 +147,10 @@ class ExportsInfo {
return this._otherExportsInfo;
}
/**
* @param {Exports} exports exports
* @private
*/
_sortExportsMap(exports) {
if (exports.size > 1) {
const namesInOrder = [];
@@ -159,7 +166,7 @@ class ExportsInfo {
}
for (; i < namesInOrder.length; i++) {
const name = namesInOrder[i];
const correctEntry = exports.get(name);
const correctEntry = /** @type {ExportInfo} */ (exports.get(name));
exports.delete(name);
exports.set(name, correctEntry);
}
@@ -261,7 +268,7 @@ class ExportsInfo {
getReadOnlyExportInfoRecursive(name) {
const exportInfo = this.getReadOnlyExportInfo(name[0]);
if (name.length === 1) return exportInfo;
if (!exportInfo.exportsInfo) return undefined;
if (!exportInfo.exportsInfo) return;
return exportInfo.exportsInfo.getReadOnlyExportInfoRecursive(name.slice(1));
}
@@ -272,7 +279,7 @@ class ExportsInfo {
getNestedExportsInfo(name) {
if (Array.isArray(name) && name.length > 0) {
const info = this.getReadOnlyExportInfo(name[0]);
if (!info.exportsInfo) return undefined;
if (!info.exportsInfo) return;
return info.exportsInfo.getNestedExportsInfo(name.slice(1));
}
return this;
@@ -451,10 +458,8 @@ class ExportsInfo {
if (this._redirectTo.isUsed(runtime)) {
return true;
}
} else {
if (this._otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
return true;
}
} else if (this._otherExportsInfo.getUsed(runtime) !== UsageState.Unused) {
return true;
}
for (const exportInfo of this._exports.values()) {
if (exportInfo.getUsed(runtime) !== UsageState.Unused) {
@@ -522,7 +527,7 @@ class ExportsInfo {
return false;
}
}
return new SortableSet(array);
return /** @type {SortableSet<string>} */ (new SortableSet(array));
}
/**
@@ -633,13 +638,11 @@ class ExportsInfo {
isEquallyUsed(runtimeA, runtimeB) {
if (this._redirectTo !== undefined) {
if (!this._redirectTo.isEquallyUsed(runtimeA, runtimeB)) return false;
} else {
if (
this._otherExportsInfo.getUsed(runtimeA) !==
this._otherExportsInfo.getUsed(runtimeB)
) {
return false;
}
} else if (
this._otherExportsInfo.getUsed(runtimeA) !==
this._otherExportsInfo.getUsed(runtimeB)
) {
return false;
}
if (
this._sideEffectsOnlyInfo.getUsed(runtimeA) !==
@@ -662,20 +665,20 @@ class ExportsInfo {
getUsed(name, runtime) {
if (Array.isArray(name)) {
if (name.length === 0) return this.otherExportsInfo.getUsed(runtime);
let info = this.getReadOnlyExportInfo(name[0]);
const info = this.getReadOnlyExportInfo(name[0]);
if (info.exportsInfo && name.length > 1) {
return info.exportsInfo.getUsed(name.slice(1), runtime);
}
return info.getUsed(runtime);
}
let info = this.getReadOnlyExportInfo(name);
const info = this.getReadOnlyExportInfo(name);
return info.getUsed(runtime);
}
/**
* @param {string | string[] | undefined} name the export name
* @param {string | string[]} name the export name
* @param {RuntimeSpec} runtime check usage for this runtime only
* @returns {string | string[] | false} the used name
* @returns {UsedName} the used name
*/
getUsedName(name, runtime) {
if (Array.isArray(name)) {
@@ -684,10 +687,12 @@ class ExportsInfo {
if (!this.isUsed(runtime)) return false;
return name;
}
let info = this.getReadOnlyExportInfo(name[0]);
const info = this.getReadOnlyExportInfo(name[0]);
const x = info.getUsedName(name[0], runtime);
if (x === false) return false;
const arr = x === name[0] && name.length === 1 ? name : [x];
const arr =
/** @type {string[]} */
(x === name[0] && name.length === 1 ? name : [x]);
if (name.length === 1) {
return arr;
}
@@ -698,14 +703,12 @@ class ExportsInfo {
const nested = info.exportsInfo.getUsedName(name.slice(1), runtime);
if (!nested) return false;
return arr.concat(nested);
} else {
return arr.concat(name.slice(1));
}
} else {
let info = this.getReadOnlyExportInfo(name);
const usedName = info.getUsedName(name, runtime);
return usedName;
return arr.concat(name.slice(1));
}
const info = this.getReadOnlyExportInfo(name);
const usedName = info.getUsedName(name, runtime);
return usedName;
}
/**
@@ -738,6 +741,9 @@ class ExportsInfo {
}
}
/**
* @returns {RestoreProvidedData} restore provided data
*/
getRestoreProvidedData() {
const otherProvided = this._otherExportsInfo.provided;
const otherCanMangleProvide = this._otherExportsInfo.canMangleProvide;
@@ -756,7 +762,8 @@ class ExportsInfo {
canMangleProvide: exportInfo.canMangleProvide,
terminalBinding: exportInfo.terminalBinding,
exportsInfo: exportInfo.exportsInfoOwned
? exportInfo.exportsInfo.getRestoreProvidedData()
? /** @type {NonNullable<ExportInfo["exportsInfo"]>} */
(exportInfo.exportsInfo).getRestoreProvidedData()
: undefined
});
}
@@ -802,6 +809,10 @@ class ExportsInfo {
}
}
/** @typedef {{ module: Module, export: string[] }} TargetItemWithoutConnection */
/** @typedef {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined }} TargetItem */
/** @typedef {Map<any, { connection: ModuleGraphConnection | null, export: string[], priority: number }>} Target */
class ExportInfo {
/**
* @param {string} name the original name of the export
@@ -817,7 +828,7 @@ class ExportInfo {
this._usedName = initFrom ? initFrom._usedName : null;
/**
* @private
* @type {UsageStateType}
* @type {UsageStateType | undefined}
*/
this._globalUsed = initFrom ? initFrom._globalUsed : undefined;
/**
@@ -864,9 +875,9 @@ class ExportInfo {
this.canMangleUse = initFrom ? initFrom.canMangleUse : undefined;
/** @type {boolean} */
this.exportsInfoOwned = false;
/** @type {ExportsInfo=} */
/** @type {ExportsInfo | undefined} */
this.exportsInfo = undefined;
/** @type {Map<any, { connection: ModuleGraphConnection | null, export: string[], priority: number }>=} */
/** @type {Target | undefined} */
this._target = undefined;
if (initFrom && initFrom._target) {
this._target = new Map();
@@ -878,19 +889,11 @@ class ExportInfo {
});
}
}
/** @type {Map<any, { connection: ModuleGraphConnection | null, export: string[], priority: number }>=} */
/** @type {Target | undefined} */
this._maxTarget = undefined;
}
// TODO webpack 5 remove
/** @private */
get used() {
throw new Error("REMOVED");
}
/** @private */
get usedName() {
throw new Error("REMOVED");
}
/**
* @private
* @param {*} v v
@@ -898,6 +901,14 @@ class ExportInfo {
set used(v) {
throw new Error("REMOVED");
}
// TODO webpack 5 remove
/** @private */
get used() {
throw new Error("REMOVED");
}
// TODO webpack 5 remove
/**
* @private
* @param {*} v v
@@ -906,6 +917,12 @@ class ExportInfo {
throw new Error("REMOVED");
}
// TODO webpack 5 remove
/** @private */
get usedName() {
throw new Error("REMOVED");
}
get canMangle() {
switch (this.canMangleProvide) {
case undefined:
@@ -973,7 +990,8 @@ class ExportInfo {
this.canMangleUse = true;
}
if (this.exportsInfoOwned) {
this.exportsInfo.setHasUseInfo();
/** @type {ExportsInfo} */
(this.exportsInfo).setHasUseInfo();
}
}
@@ -988,25 +1006,26 @@ class ExportInfo {
if (this._globalUsed === undefined) {
this._globalUsed = newValue;
return true;
} else {
if (this._globalUsed !== newValue && condition(this._globalUsed)) {
this._globalUsed = newValue;
return true;
}
}
if (this._globalUsed !== newValue && condition(this._globalUsed)) {
this._globalUsed = newValue;
return true;
}
} else if (this._usedInRuntime === undefined) {
if (newValue !== UsageState.Unused && condition(UsageState.Unused)) {
this._usedInRuntime = new Map();
forEachRuntime(runtime, runtime =>
this._usedInRuntime.set(runtime, newValue)
this._usedInRuntime.set(/** @type {string} */ (runtime), newValue)
);
return true;
}
} else {
let changed = false;
forEachRuntime(runtime, runtime => {
/** @type {UsageStateType} */
let oldValue = this._usedInRuntime.get(runtime);
forEachRuntime(runtime, _runtime => {
const runtime = /** @type {string} */ (_runtime);
let oldValue =
/** @type {UsageStateType} */
(this._usedInRuntime.get(runtime));
if (oldValue === undefined) oldValue = UsageState.Unused;
if (newValue !== oldValue && condition(oldValue)) {
if (newValue === UsageState.Unused) {
@@ -1040,15 +1059,17 @@ class ExportInfo {
if (newValue !== UsageState.Unused) {
this._usedInRuntime = new Map();
forEachRuntime(runtime, runtime =>
this._usedInRuntime.set(runtime, newValue)
this._usedInRuntime.set(/** @type {string} */ (runtime), newValue)
);
return true;
}
} else {
let changed = false;
forEachRuntime(runtime, runtime => {
/** @type {UsageStateType} */
let oldValue = this._usedInRuntime.get(runtime);
forEachRuntime(runtime, _runtime => {
const runtime = /** @type {string} */ (_runtime);
let oldValue =
/** @type {UsageStateType} */
(this._usedInRuntime.get(runtime));
if (oldValue === undefined) oldValue = UsageState.Unused;
if (newValue !== oldValue) {
if (newValue === UsageState.Unused) {
@@ -1083,7 +1104,7 @@ class ExportInfo {
/**
* @param {any} key the key
* @param {ModuleGraphConnection} connection the target module if a single one
* @param {string[]=} exportName the exported name
* @param {(string[] | null)=} exportName the exported name
* @param {number=} priority priority
* @returns {boolean} true, if something has changed
*/
@@ -1091,13 +1112,21 @@ class ExportInfo {
if (exportName) exportName = [...exportName];
if (!this._target) {
this._target = new Map();
this._target.set(key, { connection, export: exportName, priority });
this._target.set(key, {
connection,
export: /** @type {string[]} */ (exportName),
priority
});
return true;
}
const oldTarget = this._target.get(key);
if (!oldTarget) {
if (oldTarget === null && !connection) return false;
this._target.set(key, { connection, export: exportName, priority });
this._target.set(key, {
connection,
export: /** @type {string[]} */ (exportName),
priority
});
this._maxTarget = undefined;
return true;
}
@@ -1109,7 +1138,7 @@ class ExportInfo {
: oldTarget.export)
) {
oldTarget.connection = connection;
oldTarget.export = exportName;
oldTarget.export = /** @type {string[]} */ (exportName);
oldTarget.priority = priority;
this._maxTarget = undefined;
return true;
@@ -1139,20 +1168,20 @@ class ExportInfo {
if (max < value) max = value;
}
return max;
} else {
/** @type {UsageStateType} */
let max = UsageState.Unused;
for (const item of runtime) {
const value = this._usedInRuntime.get(item);
if (value !== undefined) {
if (value === UsageState.Used) {
return UsageState.Used;
}
if (max < value) max = value;
}
}
return max;
}
/** @type {UsageStateType} */
let max = UsageState.Unused;
for (const item of runtime) {
const value = this._usedInRuntime.get(item);
if (value !== undefined) {
if (value === UsageState.Used) {
return UsageState.Used;
}
if (max < value) max = value;
}
}
return max;
}
/**
@@ -1171,19 +1200,18 @@ class ExportInfo {
if (!this._usedInRuntime.has(runtime)) {
return false;
}
} else if (runtime !== undefined) {
if (
Array.from(runtime).every(
runtime => !this._usedInRuntime.has(runtime)
)
) {
return false;
}
} else if (
runtime !== undefined &&
Array.from(runtime).every(
runtime => !this._usedInRuntime.has(runtime)
)
) {
return false;
}
}
}
if (this._usedName !== null) return this._usedName;
return this.name || fallbackName;
return /** @type {string | false} */ (this.name || fallbackName);
}
/**
@@ -1204,13 +1232,13 @@ class ExportInfo {
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {function({ module: Module, export: string[] | undefined }): boolean} resolveTargetFilter filter function to further resolve target
* @param {function(TargetItem): boolean} resolveTargetFilter filter function to further resolve target
* @returns {ExportInfo | ExportsInfo | undefined} the terminal binding export(s) info if known
*/
getTerminalBinding(moduleGraph, resolveTargetFilter = RETURNS_TRUE) {
if (this.terminalBinding) return this;
const target = this.getTarget(moduleGraph, resolveTargetFilter);
if (!target) return undefined;
if (!target) return;
const exportsInfo = moduleGraph.getExportsInfo(target.module);
if (!target.export) return exportsInfo;
return exportsInfo.getReadOnlyExportInfoRecursive(target.export);
@@ -1222,10 +1250,11 @@ class ExportInfo {
_getMaxTarget() {
if (this._maxTarget !== undefined) return this._maxTarget;
if (this._target.size <= 1) return (this._maxTarget = this._target);
if (/** @type {Target} */ (this._target).size <= 1)
return (this._maxTarget = this._target);
let maxPriority = -Infinity;
let minPriority = Infinity;
for (const { priority } of this._target.values()) {
for (const { priority } of /** @type {Target} */ (this._target).values()) {
if (maxPriority < priority) maxPriority = priority;
if (minPriority > priority) minPriority = priority;
}
@@ -1234,7 +1263,7 @@ class ExportInfo {
// This is an edge case
const map = new Map();
for (const [key, value] of this._target) {
for (const [key, value] of /** @type {Target} */ (this._target)) {
if (maxPriority === value.priority) {
map.set(key, value);
}
@@ -1246,7 +1275,7 @@ class ExportInfo {
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {function(Module): boolean} validTargetModuleFilter a valid target module
* @returns {{ module: Module, export: string[] | undefined } | undefined | false} the target, undefined when there is no target, false when no target is valid
* @returns {TargetItemWithoutConnection | null | undefined | false} the target, undefined when there is no target, false when no target is valid
*/
findTarget(moduleGraph, validTargetModuleFilter) {
return this._findTarget(moduleGraph, validTargetModuleFilter, new Set());
@@ -1256,13 +1285,15 @@ class ExportInfo {
* @param {ModuleGraph} moduleGraph the module graph
* @param {function(Module): boolean} validTargetModuleFilter a valid target module
* @param {Set<ExportInfo>} alreadyVisited set of already visited export info to avoid circular references
* @returns {{ module: Module, export: string[] | undefined } | undefined | false} the target, undefined when there is no target, false when no target is valid
* @returns {TargetItemWithoutConnection | null | undefined | false} the target, undefined when there is no target, false when no target is valid
*/
_findTarget(moduleGraph, validTargetModuleFilter, alreadyVisited) {
if (!this._target || this._target.size === 0) return undefined;
let rawTarget = this._getMaxTarget().values().next().value;
if (!rawTarget) return undefined;
/** @type {{ module: Module, export: string[] | undefined }} */
if (!this._target || this._target.size === 0) return;
const rawTarget =
/** @type {Target} */
(this._getMaxTarget()).values().next().value;
if (!rawTarget) return;
/** @type {TargetItemWithoutConnection} */
let target = {
module: rawTarget.connection.module,
export: rawTarget.export
@@ -1293,26 +1324,26 @@ class ExportInfo {
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {function({ module: Module, export: string[] | undefined }): boolean} resolveTargetFilter filter function to further resolve target
* @returns {{ module: Module, export: string[] | undefined } | undefined} the target
* @param {function(TargetItem): boolean} resolveTargetFilter filter function to further resolve target
* @returns {TargetItem | undefined} the target
*/
getTarget(moduleGraph, resolveTargetFilter = RETURNS_TRUE) {
const result = this._getTarget(moduleGraph, resolveTargetFilter, undefined);
if (result === CIRCULAR) return undefined;
if (result === CIRCULAR) return;
return result;
}
/**
* @param {ModuleGraph} moduleGraph the module graph
* @param {function({ module: Module, connection: ModuleGraphConnection, export: string[] | undefined }): boolean} resolveTargetFilter filter function to further resolve target
* @param {function(TargetItem): boolean} resolveTargetFilter filter function to further resolve target
* @param {Set<ExportInfo> | undefined} alreadyVisited set of already visited export info to avoid circular references
* @returns {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined } | CIRCULAR | undefined} the target
* @returns {TargetItem | CIRCULAR | undefined} the target
*/
_getTarget(moduleGraph, resolveTargetFilter, alreadyVisited) {
/**
* @param {{ connection: ModuleGraphConnection, export: string[] | undefined } | null} inputTarget unresolved target
* @param {TargetItem | null} inputTarget unresolved target
* @param {Set<ExportInfo>} alreadyVisited set of already visited export info to avoid circular references
* @returns {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined } | CIRCULAR | null} resolved target
* @returns {TargetItem | CIRCULAR | null} resolved target
*/
const resolveTarget = (inputTarget, alreadyVisited) => {
if (!inputTarget) return null;
@@ -1323,7 +1354,7 @@ class ExportInfo {
export: undefined
};
}
/** @type {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined }} */
/** @type {TargetItem} */
let target = {
module: inputTarget.connection.module,
connection: inputTarget.connection,
@@ -1333,7 +1364,10 @@ class ExportInfo {
let alreadyVisitedOwned = false;
for (;;) {
const exportsInfo = moduleGraph.getExportsInfo(target.module);
const exportInfo = exportsInfo.getExportInfo(target.export[0]);
const exportInfo = exportsInfo.getExportInfo(
/** @type {NonNullable<TargetItem["export"]>} */
(target.export)[0]
);
if (!exportInfo) return target;
if (alreadyVisited.has(exportInfo)) return CIRCULAR;
const newTarget = exportInfo._getTarget(
@@ -1343,7 +1377,10 @@ class ExportInfo {
);
if (newTarget === CIRCULAR) return CIRCULAR;
if (!newTarget) return target;
if (target.export.length === 1) {
if (
/** @type {NonNullable<TargetItem["export"]>} */
(target.export).length === 1
) {
target = newTarget;
if (!target.export) return target;
} else {
@@ -1351,8 +1388,12 @@ class ExportInfo {
module: newTarget.module,
connection: newTarget.connection,
export: newTarget.export
? newTarget.export.concat(target.export.slice(1))
: target.export.slice(1)
? newTarget.export.concat(
/** @type {NonNullable<TargetItem["export"]>} */
(target.export).slice(1)
)
: /** @type {NonNullable<TargetItem["export"]>} */
(target.export).slice(1)
};
}
if (!resolveTargetFilter(target)) return target;
@@ -1364,26 +1405,26 @@ class ExportInfo {
}
};
if (!this._target || this._target.size === 0) return undefined;
if (!this._target || this._target.size === 0) return;
if (alreadyVisited && alreadyVisited.has(this)) return CIRCULAR;
const newAlreadyVisited = new Set(alreadyVisited);
newAlreadyVisited.add(this);
const values = this._getMaxTarget().values();
const values = /** @type {Target} */ (this._getMaxTarget()).values();
const target = resolveTarget(values.next().value, newAlreadyVisited);
if (target === CIRCULAR) return CIRCULAR;
if (target === null) return undefined;
if (target === null) return;
let result = values.next();
while (!result.done) {
const t = resolveTarget(result.value, newAlreadyVisited);
if (t === CIRCULAR) return CIRCULAR;
if (t === null) return undefined;
if (t.module !== target.module) return undefined;
if (!t.export !== !target.export) return undefined;
if (t === null) return;
if (t.module !== target.module) return;
if (!t.export !== !target.export) return;
if (
target.export &&
!equals(/** @type {ArrayLike<string>} */ (t.export), target.export)
)
return undefined;
return;
result = values.next();
}
return target;
@@ -1392,34 +1433,42 @@ class ExportInfo {
/**
* Move the target forward as long resolveTargetFilter is fulfilled
* @param {ModuleGraph} moduleGraph the module graph
* @param {function({ module: Module, export: string[] | undefined }): boolean} resolveTargetFilter filter function to further resolve target
* @param {function({ module: Module, export: string[] | undefined }): ModuleGraphConnection=} updateOriginalConnection updates the original connection instead of using the target connection
* @returns {{ module: Module, export: string[] | undefined } | undefined} the resolved target when moved
* @param {function(TargetItem): boolean} resolveTargetFilter filter function to further resolve target
* @param {function(TargetItem): ModuleGraphConnection=} updateOriginalConnection updates the original connection instead of using the target connection
* @returns {TargetItem | undefined} the resolved target when moved
*/
moveTarget(moduleGraph, resolveTargetFilter, updateOriginalConnection) {
const target = this._getTarget(moduleGraph, resolveTargetFilter, undefined);
if (target === CIRCULAR) return undefined;
if (!target) return undefined;
const originalTarget = this._getMaxTarget().values().next().value;
if (target === CIRCULAR) return;
if (!target) return;
const originalTarget =
/** @type {Target} */
(this._getMaxTarget()).values().next().value;
if (
originalTarget.connection === target.connection &&
originalTarget.export === target.export
) {
return undefined;
return;
}
this._target.clear();
this._target.set(undefined, {
/** @type {Target} */
(this._target).clear();
/** @type {Target} */
(this._target).set(undefined, {
connection: updateOriginalConnection
? updateOriginalConnection(target)
: target.connection,
export: target.export,
export: /** @type {NonNullable<TargetItem["export"]>} */ (target.export),
priority: 0
});
return target;
}
/**
* @returns {ExportsInfo} an exports info
*/
createNestedExportsInfo() {
if (this.exportsInfoOwned) return this.exportsInfo;
if (this.exportsInfoOwned)
return /** @type {ExportsInfo} */ (this.exportsInfo);
this.exportsInfoOwned = true;
const oldExportsInfo = this.exportsInfo;
this.exportsInfo = new ExportsInfo();
@@ -1434,6 +1483,11 @@ class ExportInfo {
return this.exportsInfo;
}
/**
* @param {ExportInfo} baseInfo base info
* @param {RuntimeSpec} runtime runtime
* @returns {boolean} true when has info, otherwise false
*/
hasInfo(baseInfo, runtime) {
return (
(this._usedName && this._usedName !== this.name) ||
@@ -1443,10 +1497,20 @@ class ExportInfo {
);
}
/**
* @param {Hash} hash the hash
* @param {RuntimeSpec} runtime the runtime
* @returns {void}
*/
updateHash(hash, runtime) {
this._updateHash(hash, runtime, new Set());
}
/**
* @param {Hash} hash the hash
* @param {RuntimeSpec} runtime the runtime
* @param {Set<ExportsInfo>} alreadyVisitedExportsInfo for circular references
*/
_updateHash(hash, runtime, alreadyVisitedExportsInfo) {
hash.update(
`${this._usedName || this.name}${this.getUsed(runtime)}${this.provided}${
@@ -1480,6 +1544,7 @@ class ExportInfo {
if (list !== undefined) list.push(runtime);
else map.set(used, [runtime]);
}
// eslint-disable-next-line array-callback-return
const specificInfo = Array.from(map, ([used, runtimes]) => {
switch (used) {
case UsageState.NoInfo: