Index: imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsFactoryPlugin.js
===================================================================
--- imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsFactoryPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsFactoryPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,2614 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const util = require("util");
+const { WEBPACK_MODULE_TYPE_RUNTIME } = require("../ModuleTypeConstants");
+const ModuleDependency = require("../dependencies/ModuleDependency");
+const formatLocation = require("../formatLocation");
+const { LogType } = require("../logging/Logger");
+const AggressiveSplittingPlugin = require("../optimize/AggressiveSplittingPlugin");
+const SizeLimitsPlugin = require("../performance/SizeLimitsPlugin");
+const { countIterable } = require("../util/IterableHelpers");
+const {
+	compareLocations,
+	compareChunksById,
+	compareNumbers,
+	compareIds,
+	concatComparators,
+	compareSelect,
+	compareModulesByIdentifier
+} = require("../util/comparators");
+const { makePathsRelative, parseResource } = require("../util/identifier");
+
+/** @typedef {import("webpack-sources").Source} Source */
+/** @typedef {import("../Chunk")} Chunk */
+/** @typedef {import("../Chunk").ChunkId} ChunkId */
+/** @typedef {import("../ChunkGroup")} ChunkGroup */
+/** @typedef {import("../ChunkGroup").OriginRecord} OriginRecord */
+/** @typedef {import("../Compilation")} Compilation */
+/** @typedef {import("../Compilation").Asset} Asset */
+/** @typedef {import("../Compilation").AssetInfo} AssetInfo */
+/** @typedef {import("../Compilation").NormalizedStatsOptions} NormalizedStatsOptions */
+/** @typedef {import("../Compiler")} Compiler */
+/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
+/** @typedef {import("../Dependency")} Dependency */
+/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
+/** @typedef {import("../Module")} Module */
+/** @typedef {import("../Module").BuildInfo} BuildInfo */
+/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
+/** @typedef {import("../ModuleProfile")} ModuleProfile */
+/** @typedef {import("../RequestShortener")} RequestShortener */
+/** @typedef {import("../WebpackError")} WebpackError */
+/** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
+/**
+ * @template T
+ * @typedef {import("../util/comparators").Comparator<T>} Comparator<T>
+ */
+/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
+/**
+ * @template T, R
+ * @typedef {import("../util/smartGrouping").GroupConfig<T, R>} GroupConfig
+ */
+/** @typedef {import("./StatsFactory")} StatsFactory */
+/** @typedef {import("./StatsFactory").StatsFactoryContext} StatsFactoryContext */
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsCompilation} StatsCompilation */
+/**
+ * @typedef {object} KnownStatsCompilation
+ * @property {any=} env
+ * @property {string=} name
+ * @property {string=} hash
+ * @property {string=} version
+ * @property {number=} time
+ * @property {number=} builtAt
+ * @property {boolean=} needAdditionalPass
+ * @property {string=} publicPath
+ * @property {string=} outputPath
+ * @property {Record<string, string[]>=} assetsByChunkName
+ * @property {StatsAsset[]=} assets
+ * @property {number=} filteredAssets
+ * @property {StatsChunk[]=} chunks
+ * @property {StatsModule[]=} modules
+ * @property {number=} filteredModules
+ * @property {Record<string, StatsChunkGroup>=} entrypoints
+ * @property {Record<string, StatsChunkGroup>=} namedChunkGroups
+ * @property {StatsError[]=} errors
+ * @property {number=} errorsCount
+ * @property {StatsError[]=} warnings
+ * @property {number=} warningsCount
+ * @property {StatsCompilation[]=} children
+ * @property {Record<string, StatsLogging>=} logging
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsLogging} StatsLogging */
+/**
+ * @typedef {object} KnownStatsLogging
+ * @property {StatsLoggingEntry[]} entries
+ * @property {number} filteredEntries
+ * @property {boolean} debug
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsLoggingEntry} StatsLoggingEntry */
+/**
+ * @typedef {object} KnownStatsLoggingEntry
+ * @property {string} type
+ * @property {string=} message
+ * @property {string[]=} trace
+ * @property {StatsLoggingEntry[]=} children
+ * @property {any[]=} args
+ * @property {number=} time
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsAsset} StatsAsset */
+/**
+ * @typedef {object} KnownStatsAsset
+ * @property {string} type
+ * @property {string} name
+ * @property {AssetInfo} info
+ * @property {number} size
+ * @property {boolean} emitted
+ * @property {boolean} comparedForEmit
+ * @property {boolean} cached
+ * @property {StatsAsset[]=} related
+ * @property {(string|number)[]=} chunkNames
+ * @property {(string|number)[]=} chunkIdHints
+ * @property {(string|number)[]=} chunks
+ * @property {(string|number)[]=} auxiliaryChunkNames
+ * @property {(string|number)[]=} auxiliaryChunks
+ * @property {(string|number)[]=} auxiliaryChunkIdHints
+ * @property {number=} filteredRelated
+ * @property {boolean=} isOverSizeLimit
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsChunkGroup} StatsChunkGroup */
+/**
+ * @typedef {object} KnownStatsChunkGroup
+ * @property {(string | null)=} name
+ * @property {(string | number)[]=} chunks
+ * @property {({ name: string, size?: number })[]=} assets
+ * @property {number=} filteredAssets
+ * @property {number=} assetsSize
+ * @property {({ name: string, size?: number })[]=} auxiliaryAssets
+ * @property {number=} filteredAuxiliaryAssets
+ * @property {number=} auxiliaryAssetsSize
+ * @property {{ [x: string]: StatsChunkGroup[] }=} children
+ * @property {{ [x: string]: string[] }=} childAssets
+ * @property {boolean=} isOverSizeLimit
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsModule} StatsModule */
+/**
+ * @typedef {object} KnownStatsModule
+ * @property {string=} type
+ * @property {string=} moduleType
+ * @property {(string | null)=} layer
+ * @property {string=} identifier
+ * @property {string=} name
+ * @property {(string | null)=} nameForCondition
+ * @property {number=} index
+ * @property {number=} preOrderIndex
+ * @property {number=} index2
+ * @property {number=} postOrderIndex
+ * @property {number=} size
+ * @property {{ [x: string]: number }=} sizes
+ * @property {boolean=} cacheable
+ * @property {boolean=} built
+ * @property {boolean=} codeGenerated
+ * @property {boolean=} buildTimeExecuted
+ * @property {boolean=} cached
+ * @property {boolean=} optional
+ * @property {boolean=} orphan
+ * @property {string | number=} id
+ * @property {string | number | null=} issuerId
+ * @property {(string | number)[]=} chunks
+ * @property {(string | number)[]=} assets
+ * @property {boolean=} dependent
+ * @property {(string | null)=} issuer
+ * @property {(string | null)=} issuerName
+ * @property {StatsModuleIssuer[]=} issuerPath
+ * @property {boolean=} failed
+ * @property {number=} errors
+ * @property {number=} warnings
+ * @property {StatsProfile=} profile
+ * @property {StatsModuleReason[]=} reasons
+ * @property {(boolean | null | string[])=} usedExports
+ * @property {(string[] | null)=} providedExports
+ * @property {string[]=} optimizationBailout
+ * @property {(number | null)=} depth
+ * @property {StatsModule[]=} modules
+ * @property {number=} filteredModules
+ * @property {ReturnType<Source["source"]>=} source
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsProfile} StatsProfile */
+/**
+ * @typedef {object} KnownStatsProfile
+ * @property {number} total
+ * @property {number} resolving
+ * @property {number} restoring
+ * @property {number} building
+ * @property {number} integration
+ * @property {number} storing
+ * @property {number} additionalResolving
+ * @property {number} additionalIntegration
+ * @property {number} factory
+ * @property {number} dependencies
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsModuleIssuer} StatsModuleIssuer */
+/**
+ * @typedef {object} KnownStatsModuleIssuer
+ * @property {string} identifier
+ * @property {string} name
+ * @property {(string|number)=} id
+ * @property {StatsProfile} profile
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsModuleReason} StatsModuleReason */
+/**
+ * @typedef {object} KnownStatsModuleReason
+ * @property {string | null} moduleIdentifier
+ * @property {string | null} module
+ * @property {string | null} moduleName
+ * @property {string | null} resolvedModuleIdentifier
+ * @property {string | null} resolvedModule
+ * @property {string | null} type
+ * @property {boolean} active
+ * @property {string | null} explanation
+ * @property {string | null} userRequest
+ * @property {(string | null)=} loc
+ * @property {(string | number | null)=} moduleId
+ * @property {(string | number | null)=} resolvedModuleId
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsChunk} StatsChunk */
+/**
+ * @typedef {object} KnownStatsChunk
+ * @property {boolean} rendered
+ * @property {boolean} initial
+ * @property {boolean} entry
+ * @property {boolean} recorded
+ * @property {string=} reason
+ * @property {number} size
+ * @property {Record<string, number>} sizes
+ * @property {string[]} names
+ * @property {string[]} idHints
+ * @property {string[]=} runtime
+ * @property {string[]} files
+ * @property {string[]} auxiliaryFiles
+ * @property {string} hash
+ * @property {Record<string, (string|number)[]>} childrenByOrder
+ * @property {(string|number)=} id
+ * @property {(string|number)[]=} siblings
+ * @property {(string|number)[]=} parents
+ * @property {(string|number)[]=} children
+ * @property {StatsModule[]=} modules
+ * @property {number=} filteredModules
+ * @property {StatsChunkOrigin[]=} origins
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsChunkOrigin} StatsChunkOrigin */
+/**
+ * @typedef {object} KnownStatsChunkOrigin
+ * @property {string} module
+ * @property {string} moduleIdentifier
+ * @property {string} moduleName
+ * @property {string} loc
+ * @property {string} request
+ * @property {(string | number)=} moduleId
+ */
+
+/** @typedef { Record<string, EXPECTED_ANY> & KnownStatsModuleTraceItem} StatsModuleTraceItem */
+/**
+ * @typedef {object} KnownStatsModuleTraceItem
+ * @property {string=} originIdentifier
+ * @property {string=} originName
+ * @property {string=} moduleIdentifier
+ * @property {string=} moduleName
+ * @property {StatsModuleTraceDependency[]=} dependencies
+ * @property {(string|number)=} originId
+ * @property {(string|number)=} moduleId
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsModuleTraceDependency} StatsModuleTraceDependency */
+/**
+ * @typedef {object} KnownStatsModuleTraceDependency
+ * @property {string=} loc
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsError} StatsError */
+/**
+ * @typedef {object} KnownStatsError
+ * @property {string} message
+ * @property {string=} chunkName
+ * @property {boolean=} chunkEntry
+ * @property {boolean=} chunkInitial
+ * @property {string=} file
+ * @property {string=} moduleIdentifier
+ * @property {string=} moduleName
+ * @property {string=} loc
+ * @property {ChunkId=} chunkId
+ * @property {string|number=} moduleId
+ * @property {StatsModuleTraceItem[]=} moduleTrace
+ * @property {any=} details
+ * @property {string=} stack
+ */
+
+/** @typedef {Asset & { type: string, related: PreprocessedAsset[] | undefined }} PreprocessedAsset */
+
+/**
+ * @template T
+ * @template O
+ * @typedef {Record<string, (object: O, data: T, context: StatsFactoryContext, options: NormalizedStatsOptions, factory: StatsFactory) => void>} ExtractorsByOption
+ */
+
+/**
+ * @typedef {object} SimpleExtractors
+ * @property {ExtractorsByOption<Compilation, StatsCompilation>} compilation
+ * @property {ExtractorsByOption<PreprocessedAsset, StatsAsset>} asset
+ * @property {ExtractorsByOption<PreprocessedAsset, StatsAsset>} asset$visible
+ * @property {ExtractorsByOption<{ name: string, chunkGroup: ChunkGroup }, StatsChunkGroup>} chunkGroup
+ * @property {ExtractorsByOption<Module, StatsModule>} module
+ * @property {ExtractorsByOption<Module, StatsModule>} module$visible
+ * @property {ExtractorsByOption<Module, StatsModuleIssuer>} moduleIssuer
+ * @property {ExtractorsByOption<ModuleProfile, StatsProfile>} profile
+ * @property {ExtractorsByOption<ModuleGraphConnection, StatsModuleReason>} moduleReason
+ * @property {ExtractorsByOption<Chunk, StatsChunk>} chunk
+ * @property {ExtractorsByOption<OriginRecord, StatsChunkOrigin>} chunkOrigin
+ * @property {ExtractorsByOption<WebpackError, StatsError>} error
+ * @property {ExtractorsByOption<WebpackError, StatsError>} warning
+ * @property {ExtractorsByOption<{ origin: Module, module: Module }, StatsModuleTraceItem>} moduleTraceItem
+ * @property {ExtractorsByOption<Dependency, StatsModuleTraceDependency>} moduleTraceDependency
+ */
+
+/**
+ * @template T
+ * @template I
+ * @param {Iterable<T>} items items to select from
+ * @param {function(T): Iterable<I>} selector selector function to select values from item
+ * @returns {I[]} array of values
+ */
+const uniqueArray = (items, selector) => {
+	/** @type {Set<I>} */
+	const set = new Set();
+	for (const item of items) {
+		for (const i of selector(item)) {
+			set.add(i);
+		}
+	}
+	return Array.from(set);
+};
+
+/**
+ * @template T
+ * @template I
+ * @param {Iterable<T>} items items to select from
+ * @param {function(T): Iterable<I>} selector selector function to select values from item
+ * @param {Comparator<I>} comparator comparator function
+ * @returns {I[]} array of values
+ */
+const uniqueOrderedArray = (items, selector, comparator) =>
+	uniqueArray(items, selector).sort(comparator);
+
+/** @template T @template R @typedef {{ [P in keyof T]: R }} MappedValues<T, R> */
+
+/**
+ * @template {object} T
+ * @template {object} R
+ * @param {T} obj object to be mapped
+ * @param {function(T[keyof T], keyof T): R} fn mapping function
+ * @returns {MappedValues<T, R>} mapped object
+ */
+const mapObject = (obj, fn) => {
+	const newObj = Object.create(null);
+	for (const key of Object.keys(obj)) {
+		newObj[key] = fn(
+			obj[/** @type {keyof T} */ (key)],
+			/** @type {keyof T} */ (key)
+		);
+	}
+	return newObj;
+};
+
+/**
+ * @param {Compilation} compilation the compilation
+ * @param {function(Compilation, string): any[]} getItems get items
+ * @returns {number} total number
+ */
+const countWithChildren = (compilation, getItems) => {
+	let count = getItems(compilation, "").length;
+	for (const child of compilation.children) {
+		count += countWithChildren(child, (c, type) =>
+			getItems(c, `.children[].compilation${type}`)
+		);
+	}
+	return count;
+};
+
+/** @type {ExtractorsByOption<WebpackError | string, StatsError>} */
+const EXTRACT_ERROR = {
+	_: (object, error, context, { requestShortener }) => {
+		// TODO webpack 6 disallow strings in the errors/warnings list
+		if (typeof error === "string") {
+			object.message = error;
+		} else {
+			if (error.chunk) {
+				object.chunkName = error.chunk.name;
+				object.chunkEntry = error.chunk.hasRuntime();
+				object.chunkInitial = error.chunk.canBeInitial();
+			}
+			if (error.file) {
+				object.file = error.file;
+			}
+			if (error.module) {
+				object.moduleIdentifier = error.module.identifier();
+				object.moduleName = error.module.readableIdentifier(requestShortener);
+			}
+			if (error.loc) {
+				object.loc = formatLocation(error.loc);
+			}
+			object.message = error.message;
+		}
+	},
+	ids: (object, error, { compilation: { chunkGraph } }) => {
+		if (typeof error !== "string") {
+			if (error.chunk) {
+				object.chunkId = /** @type {ChunkId} */ (error.chunk.id);
+			}
+			if (error.module) {
+				object.moduleId =
+					/** @type {ModuleId} */
+					(chunkGraph.getModuleId(error.module));
+			}
+		}
+	},
+	moduleTrace: (object, error, context, options, factory) => {
+		if (typeof error !== "string" && error.module) {
+			const {
+				type,
+				compilation: { moduleGraph }
+			} = context;
+			/** @type {Set<Module>} */
+			const visitedModules = new Set();
+			const moduleTrace = [];
+			let current = error.module;
+			while (current) {
+				if (visitedModules.has(current)) break; // circular (technically impossible, but how knows)
+				visitedModules.add(current);
+				const origin = moduleGraph.getIssuer(current);
+				if (!origin) break;
+				moduleTrace.push({ origin, module: current });
+				current = origin;
+			}
+			object.moduleTrace = factory.create(
+				`${type}.moduleTrace`,
+				moduleTrace,
+				context
+			);
+		}
+	},
+	errorDetails: (
+		object,
+		error,
+		{ type, compilation, cachedGetErrors, cachedGetWarnings },
+		{ errorDetails }
+	) => {
+		if (
+			typeof error !== "string" &&
+			(errorDetails === true ||
+				(type.endsWith(".error") && cachedGetErrors(compilation).length < 3))
+		) {
+			object.details = error.details;
+		}
+	},
+	errorStack: (object, error) => {
+		if (typeof error !== "string") {
+			object.stack = error.stack;
+		}
+	}
+};
+
+/** @type {SimpleExtractors} */
+const SIMPLE_EXTRACTORS = {
+	compilation: {
+		_: (object, compilation, context, options) => {
+			if (!context.makePathsRelative) {
+				context.makePathsRelative = makePathsRelative.bindContextCache(
+					compilation.compiler.context,
+					compilation.compiler.root
+				);
+			}
+			if (!context.cachedGetErrors) {
+				const map = new WeakMap();
+				context.cachedGetErrors = compilation =>
+					map.get(compilation) ||
+					// eslint-disable-next-line no-sequences
+					(errors => (map.set(compilation, errors), errors))(
+						compilation.getErrors()
+					);
+			}
+			if (!context.cachedGetWarnings) {
+				const map = new WeakMap();
+				context.cachedGetWarnings = compilation =>
+					map.get(compilation) ||
+					// eslint-disable-next-line no-sequences
+					(warnings => (map.set(compilation, warnings), warnings))(
+						compilation.getWarnings()
+					);
+			}
+			if (compilation.name) {
+				object.name = compilation.name;
+			}
+			if (compilation.needAdditionalPass) {
+				object.needAdditionalPass = true;
+			}
+
+			const { logging, loggingDebug, loggingTrace } = options;
+			if (logging || (loggingDebug && loggingDebug.length > 0)) {
+				const util = require("util");
+				object.logging = {};
+				let acceptedTypes;
+				let collapsedGroups = false;
+				switch (logging) {
+					case "error":
+						acceptedTypes = new Set([LogType.error]);
+						break;
+					case "warn":
+						acceptedTypes = new Set([LogType.error, LogType.warn]);
+						break;
+					case "info":
+						acceptedTypes = new Set([
+							LogType.error,
+							LogType.warn,
+							LogType.info
+						]);
+						break;
+					case "log":
+						acceptedTypes = new Set([
+							LogType.error,
+							LogType.warn,
+							LogType.info,
+							LogType.log,
+							LogType.group,
+							LogType.groupEnd,
+							LogType.groupCollapsed,
+							LogType.clear
+						]);
+						break;
+					case "verbose":
+						acceptedTypes = new Set([
+							LogType.error,
+							LogType.warn,
+							LogType.info,
+							LogType.log,
+							LogType.group,
+							LogType.groupEnd,
+							LogType.groupCollapsed,
+							LogType.profile,
+							LogType.profileEnd,
+							LogType.time,
+							LogType.status,
+							LogType.clear
+						]);
+						collapsedGroups = true;
+						break;
+					default:
+						acceptedTypes = new Set();
+						break;
+				}
+				const cachedMakePathsRelative = makePathsRelative.bindContextCache(
+					options.context,
+					compilation.compiler.root
+				);
+				let depthInCollapsedGroup = 0;
+				for (const [origin, logEntries] of compilation.logging) {
+					const debugMode = loggingDebug.some(fn => fn(origin));
+					if (logging === false && !debugMode) continue;
+					/** @type {KnownStatsLoggingEntry[]} */
+					const groupStack = [];
+					/** @type {KnownStatsLoggingEntry[]} */
+					const rootList = [];
+					let currentList = rootList;
+					let processedLogEntries = 0;
+					for (const entry of logEntries) {
+						let type = entry.type;
+						if (!debugMode && !acceptedTypes.has(type)) continue;
+
+						// Expand groups in verbose and debug modes
+						if (
+							type === LogType.groupCollapsed &&
+							(debugMode || collapsedGroups)
+						)
+							type = LogType.group;
+
+						if (depthInCollapsedGroup === 0) {
+							processedLogEntries++;
+						}
+
+						if (type === LogType.groupEnd) {
+							groupStack.pop();
+							currentList =
+								groupStack.length > 0
+									? /** @type {KnownStatsLoggingEntry[]} */ (
+											groupStack[groupStack.length - 1].children
+										)
+									: rootList;
+							if (depthInCollapsedGroup > 0) depthInCollapsedGroup--;
+							continue;
+						}
+						let message;
+						if (entry.type === LogType.time) {
+							const [label, first, second] =
+								/** @type {[string, number, number]} */
+								(entry.args);
+							message = `${label}: ${first * 1000 + second / 1000000} ms`;
+						} else if (entry.args && entry.args.length > 0) {
+							message = util.format(entry.args[0], ...entry.args.slice(1));
+						}
+						/** @type {KnownStatsLoggingEntry} */
+						const newEntry = {
+							...entry,
+							type,
+							message,
+							trace: loggingTrace ? entry.trace : undefined,
+							children:
+								type === LogType.group || type === LogType.groupCollapsed
+									? []
+									: undefined
+						};
+						currentList.push(newEntry);
+						if (newEntry.children) {
+							groupStack.push(newEntry);
+							currentList = newEntry.children;
+							if (depthInCollapsedGroup > 0) {
+								depthInCollapsedGroup++;
+							} else if (type === LogType.groupCollapsed) {
+								depthInCollapsedGroup = 1;
+							}
+						}
+					}
+					let name = cachedMakePathsRelative(origin).replace(/\|/g, " ");
+					if (name in object.logging) {
+						let i = 1;
+						while (`${name}#${i}` in object.logging) {
+							i++;
+						}
+						name = `${name}#${i}`;
+					}
+					object.logging[name] = {
+						entries: rootList,
+						filteredEntries: logEntries.length - processedLogEntries,
+						debug: debugMode
+					};
+				}
+			}
+		},
+		hash: (object, compilation) => {
+			object.hash = /** @type {string} */ (compilation.hash);
+		},
+		version: object => {
+			object.version = require("../../package.json").version;
+		},
+		env: (object, compilation, context, { _env }) => {
+			object.env = _env;
+		},
+		timings: (object, compilation) => {
+			object.time =
+				/** @type {number} */ (compilation.endTime) -
+				/** @type {number} */ (compilation.startTime);
+		},
+		builtAt: (object, compilation) => {
+			object.builtAt = /** @type {number} */ (compilation.endTime);
+		},
+		publicPath: (object, compilation) => {
+			object.publicPath = compilation.getPath(
+				/** @type {TemplatePath} */
+				(compilation.outputOptions.publicPath)
+			);
+		},
+		outputPath: (object, compilation) => {
+			object.outputPath = /** @type {string} */ (
+				compilation.outputOptions.path
+			);
+		},
+		assets: (object, compilation, context, options, factory) => {
+			const { type } = context;
+			/** @type {Map<string, Chunk[]>} */
+			const compilationFileToChunks = new Map();
+			/** @type {Map<string, Chunk[]>} */
+			const compilationAuxiliaryFileToChunks = new Map();
+			for (const chunk of compilation.chunks) {
+				for (const file of chunk.files) {
+					let array = compilationFileToChunks.get(file);
+					if (array === undefined) {
+						array = [];
+						compilationFileToChunks.set(file, array);
+					}
+					array.push(chunk);
+				}
+				for (const file of chunk.auxiliaryFiles) {
+					let array = compilationAuxiliaryFileToChunks.get(file);
+					if (array === undefined) {
+						array = [];
+						compilationAuxiliaryFileToChunks.set(file, array);
+					}
+					array.push(chunk);
+				}
+			}
+			/** @type {Map<string, PreprocessedAsset>} */
+			const assetMap = new Map();
+			/** @type {Set<PreprocessedAsset>} */
+			const assets = new Set();
+			for (const asset of compilation.getAssets()) {
+				/** @type {PreprocessedAsset} */
+				const item = {
+					...asset,
+					type: "asset",
+					related: undefined
+				};
+				assets.add(item);
+				assetMap.set(asset.name, item);
+			}
+			for (const item of assetMap.values()) {
+				const related = item.info.related;
+				if (!related) continue;
+				for (const type of Object.keys(related)) {
+					const relatedEntry = related[type];
+					const deps = Array.isArray(relatedEntry)
+						? relatedEntry
+						: [relatedEntry];
+					for (const dep of deps) {
+						const depItem = assetMap.get(dep);
+						if (!depItem) continue;
+						assets.delete(depItem);
+						depItem.type = type;
+						item.related = item.related || [];
+						item.related.push(depItem);
+					}
+				}
+			}
+
+			object.assetsByChunkName = {};
+			for (const [file, chunks] of compilationFileToChunks) {
+				for (const chunk of chunks) {
+					const name = chunk.name;
+					if (!name) continue;
+					if (
+						!Object.prototype.hasOwnProperty.call(
+							object.assetsByChunkName,
+							name
+						)
+					) {
+						object.assetsByChunkName[name] = [];
+					}
+					object.assetsByChunkName[name].push(file);
+				}
+			}
+
+			const groupedAssets = factory.create(
+				`${type}.assets`,
+				Array.from(assets),
+				{
+					...context,
+					compilationFileToChunks,
+					compilationAuxiliaryFileToChunks
+				}
+			);
+			const limited = spaceLimited(
+				groupedAssets,
+				/** @type {number} */ (options.assetsSpace)
+			);
+			object.assets = limited.children;
+			object.filteredAssets = limited.filteredChildren;
+		},
+		chunks: (object, compilation, context, options, factory) => {
+			const { type } = context;
+			object.chunks = factory.create(
+				`${type}.chunks`,
+				Array.from(compilation.chunks),
+				context
+			);
+		},
+		modules: (object, compilation, context, options, factory) => {
+			const { type } = context;
+			const array = Array.from(compilation.modules);
+			const groupedModules = factory.create(`${type}.modules`, array, context);
+			const limited = spaceLimited(groupedModules, options.modulesSpace);
+			object.modules = limited.children;
+			object.filteredModules = limited.filteredChildren;
+		},
+		entrypoints: (
+			object,
+			compilation,
+			context,
+			{ entrypoints, chunkGroups, chunkGroupAuxiliary, chunkGroupChildren },
+			factory
+		) => {
+			const { type } = context;
+			const array = Array.from(compilation.entrypoints, ([key, value]) => ({
+				name: key,
+				chunkGroup: value
+			}));
+			if (entrypoints === "auto" && !chunkGroups) {
+				if (array.length > 5) return;
+				if (
+					!chunkGroupChildren &&
+					array.every(({ chunkGroup }) => {
+						if (chunkGroup.chunks.length !== 1) return false;
+						const chunk = chunkGroup.chunks[0];
+						return (
+							chunk.files.size === 1 &&
+							(!chunkGroupAuxiliary || chunk.auxiliaryFiles.size === 0)
+						);
+					})
+				) {
+					return;
+				}
+			}
+			object.entrypoints = factory.create(
+				`${type}.entrypoints`,
+				array,
+				context
+			);
+		},
+		chunkGroups: (object, compilation, context, options, factory) => {
+			const { type } = context;
+			const array = Array.from(
+				compilation.namedChunkGroups,
+				([key, value]) => ({
+					name: key,
+					chunkGroup: value
+				})
+			);
+			object.namedChunkGroups = factory.create(
+				`${type}.namedChunkGroups`,
+				array,
+				context
+			);
+		},
+		errors: (object, compilation, context, options, factory) => {
+			const { type, cachedGetErrors } = context;
+			const rawErrors = cachedGetErrors(compilation);
+			const factorizedErrors = factory.create(
+				`${type}.errors`,
+				cachedGetErrors(compilation),
+				context
+			);
+			let filtered = 0;
+			if (options.errorDetails === "auto" && rawErrors.length >= 3) {
+				filtered = rawErrors
+					.map(e => typeof e !== "string" && e.details)
+					.filter(Boolean).length;
+			}
+			if (
+				options.errorDetails === true ||
+				!Number.isFinite(options.errorsSpace)
+			) {
+				object.errors = factorizedErrors;
+				if (filtered) object.filteredErrorDetailsCount = filtered;
+				return;
+			}
+			const [errors, filteredBySpace] = errorsSpaceLimit(
+				factorizedErrors,
+				/** @type {number} */
+				(options.errorsSpace)
+			);
+			object.filteredErrorDetailsCount = filtered + filteredBySpace;
+			object.errors = errors;
+		},
+		errorsCount: (object, compilation, { cachedGetErrors }) => {
+			object.errorsCount = countWithChildren(compilation, c =>
+				cachedGetErrors(c)
+			);
+		},
+		warnings: (object, compilation, context, options, factory) => {
+			const { type, cachedGetWarnings } = context;
+			const rawWarnings = factory.create(
+				`${type}.warnings`,
+				cachedGetWarnings(compilation),
+				context
+			);
+			let filtered = 0;
+			if (options.errorDetails === "auto") {
+				filtered = cachedGetWarnings(compilation)
+					.map(e => typeof e !== "string" && e.details)
+					.filter(Boolean).length;
+			}
+			if (
+				options.errorDetails === true ||
+				!Number.isFinite(options.warningsSpace)
+			) {
+				object.warnings = rawWarnings;
+				if (filtered) object.filteredWarningDetailsCount = filtered;
+				return;
+			}
+			const [warnings, filteredBySpace] = errorsSpaceLimit(
+				rawWarnings,
+				/** @type {number} */
+				(options.warningsSpace)
+			);
+			object.filteredWarningDetailsCount = filtered + filteredBySpace;
+			object.warnings = warnings;
+		},
+		warningsCount: (
+			object,
+			compilation,
+			context,
+			{ warningsFilter },
+			factory
+		) => {
+			const { type, cachedGetWarnings } = context;
+			object.warningsCount = countWithChildren(compilation, (c, childType) => {
+				if (
+					!warningsFilter &&
+					/** @type {((warning: StatsError, textValue: string) => boolean)[]} */
+					(warningsFilter).length === 0
+				)
+					return cachedGetWarnings(c);
+				return factory
+					.create(`${type}${childType}.warnings`, cachedGetWarnings(c), context)
+					.filter(
+						/**
+						 * @param {TODO} warning warning
+						 * @returns {boolean} result
+						 */
+						warning => {
+							const warningString = Object.keys(warning)
+								.map(
+									key =>
+										`${warning[/** @type {keyof KnownStatsError} */ (key)]}`
+								)
+								.join("\n");
+							return !warningsFilter.some(filter =>
+								filter(warning, warningString)
+							);
+						}
+					);
+			});
+		},
+		children: (object, compilation, context, options, factory) => {
+			const { type } = context;
+			object.children = factory.create(
+				`${type}.children`,
+				compilation.children,
+				context
+			);
+		}
+	},
+	asset: {
+		_: (object, asset, context, options, factory) => {
+			const { compilation } = context;
+			object.type = asset.type;
+			object.name = asset.name;
+			object.size = asset.source.size();
+			object.emitted = compilation.emittedAssets.has(asset.name);
+			object.comparedForEmit = compilation.comparedForEmitAssets.has(
+				asset.name
+			);
+			const cached = !object.emitted && !object.comparedForEmit;
+			object.cached = cached;
+			object.info = asset.info;
+			if (!cached || options.cachedAssets) {
+				Object.assign(
+					object,
+					factory.create(`${context.type}$visible`, asset, context)
+				);
+			}
+		}
+	},
+	asset$visible: {
+		_: (
+			object,
+			asset,
+			{ compilation, compilationFileToChunks, compilationAuxiliaryFileToChunks }
+		) => {
+			const chunks = compilationFileToChunks.get(asset.name) || [];
+			const auxiliaryChunks =
+				compilationAuxiliaryFileToChunks.get(asset.name) || [];
+			object.chunkNames = uniqueOrderedArray(
+				chunks,
+				c => (c.name ? [c.name] : []),
+				compareIds
+			);
+			object.chunkIdHints = uniqueOrderedArray(
+				chunks,
+				c => Array.from(c.idNameHints),
+				compareIds
+			);
+			object.auxiliaryChunkNames = uniqueOrderedArray(
+				auxiliaryChunks,
+				c => (c.name ? [c.name] : []),
+				compareIds
+			);
+			object.auxiliaryChunkIdHints = uniqueOrderedArray(
+				auxiliaryChunks,
+				c => Array.from(c.idNameHints),
+				compareIds
+			);
+			object.filteredRelated = asset.related ? asset.related.length : undefined;
+		},
+		relatedAssets: (object, asset, context, options, factory) => {
+			const { type } = context;
+			object.related = factory.create(
+				`${type.slice(0, -8)}.related`,
+				asset.related || [],
+				context
+			);
+			object.filteredRelated = asset.related
+				? asset.related.length -
+					/** @type {StatsAsset[]} */ (object.related).length
+				: undefined;
+		},
+		ids: (
+			object,
+			asset,
+			{ compilationFileToChunks, compilationAuxiliaryFileToChunks }
+		) => {
+			const chunks = compilationFileToChunks.get(asset.name) || [];
+			const auxiliaryChunks =
+				compilationAuxiliaryFileToChunks.get(asset.name) || [];
+			object.chunks = uniqueOrderedArray(
+				chunks,
+				c => /** @type {ChunkId[]} */ (c.ids),
+				compareIds
+			);
+			object.auxiliaryChunks = uniqueOrderedArray(
+				auxiliaryChunks,
+				c => /** @type {ChunkId[]} */ (c.ids),
+				compareIds
+			);
+		},
+		performance: (object, asset) => {
+			object.isOverSizeLimit = SizeLimitsPlugin.isOverSizeLimit(asset.source);
+		}
+	},
+	chunkGroup: {
+		_: (
+			object,
+			{ name, chunkGroup },
+			{ compilation, compilation: { moduleGraph, chunkGraph } },
+			{ ids, chunkGroupAuxiliary, chunkGroupChildren, chunkGroupMaxAssets }
+		) => {
+			const children =
+				chunkGroupChildren &&
+				chunkGroup.getChildrenByOrders(moduleGraph, chunkGraph);
+			/**
+			 * @param {string} name Name
+			 * @returns {{ name: string, size: number }} Asset object
+			 */
+			const toAsset = name => {
+				const asset = compilation.getAsset(name);
+				return {
+					name,
+					size: /** @type {number} */ (asset ? asset.info.size : -1)
+				};
+			};
+			/** @type {(total: number, asset: { size: number }) => number} */
+			const sizeReducer = (total, { size }) => total + size;
+			const assets = uniqueArray(chunkGroup.chunks, c => c.files).map(toAsset);
+			const auxiliaryAssets = uniqueOrderedArray(
+				chunkGroup.chunks,
+				c => c.auxiliaryFiles,
+				compareIds
+			).map(toAsset);
+			const assetsSize = assets.reduce(sizeReducer, 0);
+			const auxiliaryAssetsSize = auxiliaryAssets.reduce(sizeReducer, 0);
+			/** @type {KnownStatsChunkGroup} */
+			const statsChunkGroup = {
+				name,
+				chunks: ids
+					? /** @type {ChunkId[]} */ (chunkGroup.chunks.map(c => c.id))
+					: undefined,
+				assets: assets.length <= chunkGroupMaxAssets ? assets : undefined,
+				filteredAssets:
+					assets.length <= chunkGroupMaxAssets ? 0 : assets.length,
+				assetsSize,
+				auxiliaryAssets:
+					chunkGroupAuxiliary && auxiliaryAssets.length <= chunkGroupMaxAssets
+						? auxiliaryAssets
+						: undefined,
+				filteredAuxiliaryAssets:
+					chunkGroupAuxiliary && auxiliaryAssets.length <= chunkGroupMaxAssets
+						? 0
+						: auxiliaryAssets.length,
+				auxiliaryAssetsSize,
+				children: children
+					? mapObject(children, groups =>
+							groups.map(group => {
+								const assets = uniqueArray(group.chunks, c => c.files).map(
+									toAsset
+								);
+								const auxiliaryAssets = uniqueOrderedArray(
+									group.chunks,
+									c => c.auxiliaryFiles,
+									compareIds
+								).map(toAsset);
+
+								/** @type {KnownStatsChunkGroup} */
+								const childStatsChunkGroup = {
+									name: group.name,
+									chunks: ids
+										? /** @type {ChunkId[]} */
+											(group.chunks.map(c => c.id))
+										: undefined,
+									assets:
+										assets.length <= chunkGroupMaxAssets ? assets : undefined,
+									filteredAssets:
+										assets.length <= chunkGroupMaxAssets ? 0 : assets.length,
+									auxiliaryAssets:
+										chunkGroupAuxiliary &&
+										auxiliaryAssets.length <= chunkGroupMaxAssets
+											? auxiliaryAssets
+											: undefined,
+									filteredAuxiliaryAssets:
+										chunkGroupAuxiliary &&
+										auxiliaryAssets.length <= chunkGroupMaxAssets
+											? 0
+											: auxiliaryAssets.length
+								};
+
+								return childStatsChunkGroup;
+							})
+						)
+					: undefined,
+				childAssets: children
+					? mapObject(children, groups => {
+							/** @type {Set<string>} */
+							const set = new Set();
+							for (const group of groups) {
+								for (const chunk of group.chunks) {
+									for (const asset of chunk.files) {
+										set.add(asset);
+									}
+								}
+							}
+							return Array.from(set);
+						})
+					: undefined
+			};
+			Object.assign(object, statsChunkGroup);
+		},
+		performance: (object, { chunkGroup }) => {
+			object.isOverSizeLimit = SizeLimitsPlugin.isOverSizeLimit(chunkGroup);
+		}
+	},
+	module: {
+		_: (object, module, context, options, factory) => {
+			const { type } = context;
+			const compilation = /** @type {Compilation} */ (context.compilation);
+			const built = compilation.builtModules.has(module);
+			const codeGenerated = compilation.codeGeneratedModules.has(module);
+			const buildTimeExecuted =
+				compilation.buildTimeExecutedModules.has(module);
+			/** @type {{[x: string]: number}} */
+			const sizes = {};
+			for (const sourceType of module.getSourceTypes()) {
+				sizes[sourceType] = module.size(sourceType);
+			}
+			/** @type {KnownStatsModule} */
+			const statsModule = {
+				type: "module",
+				moduleType: module.type,
+				layer: module.layer,
+				size: module.size(),
+				sizes,
+				built,
+				codeGenerated,
+				buildTimeExecuted,
+				cached: !built && !codeGenerated
+			};
+			Object.assign(object, statsModule);
+
+			if (built || codeGenerated || options.cachedModules) {
+				Object.assign(
+					object,
+					factory.create(`${type}$visible`, module, context)
+				);
+			}
+		}
+	},
+	module$visible: {
+		_: (object, module, context, { requestShortener }, factory) => {
+			const { type, rootModules } = context;
+			const compilation = /** @type {Compilation} */ (context.compilation);
+			const { moduleGraph } = compilation;
+			/** @type {Module[]} */
+			const path = [];
+			const issuer = moduleGraph.getIssuer(module);
+			let current = issuer;
+			while (current) {
+				path.push(current);
+				current = moduleGraph.getIssuer(current);
+			}
+			path.reverse();
+			const profile = moduleGraph.getProfile(module);
+			const errors = module.getErrors();
+			const errorsCount = errors !== undefined ? countIterable(errors) : 0;
+			const warnings = module.getWarnings();
+			const warningsCount =
+				warnings !== undefined ? countIterable(warnings) : 0;
+			/** @type {KnownStatsModule} */
+			const statsModule = {
+				identifier: module.identifier(),
+				name: module.readableIdentifier(requestShortener),
+				nameForCondition: module.nameForCondition(),
+				index: /** @type {number} */ (moduleGraph.getPreOrderIndex(module)),
+				preOrderIndex: /** @type {number} */ (
+					moduleGraph.getPreOrderIndex(module)
+				),
+				index2: /** @type {number} */ (moduleGraph.getPostOrderIndex(module)),
+				postOrderIndex: /** @type {number} */ (
+					moduleGraph.getPostOrderIndex(module)
+				),
+				cacheable: /** @type {BuildInfo} */ (module.buildInfo).cacheable,
+				optional: module.isOptional(moduleGraph),
+				orphan:
+					!type.endsWith("module.modules[].module$visible") &&
+					compilation.chunkGraph.getNumberOfModuleChunks(module) === 0,
+				dependent: rootModules ? !rootModules.has(module) : undefined,
+				issuer: issuer && issuer.identifier(),
+				issuerName: issuer && issuer.readableIdentifier(requestShortener),
+				issuerPath:
+					issuer &&
+					factory.create(`${type.slice(0, -8)}.issuerPath`, path, context),
+				failed: errorsCount > 0,
+				errors: errorsCount,
+				warnings: warningsCount
+			};
+			Object.assign(object, statsModule);
+			if (profile) {
+				object.profile = factory.create(
+					`${type.slice(0, -8)}.profile`,
+					profile,
+					context
+				);
+			}
+		},
+		ids: (object, module, { compilation: { chunkGraph, moduleGraph } }) => {
+			object.id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
+			const issuer = moduleGraph.getIssuer(module);
+			object.issuerId = issuer && chunkGraph.getModuleId(issuer);
+			object.chunks =
+				/** @type {ChunkId[]} */
+				(
+					Array.from(
+						chunkGraph.getOrderedModuleChunksIterable(
+							module,
+							compareChunksById
+						),
+						chunk => chunk.id
+					)
+				);
+		},
+		moduleAssets: (object, module) => {
+			object.assets = /** @type {BuildInfo} */ (module.buildInfo).assets
+				? Object.keys(/** @type {BuildInfo} */ (module.buildInfo).assets)
+				: [];
+		},
+		reasons: (object, module, context, options, factory) => {
+			const {
+				type,
+				compilation: { moduleGraph }
+			} = context;
+			const groupsReasons = factory.create(
+				`${type.slice(0, -8)}.reasons`,
+				Array.from(moduleGraph.getIncomingConnections(module)),
+				context
+			);
+			const limited = spaceLimited(
+				groupsReasons,
+				/** @type {number} */
+				(options.reasonsSpace)
+			);
+			object.reasons = limited.children;
+			object.filteredReasons = limited.filteredChildren;
+		},
+		usedExports: (
+			object,
+			module,
+			{ runtime, compilation: { moduleGraph } }
+		) => {
+			const usedExports = moduleGraph.getUsedExports(module, runtime);
+			if (usedExports === null) {
+				object.usedExports = null;
+			} else if (typeof usedExports === "boolean") {
+				object.usedExports = usedExports;
+			} else {
+				object.usedExports = Array.from(usedExports);
+			}
+		},
+		providedExports: (object, module, { compilation: { moduleGraph } }) => {
+			const providedExports = moduleGraph.getProvidedExports(module);
+			object.providedExports = Array.isArray(providedExports)
+				? providedExports
+				: null;
+		},
+		optimizationBailout: (
+			object,
+			module,
+			{ compilation: { moduleGraph } },
+			{ requestShortener }
+		) => {
+			object.optimizationBailout = moduleGraph
+				.getOptimizationBailout(module)
+				.map(item => {
+					if (typeof item === "function") return item(requestShortener);
+					return item;
+				});
+		},
+		depth: (object, module, { compilation: { moduleGraph } }) => {
+			object.depth = moduleGraph.getDepth(module);
+		},
+		nestedModules: (object, module, context, options, factory) => {
+			const { type } = context;
+			const innerModules = /** @type {Module & { modules?: Module[] }} */ (
+				module
+			).modules;
+			if (Array.isArray(innerModules)) {
+				const groupedModules = factory.create(
+					`${type.slice(0, -8)}.modules`,
+					innerModules,
+					context
+				);
+				const limited = spaceLimited(
+					groupedModules,
+					options.nestedModulesSpace
+				);
+				object.modules = limited.children;
+				object.filteredModules = limited.filteredChildren;
+			}
+		},
+		source: (object, module) => {
+			const originalSource = module.originalSource();
+			if (originalSource) {
+				object.source = originalSource.source();
+			}
+		}
+	},
+	profile: {
+		_: (object, profile) => {
+			/** @type {KnownStatsProfile} */
+			const statsProfile = {
+				total:
+					profile.factory +
+					profile.restoring +
+					profile.integration +
+					profile.building +
+					profile.storing,
+				resolving: profile.factory,
+				restoring: profile.restoring,
+				building: profile.building,
+				integration: profile.integration,
+				storing: profile.storing,
+				additionalResolving: profile.additionalFactories,
+				additionalIntegration: profile.additionalIntegration,
+				// TODO remove this in webpack 6
+				factory: profile.factory,
+				// TODO remove this in webpack 6
+				dependencies: profile.additionalFactories
+			};
+			Object.assign(object, statsProfile);
+		}
+	},
+	moduleIssuer: {
+		_: (object, module, context, { requestShortener }, factory) => {
+			const { type } = context;
+			const compilation = /** @type {Compilation} */ (context.compilation);
+			const { moduleGraph } = compilation;
+			const profile = moduleGraph.getProfile(module);
+			/** @type {Partial<KnownStatsModuleIssuer>} */
+			const statsModuleIssuer = {
+				identifier: module.identifier(),
+				name: module.readableIdentifier(requestShortener)
+			};
+			Object.assign(object, statsModuleIssuer);
+			if (profile) {
+				object.profile = factory.create(`${type}.profile`, profile, context);
+			}
+		},
+		ids: (object, module, { compilation: { chunkGraph } }) => {
+			object.id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
+		}
+	},
+	moduleReason: {
+		_: (object, reason, { runtime }, { requestShortener }) => {
+			const dep = reason.dependency;
+			const moduleDep =
+				dep && dep instanceof ModuleDependency ? dep : undefined;
+			/** @type {KnownStatsModuleReason} */
+			const statsModuleReason = {
+				moduleIdentifier: reason.originModule
+					? reason.originModule.identifier()
+					: null,
+				module: reason.originModule
+					? reason.originModule.readableIdentifier(requestShortener)
+					: null,
+				moduleName: reason.originModule
+					? reason.originModule.readableIdentifier(requestShortener)
+					: null,
+				resolvedModuleIdentifier: reason.resolvedOriginModule
+					? reason.resolvedOriginModule.identifier()
+					: null,
+				resolvedModule: reason.resolvedOriginModule
+					? reason.resolvedOriginModule.readableIdentifier(requestShortener)
+					: null,
+				type: reason.dependency ? reason.dependency.type : null,
+				active: reason.isActive(runtime),
+				explanation: reason.explanation,
+				userRequest: (moduleDep && moduleDep.userRequest) || null
+			};
+			Object.assign(object, statsModuleReason);
+			if (reason.dependency) {
+				const locInfo = formatLocation(reason.dependency.loc);
+				if (locInfo) {
+					object.loc = locInfo;
+				}
+			}
+		},
+		ids: (object, reason, { compilation: { chunkGraph } }) => {
+			object.moduleId = reason.originModule
+				? chunkGraph.getModuleId(reason.originModule)
+				: null;
+			object.resolvedModuleId = reason.resolvedOriginModule
+				? chunkGraph.getModuleId(reason.resolvedOriginModule)
+				: null;
+		}
+	},
+	chunk: {
+		_: (object, chunk, { makePathsRelative, compilation: { chunkGraph } }) => {
+			const childIdByOrder = chunk.getChildIdsByOrders(chunkGraph);
+
+			/** @type {KnownStatsChunk} */
+			const statsChunk = {
+				rendered: chunk.rendered,
+				initial: chunk.canBeInitial(),
+				entry: chunk.hasRuntime(),
+				recorded: AggressiveSplittingPlugin.wasChunkRecorded(chunk),
+				reason: chunk.chunkReason,
+				size: chunkGraph.getChunkModulesSize(chunk),
+				sizes: chunkGraph.getChunkModulesSizes(chunk),
+				names: chunk.name ? [chunk.name] : [],
+				idHints: Array.from(chunk.idNameHints),
+				runtime:
+					chunk.runtime === undefined
+						? undefined
+						: typeof chunk.runtime === "string"
+							? [makePathsRelative(chunk.runtime)]
+							: Array.from(chunk.runtime.sort(), makePathsRelative),
+				files: Array.from(chunk.files),
+				auxiliaryFiles: Array.from(chunk.auxiliaryFiles).sort(compareIds),
+				hash: /** @type {string} */ (chunk.renderedHash),
+				childrenByOrder: childIdByOrder
+			};
+			Object.assign(object, statsChunk);
+		},
+		ids: (object, chunk) => {
+			object.id = /** @type {ChunkId} */ (chunk.id);
+		},
+		chunkRelations: (object, chunk, { compilation: { chunkGraph } }) => {
+			/** @type {Set<string|number>} */
+			const parents = new Set();
+			/** @type {Set<string|number>} */
+			const children = new Set();
+			/** @type {Set<string|number>} */
+			const siblings = new Set();
+
+			for (const chunkGroup of chunk.groupsIterable) {
+				for (const parentGroup of chunkGroup.parentsIterable) {
+					for (const chunk of parentGroup.chunks) {
+						parents.add(/** @type {ChunkId} */ (chunk.id));
+					}
+				}
+				for (const childGroup of chunkGroup.childrenIterable) {
+					for (const chunk of childGroup.chunks) {
+						children.add(/** @type {ChunkId} */ (chunk.id));
+					}
+				}
+				for (const sibling of chunkGroup.chunks) {
+					if (sibling !== chunk)
+						siblings.add(/** @type {ChunkId} */ (sibling.id));
+				}
+			}
+			object.siblings = Array.from(siblings).sort(compareIds);
+			object.parents = Array.from(parents).sort(compareIds);
+			object.children = Array.from(children).sort(compareIds);
+		},
+		chunkModules: (object, chunk, context, options, factory) => {
+			const {
+				type,
+				compilation: { chunkGraph }
+			} = context;
+			const array = chunkGraph.getChunkModules(chunk);
+			const groupedModules = factory.create(`${type}.modules`, array, {
+				...context,
+				runtime: chunk.runtime,
+				rootModules: new Set(chunkGraph.getChunkRootModules(chunk))
+			});
+			const limited = spaceLimited(groupedModules, options.chunkModulesSpace);
+			object.modules = limited.children;
+			object.filteredModules = limited.filteredChildren;
+		},
+		chunkOrigins: (object, chunk, context, options, factory) => {
+			const {
+				type,
+				compilation: { chunkGraph }
+			} = context;
+			/** @type {Set<string>} */
+			const originsKeySet = new Set();
+			const origins = [];
+			for (const g of chunk.groupsIterable) {
+				origins.push(...g.origins);
+			}
+			const array = origins.filter(origin => {
+				const key = [
+					origin.module ? chunkGraph.getModuleId(origin.module) : undefined,
+					formatLocation(origin.loc),
+					origin.request
+				].join();
+				if (originsKeySet.has(key)) return false;
+				originsKeySet.add(key);
+				return true;
+			});
+			object.origins = factory.create(`${type}.origins`, array, context);
+		}
+	},
+	chunkOrigin: {
+		_: (object, origin, context, { requestShortener }) => {
+			/** @type {KnownStatsChunkOrigin} */
+			const statsChunkOrigin = {
+				module: origin.module ? origin.module.identifier() : "",
+				moduleIdentifier: origin.module ? origin.module.identifier() : "",
+				moduleName: origin.module
+					? origin.module.readableIdentifier(requestShortener)
+					: "",
+				loc: formatLocation(origin.loc),
+				request: origin.request
+			};
+			Object.assign(object, statsChunkOrigin);
+		},
+		ids: (object, origin, { compilation: { chunkGraph } }) => {
+			object.moduleId = origin.module
+				? /** @type {ModuleId} */ (chunkGraph.getModuleId(origin.module))
+				: undefined;
+		}
+	},
+	error: EXTRACT_ERROR,
+	warning: EXTRACT_ERROR,
+	moduleTraceItem: {
+		_: (object, { origin, module }, context, { requestShortener }, factory) => {
+			const {
+				type,
+				compilation: { moduleGraph }
+			} = context;
+			object.originIdentifier = origin.identifier();
+			object.originName = origin.readableIdentifier(requestShortener);
+			object.moduleIdentifier = module.identifier();
+			object.moduleName = module.readableIdentifier(requestShortener);
+			const dependencies = Array.from(
+				moduleGraph.getIncomingConnections(module)
+			)
+				.filter(c => c.resolvedOriginModule === origin && c.dependency)
+				.map(c => c.dependency);
+			object.dependencies = factory.create(
+				`${type}.dependencies`,
+				Array.from(new Set(dependencies)),
+				context
+			);
+		},
+		ids: (object, { origin, module }, { compilation: { chunkGraph } }) => {
+			object.originId =
+				/** @type {ModuleId} */
+				(chunkGraph.getModuleId(origin));
+			object.moduleId =
+				/** @type {ModuleId} */
+				(chunkGraph.getModuleId(module));
+		}
+	},
+	moduleTraceDependency: {
+		_: (object, dependency) => {
+			object.loc = formatLocation(dependency.loc);
+		}
+	}
+};
+
+/** @type {Record<string, Record<string, (thing: any, context: StatsFactoryContext, options: NormalizedStatsOptions) => boolean | undefined>>} */
+const FILTER = {
+	"module.reasons": {
+		"!orphanModules": (reason, { compilation: { chunkGraph } }) => {
+			if (
+				reason.originModule &&
+				chunkGraph.getNumberOfModuleChunks(reason.originModule) === 0
+			) {
+				return false;
+			}
+		}
+	}
+};
+
+/** @type {Record<string, Record<string, (thing: KnownStatsError, context: StatsFactoryContext, options: NormalizedStatsOptions) => boolean | undefined>>} */
+const FILTER_RESULTS = {
+	"compilation.warnings": {
+		warningsFilter: util.deprecate(
+			(warning, context, { warningsFilter }) => {
+				const warningString = Object.keys(warning)
+					.map(key => `${warning[/** @type {keyof KnownStatsError} */ (key)]}`)
+					.join("\n");
+				return !warningsFilter.some(filter => filter(warning, warningString));
+			},
+			"config.stats.warningsFilter is deprecated in favor of config.ignoreWarnings",
+			"DEP_WEBPACK_STATS_WARNINGS_FILTER"
+		)
+	}
+};
+
+/** @type {Record<string, (comparators: Function[], context: StatsFactoryContext) => void>} */
+const MODULES_SORTER = {
+	_: (comparators, { compilation: { moduleGraph } }) => {
+		comparators.push(
+			compareSelect(
+				/**
+				 * @param {Module} m module
+				 * @returns {number | null} depth
+				 */
+				m => moduleGraph.getDepth(m),
+				compareNumbers
+			),
+			compareSelect(
+				/**
+				 * @param {Module} m module
+				 * @returns {number | null} index
+				 */
+				m => moduleGraph.getPreOrderIndex(m),
+				compareNumbers
+			),
+			compareSelect(
+				/**
+				 * @param {Module} m module
+				 * @returns {string} identifier
+				 */
+				m => m.identifier(),
+				compareIds
+			)
+		);
+	}
+};
+
+/** @type {Record<string, Record<string, (comparators: Function[], context: StatsFactoryContext) => void>>} */
+const SORTERS = {
+	"compilation.chunks": {
+		_: comparators => {
+			comparators.push(compareSelect(c => c.id, compareIds));
+		}
+	},
+	"compilation.modules": MODULES_SORTER,
+	"chunk.rootModules": MODULES_SORTER,
+	"chunk.modules": MODULES_SORTER,
+	"module.modules": MODULES_SORTER,
+	"module.reasons": {
+		_: (comparators, { compilation: { chunkGraph } }) => {
+			comparators.push(
+				compareSelect(x => x.originModule, compareModulesByIdentifier)
+			);
+			comparators.push(
+				compareSelect(x => x.resolvedOriginModule, compareModulesByIdentifier)
+			);
+			comparators.push(
+				compareSelect(
+					x => x.dependency,
+					concatComparators(
+						compareSelect(
+							/**
+							 * @param {Dependency} x dependency
+							 * @returns {DependencyLocation} location
+							 */
+							x => x.loc,
+							compareLocations
+						),
+						compareSelect(x => x.type, compareIds)
+					)
+				)
+			);
+		}
+	},
+	"chunk.origins": {
+		_: (comparators, { compilation: { chunkGraph } }) => {
+			comparators.push(
+				compareSelect(
+					origin =>
+						origin.module ? chunkGraph.getModuleId(origin.module) : undefined,
+					compareIds
+				),
+				compareSelect(origin => formatLocation(origin.loc), compareIds),
+				compareSelect(origin => origin.request, compareIds)
+			);
+		}
+	}
+};
+
+/**
+ * @template T
+ * @typedef {T & { children: Children<T>[] | undefined, filteredChildren?: number }} Children
+ */
+
+/**
+ * @template T
+ * @param {Children<T>} item item
+ * @returns {number} item size
+ */
+const getItemSize = item =>
+	// Each item takes 1 line
+	// + the size of the children
+	// + 1 extra line when it has children and filteredChildren
+	!item.children
+		? 1
+		: item.filteredChildren
+			? 2 + getTotalSize(item.children)
+			: 1 + getTotalSize(item.children);
+
+/**
+ * @template T
+ * @param {Children<T>[]} children children
+ * @returns {number} total size
+ */
+const getTotalSize = children => {
+	let size = 0;
+	for (const child of children) {
+		size += getItemSize(child);
+	}
+	return size;
+};
+
+/**
+ * @template T
+ * @param {Children<T>[]} children children
+ * @returns {number} total items
+ */
+const getTotalItems = children => {
+	let count = 0;
+	for (const child of children) {
+		if (!child.children && !child.filteredChildren) {
+			count++;
+		} else {
+			if (child.children) count += getTotalItems(child.children);
+			if (child.filteredChildren) count += child.filteredChildren;
+		}
+	}
+	return count;
+};
+
+/**
+ * @template T
+ * @param {Children<T>[]} children children
+ * @returns {Children<T>[]} collapsed children
+ */
+const collapse = children => {
+	// After collapse each child must take exactly one line
+	const newChildren = [];
+	for (const child of children) {
+		if (child.children) {
+			let filteredChildren = child.filteredChildren || 0;
+			filteredChildren += getTotalItems(child.children);
+			newChildren.push({
+				...child,
+				children: undefined,
+				filteredChildren
+			});
+		} else {
+			newChildren.push(child);
+		}
+	}
+	return newChildren;
+};
+
+/**
+ * @template T
+ * @param {Children<T>[]} itemsAndGroups item and groups
+ * @param {number} max max
+ * @param {boolean=} filteredChildrenLineReserved filtered children line reserved
+ * @returns {Children<T>} result
+ */
+const spaceLimited = (
+	itemsAndGroups,
+	max,
+	filteredChildrenLineReserved = false
+) => {
+	if (max < 1) {
+		return /** @type {Children<T>} */ ({
+			children: undefined,
+			filteredChildren: getTotalItems(itemsAndGroups)
+		});
+	}
+	/** @type {Children<T>[] | undefined} */
+	let children;
+	/** @type {number | undefined} */
+	let filteredChildren;
+	// This are the groups, which take 1+ lines each
+	/** @type {Children<T>[] | undefined} */
+	const groups = [];
+	// The sizes of the groups are stored in groupSizes
+	/** @type {number[]} */
+	const groupSizes = [];
+	// This are the items, which take 1 line each
+	const items = [];
+	// The total of group sizes
+	let groupsSize = 0;
+
+	for (const itemOrGroup of itemsAndGroups) {
+		// is item
+		if (!itemOrGroup.children && !itemOrGroup.filteredChildren) {
+			items.push(itemOrGroup);
+		} else {
+			groups.push(itemOrGroup);
+			const size = getItemSize(itemOrGroup);
+			groupSizes.push(size);
+			groupsSize += size;
+		}
+	}
+
+	if (groupsSize + items.length <= max) {
+		// The total size in the current state fits into the max
+		// keep all
+		children = groups.length > 0 ? groups.concat(items) : items;
+	} else if (groups.length === 0) {
+		// slice items to max
+		// inner space marks that lines for filteredChildren already reserved
+		const limit = max - (filteredChildrenLineReserved ? 0 : 1);
+		filteredChildren = items.length - limit;
+		items.length = limit;
+		children = items;
+	} else {
+		// limit is the size when all groups are collapsed
+		const limit =
+			groups.length +
+			(filteredChildrenLineReserved || items.length === 0 ? 0 : 1);
+		if (limit < max) {
+			// calculate how much we are over the size limit
+			// this allows to approach the limit faster
+			let oversize;
+			// If each group would take 1 line the total would be below the maximum
+			// collapse some groups, keep items
+			while (
+				(oversize =
+					groupsSize +
+					items.length +
+					(filteredChildren && !filteredChildrenLineReserved ? 1 : 0) -
+					max) > 0
+			) {
+				// Find the maximum group and process only this one
+				const maxGroupSize = Math.max(...groupSizes);
+				if (maxGroupSize < items.length) {
+					filteredChildren = items.length;
+					items.length = 0;
+					continue;
+				}
+				for (let i = 0; i < groups.length; i++) {
+					if (groupSizes[i] === maxGroupSize) {
+						const group = groups[i];
+						// run this algorithm recursively and limit the size of the children to
+						// current size - oversize / number of groups
+						// So it should always end up being smaller
+						const headerSize = group.filteredChildren ? 2 : 1;
+						const limited = spaceLimited(
+							/** @type {Children<T>} */ (group.children),
+							maxGroupSize -
+								// we should use ceil to always feet in max
+								Math.ceil(oversize / groups.length) -
+								// we substitute size of group head
+								headerSize,
+							headerSize === 2
+						);
+						groups[i] = {
+							...group,
+							children: limited.children,
+							filteredChildren: limited.filteredChildren
+								? (group.filteredChildren || 0) + limited.filteredChildren
+								: group.filteredChildren
+						};
+						const newSize = getItemSize(groups[i]);
+						groupsSize -= maxGroupSize - newSize;
+						groupSizes[i] = newSize;
+						break;
+					}
+				}
+			}
+			children = groups.concat(items);
+		} else if (limit === max) {
+			// If we have only enough space to show one line per group and one line for the filtered items
+			// collapse all groups and items
+			children = collapse(groups);
+			filteredChildren = items.length;
+		} else {
+			// If we have no space
+			// collapse complete group
+			filteredChildren = getTotalItems(itemsAndGroups);
+		}
+	}
+
+	return /** @type {Children<T>} */ ({ children, filteredChildren });
+};
+
+/**
+ * @param {StatsError[]} errors errors
+ * @param {number} max max
+ * @returns {[StatsError[], number]} error space limit
+ */
+const errorsSpaceLimit = (errors, max) => {
+	let filtered = 0;
+	// Can not fit into limit
+	// print only messages
+	if (errors.length + 1 >= max)
+		return [
+			errors.map(error => {
+				if (typeof error === "string" || !error.details) return error;
+				filtered++;
+				return { ...error, details: "" };
+			}),
+			filtered
+		];
+	let fullLength = errors.length;
+	let result = errors;
+
+	let i = 0;
+	for (; i < errors.length; i++) {
+		const error = errors[i];
+		if (typeof error !== "string" && error.details) {
+			const splitted = error.details.split("\n");
+			const len = splitted.length;
+			fullLength += len;
+			if (fullLength > max) {
+				result = i > 0 ? errors.slice(0, i) : [];
+				const overLimit = fullLength - max + 1;
+				const error = errors[i++];
+				result.push({
+					...error,
+					details: error.details.split("\n").slice(0, -overLimit).join("\n"),
+					filteredDetails: overLimit
+				});
+				filtered = errors.length - i;
+				for (; i < errors.length; i++) {
+					const error = errors[i];
+					if (typeof error === "string" || !error.details) result.push(error);
+					result.push({ ...error, details: "" });
+				}
+				break;
+			} else if (fullLength === max) {
+				result = errors.slice(0, ++i);
+				filtered = errors.length - i;
+				for (; i < errors.length; i++) {
+					const error = errors[i];
+					if (typeof error === "string" || !error.details) result.push(error);
+					result.push({ ...error, details: "" });
+				}
+				break;
+			}
+		}
+	}
+
+	return [result, filtered];
+};
+
+/**
+ * @template {{ size: number }} T
+ * @template {{ size: number }} R
+ * @param {(R | T)[]} children children
+ * @param {T[]} assets assets
+ * @returns {{ size: number }} asset size
+ */
+const assetGroup = (children, assets) => {
+	let size = 0;
+	for (const asset of children) {
+		size += asset.size;
+	}
+	return { size };
+};
+
+/**
+ * @template {{ size: number, sizes: Record<string, number> }} T
+ * @param {Children<T>[]} children children
+ * @param {KnownStatsModule[]} modules modules
+ * @returns {{ size: number, sizes: Record<string, number>}} size and sizes
+ */
+const moduleGroup = (children, modules) => {
+	let size = 0;
+	/** @type {Record<string, number>} */
+	const sizes = {};
+	for (const module of children) {
+		size += module.size;
+		for (const key of Object.keys(module.sizes)) {
+			sizes[key] = (sizes[key] || 0) + module.sizes[key];
+		}
+	}
+	return {
+		size,
+		sizes
+	};
+};
+
+/**
+ * @template {{ active: boolean }} T
+ * @param {Children<T>[]} children children
+ * @param {KnownStatsModuleReason[]} reasons reasons
+ * @returns {{ active: boolean }} reason group
+ */
+const reasonGroup = (children, reasons) => {
+	let active = false;
+	for (const reason of children) {
+		active = active || reason.active;
+	}
+	return {
+		active
+	};
+};
+
+const GROUP_EXTENSION_REGEXP = /(\.[^.]+?)(?:\?|(?: \+ \d+ modules?)?$)/;
+const GROUP_PATH_REGEXP = /(.+)[/\\][^/\\]+?(?:\?|(?: \+ \d+ modules?)?$)/;
+
+/** @typedef {Record<string, (groupConfigs: GroupConfig<KnownStatsAsset, TODO>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} AssetsGroupers */
+
+/** @type {AssetsGroupers} */
+const ASSETS_GROUPERS = {
+	_: (groupConfigs, context, options) => {
+		/**
+		 * @param {keyof KnownStatsAsset} name name
+		 * @param {boolean=} exclude need exclude?
+		 */
+		const groupByFlag = (name, exclude) => {
+			groupConfigs.push({
+				getKeys: asset => (asset[name] ? ["1"] : undefined),
+				getOptions: () => ({
+					groupChildren: !exclude,
+					force: exclude
+				}),
+				createGroup: (key, children, assets) =>
+					exclude
+						? {
+								type: "assets by status",
+								[name]: Boolean(key),
+								filteredChildren: assets.length,
+								...assetGroup(children, assets)
+							}
+						: {
+								type: "assets by status",
+								[name]: Boolean(key),
+								children,
+								...assetGroup(children, assets)
+							}
+			});
+		};
+		const {
+			groupAssetsByEmitStatus,
+			groupAssetsByPath,
+			groupAssetsByExtension
+		} = options;
+		if (groupAssetsByEmitStatus) {
+			groupByFlag("emitted");
+			groupByFlag("comparedForEmit");
+			groupByFlag("isOverSizeLimit");
+		}
+		if (groupAssetsByEmitStatus || !options.cachedAssets) {
+			groupByFlag("cached", !options.cachedAssets);
+		}
+		if (groupAssetsByPath || groupAssetsByExtension) {
+			groupConfigs.push({
+				getKeys: asset => {
+					const extensionMatch =
+						groupAssetsByExtension && GROUP_EXTENSION_REGEXP.exec(asset.name);
+					const extension = extensionMatch ? extensionMatch[1] : "";
+					const pathMatch =
+						groupAssetsByPath && GROUP_PATH_REGEXP.exec(asset.name);
+					const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
+					const keys = [];
+					if (groupAssetsByPath) {
+						keys.push(".");
+						if (extension)
+							keys.push(
+								path.length
+									? `${path.join("/")}/*${extension}`
+									: `*${extension}`
+							);
+						while (path.length > 0) {
+							keys.push(`${path.join("/")}/`);
+							path.pop();
+						}
+					} else if (extension) {
+						keys.push(`*${extension}`);
+					}
+					return keys;
+				},
+				createGroup: (key, children, assets) => ({
+					type: groupAssetsByPath ? "assets by path" : "assets by extension",
+					name: key,
+					children,
+					...assetGroup(children, assets)
+				})
+			});
+		}
+	},
+	groupAssetsByInfo: (groupConfigs, context, options) => {
+		/**
+		 * @param {string} name name
+		 */
+		const groupByAssetInfoFlag = name => {
+			groupConfigs.push({
+				getKeys: asset => (asset.info && asset.info[name] ? ["1"] : undefined),
+				createGroup: (key, children, assets) => ({
+					type: "assets by info",
+					info: {
+						[name]: Boolean(key)
+					},
+					children,
+					...assetGroup(children, assets)
+				})
+			});
+		};
+		groupByAssetInfoFlag("immutable");
+		groupByAssetInfoFlag("development");
+		groupByAssetInfoFlag("hotModuleReplacement");
+	},
+	groupAssetsByChunk: (groupConfigs, context, options) => {
+		/**
+		 * @param {keyof KnownStatsAsset} name name
+		 */
+		const groupByNames = name => {
+			groupConfigs.push({
+				getKeys: asset => /** @type {string[]} */ (asset[name]),
+				createGroup: (key, children, assets) => ({
+					type: "assets by chunk",
+					[name]: [key],
+					children,
+					...assetGroup(children, assets)
+				})
+			});
+		};
+		groupByNames("chunkNames");
+		groupByNames("auxiliaryChunkNames");
+		groupByNames("chunkIdHints");
+		groupByNames("auxiliaryChunkIdHints");
+	},
+	excludeAssets: (groupConfigs, context, { excludeAssets }) => {
+		groupConfigs.push({
+			getKeys: asset => {
+				const ident = asset.name;
+				const excluded = excludeAssets.some(fn => fn(ident, asset));
+				if (excluded) return ["excluded"];
+			},
+			getOptions: () => ({
+				groupChildren: false,
+				force: true
+			}),
+			createGroup: (key, children, assets) => ({
+				type: "hidden assets",
+				filteredChildren: assets.length,
+				...assetGroup(children, assets)
+			})
+		});
+	}
+};
+
+/** @typedef {Record<string, (groupConfigs: GroupConfig<KnownStatsModule, TODO>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} ModulesGroupers */
+
+/** @type {function("module" | "chunk" | "root-of-chunk" | "nested"): ModulesGroupers} */
+const MODULES_GROUPERS = type => ({
+	_: (groupConfigs, context, options) => {
+		/**
+		 * @param {keyof KnownStatsModule} name name
+		 * @param {string} type type
+		 * @param {boolean=} exclude need exclude?
+		 */
+		const groupByFlag = (name, type, exclude) => {
+			groupConfigs.push({
+				getKeys: module => (module[name] ? ["1"] : undefined),
+				getOptions: () => ({
+					groupChildren: !exclude,
+					force: exclude
+				}),
+				createGroup: (key, children, modules) => ({
+					type,
+					[name]: Boolean(key),
+					...(exclude ? { filteredChildren: modules.length } : { children }),
+					...moduleGroup(children, modules)
+				})
+			});
+		};
+		const {
+			groupModulesByCacheStatus,
+			groupModulesByLayer,
+			groupModulesByAttributes,
+			groupModulesByType,
+			groupModulesByPath,
+			groupModulesByExtension
+		} = options;
+		if (groupModulesByAttributes) {
+			groupByFlag("errors", "modules with errors");
+			groupByFlag("warnings", "modules with warnings");
+			groupByFlag("assets", "modules with assets");
+			groupByFlag("optional", "optional modules");
+		}
+		if (groupModulesByCacheStatus) {
+			groupByFlag("cacheable", "cacheable modules");
+			groupByFlag("built", "built modules");
+			groupByFlag("codeGenerated", "code generated modules");
+		}
+		if (groupModulesByCacheStatus || !options.cachedModules) {
+			groupByFlag("cached", "cached modules", !options.cachedModules);
+		}
+		if (groupModulesByAttributes || !options.orphanModules) {
+			groupByFlag("orphan", "orphan modules", !options.orphanModules);
+		}
+		if (groupModulesByAttributes || !options.dependentModules) {
+			groupByFlag("dependent", "dependent modules", !options.dependentModules);
+		}
+		if (groupModulesByType || !options.runtimeModules) {
+			groupConfigs.push({
+				getKeys: module => {
+					if (!module.moduleType) return;
+					if (groupModulesByType) {
+						return [module.moduleType.split("/", 1)[0]];
+					} else if (module.moduleType === WEBPACK_MODULE_TYPE_RUNTIME) {
+						return [WEBPACK_MODULE_TYPE_RUNTIME];
+					}
+				},
+				getOptions: key => {
+					const exclude =
+						key === WEBPACK_MODULE_TYPE_RUNTIME && !options.runtimeModules;
+					return {
+						groupChildren: !exclude,
+						force: exclude
+					};
+				},
+				createGroup: (key, children, modules) => {
+					const exclude =
+						key === WEBPACK_MODULE_TYPE_RUNTIME && !options.runtimeModules;
+					return {
+						type: `${key} modules`,
+						moduleType: key,
+						...(exclude ? { filteredChildren: modules.length } : { children }),
+						...moduleGroup(children, modules)
+					};
+				}
+			});
+		}
+		if (groupModulesByLayer) {
+			groupConfigs.push({
+				getKeys: module => /** @type {string[]} */ ([module.layer]),
+				createGroup: (key, children, modules) => ({
+					type: "modules by layer",
+					layer: key,
+					children,
+					...moduleGroup(children, modules)
+				})
+			});
+		}
+		if (groupModulesByPath || groupModulesByExtension) {
+			groupConfigs.push({
+				getKeys: module => {
+					if (!module.name) return;
+					const resource = parseResource(
+						/** @type {string} */ (module.name.split("!").pop())
+					).path;
+					const dataUrl = /^data:[^,;]+/.exec(resource);
+					if (dataUrl) return [dataUrl[0]];
+					const extensionMatch =
+						groupModulesByExtension && GROUP_EXTENSION_REGEXP.exec(resource);
+					const extension = extensionMatch ? extensionMatch[1] : "";
+					const pathMatch =
+						groupModulesByPath && GROUP_PATH_REGEXP.exec(resource);
+					const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
+					const keys = [];
+					if (groupModulesByPath) {
+						if (extension)
+							keys.push(
+								path.length
+									? `${path.join("/")}/*${extension}`
+									: `*${extension}`
+							);
+						while (path.length > 0) {
+							keys.push(`${path.join("/")}/`);
+							path.pop();
+						}
+					} else if (extension) {
+						keys.push(`*${extension}`);
+					}
+					return keys;
+				},
+				createGroup: (key, children, modules) => {
+					const isDataUrl = key.startsWith("data:");
+					return {
+						type: isDataUrl
+							? "modules by mime type"
+							: groupModulesByPath
+								? "modules by path"
+								: "modules by extension",
+						name: isDataUrl ? key.slice(/* 'data:'.length */ 5) : key,
+						children,
+						...moduleGroup(children, modules)
+					};
+				}
+			});
+		}
+	},
+	excludeModules: (groupConfigs, context, { excludeModules }) => {
+		groupConfigs.push({
+			getKeys: module => {
+				const name = module.name;
+				if (name) {
+					const excluded = excludeModules.some(fn => fn(name, module, type));
+					if (excluded) return ["1"];
+				}
+			},
+			getOptions: () => ({
+				groupChildren: false,
+				force: true
+			}),
+			createGroup: (key, children, modules) => ({
+				type: "hidden modules",
+				filteredChildren: children.length,
+				...moduleGroup(children, modules)
+			})
+		});
+	}
+});
+
+/** @typedef {Record<string, (groupConfigs: import("../util/smartGrouping").GroupConfig<KnownStatsModuleReason, TODO>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} ModuleReasonsGroupers */
+
+/** @type {ModuleReasonsGroupers} */
+const MODULE_REASONS_GROUPERS = {
+	groupReasonsByOrigin: groupConfigs => {
+		groupConfigs.push({
+			getKeys: reason => /** @type {string[]} */ ([reason.module]),
+			createGroup: (key, children, reasons) => ({
+				type: "from origin",
+				module: key,
+				children,
+				...reasonGroup(children, reasons)
+			})
+		});
+	}
+};
+
+/** @type {Record<string, AssetsGroupers | ModulesGroupers | ModuleReasonsGroupers>} */
+const RESULT_GROUPERS = {
+	"compilation.assets": ASSETS_GROUPERS,
+	"asset.related": ASSETS_GROUPERS,
+	"compilation.modules": MODULES_GROUPERS("module"),
+	"chunk.modules": MODULES_GROUPERS("chunk"),
+	"chunk.rootModules": MODULES_GROUPERS("root-of-chunk"),
+	"module.modules": MODULES_GROUPERS("nested"),
+	"module.reasons": MODULE_REASONS_GROUPERS
+};
+
+// remove a prefixed "!" that can be specified to reverse sort order
+/**
+ * @param {string} field a field name
+ * @returns {field} normalized field
+ */
+const normalizeFieldKey = field => {
+	if (field[0] === "!") {
+		return field.slice(1);
+	}
+	return field;
+};
+
+// if a field is prefixed by a "!" reverse sort order
+/**
+ * @param {string} field a field name
+ * @returns {boolean} result
+ */
+const sortOrderRegular = field => {
+	if (field[0] === "!") {
+		return false;
+	}
+	return true;
+};
+
+/**
+ * @template T
+ * @param {string} field field name
+ * @returns {function(T, T): 0 | 1 | -1} comparators
+ */
+const sortByField = field => {
+	if (!field) {
+		/**
+		 * @param {any} a first
+		 * @param {any} b second
+		 * @returns {-1|0|1} zero
+		 */
+		const noSort = (a, b) => 0;
+		return noSort;
+	}
+
+	const fieldKey = normalizeFieldKey(field);
+
+	let sortFn = compareSelect(m => m[fieldKey], compareIds);
+
+	// if a field is prefixed with a "!" the sort is reversed!
+	const sortIsRegular = sortOrderRegular(field);
+
+	if (!sortIsRegular) {
+		const oldSortFn = sortFn;
+		sortFn = (a, b) => oldSortFn(b, a);
+	}
+
+	return sortFn;
+};
+
+/** @type {Record<string, (comparators: Comparator<TODO>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} */
+const ASSET_SORTERS = {
+	assetsSort: (comparators, context, { assetsSort }) => {
+		comparators.push(sortByField(assetsSort));
+	},
+	_: comparators => {
+		comparators.push(compareSelect(a => a.name, compareIds));
+	}
+};
+
+/** @type {Record<string, Record<string, (comparators: Comparator<TODO>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>>} */
+const RESULT_SORTERS = {
+	"compilation.chunks": {
+		chunksSort: (comparators, context, { chunksSort }) => {
+			comparators.push(sortByField(chunksSort));
+		}
+	},
+	"compilation.modules": {
+		modulesSort: (comparators, context, { modulesSort }) => {
+			comparators.push(sortByField(modulesSort));
+		}
+	},
+	"chunk.modules": {
+		chunkModulesSort: (comparators, context, { chunkModulesSort }) => {
+			comparators.push(sortByField(chunkModulesSort));
+		}
+	},
+	"module.modules": {
+		nestedModulesSort: (comparators, context, { nestedModulesSort }) => {
+			comparators.push(sortByField(nestedModulesSort));
+		}
+	},
+	"compilation.assets": ASSET_SORTERS,
+	"asset.related": ASSET_SORTERS
+};
+
+/**
+ * @param {Record<string, Record<string, Function>>} config the config see above
+ * @param {NormalizedStatsOptions} options stats options
+ * @param {function(string, Function): void} fn handler function called for every active line in config
+ * @returns {void}
+ */
+const iterateConfig = (config, options, fn) => {
+	for (const hookFor of Object.keys(config)) {
+		const subConfig = config[hookFor];
+		for (const option of Object.keys(subConfig)) {
+			if (option !== "_") {
+				if (option.startsWith("!")) {
+					if (options[option.slice(1)]) continue;
+				} else {
+					const value = options[option];
+					if (
+						value === false ||
+						value === undefined ||
+						(Array.isArray(value) && value.length === 0)
+					)
+						continue;
+				}
+			}
+			fn(hookFor, subConfig[option]);
+		}
+	}
+};
+
+/** @type {Record<string, string>} */
+const ITEM_NAMES = {
+	"compilation.children[]": "compilation",
+	"compilation.modules[]": "module",
+	"compilation.entrypoints[]": "chunkGroup",
+	"compilation.namedChunkGroups[]": "chunkGroup",
+	"compilation.errors[]": "error",
+	"compilation.warnings[]": "warning",
+	"chunk.modules[]": "module",
+	"chunk.rootModules[]": "module",
+	"chunk.origins[]": "chunkOrigin",
+	"compilation.chunks[]": "chunk",
+	"compilation.assets[]": "asset",
+	"asset.related[]": "asset",
+	"module.issuerPath[]": "moduleIssuer",
+	"module.reasons[]": "moduleReason",
+	"module.modules[]": "module",
+	"module.children[]": "module",
+	"moduleTrace[]": "moduleTraceItem",
+	"moduleTraceItem.dependencies[]": "moduleTraceDependency"
+};
+
+/**
+ * @template T
+ * @typedef {{ name: T }} NamedObject
+ */
+
+/**
+ * @template {{ name: string }} T
+ * @param {T[]} items items to be merged
+ * @returns {NamedObject<T>} an object
+ */
+const mergeToObject = items => {
+	const obj = Object.create(null);
+	for (const item of items) {
+		obj[item.name] = item;
+	}
+	return obj;
+};
+
+/**
+ * @template {{ name: string }} T
+ * @type {Record<string, (items: T[]) => NamedObject<T>>}
+ */
+const MERGER = {
+	"compilation.entrypoints": mergeToObject,
+	"compilation.namedChunkGroups": mergeToObject
+};
+
+class DefaultStatsFactoryPlugin {
+	/**
+	 * Apply the plugin
+	 * @param {Compiler} compiler the compiler instance
+	 * @returns {void}
+	 */
+	apply(compiler) {
+		compiler.hooks.compilation.tap("DefaultStatsFactoryPlugin", compilation => {
+			compilation.hooks.statsFactory.tap(
+				"DefaultStatsFactoryPlugin",
+				/**
+				 * @param {StatsFactory} stats stats factory
+				 * @param {NormalizedStatsOptions} options stats options
+				 */
+				(stats, options) => {
+					iterateConfig(SIMPLE_EXTRACTORS, options, (hookFor, fn) => {
+						stats.hooks.extract
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (obj, data, ctx) =>
+								fn(obj, data, ctx, options, stats)
+							);
+					});
+					iterateConfig(FILTER, options, (hookFor, fn) => {
+						stats.hooks.filter
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (item, ctx, idx, i) =>
+								fn(item, ctx, options, idx, i)
+							);
+					});
+					iterateConfig(FILTER_RESULTS, options, (hookFor, fn) => {
+						stats.hooks.filterResults
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (item, ctx, idx, i) =>
+								fn(item, ctx, options, idx, i)
+							);
+					});
+					iterateConfig(SORTERS, options, (hookFor, fn) => {
+						stats.hooks.sort
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (comparators, ctx) =>
+								fn(comparators, ctx, options)
+							);
+					});
+					iterateConfig(RESULT_SORTERS, options, (hookFor, fn) => {
+						stats.hooks.sortResults
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (comparators, ctx) =>
+								fn(comparators, ctx, options)
+							);
+					});
+					iterateConfig(RESULT_GROUPERS, options, (hookFor, fn) => {
+						stats.hooks.groupResults
+							.for(hookFor)
+							.tap("DefaultStatsFactoryPlugin", (groupConfigs, ctx) =>
+								fn(groupConfigs, ctx, options)
+							);
+					});
+					for (const key of Object.keys(ITEM_NAMES)) {
+						const itemName = ITEM_NAMES[key];
+						stats.hooks.getItemName
+							.for(key)
+							.tap("DefaultStatsFactoryPlugin", () => itemName);
+					}
+					for (const key of Object.keys(MERGER)) {
+						const merger = MERGER[key];
+						stats.hooks.merge.for(key).tap("DefaultStatsFactoryPlugin", merger);
+					}
+					if (options.children) {
+						if (Array.isArray(options.children)) {
+							stats.hooks.getItemFactory
+								.for("compilation.children[].compilation")
+								.tap(
+									"DefaultStatsFactoryPlugin",
+									/**
+									 * @param {Compilation} comp compilation
+									 * @param {StatsFactoryContext} options options
+									 * @returns {StatsFactory | undefined} stats factory
+									 */
+									(comp, { _index: idx }) => {
+										const children =
+											/** @type {TODO} */
+											(options.children);
+										if (idx < children.length) {
+											return compilation.createStatsFactory(
+												compilation.createStatsOptions(children[idx])
+											);
+										}
+									}
+								);
+						} else if (options.children !== true) {
+							const childFactory = compilation.createStatsFactory(
+								compilation.createStatsOptions(options.children)
+							);
+							stats.hooks.getItemFactory
+								.for("compilation.children[].compilation")
+								.tap("DefaultStatsFactoryPlugin", () => childFactory);
+						}
+					}
+				}
+			);
+		});
+	}
+}
+module.exports = DefaultStatsFactoryPlugin;
Index: imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPresetPlugin.js
===================================================================
--- imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPresetPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPresetPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,386 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const RequestShortener = require("../RequestShortener");
+
+/** @typedef {import("../../declarations/WebpackOptions").StatsOptions} StatsOptions */
+/** @typedef {import("../Compilation")} Compilation */
+/** @typedef {import("../Compilation").CreateStatsOptionsContext} CreateStatsOptionsContext */
+/** @typedef {import("../Compiler")} Compiler */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsError} StatsError */
+
+/**
+ * @param {StatsOptions} options options
+ * @param {StatsOptions} defaults default options
+ */
+const applyDefaults = (options, defaults) => {
+	for (const _k of Object.keys(defaults)) {
+		const key = /** @type {keyof StatsOptions} */ (_k);
+		if (typeof options[key] === "undefined") {
+			/** @type {TODO} */
+			(options)[key] = defaults[key];
+		}
+	}
+};
+
+/** @typedef {Record<string, StatsOptions>} NamedPresets */
+/** @type {NamedPresets} */
+const NAMED_PRESETS = {
+	verbose: {
+		hash: true,
+		builtAt: true,
+		relatedAssets: true,
+		entrypoints: true,
+		chunkGroups: true,
+		ids: true,
+		modules: false,
+		chunks: true,
+		chunkRelations: true,
+		chunkModules: true,
+		dependentModules: true,
+		chunkOrigins: true,
+		depth: true,
+		env: true,
+		reasons: true,
+		usedExports: true,
+		providedExports: true,
+		optimizationBailout: true,
+		errorDetails: true,
+		errorStack: true,
+		publicPath: true,
+		logging: "verbose",
+		orphanModules: true,
+		runtimeModules: true,
+		exclude: false,
+		errorsSpace: Infinity,
+		warningsSpace: Infinity,
+		modulesSpace: Infinity,
+		chunkModulesSpace: Infinity,
+		assetsSpace: Infinity,
+		reasonsSpace: Infinity,
+		children: true
+	},
+	detailed: {
+		hash: true,
+		builtAt: true,
+		relatedAssets: true,
+		entrypoints: true,
+		chunkGroups: true,
+		ids: true,
+		chunks: true,
+		chunkRelations: true,
+		chunkModules: false,
+		chunkOrigins: true,
+		depth: true,
+		usedExports: true,
+		providedExports: true,
+		optimizationBailout: true,
+		errorDetails: true,
+		publicPath: true,
+		logging: true,
+		runtimeModules: true,
+		exclude: false,
+		errorsSpace: 1000,
+		warningsSpace: 1000,
+		modulesSpace: 1000,
+		assetsSpace: 1000,
+		reasonsSpace: 1000
+	},
+	minimal: {
+		all: false,
+		version: true,
+		timings: true,
+		modules: true,
+		errorsSpace: 0,
+		warningsSpace: 0,
+		modulesSpace: 0,
+		assets: true,
+		assetsSpace: 0,
+		errors: true,
+		errorsCount: true,
+		warnings: true,
+		warningsCount: true,
+		logging: "warn"
+	},
+	"errors-only": {
+		all: false,
+		errors: true,
+		errorsCount: true,
+		errorsSpace: Infinity,
+		moduleTrace: true,
+		logging: "error"
+	},
+	"errors-warnings": {
+		all: false,
+		errors: true,
+		errorsCount: true,
+		errorsSpace: Infinity,
+		warnings: true,
+		warningsCount: true,
+		warningsSpace: Infinity,
+		logging: "warn"
+	},
+	summary: {
+		all: false,
+		version: true,
+		errorsCount: true,
+		warningsCount: true
+	},
+	none: {
+		all: false
+	}
+};
+
+/**
+ * @param {StatsOptions} all stats option
+ * @returns {boolean} true when enabled, otherwise false
+ */
+const NORMAL_ON = ({ all }) => all !== false;
+/**
+ * @param {StatsOptions} all stats option
+ * @returns {boolean} true when enabled, otherwise false
+ */
+const NORMAL_OFF = ({ all }) => all === true;
+/**
+ * @param {StatsOptions} all stats option
+ * @param {CreateStatsOptionsContext} forToString stats options context
+ * @returns {boolean} true when enabled, otherwise false
+ */
+const ON_FOR_TO_STRING = ({ all }, { forToString }) =>
+	forToString ? all !== false : all === true;
+/**
+ * @param {StatsOptions} all stats option
+ * @param {CreateStatsOptionsContext} forToString stats options context
+ * @returns {boolean} true when enabled, otherwise false
+ */
+const OFF_FOR_TO_STRING = ({ all }, { forToString }) =>
+	forToString ? all === true : all !== false;
+/**
+ * @param {StatsOptions} all stats option
+ * @param {CreateStatsOptionsContext} forToString stats options context
+ * @returns {boolean | "auto"} true when enabled, otherwise false
+ */
+const AUTO_FOR_TO_STRING = ({ all }, { forToString }) => {
+	if (all === false) return false;
+	if (all === true) return true;
+	if (forToString) return "auto";
+	return true;
+};
+
+/** @typedef {Record<string, (options: StatsOptions, context: CreateStatsOptionsContext, compilation: Compilation) => StatsOptions[keyof StatsOptions] | RequestShortener>} Defaults */
+
+/** @type {Defaults} */
+const DEFAULTS = {
+	context: (options, context, compilation) => compilation.compiler.context,
+	requestShortener: (options, context, compilation) =>
+		compilation.compiler.context === options.context
+			? compilation.requestShortener
+			: new RequestShortener(
+					/** @type {string} */
+					(options.context),
+					compilation.compiler.root
+				),
+	performance: NORMAL_ON,
+	hash: OFF_FOR_TO_STRING,
+	env: NORMAL_OFF,
+	version: NORMAL_ON,
+	timings: NORMAL_ON,
+	builtAt: OFF_FOR_TO_STRING,
+	assets: NORMAL_ON,
+	entrypoints: AUTO_FOR_TO_STRING,
+	chunkGroups: OFF_FOR_TO_STRING,
+	chunkGroupAuxiliary: OFF_FOR_TO_STRING,
+	chunkGroupChildren: OFF_FOR_TO_STRING,
+	chunkGroupMaxAssets: (o, { forToString }) => (forToString ? 5 : Infinity),
+	chunks: OFF_FOR_TO_STRING,
+	chunkRelations: OFF_FOR_TO_STRING,
+	chunkModules: ({ all, modules }) => {
+		if (all === false) return false;
+		if (all === true) return true;
+		if (modules) return false;
+		return true;
+	},
+	dependentModules: OFF_FOR_TO_STRING,
+	chunkOrigins: OFF_FOR_TO_STRING,
+	ids: OFF_FOR_TO_STRING,
+	modules: ({ all, chunks, chunkModules }, { forToString }) => {
+		if (all === false) return false;
+		if (all === true) return true;
+		if (forToString && chunks && chunkModules) return false;
+		return true;
+	},
+	nestedModules: OFF_FOR_TO_STRING,
+	groupModulesByType: ON_FOR_TO_STRING,
+	groupModulesByCacheStatus: ON_FOR_TO_STRING,
+	groupModulesByLayer: ON_FOR_TO_STRING,
+	groupModulesByAttributes: ON_FOR_TO_STRING,
+	groupModulesByPath: ON_FOR_TO_STRING,
+	groupModulesByExtension: ON_FOR_TO_STRING,
+	modulesSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
+	chunkModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
+	nestedModulesSpace: (o, { forToString }) => (forToString ? 10 : Infinity),
+	relatedAssets: OFF_FOR_TO_STRING,
+	groupAssetsByEmitStatus: ON_FOR_TO_STRING,
+	groupAssetsByInfo: ON_FOR_TO_STRING,
+	groupAssetsByPath: ON_FOR_TO_STRING,
+	groupAssetsByExtension: ON_FOR_TO_STRING,
+	groupAssetsByChunk: ON_FOR_TO_STRING,
+	assetsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
+	orphanModules: OFF_FOR_TO_STRING,
+	runtimeModules: ({ all, runtime }, { forToString }) =>
+		runtime !== undefined
+			? runtime
+			: forToString
+				? all === true
+				: all !== false,
+	cachedModules: ({ all, cached }, { forToString }) =>
+		cached !== undefined ? cached : forToString ? all === true : all !== false,
+	moduleAssets: OFF_FOR_TO_STRING,
+	depth: OFF_FOR_TO_STRING,
+	cachedAssets: OFF_FOR_TO_STRING,
+	reasons: OFF_FOR_TO_STRING,
+	reasonsSpace: (o, { forToString }) => (forToString ? 15 : Infinity),
+	groupReasonsByOrigin: ON_FOR_TO_STRING,
+	usedExports: OFF_FOR_TO_STRING,
+	providedExports: OFF_FOR_TO_STRING,
+	optimizationBailout: OFF_FOR_TO_STRING,
+	children: OFF_FOR_TO_STRING,
+	source: NORMAL_OFF,
+	moduleTrace: NORMAL_ON,
+	errors: NORMAL_ON,
+	errorsCount: NORMAL_ON,
+	errorDetails: AUTO_FOR_TO_STRING,
+	errorStack: OFF_FOR_TO_STRING,
+	warnings: NORMAL_ON,
+	warningsCount: NORMAL_ON,
+	publicPath: OFF_FOR_TO_STRING,
+	logging: ({ all }, { forToString }) =>
+		forToString && all !== false ? "info" : false,
+	loggingDebug: () => [],
+	loggingTrace: OFF_FOR_TO_STRING,
+	excludeModules: () => [],
+	excludeAssets: () => [],
+	modulesSort: () => "depth",
+	chunkModulesSort: () => "name",
+	nestedModulesSort: () => false,
+	chunksSort: () => false,
+	assetsSort: () => "!size",
+	outputPath: OFF_FOR_TO_STRING,
+	colors: () => false
+};
+
+/**
+ * @param {string | ({ test: function(string): boolean }) | (function(string): boolean) | boolean} item item to normalize
+ * @returns {(function(string): boolean) | undefined} normalize fn
+ */
+const normalizeFilter = item => {
+	if (typeof item === "string") {
+		const regExp = new RegExp(
+			`[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, "\\$&")}([\\\\/]|$|!|\\?)`
+		);
+		return ident => regExp.test(ident);
+	}
+	if (item && typeof item === "object" && typeof item.test === "function") {
+		return ident => item.test(ident);
+	}
+	if (typeof item === "function") {
+		return item;
+	}
+	if (typeof item === "boolean") {
+		return () => item;
+	}
+};
+
+/** @type {Record<string, function(any): any[]>} */
+const NORMALIZER = {
+	excludeModules: value => {
+		if (!Array.isArray(value)) {
+			value = value ? [value] : [];
+		}
+		return value.map(normalizeFilter);
+	},
+	excludeAssets: value => {
+		if (!Array.isArray(value)) {
+			value = value ? [value] : [];
+		}
+		return value.map(normalizeFilter);
+	},
+	warningsFilter: value => {
+		if (!Array.isArray(value)) {
+			value = value ? [value] : [];
+		}
+		/**
+		 * @callback WarningFilterFn
+		 * @param {StatsError} warning warning
+		 * @param {string} warningString warning string
+		 * @returns {boolean} result
+		 */
+		return value.map(
+			/**
+			 * @param {StatsOptions["warningsFilter"]} filter a warning filter
+			 * @returns {WarningFilterFn} result
+			 */
+			filter => {
+				if (typeof filter === "string") {
+					return (warning, warningString) => warningString.includes(filter);
+				}
+				if (filter instanceof RegExp) {
+					return (warning, warningString) => filter.test(warningString);
+				}
+				if (typeof filter === "function") {
+					return filter;
+				}
+				throw new Error(
+					`Can only filter warnings with Strings or RegExps. (Given: ${filter})`
+				);
+			}
+		);
+	},
+	logging: value => {
+		if (value === true) value = "log";
+		return value;
+	},
+	loggingDebug: value => {
+		if (!Array.isArray(value)) {
+			value = value ? [value] : [];
+		}
+		return value.map(normalizeFilter);
+	}
+};
+
+class DefaultStatsPresetPlugin {
+	/**
+	 * Apply the plugin
+	 * @param {Compiler} compiler the compiler instance
+	 * @returns {void}
+	 */
+	apply(compiler) {
+		compiler.hooks.compilation.tap("DefaultStatsPresetPlugin", compilation => {
+			for (const key of Object.keys(NAMED_PRESETS)) {
+				const defaults = NAMED_PRESETS[/** @type {keyof NamedPresets} */ (key)];
+				compilation.hooks.statsPreset
+					.for(key)
+					.tap("DefaultStatsPresetPlugin", (options, context) => {
+						applyDefaults(options, defaults);
+					});
+			}
+			compilation.hooks.statsNormalize.tap(
+				"DefaultStatsPresetPlugin",
+				(options, context) => {
+					for (const key of Object.keys(DEFAULTS)) {
+						if (options[key] === undefined)
+							options[key] = DEFAULTS[key](options, context, compilation);
+					}
+					for (const key of Object.keys(NORMALIZER)) {
+						options[key] = NORMALIZER[key](options[key]);
+					}
+				}
+			);
+		});
+	}
+}
+module.exports = DefaultStatsPresetPlugin;
Index: imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPrinterPlugin.js
===================================================================
--- imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPrinterPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/webpack/lib/stats/DefaultStatsPrinterPlugin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,1695 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+/** @typedef {import("../Compiler")} Compiler */
+/** @typedef {import("./DefaultStatsFactoryPlugin").KnownStatsChunkGroup} KnownStatsChunkGroup */
+/** @typedef {import("./StatsPrinter")} StatsPrinter */
+/** @typedef {import("./StatsPrinter").KnownStatsPrinterColorFn} KnownStatsPrinterColorFn */
+/** @typedef {import("./StatsPrinter").KnownStatsPrinterFormaters} KnownStatsPrinterFormaters */
+/** @typedef {import("./StatsPrinter").StatsPrinterContext} StatsPrinterContext */
+
+const DATA_URI_CONTENT_LENGTH = 16;
+const MAX_MODULE_IDENTIFIER_LENGTH = 80;
+
+/**
+ * @param {number} n a number
+ * @param {string} singular singular
+ * @param {string} plural plural
+ * @returns {string} if n is 1, singular, else plural
+ */
+const plural = (n, singular, plural) => (n === 1 ? singular : plural);
+
+/**
+ * @param {Record<string, number>} sizes sizes by source type
+ * @param {StatsPrinterContext} options options
+ * @returns {string | undefined} text
+ */
+const printSizes = (sizes, { formatSize = n => `${n}` }) => {
+	const keys = Object.keys(sizes);
+	if (keys.length > 1) {
+		return keys.map(key => `${formatSize(sizes[key])} (${key})`).join(" ");
+	} else if (keys.length === 1) {
+		return formatSize(sizes[keys[0]]);
+	}
+};
+
+/**
+ * @param {string} resource resource
+ * @returns {string} resource name for display
+ */
+const getResourceName = resource => {
+	const dataUrl = /^data:[^,]+,/.exec(resource);
+	if (!dataUrl) return resource;
+
+	const len = dataUrl[0].length + DATA_URI_CONTENT_LENGTH;
+	if (resource.length < len) return resource;
+	return `${resource.slice(
+		0,
+		Math.min(resource.length - /* '..'.length */ 2, len)
+	)}..`;
+};
+
+/**
+ * @param {string} name module name
+ * @returns {[string,string]} prefix and module name
+ */
+const getModuleName = name => {
+	const [, prefix, resource] =
+		/** @type {[any, string, string]} */
+		(/** @type {unknown} */ (/^(.*!)?([^!]*)$/.exec(name)));
+
+	if (resource.length > MAX_MODULE_IDENTIFIER_LENGTH) {
+		const truncatedResource = `${resource.slice(
+			0,
+			Math.min(
+				resource.length - /* '...(truncated)'.length */ 14,
+				MAX_MODULE_IDENTIFIER_LENGTH
+			)
+		)}...(truncated)`;
+
+		return [prefix, getResourceName(truncatedResource)];
+	}
+
+	return [prefix, getResourceName(resource)];
+};
+
+/**
+ * @param {string} str string
+ * @param {function(string): string} fn function to apply to each line
+ * @returns {string} joined string
+ */
+const mapLines = (str, fn) => str.split("\n").map(fn).join("\n");
+
+/**
+ * @param {number} n a number
+ * @returns {string} number as two digit string, leading 0
+ */
+const twoDigit = n => (n >= 10 ? `${n}` : `0${n}`);
+
+/**
+ * @param {string | number} id an id
+ * @returns {boolean | string} is i
+ */
+const isValidId = id => typeof id === "number" || id;
+
+/**
+ * @template T
+ * @param {Array<T> | undefined} list of items
+ * @param {number} count number of items to show
+ * @returns {string} string representation of list
+ */
+const moreCount = (list, count) =>
+	list && list.length > 0 ? `+ ${count}` : `${count}`;
+
+/**
+ * @template T
+ * @template {keyof T} K
+ * @typedef {{ [P in K]-?: T[P] }} WithRequired
+ */
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation">, printer: StatsPrinter) => string | undefined>} */
+const COMPILATION_SIMPLE_PRINTERS = {
+	"compilation.summary!": (
+		_,
+		{
+			type,
+			bold,
+			green,
+			red,
+			yellow,
+			formatDateTime,
+			formatTime,
+			compilation: {
+				name,
+				hash,
+				version,
+				time,
+				builtAt,
+				errorsCount,
+				warningsCount
+			}
+		}
+	) => {
+		const root = type === "compilation.summary!";
+		const warningsMessage =
+			/** @type {number} */ (warningsCount) > 0
+				? yellow(
+						`${warningsCount} ${plural(/** @type {number} */ (warningsCount), "warning", "warnings")}`
+					)
+				: "";
+		const errorsMessage =
+			/** @type {number} */ (errorsCount) > 0
+				? red(
+						`${errorsCount} ${plural(/** @type {number} */ (errorsCount), "error", "errors")}`
+					)
+				: "";
+		const timeMessage = root && time ? ` in ${formatTime(time)}` : "";
+		const hashMessage = hash ? ` (${hash})` : "";
+		const builtAtMessage =
+			root && builtAt ? `${formatDateTime(builtAt)}: ` : "";
+		const versionMessage = root && version ? `webpack ${version}` : "";
+		const nameMessage =
+			root && name
+				? bold(name)
+				: name
+					? `Child ${bold(name)}`
+					: root
+						? ""
+						: "Child";
+		const subjectMessage =
+			nameMessage && versionMessage
+				? `${nameMessage} (${versionMessage})`
+				: versionMessage || nameMessage || "webpack";
+		let statusMessage;
+		if (errorsMessage && warningsMessage) {
+			statusMessage = `compiled with ${errorsMessage} and ${warningsMessage}`;
+		} else if (errorsMessage) {
+			statusMessage = `compiled with ${errorsMessage}`;
+		} else if (warningsMessage) {
+			statusMessage = `compiled with ${warningsMessage}`;
+		} else if (errorsCount === 0 && warningsCount === 0) {
+			statusMessage = `compiled ${green("successfully")}`;
+		} else {
+			statusMessage = "compiled";
+		}
+		if (
+			builtAtMessage ||
+			versionMessage ||
+			errorsMessage ||
+			warningsMessage ||
+			(errorsCount === 0 && warningsCount === 0) ||
+			timeMessage ||
+			hashMessage
+		)
+			return `${builtAtMessage}${subjectMessage} ${statusMessage}${timeMessage}${hashMessage}`;
+	},
+	"compilation.filteredWarningDetailsCount": count =>
+		count
+			? `${count} ${plural(
+					count,
+					"warning has",
+					"warnings have"
+				)} detailed information that is not shown.\nUse 'stats.errorDetails: true' resp. '--stats-error-details' to show it.`
+			: undefined,
+	"compilation.filteredErrorDetailsCount": (count, { yellow }) =>
+		count
+			? yellow(
+					`${count} ${plural(
+						count,
+						"error has",
+						"errors have"
+					)} detailed information that is not shown.\nUse 'stats.errorDetails: true' resp. '--stats-error-details' to show it.`
+				)
+			: undefined,
+	"compilation.env": (env, { bold }) =>
+		env
+			? `Environment (--env): ${bold(JSON.stringify(env, null, 2))}`
+			: undefined,
+	"compilation.publicPath": (publicPath, { bold }) =>
+		`PublicPath: ${bold(publicPath || "(none)")}`,
+	"compilation.entrypoints": (entrypoints, context, printer) =>
+		Array.isArray(entrypoints)
+			? undefined
+			: printer.print(context.type, Object.values(entrypoints), {
+					...context,
+					chunkGroupKind: "Entrypoint"
+				}),
+	"compilation.namedChunkGroups": (namedChunkGroups, context, printer) => {
+		if (!Array.isArray(namedChunkGroups)) {
+			const {
+				compilation: { entrypoints }
+			} = context;
+			let chunkGroups = Object.values(namedChunkGroups);
+			if (entrypoints) {
+				chunkGroups = chunkGroups.filter(
+					group =>
+						!Object.prototype.hasOwnProperty.call(entrypoints, group.name)
+				);
+			}
+			return printer.print(context.type, chunkGroups, {
+				...context,
+				chunkGroupKind: "Chunk Group"
+			});
+		}
+	},
+	"compilation.assetsByChunkName": () => "",
+
+	"compilation.filteredModules": (
+		filteredModules,
+		{ compilation: { modules } }
+	) =>
+		filteredModules > 0
+			? `${moreCount(modules, filteredModules)} ${plural(
+					filteredModules,
+					"module",
+					"modules"
+				)}`
+			: undefined,
+	"compilation.filteredAssets": (
+		filteredAssets,
+		{ compilation: { assets } }
+	) =>
+		filteredAssets > 0
+			? `${moreCount(assets, filteredAssets)} ${plural(
+					filteredAssets,
+					"asset",
+					"assets"
+				)}`
+			: undefined,
+	"compilation.logging": (logging, context, printer) =>
+		Array.isArray(logging)
+			? undefined
+			: printer.print(
+					context.type,
+					Object.entries(logging).map(([name, value]) => ({ ...value, name })),
+					context
+				),
+	"compilation.warningsInChildren!": (_, { yellow, compilation }) => {
+		if (
+			!compilation.children &&
+			/** @type {number} */ (compilation.warningsCount) > 0 &&
+			compilation.warnings
+		) {
+			const childWarnings =
+				/** @type {number} */ (compilation.warningsCount) -
+				compilation.warnings.length;
+			if (childWarnings > 0) {
+				return yellow(
+					`${childWarnings} ${plural(
+						childWarnings,
+						"WARNING",
+						"WARNINGS"
+					)} in child compilations${
+						compilation.children
+							? ""
+							: " (Use 'stats.children: true' resp. '--stats-children' for more details)"
+					}`
+				);
+			}
+		}
+	},
+	"compilation.errorsInChildren!": (_, { red, compilation }) => {
+		if (
+			!compilation.children &&
+			/** @type {number} */ (compilation.errorsCount) > 0 &&
+			compilation.errors
+		) {
+			const childErrors =
+				/** @type {number} */ (compilation.errorsCount) -
+				compilation.errors.length;
+			if (childErrors > 0) {
+				return red(
+					`${childErrors} ${plural(
+						childErrors,
+						"ERROR",
+						"ERRORS"
+					)} in child compilations${
+						compilation.children
+							? ""
+							: " (Use 'stats.children: true' resp. '--stats-children' for more details)"
+					}`
+				);
+			}
+		}
+	}
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "asset">, printer: StatsPrinter) => string | undefined>} */
+const ASSET_SIMPLE_PRINTERS = {
+	"asset.type": type => type,
+	"asset.name": (name, { formatFilename, asset: { isOverSizeLimit } }) =>
+		formatFilename(name, isOverSizeLimit),
+	"asset.size": (size, { asset: { isOverSizeLimit }, yellow, formatSize }) =>
+		isOverSizeLimit ? yellow(formatSize(size)) : formatSize(size),
+	"asset.emitted": (emitted, { green, formatFlag }) =>
+		emitted ? green(formatFlag("emitted")) : undefined,
+	"asset.comparedForEmit": (comparedForEmit, { yellow, formatFlag }) =>
+		comparedForEmit ? yellow(formatFlag("compared for emit")) : undefined,
+	"asset.cached": (cached, { green, formatFlag }) =>
+		cached ? green(formatFlag("cached")) : undefined,
+	"asset.isOverSizeLimit": (isOverSizeLimit, { yellow, formatFlag }) =>
+		isOverSizeLimit ? yellow(formatFlag("big")) : undefined,
+
+	"asset.info.immutable": (immutable, { green, formatFlag }) =>
+		immutable ? green(formatFlag("immutable")) : undefined,
+	"asset.info.javascriptModule": (javascriptModule, { formatFlag }) =>
+		javascriptModule ? formatFlag("javascript module") : undefined,
+	"asset.info.sourceFilename": (sourceFilename, { formatFlag }) =>
+		sourceFilename
+			? formatFlag(
+					sourceFilename === true
+						? "from source file"
+						: `from: ${sourceFilename}`
+				)
+			: undefined,
+	"asset.info.development": (development, { green, formatFlag }) =>
+		development ? green(formatFlag("dev")) : undefined,
+	"asset.info.hotModuleReplacement": (
+		hotModuleReplacement,
+		{ green, formatFlag }
+	) => (hotModuleReplacement ? green(formatFlag("hmr")) : undefined),
+	"asset.separator!": () => "\n",
+	"asset.filteredRelated": (filteredRelated, { asset: { related } }) =>
+		filteredRelated > 0
+			? `${moreCount(related, filteredRelated)} related ${plural(
+					filteredRelated,
+					"asset",
+					"assets"
+				)}`
+			: undefined,
+	"asset.filteredChildren": (filteredChildren, { asset: { children } }) =>
+		filteredChildren > 0
+			? `${moreCount(children, filteredChildren)} ${plural(
+					filteredChildren,
+					"asset",
+					"assets"
+				)}`
+			: undefined,
+
+	assetChunk: (id, { formatChunkId }) => formatChunkId(id),
+
+	assetChunkName: name => name,
+	assetChunkIdHint: name => name
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "module">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_SIMPLE_PRINTERS = {
+	"module.type": type => (type !== "module" ? type : undefined),
+	"module.id": (id, { formatModuleId }) =>
+		isValidId(id) ? formatModuleId(id) : undefined,
+	"module.name": (name, { bold }) => {
+		const [prefix, resource] = getModuleName(name);
+		return `${prefix || ""}${bold(resource || "")}`;
+	},
+	"module.identifier": identifier => undefined,
+	"module.layer": (layer, { formatLayer }) =>
+		layer ? formatLayer(layer) : undefined,
+	"module.sizes": printSizes,
+	"module.chunks[]": (id, { formatChunkId }) => formatChunkId(id),
+	"module.depth": (depth, { formatFlag }) =>
+		depth !== null ? formatFlag(`depth ${depth}`) : undefined,
+	"module.cacheable": (cacheable, { formatFlag, red }) =>
+		cacheable === false ? red(formatFlag("not cacheable")) : undefined,
+	"module.orphan": (orphan, { formatFlag, yellow }) =>
+		orphan ? yellow(formatFlag("orphan")) : undefined,
+	"module.runtime": (runtime, { formatFlag, yellow }) =>
+		runtime ? yellow(formatFlag("runtime")) : undefined,
+	"module.optional": (optional, { formatFlag, yellow }) =>
+		optional ? yellow(formatFlag("optional")) : undefined,
+	"module.dependent": (dependent, { formatFlag, cyan }) =>
+		dependent ? cyan(formatFlag("dependent")) : undefined,
+	"module.built": (built, { formatFlag, yellow }) =>
+		built ? yellow(formatFlag("built")) : undefined,
+	"module.codeGenerated": (codeGenerated, { formatFlag, yellow }) =>
+		codeGenerated ? yellow(formatFlag("code generated")) : undefined,
+	"module.buildTimeExecuted": (buildTimeExecuted, { formatFlag, green }) =>
+		buildTimeExecuted ? green(formatFlag("build time executed")) : undefined,
+	"module.cached": (cached, { formatFlag, green }) =>
+		cached ? green(formatFlag("cached")) : undefined,
+	"module.assets": (assets, { formatFlag, magenta }) =>
+		assets && assets.length
+			? magenta(
+					formatFlag(
+						`${assets.length} ${plural(assets.length, "asset", "assets")}`
+					)
+				)
+			: undefined,
+	"module.warnings": (warnings, { formatFlag, yellow }) =>
+		warnings === true
+			? yellow(formatFlag("warnings"))
+			: warnings
+				? yellow(
+						formatFlag(`${warnings} ${plural(warnings, "warning", "warnings")}`)
+					)
+				: undefined,
+	"module.errors": (errors, { formatFlag, red }) =>
+		errors === true
+			? red(formatFlag("errors"))
+			: errors
+				? red(formatFlag(`${errors} ${plural(errors, "error", "errors")}`))
+				: undefined,
+	"module.providedExports": (providedExports, { formatFlag, cyan }) => {
+		if (Array.isArray(providedExports)) {
+			if (providedExports.length === 0) return cyan(formatFlag("no exports"));
+			return cyan(formatFlag(`exports: ${providedExports.join(", ")}`));
+		}
+	},
+	"module.usedExports": (usedExports, { formatFlag, cyan, module }) => {
+		if (usedExports !== true) {
+			if (usedExports === null) return cyan(formatFlag("used exports unknown"));
+			if (usedExports === false) return cyan(formatFlag("module unused"));
+			if (Array.isArray(usedExports)) {
+				if (usedExports.length === 0)
+					return cyan(formatFlag("no exports used"));
+				const providedExportsCount = Array.isArray(module.providedExports)
+					? module.providedExports.length
+					: null;
+				if (
+					providedExportsCount !== null &&
+					providedExportsCount === usedExports.length
+				) {
+					return cyan(formatFlag("all exports used"));
+				}
+
+				return cyan(
+					formatFlag(`only some exports used: ${usedExports.join(", ")}`)
+				);
+			}
+		}
+	},
+	"module.optimizationBailout[]": (optimizationBailout, { yellow }) =>
+		yellow(optimizationBailout),
+	"module.issuerPath": (issuerPath, { module }) =>
+		module.profile ? undefined : "",
+	"module.profile": profile => undefined,
+	"module.filteredModules": (filteredModules, { module: { modules } }) =>
+		filteredModules > 0
+			? `${moreCount(modules, filteredModules)} nested ${plural(
+					filteredModules,
+					"module",
+					"modules"
+				)}`
+			: undefined,
+	"module.filteredReasons": (filteredReasons, { module: { reasons } }) =>
+		filteredReasons > 0
+			? `${moreCount(reasons, filteredReasons)} ${plural(
+					filteredReasons,
+					"reason",
+					"reasons"
+				)}`
+			: undefined,
+	"module.filteredChildren": (filteredChildren, { module: { children } }) =>
+		filteredChildren > 0
+			? `${moreCount(children, filteredChildren)} ${plural(
+					filteredChildren,
+					"module",
+					"modules"
+				)}`
+			: undefined,
+	"module.separator!": () => "\n"
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleIssuer">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_ISSUER_PRINTERS = {
+	"moduleIssuer.id": (id, { formatModuleId }) => formatModuleId(id),
+	"moduleIssuer.profile.total": (value, { formatTime }) => formatTime(value)
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleReason">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_REASON_PRINTERS = {
+	"moduleReason.type": type => type,
+	"moduleReason.userRequest": (userRequest, { cyan }) =>
+		cyan(getResourceName(userRequest)),
+	"moduleReason.moduleId": (moduleId, { formatModuleId }) =>
+		isValidId(moduleId) ? formatModuleId(moduleId) : undefined,
+	"moduleReason.module": (module, { magenta }) => magenta(module),
+	"moduleReason.loc": loc => loc,
+	"moduleReason.explanation": (explanation, { cyan }) => cyan(explanation),
+	"moduleReason.active": (active, { formatFlag }) =>
+		active ? undefined : formatFlag("inactive"),
+	"moduleReason.resolvedModule": (module, { magenta }) => magenta(module),
+	"moduleReason.filteredChildren": (
+		filteredChildren,
+		{ moduleReason: { children } }
+	) =>
+		filteredChildren > 0
+			? `${moreCount(children, filteredChildren)} ${plural(
+					filteredChildren,
+					"reason",
+					"reasons"
+				)}`
+			: undefined
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "profile">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_PROFILE_PRINTERS = {
+	"module.profile.total": (value, { formatTime }) => formatTime(value),
+	"module.profile.resolving": (value, { formatTime }) =>
+		`resolving: ${formatTime(value)}`,
+	"module.profile.restoring": (value, { formatTime }) =>
+		`restoring: ${formatTime(value)}`,
+	"module.profile.integration": (value, { formatTime }) =>
+		`integration: ${formatTime(value)}`,
+	"module.profile.building": (value, { formatTime }) =>
+		`building: ${formatTime(value)}`,
+	"module.profile.storing": (value, { formatTime }) =>
+		`storing: ${formatTime(value)}`,
+	"module.profile.additionalResolving": (value, { formatTime }) =>
+		value ? `additional resolving: ${formatTime(value)}` : undefined,
+	"module.profile.additionalIntegration": (value, { formatTime }) =>
+		value ? `additional integration: ${formatTime(value)}` : undefined
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "chunkGroupKind" | "chunkGroup">, printer: StatsPrinter) => string | undefined>} */
+const CHUNK_GROUP_PRINTERS = {
+	"chunkGroup.kind!": (_, { chunkGroupKind }) => chunkGroupKind,
+	"chunkGroup.separator!": () => "\n",
+	"chunkGroup.name": (name, { bold }) => bold(name),
+	"chunkGroup.isOverSizeLimit": (isOverSizeLimit, { formatFlag, yellow }) =>
+		isOverSizeLimit ? yellow(formatFlag("big")) : undefined,
+	"chunkGroup.assetsSize": (size, { formatSize }) =>
+		size ? formatSize(size) : undefined,
+	"chunkGroup.auxiliaryAssetsSize": (size, { formatSize }) =>
+		size ? `(${formatSize(size)})` : undefined,
+	"chunkGroup.filteredAssets": (n, { chunkGroup: { assets } }) =>
+		n > 0
+			? `${moreCount(assets, n)} ${plural(n, "asset", "assets")}`
+			: undefined,
+	"chunkGroup.filteredAuxiliaryAssets": (
+		n,
+		{ chunkGroup: { auxiliaryAssets } }
+	) =>
+		n > 0
+			? `${moreCount(auxiliaryAssets, n)} auxiliary ${plural(
+					n,
+					"asset",
+					"assets"
+				)}`
+			: undefined,
+	"chunkGroup.is!": () => "=",
+	"chunkGroupAsset.name": (asset, { green }) => green(asset),
+	"chunkGroupAsset.size": (size, { formatSize, chunkGroup }) =>
+		chunkGroup.assets &&
+		(chunkGroup.assets.length > 1 ||
+		(chunkGroup.auxiliaryAssets && chunkGroup.auxiliaryAssets.length > 0)
+			? formatSize(size)
+			: undefined),
+	"chunkGroup.children": (children, context, printer) =>
+		Array.isArray(children)
+			? undefined
+			: printer.print(
+					context.type,
+					Object.keys(children).map(key => ({
+						type: key,
+						children: children[key]
+					})),
+					context
+				),
+	"chunkGroupChildGroup.type": type => `${type}:`,
+	"chunkGroupChild.assets[]": (file, { formatFilename }) =>
+		formatFilename(file),
+	"chunkGroupChild.chunks[]": (id, { formatChunkId }) => formatChunkId(id),
+	"chunkGroupChild.name": name => (name ? `(name: ${name})` : undefined)
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "chunk">, printer: StatsPrinter) => string | undefined>} */
+const CHUNK_PRINTERS = {
+	"chunk.id": (id, { formatChunkId }) => formatChunkId(id),
+	"chunk.files[]": (file, { formatFilename }) => formatFilename(file),
+	"chunk.names[]": name => name,
+	"chunk.idHints[]": name => name,
+	"chunk.runtime[]": name => name,
+	"chunk.sizes": (sizes, context) => printSizes(sizes, context),
+	"chunk.parents[]": (parents, context) =>
+		context.formatChunkId(parents, "parent"),
+	"chunk.siblings[]": (siblings, context) =>
+		context.formatChunkId(siblings, "sibling"),
+	"chunk.children[]": (children, context) =>
+		context.formatChunkId(children, "child"),
+	"chunk.childrenByOrder": (childrenByOrder, context, printer) =>
+		Array.isArray(childrenByOrder)
+			? undefined
+			: printer.print(
+					context.type,
+					Object.keys(childrenByOrder).map(key => ({
+						type: key,
+						children: childrenByOrder[key]
+					})),
+					context
+				),
+	"chunk.childrenByOrder[].type": type => `${type}:`,
+	"chunk.childrenByOrder[].children[]": (id, { formatChunkId }) =>
+		isValidId(id) ? formatChunkId(id) : undefined,
+	"chunk.entry": (entry, { formatFlag, yellow }) =>
+		entry ? yellow(formatFlag("entry")) : undefined,
+	"chunk.initial": (initial, { formatFlag, yellow }) =>
+		initial ? yellow(formatFlag("initial")) : undefined,
+	"chunk.rendered": (rendered, { formatFlag, green }) =>
+		rendered ? green(formatFlag("rendered")) : undefined,
+	"chunk.recorded": (recorded, { formatFlag, green }) =>
+		recorded ? green(formatFlag("recorded")) : undefined,
+	"chunk.reason": (reason, { yellow }) => (reason ? yellow(reason) : undefined),
+	"chunk.filteredModules": (filteredModules, { chunk: { modules } }) =>
+		filteredModules > 0
+			? `${moreCount(modules, filteredModules)} chunk ${plural(
+					filteredModules,
+					"module",
+					"modules"
+				)}`
+			: undefined,
+	"chunk.separator!": () => "\n",
+
+	"chunkOrigin.request": request => request,
+	"chunkOrigin.moduleId": (moduleId, { formatModuleId }) =>
+		isValidId(moduleId) ? formatModuleId(moduleId) : undefined,
+	"chunkOrigin.moduleName": (moduleName, { bold }) => bold(moduleName),
+	"chunkOrigin.loc": loc => loc
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "error">, printer: StatsPrinter) => string | undefined>} */
+const ERROR_PRINTERS = {
+	"error.compilerPath": (compilerPath, { bold }) =>
+		compilerPath ? bold(`(${compilerPath})`) : undefined,
+	"error.chunkId": (chunkId, { formatChunkId }) =>
+		isValidId(chunkId) ? formatChunkId(chunkId) : undefined,
+	"error.chunkEntry": (chunkEntry, { formatFlag }) =>
+		chunkEntry ? formatFlag("entry") : undefined,
+	"error.chunkInitial": (chunkInitial, { formatFlag }) =>
+		chunkInitial ? formatFlag("initial") : undefined,
+	"error.file": (file, { bold }) => bold(file),
+	"error.moduleName": (moduleName, { bold }) =>
+		moduleName.includes("!")
+			? `${bold(moduleName.replace(/^(\s|\S)*!/, ""))} (${moduleName})`
+			: `${bold(moduleName)}`,
+	"error.loc": (loc, { green }) => green(loc),
+	"error.message": (message, { bold, formatError }) =>
+		message.includes("\u001B[") ? message : bold(formatError(message)),
+	"error.details": (details, { formatError }) => formatError(details),
+	"error.filteredDetails": filteredDetails =>
+		filteredDetails ? `+ ${filteredDetails} hidden lines` : undefined,
+	"error.stack": stack => stack,
+	"error.moduleTrace": moduleTrace => undefined,
+	"error.separator!": () => "\n"
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "logging">, printer: StatsPrinter) => string | undefined>} */
+const LOG_ENTRY_PRINTERS = {
+	"loggingEntry(error).loggingEntry.message": (message, { red }) =>
+		mapLines(message, x => `<e> ${red(x)}`),
+	"loggingEntry(warn).loggingEntry.message": (message, { yellow }) =>
+		mapLines(message, x => `<w> ${yellow(x)}`),
+	"loggingEntry(info).loggingEntry.message": (message, { green }) =>
+		mapLines(message, x => `<i> ${green(x)}`),
+	"loggingEntry(log).loggingEntry.message": (message, { bold }) =>
+		mapLines(message, x => `    ${bold(x)}`),
+	"loggingEntry(debug).loggingEntry.message": message =>
+		mapLines(message, x => `    ${x}`),
+	"loggingEntry(trace).loggingEntry.message": message =>
+		mapLines(message, x => `    ${x}`),
+	"loggingEntry(status).loggingEntry.message": (message, { magenta }) =>
+		mapLines(message, x => `<s> ${magenta(x)}`),
+	"loggingEntry(profile).loggingEntry.message": (message, { magenta }) =>
+		mapLines(message, x => `<p> ${magenta(x)}`),
+	"loggingEntry(profileEnd).loggingEntry.message": (message, { magenta }) =>
+		mapLines(message, x => `</p> ${magenta(x)}`),
+	"loggingEntry(time).loggingEntry.message": (message, { magenta }) =>
+		mapLines(message, x => `<t> ${magenta(x)}`),
+	"loggingEntry(group).loggingEntry.message": (message, { cyan }) =>
+		mapLines(message, x => `<-> ${cyan(x)}`),
+	"loggingEntry(groupCollapsed).loggingEntry.message": (message, { cyan }) =>
+		mapLines(message, x => `<+> ${cyan(x)}`),
+	"loggingEntry(clear).loggingEntry": () => "    -------",
+	"loggingEntry(groupCollapsed).loggingEntry.children": () => "",
+	"loggingEntry.trace[]": trace =>
+		trace ? mapLines(trace, x => `| ${x}`) : undefined,
+
+	loggingGroup: loggingGroup =>
+		loggingGroup.entries.length === 0 ? "" : undefined,
+	"loggingGroup.debug": (flag, { red }) => (flag ? red("DEBUG") : undefined),
+	"loggingGroup.name": (name, { bold }) => bold(`LOG from ${name}`),
+	"loggingGroup.separator!": () => "\n",
+	"loggingGroup.filteredEntries": filteredEntries =>
+		filteredEntries > 0 ? `+ ${filteredEntries} hidden lines` : undefined
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleTraceItem">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_TRACE_ITEM_PRINTERS = {
+	"moduleTraceItem.originName": originName => originName
+};
+
+/** @type {Record<string, (thing: any, context: Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleTraceDependency">, printer: StatsPrinter) => string | undefined>} */
+const MODULE_TRACE_DEPENDENCY_PRINTERS = {
+	"moduleTraceDependency.loc": loc => loc
+};
+
+/** @type {Record<string, string | function(any): string>} */
+const ITEM_NAMES = {
+	"compilation.assets[]": "asset",
+	"compilation.modules[]": "module",
+	"compilation.chunks[]": "chunk",
+	"compilation.entrypoints[]": "chunkGroup",
+	"compilation.namedChunkGroups[]": "chunkGroup",
+	"compilation.errors[]": "error",
+	"compilation.warnings[]": "error",
+	"compilation.logging[]": "loggingGroup",
+	"compilation.children[]": "compilation",
+	"asset.related[]": "asset",
+	"asset.children[]": "asset",
+	"asset.chunks[]": "assetChunk",
+	"asset.auxiliaryChunks[]": "assetChunk",
+	"asset.chunkNames[]": "assetChunkName",
+	"asset.chunkIdHints[]": "assetChunkIdHint",
+	"asset.auxiliaryChunkNames[]": "assetChunkName",
+	"asset.auxiliaryChunkIdHints[]": "assetChunkIdHint",
+	"chunkGroup.assets[]": "chunkGroupAsset",
+	"chunkGroup.auxiliaryAssets[]": "chunkGroupAsset",
+	"chunkGroupChild.assets[]": "chunkGroupAsset",
+	"chunkGroupChild.auxiliaryAssets[]": "chunkGroupAsset",
+	"chunkGroup.children[]": "chunkGroupChildGroup",
+	"chunkGroupChildGroup.children[]": "chunkGroupChild",
+	"module.modules[]": "module",
+	"module.children[]": "module",
+	"module.reasons[]": "moduleReason",
+	"moduleReason.children[]": "moduleReason",
+	"module.issuerPath[]": "moduleIssuer",
+	"chunk.origins[]": "chunkOrigin",
+	"chunk.modules[]": "module",
+	"loggingGroup.entries[]": logEntry =>
+		`loggingEntry(${logEntry.type}).loggingEntry`,
+	"loggingEntry.children[]": logEntry =>
+		`loggingEntry(${logEntry.type}).loggingEntry`,
+	"error.moduleTrace[]": "moduleTraceItem",
+	"moduleTraceItem.dependencies[]": "moduleTraceDependency"
+};
+
+const ERROR_PREFERRED_ORDER = [
+	"compilerPath",
+	"chunkId",
+	"chunkEntry",
+	"chunkInitial",
+	"file",
+	"separator!",
+	"moduleName",
+	"loc",
+	"separator!",
+	"message",
+	"separator!",
+	"details",
+	"separator!",
+	"filteredDetails",
+	"separator!",
+	"stack",
+	"separator!",
+	"missing",
+	"separator!",
+	"moduleTrace"
+];
+
+/** @type {Record<string, string[]>} */
+const PREFERRED_ORDERS = {
+	compilation: [
+		"name",
+		"hash",
+		"version",
+		"time",
+		"builtAt",
+		"env",
+		"publicPath",
+		"assets",
+		"filteredAssets",
+		"entrypoints",
+		"namedChunkGroups",
+		"chunks",
+		"modules",
+		"filteredModules",
+		"children",
+		"logging",
+		"warnings",
+		"warningsInChildren!",
+		"filteredWarningDetailsCount",
+		"errors",
+		"errorsInChildren!",
+		"filteredErrorDetailsCount",
+		"summary!",
+		"needAdditionalPass"
+	],
+	asset: [
+		"type",
+		"name",
+		"size",
+		"chunks",
+		"auxiliaryChunks",
+		"emitted",
+		"comparedForEmit",
+		"cached",
+		"info",
+		"isOverSizeLimit",
+		"chunkNames",
+		"auxiliaryChunkNames",
+		"chunkIdHints",
+		"auxiliaryChunkIdHints",
+		"related",
+		"filteredRelated",
+		"children",
+		"filteredChildren"
+	],
+	"asset.info": [
+		"immutable",
+		"sourceFilename",
+		"javascriptModule",
+		"development",
+		"hotModuleReplacement"
+	],
+	chunkGroup: [
+		"kind!",
+		"name",
+		"isOverSizeLimit",
+		"assetsSize",
+		"auxiliaryAssetsSize",
+		"is!",
+		"assets",
+		"filteredAssets",
+		"auxiliaryAssets",
+		"filteredAuxiliaryAssets",
+		"separator!",
+		"children"
+	],
+	chunkGroupAsset: ["name", "size"],
+	chunkGroupChildGroup: ["type", "children"],
+	chunkGroupChild: ["assets", "chunks", "name"],
+	module: [
+		"type",
+		"name",
+		"identifier",
+		"id",
+		"layer",
+		"sizes",
+		"chunks",
+		"depth",
+		"cacheable",
+		"orphan",
+		"runtime",
+		"optional",
+		"dependent",
+		"built",
+		"codeGenerated",
+		"cached",
+		"assets",
+		"failed",
+		"warnings",
+		"errors",
+		"children",
+		"filteredChildren",
+		"providedExports",
+		"usedExports",
+		"optimizationBailout",
+		"reasons",
+		"filteredReasons",
+		"issuerPath",
+		"profile",
+		"modules",
+		"filteredModules"
+	],
+	moduleReason: [
+		"active",
+		"type",
+		"userRequest",
+		"moduleId",
+		"module",
+		"resolvedModule",
+		"loc",
+		"explanation",
+		"children",
+		"filteredChildren"
+	],
+	"module.profile": [
+		"total",
+		"separator!",
+		"resolving",
+		"restoring",
+		"integration",
+		"building",
+		"storing",
+		"additionalResolving",
+		"additionalIntegration"
+	],
+	chunk: [
+		"id",
+		"runtime",
+		"files",
+		"names",
+		"idHints",
+		"sizes",
+		"parents",
+		"siblings",
+		"children",
+		"childrenByOrder",
+		"entry",
+		"initial",
+		"rendered",
+		"recorded",
+		"reason",
+		"separator!",
+		"origins",
+		"separator!",
+		"modules",
+		"separator!",
+		"filteredModules"
+	],
+	chunkOrigin: ["request", "moduleId", "moduleName", "loc"],
+	error: ERROR_PREFERRED_ORDER,
+	warning: ERROR_PREFERRED_ORDER,
+	"chunk.childrenByOrder[]": ["type", "children"],
+	loggingGroup: [
+		"debug",
+		"name",
+		"separator!",
+		"entries",
+		"separator!",
+		"filteredEntries"
+	],
+	loggingEntry: ["message", "trace", "children"]
+};
+
+/** @typedef {(items: string[]) => string | undefined} SimpleItemsJoiner */
+
+/** @type {SimpleItemsJoiner} */
+const itemsJoinOneLine = items => items.filter(Boolean).join(" ");
+/** @type {SimpleItemsJoiner} */
+const itemsJoinOneLineBrackets = items =>
+	items.length > 0 ? `(${items.filter(Boolean).join(" ")})` : undefined;
+/** @type {SimpleItemsJoiner} */
+const itemsJoinMoreSpacing = items => items.filter(Boolean).join("\n\n");
+/** @type {SimpleItemsJoiner} */
+const itemsJoinComma = items => items.filter(Boolean).join(", ");
+/** @type {SimpleItemsJoiner} */
+const itemsJoinCommaBrackets = items =>
+	items.length > 0 ? `(${items.filter(Boolean).join(", ")})` : undefined;
+/** @type {function(string): SimpleItemsJoiner} */
+const itemsJoinCommaBracketsWithName = name => items =>
+	items.length > 0
+		? `(${name}: ${items.filter(Boolean).join(", ")})`
+		: undefined;
+
+/** @type {Record<string, SimpleItemsJoiner>} */
+const SIMPLE_ITEMS_JOINER = {
+	"chunk.parents": itemsJoinOneLine,
+	"chunk.siblings": itemsJoinOneLine,
+	"chunk.children": itemsJoinOneLine,
+	"chunk.names": itemsJoinCommaBrackets,
+	"chunk.idHints": itemsJoinCommaBracketsWithName("id hint"),
+	"chunk.runtime": itemsJoinCommaBracketsWithName("runtime"),
+	"chunk.files": itemsJoinComma,
+	"chunk.childrenByOrder": itemsJoinOneLine,
+	"chunk.childrenByOrder[].children": itemsJoinOneLine,
+	"chunkGroup.assets": itemsJoinOneLine,
+	"chunkGroup.auxiliaryAssets": itemsJoinOneLineBrackets,
+	"chunkGroupChildGroup.children": itemsJoinComma,
+	"chunkGroupChild.assets": itemsJoinOneLine,
+	"chunkGroupChild.auxiliaryAssets": itemsJoinOneLineBrackets,
+	"asset.chunks": itemsJoinComma,
+	"asset.auxiliaryChunks": itemsJoinCommaBrackets,
+	"asset.chunkNames": itemsJoinCommaBracketsWithName("name"),
+	"asset.auxiliaryChunkNames": itemsJoinCommaBracketsWithName("auxiliary name"),
+	"asset.chunkIdHints": itemsJoinCommaBracketsWithName("id hint"),
+	"asset.auxiliaryChunkIdHints":
+		itemsJoinCommaBracketsWithName("auxiliary id hint"),
+	"module.chunks": itemsJoinOneLine,
+	"module.issuerPath": items =>
+		items
+			.filter(Boolean)
+			.map(item => `${item} ->`)
+			.join(" "),
+	"compilation.errors": itemsJoinMoreSpacing,
+	"compilation.warnings": itemsJoinMoreSpacing,
+	"compilation.logging": itemsJoinMoreSpacing,
+	"compilation.children": items =>
+		indent(/** @type {string} */ (itemsJoinMoreSpacing(items)), "  "),
+	"moduleTraceItem.dependencies": itemsJoinOneLine,
+	"loggingEntry.children": items =>
+		indent(items.filter(Boolean).join("\n"), "  ", false)
+};
+
+/**
+ * @param {Item[]} items items
+ * @returns {string} result
+ */
+const joinOneLine = items =>
+	items
+		.map(item => item.content)
+		.filter(Boolean)
+		.join(" ");
+
+/**
+ * @param {Item[]} items items
+ * @returns {string} result
+ */
+const joinInBrackets = items => {
+	const res = [];
+	let mode = 0;
+	for (const item of items) {
+		if (item.element === "separator!") {
+			switch (mode) {
+				case 0:
+				case 1:
+					mode += 2;
+					break;
+				case 4:
+					res.push(")");
+					mode = 3;
+					break;
+			}
+		}
+		if (!item.content) continue;
+		switch (mode) {
+			case 0:
+				mode = 1;
+				break;
+			case 1:
+				res.push(" ");
+				break;
+			case 2:
+				res.push("(");
+				mode = 4;
+				break;
+			case 3:
+				res.push(" (");
+				mode = 4;
+				break;
+			case 4:
+				res.push(", ");
+				break;
+		}
+		res.push(item.content);
+	}
+	if (mode === 4) res.push(")");
+	return res.join("");
+};
+
+/**
+ * @param {string} str a string
+ * @param {string} prefix prefix
+ * @param {boolean=} noPrefixInFirstLine need prefix in the first line?
+ * @returns {string} result
+ */
+const indent = (str, prefix, noPrefixInFirstLine) => {
+	const rem = str.replace(/\n([^\n])/g, `\n${prefix}$1`);
+	if (noPrefixInFirstLine) return rem;
+	const ind = str[0] === "\n" ? "" : prefix;
+	return ind + rem;
+};
+
+/**
+ * @param {(false | Item)[]} items items
+ * @param {string} indenter indenter
+ * @returns {string} result
+ */
+const joinExplicitNewLine = (items, indenter) => {
+	let firstInLine = true;
+	let first = true;
+	return items
+		.map(item => {
+			if (!item || !item.content) return;
+			let content = indent(item.content, first ? "" : indenter, !firstInLine);
+			if (firstInLine) {
+				content = content.replace(/^\n+/, "");
+			}
+			if (!content) return;
+			first = false;
+			const noJoiner = firstInLine || content.startsWith("\n");
+			firstInLine = content.endsWith("\n");
+			return noJoiner ? content : ` ${content}`;
+		})
+		.filter(Boolean)
+		.join("")
+		.trim();
+};
+
+/**
+ * @param {boolean} error is an error
+ * @returns {SimpleElementJoiner} joiner
+ */
+const joinError =
+	error =>
+	/**
+	 * @param {Item[]} items items
+	 * @param {Required<StatsPrinterContext>} ctx context
+	 * @returns {string} result
+	 */
+	(items, { red, yellow }) =>
+		`${error ? red("ERROR") : yellow("WARNING")} in ${joinExplicitNewLine(
+			items,
+			""
+		)}`;
+
+/** @typedef {{ element: string, content: string }} Item */
+/** @typedef {(items: Item[], context: Required<StatsPrinterContext>) => string} SimpleElementJoiner */
+
+/** @type {Record<string, SimpleElementJoiner>} */
+const SIMPLE_ELEMENT_JOINERS = {
+	compilation: items => {
+		const result = [];
+		let lastNeedMore = false;
+		for (const item of items) {
+			if (!item.content) continue;
+			const needMoreSpace =
+				item.element === "warnings" ||
+				item.element === "filteredWarningDetailsCount" ||
+				item.element === "errors" ||
+				item.element === "filteredErrorDetailsCount" ||
+				item.element === "logging";
+			if (result.length !== 0) {
+				result.push(needMoreSpace || lastNeedMore ? "\n\n" : "\n");
+			}
+			result.push(item.content);
+			lastNeedMore = needMoreSpace;
+		}
+		if (lastNeedMore) result.push("\n");
+		return result.join("");
+	},
+	asset: items =>
+		joinExplicitNewLine(
+			items.map(item => {
+				if (
+					(item.element === "related" || item.element === "children") &&
+					item.content
+				) {
+					return {
+						...item,
+						content: `\n${item.content}\n`
+					};
+				}
+				return item;
+			}),
+			"  "
+		),
+	"asset.info": joinOneLine,
+	module: (items, { module }) => {
+		let hasName = false;
+		return joinExplicitNewLine(
+			items.map(item => {
+				switch (item.element) {
+					case "id":
+						if (module.id === module.name) {
+							if (hasName) return false;
+							if (item.content) hasName = true;
+						}
+						break;
+					case "name":
+						if (hasName) return false;
+						if (item.content) hasName = true;
+						break;
+					case "providedExports":
+					case "usedExports":
+					case "optimizationBailout":
+					case "reasons":
+					case "issuerPath":
+					case "profile":
+					case "children":
+					case "modules":
+						if (item.content) {
+							return {
+								...item,
+								content: `\n${item.content}\n`
+							};
+						}
+						break;
+				}
+				return item;
+			}),
+			"  "
+		);
+	},
+	chunk: items => {
+		let hasEntry = false;
+		return `chunk ${joinExplicitNewLine(
+			items.filter(item => {
+				switch (item.element) {
+					case "entry":
+						if (item.content) hasEntry = true;
+						break;
+					case "initial":
+						if (hasEntry) return false;
+						break;
+				}
+				return true;
+			}),
+			"  "
+		)}`;
+	},
+	"chunk.childrenByOrder[]": items => `(${joinOneLine(items)})`,
+	chunkGroup: items => joinExplicitNewLine(items, "  "),
+	chunkGroupAsset: joinOneLine,
+	chunkGroupChildGroup: joinOneLine,
+	chunkGroupChild: joinOneLine,
+	// moduleReason: (items, { moduleReason }) => {
+	// 	let hasName = false;
+	// 	return joinOneLine(
+	// 		items.filter(item => {
+	// 			switch (item.element) {
+	// 				case "moduleId":
+	// 					if (moduleReason.moduleId === moduleReason.module && item.content)
+	// 						hasName = true;
+	// 					break;
+	// 				case "module":
+	// 					if (hasName) return false;
+	// 					break;
+	// 				case "resolvedModule":
+	// 					return (
+	// 						moduleReason.module !== moduleReason.resolvedModule &&
+	// 						item.content
+	// 					);
+	// 			}
+	// 			return true;
+	// 		})
+	// 	);
+	// },
+	moduleReason: (items, { moduleReason }) => {
+		let hasName = false;
+		return joinExplicitNewLine(
+			items.map(item => {
+				switch (item.element) {
+					case "moduleId":
+						if (moduleReason.moduleId === moduleReason.module && item.content)
+							hasName = true;
+						break;
+					case "module":
+						if (hasName) return false;
+						break;
+					case "resolvedModule":
+						if (moduleReason.module === moduleReason.resolvedModule)
+							return false;
+						break;
+					case "children":
+						if (item.content) {
+							return {
+								...item,
+								content: `\n${item.content}\n`
+							};
+						}
+						break;
+				}
+				return item;
+			}),
+			"  "
+		);
+	},
+	"module.profile": joinInBrackets,
+	moduleIssuer: joinOneLine,
+	chunkOrigin: items => `> ${joinOneLine(items)}`,
+	"errors[].error": joinError(true),
+	"warnings[].error": joinError(false),
+	loggingGroup: items => joinExplicitNewLine(items, "").trimEnd(),
+	moduleTraceItem: items => ` @ ${joinOneLine(items)}`,
+	moduleTraceDependency: joinOneLine
+};
+
+/** @typedef {"bold" | "yellow" | "red" | "green" | "cyan" | "magenta"} ColorNames */
+
+/** @type {Record<ColorNames, string>} */
+const AVAILABLE_COLORS = {
+	bold: "\u001B[1m",
+	yellow: "\u001B[1m\u001B[33m",
+	red: "\u001B[1m\u001B[31m",
+	green: "\u001B[1m\u001B[32m",
+	cyan: "\u001B[1m\u001B[36m",
+	magenta: "\u001B[1m\u001B[35m"
+};
+
+/** @type {Record<string, function(any, Required<KnownStatsPrinterColorFn> & StatsPrinterContext, ...any): string>} */
+const AVAILABLE_FORMATS = {
+	formatChunkId: (id, { yellow }, direction) => {
+		switch (direction) {
+			case "parent":
+				return `<{${yellow(id)}}>`;
+			case "sibling":
+				return `={${yellow(id)}}=`;
+			case "child":
+				return `>{${yellow(id)}}<`;
+			default:
+				return `{${yellow(id)}}`;
+		}
+	},
+	formatModuleId: id => `[${id}]`,
+	formatFilename: (filename, { green, yellow }, oversize) =>
+		(oversize ? yellow : green)(filename),
+	formatFlag: flag => `[${flag}]`,
+	formatLayer: layer => `(in ${layer})`,
+	formatSize: require("../SizeFormatHelpers").formatSize,
+	formatDateTime: (dateTime, { bold }) => {
+		const d = new Date(dateTime);
+		const x = twoDigit;
+		const date = `${d.getFullYear()}-${x(d.getMonth() + 1)}-${x(d.getDate())}`;
+		const time = `${x(d.getHours())}:${x(d.getMinutes())}:${x(d.getSeconds())}`;
+		return `${date} ${bold(time)}`;
+	},
+	formatTime: (
+		time,
+		{ timeReference, bold, green, yellow, red },
+		boldQuantity
+	) => {
+		const unit = " ms";
+		if (timeReference && time !== timeReference) {
+			const times = [
+				timeReference / 2,
+				timeReference / 4,
+				timeReference / 8,
+				timeReference / 16
+			];
+			if (time < times[3]) return `${time}${unit}`;
+			else if (time < times[2]) return bold(`${time}${unit}`);
+			else if (time < times[1]) return green(`${time}${unit}`);
+			else if (time < times[0]) return yellow(`${time}${unit}`);
+			return red(`${time}${unit}`);
+		}
+		return `${boldQuantity ? bold(time) : time}${unit}`;
+	},
+	formatError: (message, { green, yellow, red }) => {
+		if (message.includes("\u001B[")) return message;
+		const highlights = [
+			{ regExp: /(Did you mean .+)/g, format: green },
+			{
+				regExp: /(Set 'mode' option to 'development' or 'production')/g,
+				format: green
+			},
+			{ regExp: /(\(module has no exports\))/g, format: red },
+			{ regExp: /\(possible exports: (.+)\)/g, format: green },
+			{ regExp: /(?:^|\n)(.* doesn't exist)/g, format: red },
+			{ regExp: /('\w+' option has not been set)/g, format: red },
+			{
+				regExp: /(Emitted value instead of an instance of Error)/g,
+				format: yellow
+			},
+			{ regExp: /(Used? .+ instead)/gi, format: yellow },
+			{ regExp: /\b(deprecated|must|required)\b/g, format: yellow },
+			{
+				regExp: /\b(BREAKING CHANGE)\b/gi,
+				format: red
+			},
+			{
+				regExp:
+					/\b(error|failed|unexpected|invalid|not found|not supported|not available|not possible|not implemented|doesn't support|conflict|conflicting|not existing|duplicate)\b/gi,
+				format: red
+			}
+		];
+		for (const { regExp, format } of highlights) {
+			message = message.replace(
+				regExp,
+				/**
+				 * @param {string} match match
+				 * @param {string} content content
+				 * @returns {string} result
+				 */
+				(match, content) => match.replace(content, format(content))
+			);
+		}
+		return message;
+	}
+};
+
+/** @typedef {function(string): string} ResultModifierFn */
+/** @type {Record<string, ResultModifierFn>} */
+const RESULT_MODIFIER = {
+	"module.modules": result => indent(result, "| ")
+};
+
+/**
+ * @param {string[]} array array
+ * @param {string[]} preferredOrder preferred order
+ * @returns {string[]} result
+ */
+const createOrder = (array, preferredOrder) => {
+	const originalArray = array.slice();
+	/** @type {Set<string>} */
+	const set = new Set(array);
+	/** @type {Set<string>} */
+	const usedSet = new Set();
+	array.length = 0;
+	for (const element of preferredOrder) {
+		if (element.endsWith("!") || set.has(element)) {
+			array.push(element);
+			usedSet.add(element);
+		}
+	}
+	for (const element of originalArray) {
+		if (!usedSet.has(element)) {
+			array.push(element);
+		}
+	}
+	return array;
+};
+
+class DefaultStatsPrinterPlugin {
+	/**
+	 * Apply the plugin
+	 * @param {Compiler} compiler the compiler instance
+	 * @returns {void}
+	 */
+	apply(compiler) {
+		compiler.hooks.compilation.tap("DefaultStatsPrinterPlugin", compilation => {
+			compilation.hooks.statsPrinter.tap(
+				"DefaultStatsPrinterPlugin",
+				(stats, options) => {
+					// Put colors into context
+					stats.hooks.print
+						.for("compilation")
+						.tap("DefaultStatsPrinterPlugin", (compilation, context) => {
+							for (const color of Object.keys(AVAILABLE_COLORS)) {
+								const name = /** @type {ColorNames} */ (color);
+								/** @type {string | undefined} */
+								let start;
+								if (options.colors) {
+									if (
+										typeof options.colors === "object" &&
+										typeof options.colors[name] === "string"
+									) {
+										start = options.colors[name];
+									} else {
+										start = AVAILABLE_COLORS[name];
+									}
+								}
+								if (start) {
+									/**
+									 * @param {string} str string
+									 * @returns {string} string with color
+									 */
+									context[color] = str =>
+										`${start}${
+											typeof str === "string"
+												? str.replace(
+														/((\u001B\[39m|\u001B\[22m|\u001B\[0m)+)/g,
+														`$1${start}`
+													)
+												: str
+										}\u001B[39m\u001B[22m`;
+								} else {
+									/**
+									 * @param {string} str string
+									 * @returns {string} str string
+									 */
+									context[color] = str => str;
+								}
+							}
+							for (const format of Object.keys(AVAILABLE_FORMATS)) {
+								context[format] =
+									/**
+									 * @param {string | number} content content
+									 * @param {...TODO} args args
+									 * @returns {string} result
+									 */
+									(content, ...args) =>
+										AVAILABLE_FORMATS[format](
+											content,
+											/** @type {Required<KnownStatsPrinterColorFn> & StatsPrinterContext} */
+											(context),
+											...args
+										);
+							}
+							context.timeReference = compilation.time;
+						});
+
+					for (const key of Object.keys(COMPILATION_SIMPLE_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								COMPILATION_SIMPLE_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(ASSET_SIMPLE_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								ASSET_SIMPLE_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "asset">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_SIMPLE_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_SIMPLE_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "module">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_ISSUER_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_ISSUER_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleIssuer">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_REASON_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_REASON_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleReason">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_PROFILE_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_PROFILE_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "profile">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(CHUNK_GROUP_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								CHUNK_GROUP_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "chunkGroupKind" | "chunkGroup">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(CHUNK_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								CHUNK_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "chunk">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(ERROR_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								ERROR_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "error">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(LOG_ENTRY_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								LOG_ENTRY_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "logging">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_TRACE_DEPENDENCY_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_TRACE_DEPENDENCY_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleTraceDependency">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(MODULE_TRACE_ITEM_PRINTERS)) {
+						stats.hooks.print
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (obj, ctx) =>
+								MODULE_TRACE_ITEM_PRINTERS[key](
+									obj,
+									/** @type {Required<KnownStatsPrinterColorFn> & Required<KnownStatsPrinterFormaters> & WithRequired<StatsPrinterContext, "type" | "compilation" | "moduleTraceItem">} */
+									(ctx),
+									stats
+								)
+							);
+					}
+
+					for (const key of Object.keys(PREFERRED_ORDERS)) {
+						const preferredOrder = PREFERRED_ORDERS[key];
+						stats.hooks.sortElements
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", (elements, context) => {
+								createOrder(elements, preferredOrder);
+							});
+					}
+
+					for (const key of Object.keys(ITEM_NAMES)) {
+						const itemName = ITEM_NAMES[key];
+						stats.hooks.getItemName
+							.for(key)
+							.tap(
+								"DefaultStatsPrinterPlugin",
+								typeof itemName === "string" ? () => itemName : itemName
+							);
+					}
+
+					for (const key of Object.keys(SIMPLE_ITEMS_JOINER)) {
+						const joiner = SIMPLE_ITEMS_JOINER[key];
+						stats.hooks.printItems
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", joiner);
+					}
+
+					for (const key of Object.keys(SIMPLE_ELEMENT_JOINERS)) {
+						const joiner = SIMPLE_ELEMENT_JOINERS[key];
+						stats.hooks.printElements
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", /** @type {TODO} */ (joiner));
+					}
+
+					for (const key of Object.keys(RESULT_MODIFIER)) {
+						const modifier = RESULT_MODIFIER[key];
+						stats.hooks.result
+							.for(key)
+							.tap("DefaultStatsPrinterPlugin", modifier);
+					}
+				}
+			);
+		});
+	}
+}
+module.exports = DefaultStatsPrinterPlugin;
Index: imaps-frontend/node_modules/webpack/lib/stats/StatsFactory.js
===================================================================
--- imaps-frontend/node_modules/webpack/lib/stats/StatsFactory.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/webpack/lib/stats/StatsFactory.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -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], 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({
+			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 | 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(/** @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;
Index: imaps-frontend/node_modules/webpack/lib/stats/StatsPrinter.js
===================================================================
--- imaps-frontend/node_modules/webpack/lib/stats/StatsPrinter.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/webpack/lib/stats/StatsPrinter.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,280 @@
+/*
+	MIT License http://www.opensource.org/licenses/mit-license.php
+	Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const { HookMap, SyncWaterfallHook, SyncBailHook } = require("tapable");
+
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsChunk} StatsChunk */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsChunkGroup} StatsChunkGroup */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsCompilation} StatsCompilation */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsError} StatsError */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsLogging} StatsLogging */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModule} StatsModule */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleIssuer} StatsModuleIssuer */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleReason} StatsModuleReason */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleTraceDependency} StatsModuleTraceDependency */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleTraceItem} StatsModuleTraceItem */
+/** @typedef {import("./DefaultStatsFactoryPlugin").StatsProfile} StatsProfile */
+
+/**
+ * @typedef {object} PrintedElement
+ * @property {string} element
+ * @property {string} content
+ */
+
+/**
+ * @typedef {object} KnownStatsPrinterContext
+ * @property {string=} type
+ * @property {StatsCompilation=} compilation
+ * @property {StatsChunkGroup=} chunkGroup
+ * @property {string=} chunkGroupKind
+ * @property {StatsAsset=} asset
+ * @property {StatsModule=} module
+ * @property {StatsChunk=} chunk
+ * @property {StatsModuleReason=} moduleReason
+ * @property {StatsModuleIssuer=} moduleIssuer
+ * @property {StatsError=} error
+ * @property {StatsProfile=} profile
+ * @property {StatsLogging=} logging
+ * @property {StatsModuleTraceItem=} moduleTraceItem
+ * @property {StatsModuleTraceDependency=} moduleTraceDependency
+ */
+
+/**
+ * @typedef {object} KnownStatsPrinterColorFn
+ * @property {(str: string) => string=} bold
+ * @property {(str: string) => string=} yellow
+ * @property {(str: string) => string=} red
+ * @property {(str: string) => string=} green
+ * @property {(str: string) => string=} magenta
+ * @property {(str: string) => string=} cyan
+ */
+
+/**
+ * @typedef {object} KnownStatsPrinterFormaters
+ * @property {(file: string, oversize?: boolean) => string=} formatFilename
+ * @property {(id: string) => string=} formatModuleId
+ * @property {(id: string, direction?: "parent"|"child"|"sibling") => string=} formatChunkId
+ * @property {(size: number) => string=} formatSize
+ * @property {(size: string) => string=} formatLayer
+ * @property {(dateTime: number) => string=} formatDateTime
+ * @property {(flag: string) => string=} formatFlag
+ * @property {(time: number, boldQuantity?: boolean) => string=} formatTime
+ * @property {(message: string) => string=} formatError
+ */
+
+/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsPrinterColorFn & KnownStatsPrinterFormaters & KnownStatsPrinterContext} StatsPrinterContext */
+/** @typedef {any} PrintObject */
+
+/**
+ * @typedef {object} StatsPrintHooks
+ * @property {HookMap<SyncBailHook<[string[], StatsPrinterContext], void>>} sortElements
+ * @property {HookMap<SyncBailHook<[PrintedElement[], StatsPrinterContext], string | void>>} printElements
+ * @property {HookMap<SyncBailHook<[PrintObject[], StatsPrinterContext], boolean | void>>} sortItems
+ * @property {HookMap<SyncBailHook<[PrintObject, StatsPrinterContext], string | void>>} getItemName
+ * @property {HookMap<SyncBailHook<[string[], StatsPrinterContext], string | void>>} printItems
+ * @property {HookMap<SyncBailHook<[PrintObject, StatsPrinterContext], string | void>>} print
+ * @property {HookMap<SyncWaterfallHook<[string, StatsPrinterContext]>>} result
+ */
+
+class StatsPrinter {
+	constructor() {
+		/** @type {StatsPrintHooks} */
+		this.hooks = Object.freeze({
+			sortElements: new HookMap(
+				() => new SyncBailHook(["elements", "context"])
+			),
+			printElements: new HookMap(
+				() => new SyncBailHook(["printedElements", "context"])
+			),
+			sortItems: new HookMap(() => new SyncBailHook(["items", "context"])),
+			getItemName: new HookMap(() => new SyncBailHook(["item", "context"])),
+			printItems: new HookMap(
+				() => new SyncBailHook(["printedItems", "context"])
+			),
+			print: new HookMap(() => new SyncBailHook(["object", "context"])),
+			/** @type {HookMap<SyncWaterfallHook<[string, StatsPrinterContext]>>} */
+			result: new HookMap(() => new SyncWaterfallHook(["result", "context"]))
+		});
+		/**
+		 * @type {TODO}
+		 */
+		this._levelHookCache = new Map();
+		this._inPrint = false;
+	}
+
+	/**
+	 * get all level hooks
+	 * @private
+	 * @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
+	 * @template {HM extends HookMap<infer H> ? H : never} H
+	 * @param {HM} hookMap hook map
+	 * @param {string} type type
+	 * @returns {H[]} hooks
+	 */
+	_getAllLevelHooks(hookMap, type) {
+		let cache = this._levelHookCache.get(hookMap);
+		if (cache === undefined) {
+			cache = new Map();
+			this._levelHookCache.set(hookMap, cache);
+		}
+		const cacheEntry = cache.get(type);
+		if (cacheEntry !== undefined) {
+			return cacheEntry;
+		}
+		/** @type {H[]} */
+		const hooks = [];
+		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;
+	}
+
+	/**
+	 * Run `fn` for each level
+	 * @private
+	 * @template {StatsPrintHooks[keyof StatsPrintHooks]} 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 {string} type type
+	 * @param {function(H): R | void} fn fn
+	 * @returns {R | void} hook
+	 */
+	_forEachLevel(hookMap, type, fn) {
+		for (const hook of this._getAllLevelHooks(hookMap, type)) {
+			const result = fn(/** @type {H} */ (hook));
+			if (result !== undefined) return result;
+		}
+	}
+
+	/**
+	 * Run `fn` for each level
+	 * @private
+	 * @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
+	 * @template {HM extends HookMap<infer H> ? H : never} H
+	 * @param {HM} hookMap hook map
+	 * @param {string} type type
+	 * @param {string} data data
+	 * @param {function(H, string): string} fn fn
+	 * @returns {string} result of `fn`
+	 */
+	_forEachLevelWaterfall(hookMap, type, data, fn) {
+		for (const hook of this._getAllLevelHooks(hookMap, type)) {
+			data = fn(/** @type {H} */ (hook), data);
+		}
+		return data;
+	}
+
+	/**
+	 * @param {string} type The type
+	 * @param {PrintObject} object Object to print
+	 * @param {StatsPrinterContext=} baseContext The base context
+	 * @returns {string} printed result
+	 */
+	print(type, object, baseContext) {
+		if (this._inPrint) {
+			return this._print(type, object, baseContext);
+		}
+		try {
+			this._inPrint = true;
+			return this._print(type, object, baseContext);
+		} finally {
+			this._levelHookCache.clear();
+			this._inPrint = false;
+		}
+	}
+
+	/**
+	 * @private
+	 * @param {string} type type
+	 * @param {PrintObject} object object
+	 * @param {StatsPrinterContext=} baseContext context
+	 * @returns {string} printed result
+	 */
+	_print(type, object, baseContext) {
+		/** @type {StatsPrinterContext} */
+		const context = {
+			...baseContext,
+			type,
+			[type]: object
+		};
+
+		let printResult = this._forEachLevel(this.hooks.print, type, hook =>
+			hook.call(object, context)
+		);
+		if (printResult === undefined) {
+			if (Array.isArray(object)) {
+				const sortedItems = object.slice();
+				this._forEachLevel(this.hooks.sortItems, type, h =>
+					h.call(sortedItems, context)
+				);
+				const printedItems = sortedItems.map((item, i) => {
+					/** @type {StatsPrinterContext} */
+					const itemContext = {
+						...context,
+						_index: i
+					};
+					const itemName = this._forEachLevel(
+						this.hooks.getItemName,
+						`${type}[]`,
+						h => h.call(item, itemContext)
+					);
+					if (itemName) itemContext[itemName] = item;
+					return this.print(
+						itemName ? `${type}[].${itemName}` : `${type}[]`,
+						item,
+						itemContext
+					);
+				});
+				printResult = this._forEachLevel(this.hooks.printItems, type, h =>
+					h.call(printedItems, context)
+				);
+				if (printResult === undefined) {
+					const result = printedItems.filter(Boolean);
+					if (result.length > 0) printResult = result.join("\n");
+				}
+			} else if (object !== null && typeof object === "object") {
+				const elements = Object.keys(object).filter(
+					key => object[key] !== undefined
+				);
+				this._forEachLevel(this.hooks.sortElements, type, h =>
+					h.call(elements, context)
+				);
+				const printedElements = elements.map(element => {
+					const content = this.print(`${type}.${element}`, object[element], {
+						...context,
+						_parent: object,
+						_element: element,
+						[element]: object[element]
+					});
+					return { element, content };
+				});
+				printResult = this._forEachLevel(this.hooks.printElements, type, h =>
+					h.call(printedElements, context)
+				);
+				if (printResult === undefined) {
+					const result = printedElements.map(e => e.content).filter(Boolean);
+					if (result.length > 0) printResult = result.join("\n");
+				}
+			}
+		}
+
+		return this._forEachLevelWaterfall(
+			this.hooks.result,
+			type,
+			/** @type {string} */ (printResult),
+			(h, r) => h.call(r, context)
+		);
+	}
+}
+module.exports = StatsPrinter;
