source: imaps-frontend/node_modules/webpack/lib/stats/StatsPrinter.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { HookMap, SyncWaterfallHook, SyncBailHook } = require("tapable");
9
10/** @typedef {import("./DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
11/** @typedef {import("./DefaultStatsFactoryPlugin").StatsChunk} StatsChunk */
12/** @typedef {import("./DefaultStatsFactoryPlugin").StatsChunkGroup} StatsChunkGroup */
13/** @typedef {import("./DefaultStatsFactoryPlugin").StatsCompilation} StatsCompilation */
14/** @typedef {import("./DefaultStatsFactoryPlugin").StatsError} StatsError */
15/** @typedef {import("./DefaultStatsFactoryPlugin").StatsLogging} StatsLogging */
16/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModule} StatsModule */
17/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleIssuer} StatsModuleIssuer */
18/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleReason} StatsModuleReason */
19/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleTraceDependency} StatsModuleTraceDependency */
20/** @typedef {import("./DefaultStatsFactoryPlugin").StatsModuleTraceItem} StatsModuleTraceItem */
21/** @typedef {import("./DefaultStatsFactoryPlugin").StatsProfile} StatsProfile */
22
23/**
24 * @typedef {object} PrintedElement
25 * @property {string} element
26 * @property {string} content
27 */
28
29/**
30 * @typedef {object} KnownStatsPrinterContext
31 * @property {string=} type
32 * @property {StatsCompilation=} compilation
33 * @property {StatsChunkGroup=} chunkGroup
34 * @property {string=} chunkGroupKind
35 * @property {StatsAsset=} asset
36 * @property {StatsModule=} module
37 * @property {StatsChunk=} chunk
38 * @property {StatsModuleReason=} moduleReason
39 * @property {StatsModuleIssuer=} moduleIssuer
40 * @property {StatsError=} error
41 * @property {StatsProfile=} profile
42 * @property {StatsLogging=} logging
43 * @property {StatsModuleTraceItem=} moduleTraceItem
44 * @property {StatsModuleTraceDependency=} moduleTraceDependency
45 */
46
47/**
48 * @typedef {object} KnownStatsPrinterColorFn
49 * @property {(str: string) => string=} bold
50 * @property {(str: string) => string=} yellow
51 * @property {(str: string) => string=} red
52 * @property {(str: string) => string=} green
53 * @property {(str: string) => string=} magenta
54 * @property {(str: string) => string=} cyan
55 */
56
57/**
58 * @typedef {object} KnownStatsPrinterFormaters
59 * @property {(file: string, oversize?: boolean) => string=} formatFilename
60 * @property {(id: string) => string=} formatModuleId
61 * @property {(id: string, direction?: "parent"|"child"|"sibling") => string=} formatChunkId
62 * @property {(size: number) => string=} formatSize
63 * @property {(size: string) => string=} formatLayer
64 * @property {(dateTime: number) => string=} formatDateTime
65 * @property {(flag: string) => string=} formatFlag
66 * @property {(time: number, boldQuantity?: boolean) => string=} formatTime
67 * @property {(message: string) => string=} formatError
68 */
69
70/** @typedef {Record<string, EXPECTED_ANY> & KnownStatsPrinterColorFn & KnownStatsPrinterFormaters & KnownStatsPrinterContext} StatsPrinterContext */
71/** @typedef {any} PrintObject */
72
73/**
74 * @typedef {object} StatsPrintHooks
75 * @property {HookMap<SyncBailHook<[string[], StatsPrinterContext], void>>} sortElements
76 * @property {HookMap<SyncBailHook<[PrintedElement[], StatsPrinterContext], string | void>>} printElements
77 * @property {HookMap<SyncBailHook<[PrintObject[], StatsPrinterContext], boolean | void>>} sortItems
78 * @property {HookMap<SyncBailHook<[PrintObject, StatsPrinterContext], string | void>>} getItemName
79 * @property {HookMap<SyncBailHook<[string[], StatsPrinterContext], string | void>>} printItems
80 * @property {HookMap<SyncBailHook<[PrintObject, StatsPrinterContext], string | void>>} print
81 * @property {HookMap<SyncWaterfallHook<[string, StatsPrinterContext]>>} result
82 */
83
84class StatsPrinter {
85 constructor() {
86 /** @type {StatsPrintHooks} */
87 this.hooks = Object.freeze({
88 sortElements: new HookMap(
89 () => new SyncBailHook(["elements", "context"])
90 ),
91 printElements: new HookMap(
92 () => new SyncBailHook(["printedElements", "context"])
93 ),
94 sortItems: new HookMap(() => new SyncBailHook(["items", "context"])),
95 getItemName: new HookMap(() => new SyncBailHook(["item", "context"])),
96 printItems: new HookMap(
97 () => new SyncBailHook(["printedItems", "context"])
98 ),
99 print: new HookMap(() => new SyncBailHook(["object", "context"])),
100 /** @type {HookMap<SyncWaterfallHook<[string, StatsPrinterContext]>>} */
101 result: new HookMap(() => new SyncWaterfallHook(["result", "context"]))
102 });
103 /**
104 * @type {TODO}
105 */
106 this._levelHookCache = new Map();
107 this._inPrint = false;
108 }
109
110 /**
111 * get all level hooks
112 * @private
113 * @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
114 * @template {HM extends HookMap<infer H> ? H : never} H
115 * @param {HM} hookMap hook map
116 * @param {string} type type
117 * @returns {H[]} hooks
118 */
119 _getAllLevelHooks(hookMap, type) {
120 let cache = this._levelHookCache.get(hookMap);
121 if (cache === undefined) {
122 cache = new Map();
123 this._levelHookCache.set(hookMap, cache);
124 }
125 const cacheEntry = cache.get(type);
126 if (cacheEntry !== undefined) {
127 return cacheEntry;
128 }
129 /** @type {H[]} */
130 const hooks = [];
131 const typeParts = type.split(".");
132 for (let i = 0; i < typeParts.length; i++) {
133 const hook = /** @type {H} */ (hookMap.get(typeParts.slice(i).join(".")));
134 if (hook) {
135 hooks.push(hook);
136 }
137 }
138 cache.set(type, hooks);
139 return hooks;
140 }
141
142 /**
143 * Run `fn` for each level
144 * @private
145 * @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
146 * @template {HM extends HookMap<infer H> ? H : never} H
147 * @template {H extends import("tapable").Hook<any, infer R> ? R : never} R
148 * @param {HM} hookMap hook map
149 * @param {string} type type
150 * @param {function(H): R | void} fn fn
151 * @returns {R | void} hook
152 */
153 _forEachLevel(hookMap, type, fn) {
154 for (const hook of this._getAllLevelHooks(hookMap, type)) {
155 const result = fn(/** @type {H} */ (hook));
156 if (result !== undefined) return result;
157 }
158 }
159
160 /**
161 * Run `fn` for each level
162 * @private
163 * @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
164 * @template {HM extends HookMap<infer H> ? H : never} H
165 * @param {HM} hookMap hook map
166 * @param {string} type type
167 * @param {string} data data
168 * @param {function(H, string): string} fn fn
169 * @returns {string} result of `fn`
170 */
171 _forEachLevelWaterfall(hookMap, type, data, fn) {
172 for (const hook of this._getAllLevelHooks(hookMap, type)) {
173 data = fn(/** @type {H} */ (hook), data);
174 }
175 return data;
176 }
177
178 /**
179 * @param {string} type The type
180 * @param {PrintObject} object Object to print
181 * @param {StatsPrinterContext=} baseContext The base context
182 * @returns {string} printed result
183 */
184 print(type, object, baseContext) {
185 if (this._inPrint) {
186 return this._print(type, object, baseContext);
187 }
188 try {
189 this._inPrint = true;
190 return this._print(type, object, baseContext);
191 } finally {
192 this._levelHookCache.clear();
193 this._inPrint = false;
194 }
195 }
196
197 /**
198 * @private
199 * @param {string} type type
200 * @param {PrintObject} object object
201 * @param {StatsPrinterContext=} baseContext context
202 * @returns {string} printed result
203 */
204 _print(type, object, baseContext) {
205 /** @type {StatsPrinterContext} */
206 const context = {
207 ...baseContext,
208 type,
209 [type]: object
210 };
211
212 let printResult = this._forEachLevel(this.hooks.print, type, hook =>
213 hook.call(object, context)
214 );
215 if (printResult === undefined) {
216 if (Array.isArray(object)) {
217 const sortedItems = object.slice();
218 this._forEachLevel(this.hooks.sortItems, type, h =>
219 h.call(sortedItems, context)
220 );
221 const printedItems = sortedItems.map((item, i) => {
222 /** @type {StatsPrinterContext} */
223 const itemContext = {
224 ...context,
225 _index: i
226 };
227 const itemName = this._forEachLevel(
228 this.hooks.getItemName,
229 `${type}[]`,
230 h => h.call(item, itemContext)
231 );
232 if (itemName) itemContext[itemName] = item;
233 return this.print(
234 itemName ? `${type}[].${itemName}` : `${type}[]`,
235 item,
236 itemContext
237 );
238 });
239 printResult = this._forEachLevel(this.hooks.printItems, type, h =>
240 h.call(printedItems, context)
241 );
242 if (printResult === undefined) {
243 const result = printedItems.filter(Boolean);
244 if (result.length > 0) printResult = result.join("\n");
245 }
246 } else if (object !== null && typeof object === "object") {
247 const elements = Object.keys(object).filter(
248 key => object[key] !== undefined
249 );
250 this._forEachLevel(this.hooks.sortElements, type, h =>
251 h.call(elements, context)
252 );
253 const printedElements = elements.map(element => {
254 const content = this.print(`${type}.${element}`, object[element], {
255 ...context,
256 _parent: object,
257 _element: element,
258 [element]: object[element]
259 });
260 return { element, content };
261 });
262 printResult = this._forEachLevel(this.hooks.printElements, type, h =>
263 h.call(printedElements, context)
264 );
265 if (printResult === undefined) {
266 const result = printedElements.map(e => e.content).filter(Boolean);
267 if (result.length > 0) printResult = result.join("\n");
268 }
269 }
270 }
271
272 return this._forEachLevelWaterfall(
273 this.hooks.result,
274 type,
275 /** @type {string} */ (printResult),
276 (h, r) => h.call(r, context)
277 );
278 }
279}
280module.exports = StatsPrinter;
Note: See TracBrowser for help on using the repository browser.