summaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/stats/StatsFactory.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2024-08-30 17:21:18 +0800
committerlittleblack111 <littleblack11111@gmail.com>2024-08-30 17:21:18 +0800
commitefbc2ffe6a1ee5ec38a4396305561d6515d0943e (patch)
tree2b4c94f18f2c792dfda813050755d5c0273fae22 /node_modules/webpack/lib/stats/StatsFactory.js
parent43acceb75957c880a5ba5a31aae221394a36d5f6 (diff)
node fixes, updates
Diffstat (limited to 'node_modules/webpack/lib/stats/StatsFactory.js')
-rw-r--r--node_modules/webpack/lib/stats/StatsFactory.js363
1 files changed, 363 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/stats/StatsFactory.js b/node_modules/webpack/lib/stats/StatsFactory.js
new file mode 100644
index 00000000..18f21fb9
--- /dev/null
+++ b/node_modules/webpack/lib/stats/StatsFactory.js
@@ -0,0 +1,363 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const { HookMap, SyncBailHook, SyncWaterfallHook } = require("tapable");
+const { concatComparators, keepOriginalOrder } = require("../util/comparators");
+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
+ */
+
+/** @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], undefined>>} extract
+ * @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | undefined>>} filter
+ * @property {HookMap<SyncBailHook<[Comparator[], StatsFactoryContext], undefined>>} sort
+ * @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | undefined>>} filterSorted
+ * @property {HookMap<SyncBailHook<[GroupConfig[], StatsFactoryContext], undefined>>} groupResults
+ * @property {HookMap<SyncBailHook<[Comparator[], StatsFactoryContext], undefined>>} sortResults
+ * @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext, number, number], boolean | undefined>>} filterResults
+ * @property {HookMap<SyncBailHook<[FactoryDataItem[], StatsFactoryContext], Result>>} merge
+ * @property {HookMap<SyncBailHook<[Result, StatsFactoryContext], Result>>} result
+ * @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext], string>>} getItemName
+ * @property {HookMap<SyncBailHook<[FactoryDataItem, StatsFactoryContext], StatsFactory | undefined>>} getItemFactory
+ */
+
+/**
+ * @template T
+ * @typedef {Map<string, T[]>} Caches
+ */
+
+class StatsFactory {
+ constructor() {
+ /** @type {StatsFactoryHooks} */
+ this.hooks = Object.freeze({
+ extract: new HookMap(
+ () => new SyncBailHook(["object", "data", "context"])
+ ),
+ filter: new HookMap(
+ () => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
+ ),
+ sort: new HookMap(() => new SyncBailHook(["comparators", "context"])),
+ filterSorted: new HookMap(
+ () => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
+ ),
+ groupResults: new HookMap(
+ () => new SyncBailHook(["groupConfigs", "context"])
+ ),
+ sortResults: new HookMap(
+ () => new SyncBailHook(["comparators", "context"])
+ ),
+ filterResults: new HookMap(
+ () => new SyncBailHook(["item", "context", "index", "unfilteredIndex"])
+ ),
+ merge: new HookMap(() => new SyncBailHook(["items", "context"])),
+ result: new HookMap(() => new SyncWaterfallHook(["result", "context"])),
+ getItemName: new HookMap(() => new SyncBailHook(["item", "context"])),
+ getItemFactory: new HookMap(() => new SyncBailHook(["item", "context"]))
+ });
+ const hooks = this.hooks;
+ this._caches = /** @type {TODO} */ ({});
+ for (const key of Object.keys(hooks)) {
+ 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 = /** @type {H[]} */ ([]);
+ const typeParts = type.split(".");
+ for (let i = 0; i < typeParts.length; i++) {
+ const hook = /** @type {H} */ (hookMap.get(typeParts.slice(i).join(".")));
+ if (hook) {
+ hooks.push(hook);
+ }
+ }
+ cache.set(type, hooks);
+ 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 | undefined} fn fn
+ * @returns {R | undefined} hook
+ * @private
+ */
+ _forEachLevel(hookMap, cache, type, fn) {
+ for (const hook of this._getAllLevelHooks(hookMap, cache, type)) {
+ 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(/** @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(/** @type {H} */ (hook), item, idx, i);
+ if (r !== undefined) {
+ if (r) i++;
+ return r;
+ }
+ }
+ i++;
+ return true;
+ });
+ }
+
+ /**
+ * @param {string} type type
+ * @param {FactoryData} data factory data
+ * @param {Omit<StatsFactoryContext, "type">} baseContext context used as base
+ * @returns {CreatedObject} created object
+ */
+ create(type, data, baseContext) {
+ if (this._inCreate) {
+ return this._create(type, data, baseContext);
+ }
+ 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 = /** @type {StatsFactoryContext} */ ({
+ ...baseContext,
+ type,
+ [type]: data
+ });
+ if (Array.isArray(data)) {
+ // run filter on unsorted items
+ const items = this._forEachLevelFilter(
+ this.hooks.filter,
+ this._caches.filter,
+ type,
+ data,
+ (h, r, idx, i) => h.call(r, context, idx, i),
+ true
+ );
+
+ // sort items
+ /** @type {Comparator[]} */
+ const comparators = [];
+ this._forEachLevel(this.hooks.sort, this._caches.sort, type, h =>
+ h.call(comparators, context)
+ );
+ if (comparators.length > 0) {
+ items.sort(
+ // @ts-expect-error number of arguments is correct
+ concatComparators(...comparators, keepOriginalOrder(items))
+ );
+ }
+
+ // run filter on sorted items
+ const items2 = this._forEachLevelFilter(
+ this.hooks.filterSorted,
+ this._caches.filterSorted,
+ type,
+ items,
+ (h, r, idx, i) => h.call(r, context, idx, i),
+ false
+ );
+
+ // for each item
+ let resultItems = items2.map((item, i) => {
+ /** @type {StatsFactoryContext} */
+ const itemContext = {
+ ...context,
+ _index: i
+ };
+
+ // run getItemName
+ const itemName = this._forEachLevel(
+ this.hooks.getItemName,
+ this._caches.getItemName,
+ `${type}[]`,
+ h => h.call(item, itemContext)
+ );
+ if (itemName) itemContext[itemName] = item;
+ const innerType = itemName ? `${type}[].${itemName}` : `${type}[]`;
+
+ // run getItemFactory
+ const itemFactory =
+ this._forEachLevel(
+ this.hooks.getItemFactory,
+ this._caches.getItemFactory,
+ innerType,
+ h => h.call(item, itemContext)
+ ) || this;
+
+ // run item factory
+ return itemFactory.create(innerType, item, itemContext);
+ });
+
+ // sort result items
+ /** @type {Comparator[]} */
+ const comparators2 = [];
+ this._forEachLevel(
+ this.hooks.sortResults,
+ this._caches.sortResults,
+ type,
+ h => h.call(comparators2, context)
+ );
+ if (comparators2.length > 0) {
+ resultItems.sort(
+ // @ts-expect-error number of arguments is correct
+ concatComparators(...comparators2, keepOriginalOrder(resultItems))
+ );
+ }
+
+ // group result items
+ /** @type {GroupConfig[]} */
+ const groupConfigs = [];
+ this._forEachLevel(
+ this.hooks.groupResults,
+ this._caches.groupResults,
+ type,
+ h => h.call(groupConfigs, context)
+ );
+ if (groupConfigs.length > 0) {
+ resultItems = smartGrouping(resultItems, groupConfigs);
+ }
+
+ // run filter on sorted result items
+ const finalResultItems = this._forEachLevelFilter(
+ this.hooks.filterResults,
+ this._caches.filterResults,
+ type,
+ resultItems,
+ (h, r, idx, i) => h.call(r, context, idx, i),
+ false
+ );
+
+ // run merge on mapped items
+ let result = this._forEachLevel(
+ this.hooks.merge,
+ this._caches.merge,
+ type,
+ h => h.call(finalResultItems, context)
+ );
+ if (result === undefined) result = finalResultItems;
+
+ // run result on merged items
+ return this._forEachLevelWaterfall(
+ this.hooks.result,
+ this._caches.result,
+ type,
+ result,
+ (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;