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

@@ -11,83 +11,108 @@ const smartGrouping = require("../util/smartGrouping");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").NormalizedStatsOptions} NormalizedStatsOptions */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../util/comparators").Comparator<any>} Comparator */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
/** @typedef {import("../util/smartGrouping").GroupConfig<any, object>} GroupConfig */
/**
* @typedef {object} KnownStatsFactoryContext
* @property {string} type
* @property {function(string): string=} makePathsRelative
* @property {Compilation=} compilation
* @property {Set<Module>=} rootModules
* @property {Map<string,Chunk[]>=} compilationFileToChunks
* @property {Map<string,Chunk[]>=} compilationAuxiliaryFileToChunks
* @property {RuntimeSpec=} runtime
* @property {function(Compilation): WebpackError[]=} cachedGetErrors
* @property {function(Compilation): WebpackError[]=} cachedGetWarnings
* @property {function(string): string} makePathsRelative
* @property {Compilation} compilation
* @property {Set<Module>} rootModules
* @property {Map<string,Chunk[]>} compilationFileToChunks
* @property {Map<string,Chunk[]>} compilationAuxiliaryFileToChunks
* @property {RuntimeSpec} runtime
* @property {function(Compilation): WebpackError[]} cachedGetErrors
* @property {function(Compilation): WebpackError[]} cachedGetWarnings
*/
/** @typedef {KnownStatsFactoryContext & Record<string, any>} StatsFactoryContext */
/** @typedef {Record<string, any> & KnownStatsFactoryContext} StatsFactoryContext */
/** @typedef {any} CreatedObject */
/** @typedef {any} FactoryData */
/** @typedef {any} FactoryDataItem */
/** @typedef {any} Result */
/** @typedef {Record<string, any>} ObjectForExtract */
/**
* @typedef {object} StatsFactoryHooks
* @property {HookMap<SyncBailHook<[ObjectForExtract, FactoryData, StatsFactoryContext], void>>} extract
* @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | void>>} filter
* @property {HookMap<SyncBailHook<[Comparator[], StatsFactoryContext], void>>} sort
* @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | void>>} filterSorted
* @property {HookMap<SyncBailHook<[GroupConfig[], StatsFactoryContext], void>>} groupResults
* @property {HookMap<SyncBailHook<[Comparator[], StatsFactoryContext], void>>} sortResults
* @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | void>>} filterResults
* @property {HookMap<SyncBailHook<[FactoryDataItem[], StatsFactoryContext], Result | void>>} merge
* @property {HookMap<SyncBailHook<[Result, StatsFactoryContext], Result>>} result
* @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext], string | void>>} getItemName
* @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext], StatsFactory | void>>} getItemFactory
*/
/**
* @template T
* @typedef {Map<string, T[]>} Caches
*/
class StatsFactory {
constructor() {
/** @type {StatsFactoryHooks} */
this.hooks = Object.freeze({
/** @type {HookMap<SyncBailHook<[object, any, StatsFactoryContext]>>} */
extract: new HookMap(
() => new SyncBailHook(["object", "data", "context"])
),
/** @type {HookMap<SyncBailHook<[any, StatsFactoryContext, number, number]>>} */
filter: new HookMap(
() => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
),
/** @type {HookMap<SyncBailHook<[(function(any, any): number)[], StatsFactoryContext]>>} */
sort: new HookMap(() => new SyncBailHook(["comparators", "context"])),
/** @type {HookMap<SyncBailHook<[any, StatsFactoryContext, number, number]>>} */
filterSorted: new HookMap(
() => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
),
/** @type {HookMap<SyncBailHook<[GroupConfig[], StatsFactoryContext]>>} */
groupResults: new HookMap(
() => new SyncBailHook(["groupConfigs", "context"])
),
/** @type {HookMap<SyncBailHook<[(function(any, any): number)[], StatsFactoryContext]>>} */
sortResults: new HookMap(
() => new SyncBailHook(["comparators", "context"])
),
/** @type {HookMap<SyncBailHook<[any, StatsFactoryContext, number, number]>>} */
filterResults: new HookMap(
() => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
),
/** @type {HookMap<SyncBailHook<[any[], StatsFactoryContext]>>} */
merge: new HookMap(() => new SyncBailHook(["items", "context"])),
/** @type {HookMap<SyncBailHook<[any[], StatsFactoryContext]>>} */
result: new HookMap(() => new SyncWaterfallHook(["result", "context"])),
/** @type {HookMap<SyncBailHook<[any, StatsFactoryContext]>>} */
getItemName: new HookMap(() => new SyncBailHook(["item", "context"])),
/** @type {HookMap<SyncBailHook<[any, StatsFactoryContext]>>} */
getItemFactory: new HookMap(() => new SyncBailHook(["item", "context"]))
});
const hooks = this.hooks;
this._caches =
/** @type {Record<keyof typeof hooks, Map<string, SyncBailHook<[any[], StatsFactoryContext]>[]>>} */ ({});
this._caches = /** @type {TODO} */ ({});
for (const key of Object.keys(hooks)) {
this._caches[key] = new Map();
this._caches[/** @type {keyof StatsFactoryHooks} */ (key)] = new Map();
}
this._inCreate = false;
}
/**
* @template {StatsFactoryHooks[keyof StatsFactoryHooks]} HM
* @template {HM extends HookMap<infer H> ? H : never} H
* @param {HM} hookMap hook map
* @param {Caches<H>} cache cache
* @param {string} type type
* @returns {H[]} hooks
* @private
*/
_getAllLevelHooks(hookMap, cache, type) {
const cacheEntry = cache.get(type);
if (cacheEntry !== undefined) {
return cacheEntry;
}
const hooks = [];
const hooks = /** @type {H[]} */ ([]);
const typeParts = type.split(".");
for (let i = 0; i < typeParts.length; i++) {
const hook = hookMap.get(typeParts.slice(i).join("."));
const hook = /** @type {H} */ (hookMap.get(typeParts.slice(i).join(".")));
if (hook) {
hooks.push(hook);
}
@@ -96,27 +121,62 @@ class StatsFactory {
return hooks;
}
/**
* @template {StatsFactoryHooks[keyof StatsFactoryHooks]} HM
* @template {HM extends HookMap<infer H> ? H : never} H
* @template {H extends import("tapable").Hook<any, infer R> ? R : never} R
* @param {HM} hookMap hook map
* @param {Caches<H>} cache cache
* @param {string} type type
* @param {function(H): R | void} fn fn
* @returns {R | void} hook
* @private
*/
_forEachLevel(hookMap, cache, type, fn) {
for (const hook of this._getAllLevelHooks(hookMap, cache, type)) {
const result = fn(hook);
const result = fn(/** @type {H} */ (hook));
if (result !== undefined) return result;
}
}
/**
* @template {StatsFactoryHooks[keyof StatsFactoryHooks]} HM
* @template {HM extends HookMap<infer H> ? H : never} H
* @param {HM} hookMap hook map
* @param {Caches<H>} cache cache
* @param {string} type type
* @param {FactoryData} data data
* @param {function(H, FactoryData): FactoryData} fn fn
* @returns {FactoryData} data
* @private
*/
_forEachLevelWaterfall(hookMap, cache, type, data, fn) {
for (const hook of this._getAllLevelHooks(hookMap, cache, type)) {
data = fn(hook, data);
data = fn(/** @type {H} */ (hook), data);
}
return data;
}
/**
* @template {StatsFactoryHooks[keyof StatsFactoryHooks]} T
* @template {T extends HookMap<infer H> ? H : never} H
* @template {H extends import("tapable").Hook<any, infer R> ? R : never} R
* @param {T} hookMap hook map
* @param {Caches<H>} cache cache
* @param {string} type type
* @param {Array<FactoryData>} items items
* @param {function(H, R, number, number): R | undefined} fn fn
* @param {boolean} forceClone force clone
* @returns {R[]} result for each level
* @private
*/
_forEachLevelFilter(hookMap, cache, type, items, fn, forceClone) {
const hooks = this._getAllLevelHooks(hookMap, cache, type);
if (hooks.length === 0) return forceClone ? items.slice() : items;
let i = 0;
return items.filter((item, idx) => {
for (const hook of hooks) {
const r = fn(hook, item, idx, i);
const r = fn(/** @type {H} */ (hook), item, idx, i);
if (r !== undefined) {
if (r) i++;
return r;
@@ -129,30 +189,37 @@ class StatsFactory {
/**
* @param {string} type type
* @param {any} data factory data
* @param {FactoryData} data factory data
* @param {Omit<StatsFactoryContext, "type">} baseContext context used as base
* @returns {any} created object
* @returns {CreatedObject} created object
*/
create(type, data, baseContext) {
if (this._inCreate) {
return this._create(type, data, baseContext);
} else {
try {
this._inCreate = true;
return this._create(type, data, baseContext);
} finally {
for (const key of Object.keys(this._caches)) this._caches[key].clear();
this._inCreate = false;
}
}
try {
this._inCreate = true;
return this._create(type, data, baseContext);
} finally {
for (const key of Object.keys(this._caches))
this._caches[/** @type {keyof StatsFactoryHooks} */ (key)].clear();
this._inCreate = false;
}
}
/**
* @param {string} type type
* @param {FactoryData} data factory data
* @param {Omit<StatsFactoryContext, "type">} baseContext context used as base
* @returns {CreatedObject} created object
* @private
*/
_create(type, data, baseContext) {
const context = {
const context = /** @type {StatsFactoryContext} */ ({
...baseContext,
type,
[type]: data
};
});
if (Array.isArray(data)) {
// run filter on unsorted items
const items = this._forEachLevelFilter(
@@ -165,6 +232,7 @@ class StatsFactory {
);
// sort items
/** @type {Comparator[]} */
const comparators = [];
this._forEachLevel(this.hooks.sort, this._caches.sort, type, h =>
h.call(comparators, context)
@@ -188,6 +256,7 @@ class StatsFactory {
// for each item
let resultItems = items2.map((item, i) => {
/** @type {StatsFactoryContext} */
const itemContext = {
...context,
_index: i
@@ -217,6 +286,7 @@ class StatsFactory {
});
// sort result items
/** @type {Comparator[]} */
const comparators2 = [];
this._forEachLevel(
this.hooks.sortResults,
@@ -232,6 +302,7 @@ class StatsFactory {
}
// group result items
/** @type {GroupConfig[]} */
const groupConfigs = [];
this._forEachLevel(
this.hooks.groupResults,
@@ -270,23 +341,23 @@ class StatsFactory {
result,
(h, r) => h.call(r, context)
);
} else {
const object = {};
// run extract on value
this._forEachLevel(this.hooks.extract, this._caches.extract, type, h =>
h.call(object, data, context)
);
// run result on extracted object
return this._forEachLevelWaterfall(
this.hooks.result,
this._caches.result,
type,
object,
(h, r) => h.call(r, context)
);
}
/** @type {ObjectForExtract} */
const object = {};
// run extract on value
this._forEachLevel(this.hooks.extract, this._caches.extract, type, h =>
h.call(object, data, context)
);
// run result on extracted object
return this._forEachLevelWaterfall(
this.hooks.result,
this._caches.result,
type,
object,
(h, r) => h.call(r, context)
);
}
}
module.exports = StatsFactory;