a zip code crypto-currency system good for red ONLY

Stats.js 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RequestShortener = require("./RequestShortener");
  7. const SizeFormatHelpers = require("./SizeFormatHelpers");
  8. const formatLocation = require("./formatLocation");
  9. const identifierUtils = require("./util/identifier");
  10. const optionsOrFallback = function() {
  11. let optionValues = [];
  12. optionValues.push.apply(optionValues, arguments);
  13. return optionValues.find(optionValue => typeof optionValue !== "undefined");
  14. };
  15. class Stats {
  16. constructor(compilation) {
  17. this.compilation = compilation;
  18. this.hash = compilation.hash;
  19. }
  20. static filterWarnings(warnings, warningsFilter) {
  21. // we dont have anything to filter so all warnings can be shown
  22. if(!warningsFilter) {
  23. return warnings;
  24. }
  25. // create a chain of filters
  26. // if they return "true" a warning should be surpressed
  27. const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => {
  28. if(typeof filter === "string") {
  29. return warning => warning.indexOf(filter) > -1;
  30. }
  31. if(filter instanceof RegExp) {
  32. return warning => filter.test(warning);
  33. }
  34. if(typeof filter === "function") {
  35. return filter;
  36. }
  37. throw new Error(`Can only filter warnings with Strings or RegExps. (Given: ${filter})`);
  38. });
  39. return warnings.filter(warning => {
  40. return !normalizedWarningsFilters.some(check => check(warning));
  41. });
  42. }
  43. hasWarnings() {
  44. return this.compilation.warnings.length > 0;
  45. }
  46. hasErrors() {
  47. return this.compilation.errors.length > 0;
  48. }
  49. // remove a prefixed "!" that can be specified to reverse sort order
  50. normalizeFieldKey(field) {
  51. if(field[0] === "!") {
  52. return field.substr(1);
  53. }
  54. return field;
  55. }
  56. // if a field is prefixed by a "!" reverse sort order
  57. sortOrderRegular(field) {
  58. if(field[0] === "!") {
  59. return false;
  60. }
  61. return true;
  62. }
  63. toJson(options, forToString) {
  64. if(typeof options === "boolean" || typeof options === "string") {
  65. options = Stats.presetToOptions(options);
  66. } else if(!options) {
  67. options = {};
  68. }
  69. const optionOrLocalFallback = (v, def) =>
  70. typeof v !== "undefined" ? v :
  71. typeof options.all !== "undefined" ? options.all : def;
  72. const testAgainstGivenOption = (item) => {
  73. if(typeof item === "string") {
  74. const regExp = new RegExp(`[\\\\/]${item.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")}([\\\\/]|$|!|\\?)`); // eslint-disable-line no-useless-escape
  75. return ident => regExp.test(ident);
  76. }
  77. if(item && typeof item === "object" && typeof item.test === "function")
  78. return ident => item.test(ident);
  79. if(typeof item === "function")
  80. return item;
  81. };
  82. const compilation = this.compilation;
  83. const context = optionsOrFallback(options.context, process.cwd());
  84. const requestShortener = new RequestShortener(context);
  85. const showPerformance = optionOrLocalFallback(options.performance, true);
  86. const showHash = optionOrLocalFallback(options.hash, true);
  87. const showEnv = optionOrLocalFallback(options.env, false);
  88. const showVersion = optionOrLocalFallback(options.version, true);
  89. const showTimings = optionOrLocalFallback(options.timings, true);
  90. const showAssets = optionOrLocalFallback(options.assets, true);
  91. const showEntrypoints = optionOrLocalFallback(options.entrypoints, !forToString);
  92. const showChunks = optionOrLocalFallback(options.chunks, !forToString);
  93. const showChunkModules = optionOrLocalFallback(options.chunkModules, true);
  94. const showChunkOrigins = optionOrLocalFallback(options.chunkOrigins, !forToString);
  95. const showModules = optionOrLocalFallback(options.modules, true);
  96. const showDepth = optionOrLocalFallback(options.depth, !forToString);
  97. const showCachedModules = optionOrLocalFallback(options.cached, true);
  98. const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true);
  99. const showReasons = optionOrLocalFallback(options.reasons, !forToString);
  100. const showUsedExports = optionOrLocalFallback(options.usedExports, !forToString);
  101. const showProvidedExports = optionOrLocalFallback(options.providedExports, !forToString);
  102. const showOptimizationBailout = optionOrLocalFallback(options.optimizationBailout, !forToString);
  103. const showChildren = optionOrLocalFallback(options.children, true);
  104. const showSource = optionOrLocalFallback(options.source, !forToString);
  105. const showModuleTrace = optionOrLocalFallback(options.moduleTrace, true);
  106. const showErrors = optionOrLocalFallback(options.errors, true);
  107. const showErrorDetails = optionOrLocalFallback(options.errorDetails, !forToString);
  108. const showWarnings = optionOrLocalFallback(options.warnings, true);
  109. const warningsFilter = optionsOrFallback(options.warningsFilter, null);
  110. const showPublicPath = optionOrLocalFallback(options.publicPath, !forToString);
  111. const excludeModules = [].concat(optionsOrFallback(options.excludeModules, options.exclude, [])).map(testAgainstGivenOption);
  112. const excludeAssets = [].concat(optionsOrFallback(options.excludeAssets, [])).map(testAgainstGivenOption);
  113. const maxModules = optionsOrFallback(options.maxModules, forToString ? 15 : Infinity);
  114. const sortModules = optionsOrFallback(options.modulesSort, "id");
  115. const sortChunks = optionsOrFallback(options.chunksSort, "id");
  116. const sortAssets = optionsOrFallback(options.assetsSort, "");
  117. if(!showCachedModules) {
  118. excludeModules.push((ident, module) => !module.built);
  119. }
  120. const createModuleFilter = () => {
  121. let i = 0;
  122. return module => {
  123. if(excludeModules.length > 0) {
  124. const ident = requestShortener.shorten(module.resource);
  125. const excluded = excludeModules.some(fn => fn(ident, module));
  126. if(excluded)
  127. return false;
  128. }
  129. return i++ < maxModules;
  130. };
  131. };
  132. const createAssetFilter = () => {
  133. return asset => {
  134. if(excludeAssets.length > 0) {
  135. const ident = asset.name;
  136. const excluded = excludeAssets.some(fn => fn(ident, asset));
  137. if(excluded)
  138. return false;
  139. }
  140. return showCachedAssets || asset.emitted;
  141. };
  142. };
  143. const sortByFieldAndOrder = (fieldKey, a, b) => {
  144. if(a[fieldKey] === null && b[fieldKey] === null) return 0;
  145. if(a[fieldKey] === null) return 1;
  146. if(b[fieldKey] === null) return -1;
  147. if(a[fieldKey] === b[fieldKey]) return 0;
  148. return a[fieldKey] < b[fieldKey] ? -1 : 1;
  149. };
  150. const sortByField = (field) => (a, b) => {
  151. if(!field) {
  152. return 0;
  153. }
  154. const fieldKey = this.normalizeFieldKey(field);
  155. // if a field is prefixed with a "!" the sort is reversed!
  156. const sortIsRegular = this.sortOrderRegular(field);
  157. return sortByFieldAndOrder(fieldKey, sortIsRegular ? a : b, sortIsRegular ? b : a);
  158. };
  159. const formatError = (e) => {
  160. let text = "";
  161. if(typeof e === "string")
  162. e = {
  163. message: e
  164. };
  165. if(e.chunk) {
  166. text += `chunk ${e.chunk.name || e.chunk.id}${e.chunk.hasRuntime() ? " [entry]" : e.chunk.isInitial() ? " [initial]" : ""}\n`;
  167. }
  168. if(e.file) {
  169. text += `${e.file}\n`;
  170. }
  171. if(e.module && e.module.readableIdentifier && typeof e.module.readableIdentifier === "function") {
  172. text += `${e.module.readableIdentifier(requestShortener)}\n`;
  173. }
  174. text += e.message;
  175. if(showErrorDetails && e.details) text += `\n${e.details}`;
  176. if(showErrorDetails && e.missing) text += e.missing.map(item => `\n[${item}]`).join("");
  177. if(showModuleTrace && e.origin) {
  178. text += `\n @ ${e.origin.readableIdentifier(requestShortener)}`;
  179. if(typeof e.originLoc === "object") {
  180. const locInfo = formatLocation(e.originLoc);
  181. if(locInfo)
  182. text += ` ${locInfo}`;
  183. }
  184. if(e.dependencies) {
  185. e.dependencies.forEach(dep => {
  186. if(!dep.loc) return;
  187. if(typeof dep.loc === "string") return;
  188. const locInfo = formatLocation(dep.loc);
  189. if(!locInfo) return;
  190. text += ` ${locInfo}`;
  191. });
  192. }
  193. let current = e.origin;
  194. while(current.issuer) {
  195. current = current.issuer;
  196. text += `\n @ ${current.readableIdentifier(requestShortener)}`;
  197. }
  198. }
  199. return text;
  200. };
  201. const obj = {
  202. errors: compilation.errors.map(formatError),
  203. warnings: Stats.filterWarnings(compilation.warnings.map(formatError), warningsFilter)
  204. };
  205. //We just hint other renderers since actually omitting
  206. //errors/warnings from the JSON would be kind of weird.
  207. Object.defineProperty(obj, "_showWarnings", {
  208. value: showWarnings,
  209. enumerable: false
  210. });
  211. Object.defineProperty(obj, "_showErrors", {
  212. value: showErrors,
  213. enumerable: false
  214. });
  215. if(showVersion) {
  216. obj.version = require("../package.json").version;
  217. }
  218. if(showHash) obj.hash = this.hash;
  219. if(showTimings && this.startTime && this.endTime) {
  220. obj.time = this.endTime - this.startTime;
  221. }
  222. if(showEnv && options._env) {
  223. obj.env = options._env;
  224. }
  225. if(compilation.needAdditionalPass) {
  226. obj.needAdditionalPass = true;
  227. }
  228. if(showPublicPath) {
  229. obj.publicPath = this.compilation.mainTemplate.getPublicPath({
  230. hash: this.compilation.hash
  231. });
  232. }
  233. if(showAssets) {
  234. const assetsByFile = {};
  235. const compilationAssets = Object.keys(compilation.assets);
  236. obj.assetsByChunkName = {};
  237. obj.assets = compilationAssets.map(asset => {
  238. const obj = {
  239. name: asset,
  240. size: compilation.assets[asset].size(),
  241. chunks: [],
  242. chunkNames: [],
  243. emitted: compilation.assets[asset].emitted
  244. };
  245. if(showPerformance) {
  246. obj.isOverSizeLimit = compilation.assets[asset].isOverSizeLimit;
  247. }
  248. assetsByFile[asset] = obj;
  249. return obj;
  250. }).filter(createAssetFilter());
  251. obj.filteredAssets = compilationAssets.length - obj.assets.length;
  252. compilation.chunks.forEach(chunk => {
  253. chunk.files.forEach(asset => {
  254. if(assetsByFile[asset]) {
  255. chunk.ids.forEach(id => {
  256. assetsByFile[asset].chunks.push(id);
  257. });
  258. if(chunk.name) {
  259. assetsByFile[asset].chunkNames.push(chunk.name);
  260. if(obj.assetsByChunkName[chunk.name])
  261. obj.assetsByChunkName[chunk.name] = [].concat(obj.assetsByChunkName[chunk.name]).concat([asset]);
  262. else
  263. obj.assetsByChunkName[chunk.name] = asset;
  264. }
  265. }
  266. });
  267. });
  268. obj.assets.sort(sortByField(sortAssets));
  269. }
  270. if(showEntrypoints) {
  271. obj.entrypoints = {};
  272. Object.keys(compilation.entrypoints).forEach(name => {
  273. const ep = compilation.entrypoints[name];
  274. obj.entrypoints[name] = {
  275. chunks: ep.chunks.map(c => c.id),
  276. assets: ep.chunks.reduce((array, c) => array.concat(c.files || []), [])
  277. };
  278. if(showPerformance) {
  279. obj.entrypoints[name].isOverSizeLimit = ep.isOverSizeLimit;
  280. }
  281. });
  282. }
  283. function fnModule(module) {
  284. const obj = {
  285. id: module.id,
  286. identifier: module.identifier(),
  287. name: module.readableIdentifier(requestShortener),
  288. index: module.index,
  289. index2: module.index2,
  290. size: module.size(),
  291. cacheable: !!module.cacheable,
  292. built: !!module.built,
  293. optional: !!module.optional,
  294. prefetched: !!module.prefetched,
  295. chunks: module.mapChunks(chunk => chunk.id),
  296. assets: Object.keys(module.assets || {}),
  297. issuer: module.issuer && module.issuer.identifier(),
  298. issuerId: module.issuer && module.issuer.id,
  299. issuerName: module.issuer && module.issuer.readableIdentifier(requestShortener),
  300. profile: module.profile,
  301. failed: !!module.error,
  302. errors: module.errors && module.dependenciesErrors && (module.errors.length + module.dependenciesErrors.length),
  303. warnings: module.errors && module.dependenciesErrors && (module.warnings.length + module.dependenciesWarnings.length)
  304. };
  305. if(showReasons) {
  306. obj.reasons = module.reasons.filter(reason => reason.dependency && reason.module).map(reason => {
  307. const obj = {
  308. moduleId: reason.module.id,
  309. moduleIdentifier: reason.module.identifier(),
  310. module: reason.module.readableIdentifier(requestShortener),
  311. moduleName: reason.module.readableIdentifier(requestShortener),
  312. type: reason.dependency.type,
  313. userRequest: reason.dependency.userRequest
  314. };
  315. const locInfo = formatLocation(reason.dependency.loc);
  316. if(locInfo) obj.loc = locInfo;
  317. return obj;
  318. }).sort((a, b) => a.moduleId - b.moduleId);
  319. }
  320. if(showUsedExports) {
  321. obj.usedExports = module.used ? module.usedExports : false;
  322. }
  323. if(showProvidedExports) {
  324. obj.providedExports = Array.isArray(module.providedExports) ? module.providedExports : null;
  325. }
  326. if(showOptimizationBailout) {
  327. obj.optimizationBailout = module.optimizationBailout.map(item => {
  328. if(typeof item === "function") return item(requestShortener);
  329. return item;
  330. });
  331. }
  332. if(showDepth) {
  333. obj.depth = module.depth;
  334. }
  335. if(showSource && module._source) {
  336. obj.source = module._source.source();
  337. }
  338. return obj;
  339. }
  340. if(showChunks) {
  341. obj.chunks = compilation.chunks.map(chunk => {
  342. const obj = {
  343. id: chunk.id,
  344. rendered: chunk.rendered,
  345. initial: chunk.isInitial(),
  346. entry: chunk.hasRuntime(),
  347. recorded: chunk.recorded,
  348. extraAsync: !!chunk.extraAsync,
  349. size: chunk.mapModules(m => m.size()).reduce((size, moduleSize) => size + moduleSize, 0),
  350. names: chunk.name ? [chunk.name] : [],
  351. files: chunk.files.slice(),
  352. hash: chunk.renderedHash,
  353. parents: chunk.parents.map(c => c.id)
  354. };
  355. if(showChunkModules) {
  356. obj.modules = chunk
  357. .getModules()
  358. .sort(sortByField("depth"))
  359. .filter(createModuleFilter())
  360. .map(fnModule);
  361. obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length;
  362. obj.modules.sort(sortByField(sortModules));
  363. }
  364. if(showChunkOrigins) {
  365. obj.origins = chunk.origins.map(origin => ({
  366. moduleId: origin.module ? origin.module.id : undefined,
  367. module: origin.module ? origin.module.identifier() : "",
  368. moduleIdentifier: origin.module ? origin.module.identifier() : "",
  369. moduleName: origin.module ? origin.module.readableIdentifier(requestShortener) : "",
  370. loc: formatLocation(origin.loc),
  371. name: origin.name,
  372. reasons: origin.reasons || []
  373. }));
  374. }
  375. return obj;
  376. });
  377. obj.chunks.sort(sortByField(sortChunks));
  378. }
  379. if(showModules) {
  380. obj.modules = compilation.modules
  381. .slice()
  382. .sort(sortByField("depth"))
  383. .filter(createModuleFilter())
  384. .map(fnModule);
  385. obj.filteredModules = compilation.modules.length - obj.modules.length;
  386. obj.modules.sort(sortByField(sortModules));
  387. }
  388. if(showChildren) {
  389. obj.children = compilation.children.map((child, idx) => {
  390. const childOptions = Stats.getChildOptions(options, idx);
  391. const obj = new Stats(child).toJson(childOptions, forToString);
  392. delete obj.hash;
  393. delete obj.version;
  394. if(child.name)
  395. obj.name = identifierUtils.makePathsRelative(context, child.name, compilation.cache);
  396. return obj;
  397. });
  398. }
  399. return obj;
  400. }
  401. toString(options) {
  402. if(typeof options === "boolean" || typeof options === "string") {
  403. options = Stats.presetToOptions(options);
  404. } else if(!options) {
  405. options = {};
  406. }
  407. const useColors = optionsOrFallback(options.colors, false);
  408. const obj = this.toJson(options, true);
  409. return Stats.jsonToString(obj, useColors);
  410. }
  411. static jsonToString(obj, useColors) {
  412. const buf = [];
  413. const defaultColors = {
  414. bold: "\u001b[1m",
  415. yellow: "\u001b[1m\u001b[33m",
  416. red: "\u001b[1m\u001b[31m",
  417. green: "\u001b[1m\u001b[32m",
  418. cyan: "\u001b[1m\u001b[36m",
  419. magenta: "\u001b[1m\u001b[35m"
  420. };
  421. const colors = Object.keys(defaultColors).reduce((obj, color) => {
  422. obj[color] = str => {
  423. if(useColors) {
  424. buf.push(
  425. (useColors === true || useColors[color] === undefined) ?
  426. defaultColors[color] : useColors[color]
  427. );
  428. }
  429. buf.push(str);
  430. if(useColors) {
  431. buf.push("\u001b[39m\u001b[22m");
  432. }
  433. };
  434. return obj;
  435. }, {
  436. normal: (str) => buf.push(str)
  437. });
  438. const coloredTime = (time) => {
  439. let times = [800, 400, 200, 100];
  440. if(obj.time) {
  441. times = [obj.time / 2, obj.time / 4, obj.time / 8, obj.time / 16];
  442. }
  443. if(time < times[3])
  444. colors.normal(`${time}ms`);
  445. else if(time < times[2])
  446. colors.bold(`${time}ms`);
  447. else if(time < times[1])
  448. colors.green(`${time}ms`);
  449. else if(time < times[0])
  450. colors.yellow(`${time}ms`);
  451. else
  452. colors.red(`${time}ms`);
  453. };
  454. const newline = () => buf.push("\n");
  455. const getText = (arr, row, col) => {
  456. return arr[row][col].value;
  457. };
  458. const table = (array, align, splitter) => {
  459. const rows = array.length;
  460. const cols = array[0].length;
  461. const colSizes = new Array(cols);
  462. for(let col = 0; col < cols; col++)
  463. colSizes[col] = 0;
  464. for(let row = 0; row < rows; row++) {
  465. for(let col = 0; col < cols; col++) {
  466. const value = `${getText(array, row, col)}`;
  467. if(value.length > colSizes[col]) {
  468. colSizes[col] = value.length;
  469. }
  470. }
  471. }
  472. for(let row = 0; row < rows; row++) {
  473. for(let col = 0; col < cols; col++) {
  474. const format = array[row][col].color;
  475. const value = `${getText(array, row, col)}`;
  476. let l = value.length;
  477. if(align[col] === "l")
  478. format(value);
  479. for(; l < colSizes[col] && col !== cols - 1; l++)
  480. colors.normal(" ");
  481. if(align[col] === "r")
  482. format(value);
  483. if(col + 1 < cols && colSizes[col] !== 0)
  484. colors.normal(splitter || " ");
  485. }
  486. newline();
  487. }
  488. };
  489. const getAssetColor = (asset, defaultColor) => {
  490. if(asset.isOverSizeLimit) {
  491. return colors.yellow;
  492. }
  493. return defaultColor;
  494. };
  495. if(obj.hash) {
  496. colors.normal("Hash: ");
  497. colors.bold(obj.hash);
  498. newline();
  499. }
  500. if(obj.version) {
  501. colors.normal("Version: webpack ");
  502. colors.bold(obj.version);
  503. newline();
  504. }
  505. if(typeof obj.time === "number") {
  506. colors.normal("Time: ");
  507. colors.bold(obj.time);
  508. colors.normal("ms");
  509. newline();
  510. }
  511. if(obj.env) {
  512. colors.normal("Environment (--env): ");
  513. colors.bold(JSON.stringify(obj.env, null, 2));
  514. newline();
  515. }
  516. if(obj.publicPath) {
  517. colors.normal("PublicPath: ");
  518. colors.bold(obj.publicPath);
  519. newline();
  520. }
  521. if(obj.assets && obj.assets.length > 0) {
  522. const t = [
  523. [{
  524. value: "Asset",
  525. color: colors.bold
  526. }, {
  527. value: "Size",
  528. color: colors.bold
  529. }, {
  530. value: "Chunks",
  531. color: colors.bold
  532. }, {
  533. value: "",
  534. color: colors.bold
  535. }, {
  536. value: "",
  537. color: colors.bold
  538. }, {
  539. value: "Chunk Names",
  540. color: colors.bold
  541. }]
  542. ];
  543. obj.assets.forEach(asset => {
  544. t.push([{
  545. value: asset.name,
  546. color: getAssetColor(asset, colors.green)
  547. }, {
  548. value: SizeFormatHelpers.formatSize(asset.size),
  549. color: getAssetColor(asset, colors.normal)
  550. }, {
  551. value: asset.chunks.join(", "),
  552. color: colors.bold
  553. }, {
  554. value: asset.emitted ? "[emitted]" : "",
  555. color: colors.green
  556. }, {
  557. value: asset.isOverSizeLimit ? "[big]" : "",
  558. color: getAssetColor(asset, colors.normal)
  559. }, {
  560. value: asset.chunkNames.join(", "),
  561. color: colors.normal
  562. }]);
  563. });
  564. table(t, "rrrlll");
  565. }
  566. if(obj.filteredAssets > 0) {
  567. colors.normal(" ");
  568. if(obj.assets.length > 0)
  569. colors.normal("+ ");
  570. colors.normal(obj.filteredAssets);
  571. if(obj.assets.length > 0)
  572. colors.normal(" hidden");
  573. colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset");
  574. newline();
  575. }
  576. if(obj.entrypoints) {
  577. Object.keys(obj.entrypoints).forEach(name => {
  578. const ep = obj.entrypoints[name];
  579. colors.normal("Entrypoint ");
  580. colors.bold(name);
  581. if(ep.isOverSizeLimit) {
  582. colors.normal(" ");
  583. colors.yellow("[big]");
  584. }
  585. colors.normal(" =");
  586. ep.assets.forEach(asset => {
  587. colors.normal(" ");
  588. colors.green(asset);
  589. });
  590. newline();
  591. });
  592. }
  593. const modulesByIdentifier = {};
  594. if(obj.modules) {
  595. obj.modules.forEach(module => {
  596. modulesByIdentifier[`$${module.identifier}`] = module;
  597. });
  598. } else if(obj.chunks) {
  599. obj.chunks.forEach(chunk => {
  600. if(chunk.modules) {
  601. chunk.modules.forEach(module => {
  602. modulesByIdentifier[`$${module.identifier}`] = module;
  603. });
  604. }
  605. });
  606. }
  607. const processModuleAttributes = (module) => {
  608. colors.normal(" ");
  609. colors.normal(SizeFormatHelpers.formatSize(module.size));
  610. if(module.chunks) {
  611. module.chunks.forEach(chunk => {
  612. colors.normal(" {");
  613. colors.yellow(chunk);
  614. colors.normal("}");
  615. });
  616. }
  617. if(typeof module.depth === "number") {
  618. colors.normal(` [depth ${module.depth}]`);
  619. }
  620. if(!module.cacheable) {
  621. colors.red(" [not cacheable]");
  622. }
  623. if(module.optional) {
  624. colors.yellow(" [optional]");
  625. }
  626. if(module.built) {
  627. colors.green(" [built]");
  628. }
  629. if(module.prefetched) {
  630. colors.magenta(" [prefetched]");
  631. }
  632. if(module.failed)
  633. colors.red(" [failed]");
  634. if(module.warnings)
  635. colors.yellow(` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]`);
  636. if(module.errors)
  637. colors.red(` [${module.errors} error${module.errors === 1 ? "" : "s"}]`);
  638. };
  639. const processModuleContent = (module, prefix) => {
  640. if(Array.isArray(module.providedExports)) {
  641. colors.normal(prefix);
  642. if(module.providedExports.length === 0)
  643. colors.cyan("[no exports]");
  644. else
  645. colors.cyan(`[exports: ${module.providedExports.join(", ")}]`);
  646. newline();
  647. }
  648. if(module.usedExports !== undefined) {
  649. if(module.usedExports !== true) {
  650. colors.normal(prefix);
  651. if(module.usedExports === false || module.usedExports.length === 0)
  652. colors.cyan("[no exports used]");
  653. else
  654. colors.cyan(`[only some exports used: ${module.usedExports.join(", ")}]`);
  655. newline();
  656. }
  657. }
  658. if(Array.isArray(module.optimizationBailout)) {
  659. module.optimizationBailout.forEach(item => {
  660. colors.normal(prefix);
  661. colors.yellow(item);
  662. newline();
  663. });
  664. }
  665. if(module.reasons) {
  666. module.reasons.forEach(reason => {
  667. colors.normal(prefix);
  668. colors.normal(reason.type);
  669. colors.normal(" ");
  670. colors.cyan(reason.userRequest);
  671. colors.normal(" [");
  672. colors.normal(reason.moduleId);
  673. colors.normal("] ");
  674. colors.magenta(reason.module);
  675. if(reason.loc) {
  676. colors.normal(" ");
  677. colors.normal(reason.loc);
  678. }
  679. newline();
  680. });
  681. }
  682. if(module.profile) {
  683. colors.normal(prefix);
  684. let sum = 0;
  685. const path = [];
  686. let current = module;
  687. while(current.issuer) {
  688. path.push(current = current.issuer);
  689. }
  690. path.reverse().forEach(module => {
  691. colors.normal("[");
  692. colors.normal(module.id);
  693. colors.normal("] ");
  694. if(module.profile) {
  695. const time = (module.profile.factory || 0) + (module.profile.building || 0);
  696. coloredTime(time);
  697. sum += time;
  698. colors.normal(" ");
  699. }
  700. colors.normal("->");
  701. });
  702. Object.keys(module.profile).forEach(key => {
  703. colors.normal(` ${key}:`);
  704. const time = module.profile[key];
  705. coloredTime(time);
  706. sum += time;
  707. });
  708. colors.normal(" = ");
  709. coloredTime(sum);
  710. newline();
  711. }
  712. };
  713. const processModulesList = (obj, prefix) => {
  714. if(obj.modules) {
  715. obj.modules.forEach(module => {
  716. colors.normal(prefix);
  717. if(module.id < 1000) colors.normal(" ");
  718. if(module.id < 100) colors.normal(" ");
  719. if(module.id < 10) colors.normal(" ");
  720. colors.normal("[");
  721. colors.normal(module.id);
  722. colors.normal("] ");
  723. colors.bold(module.name || module.identifier);
  724. processModuleAttributes(module);
  725. newline();
  726. processModuleContent(module, prefix + " ");
  727. });
  728. if(obj.filteredModules > 0) {
  729. colors.normal(prefix);
  730. colors.normal(" ");
  731. if(obj.modules.length > 0)
  732. colors.normal(" + ");
  733. colors.normal(obj.filteredModules);
  734. if(obj.modules.length > 0)
  735. colors.normal(" hidden");
  736. colors.normal(obj.filteredModules !== 1 ? " modules" : " module");
  737. newline();
  738. }
  739. }
  740. };
  741. if(obj.chunks) {
  742. obj.chunks.forEach(chunk => {
  743. colors.normal("chunk ");
  744. if(chunk.id < 1000) colors.normal(" ");
  745. if(chunk.id < 100) colors.normal(" ");
  746. if(chunk.id < 10) colors.normal(" ");
  747. colors.normal("{");
  748. colors.yellow(chunk.id);
  749. colors.normal("} ");
  750. colors.green(chunk.files.join(", "));
  751. if(chunk.names && chunk.names.length > 0) {
  752. colors.normal(" (");
  753. colors.normal(chunk.names.join(", "));
  754. colors.normal(")");
  755. }
  756. colors.normal(" ");
  757. colors.normal(SizeFormatHelpers.formatSize(chunk.size));
  758. chunk.parents.forEach(id => {
  759. colors.normal(" {");
  760. colors.yellow(id);
  761. colors.normal("}");
  762. });
  763. if(chunk.entry) {
  764. colors.yellow(" [entry]");
  765. } else if(chunk.initial) {
  766. colors.yellow(" [initial]");
  767. }
  768. if(chunk.rendered) {
  769. colors.green(" [rendered]");
  770. }
  771. if(chunk.recorded) {
  772. colors.green(" [recorded]");
  773. }
  774. newline();
  775. if(chunk.origins) {
  776. chunk.origins.forEach(origin => {
  777. colors.normal(" > ");
  778. if(origin.reasons && origin.reasons.length) {
  779. colors.yellow(origin.reasons.join(" "));
  780. colors.normal(" ");
  781. }
  782. if(origin.name) {
  783. colors.normal(origin.name);
  784. colors.normal(" ");
  785. }
  786. if(origin.module) {
  787. colors.normal("[");
  788. colors.normal(origin.moduleId);
  789. colors.normal("] ");
  790. const module = modulesByIdentifier[`$${origin.module}`];
  791. if(module) {
  792. colors.bold(module.name);
  793. colors.normal(" ");
  794. }
  795. if(origin.loc) {
  796. colors.normal(origin.loc);
  797. }
  798. }
  799. newline();
  800. });
  801. }
  802. processModulesList(chunk, " ");
  803. });
  804. }
  805. processModulesList(obj, "");
  806. if(obj._showWarnings && obj.warnings) {
  807. obj.warnings.forEach(warning => {
  808. newline();
  809. colors.yellow(`WARNING in ${warning}`);
  810. newline();
  811. });
  812. }
  813. if(obj._showErrors && obj.errors) {
  814. obj.errors.forEach(error => {
  815. newline();
  816. colors.red(`ERROR in ${error}`);
  817. newline();
  818. });
  819. }
  820. if(obj.children) {
  821. obj.children.forEach(child => {
  822. const childString = Stats.jsonToString(child, useColors);
  823. if(childString) {
  824. if(child.name) {
  825. colors.normal("Child ");
  826. colors.bold(child.name);
  827. colors.normal(":");
  828. } else {
  829. colors.normal("Child");
  830. }
  831. newline();
  832. buf.push(" ");
  833. buf.push(childString.replace(/\n/g, "\n "));
  834. newline();
  835. }
  836. });
  837. }
  838. if(obj.needAdditionalPass) {
  839. colors.yellow("Compilation needs an additional pass and will compile again.");
  840. }
  841. while(buf[buf.length - 1] === "\n") buf.pop();
  842. return buf.join("");
  843. }
  844. static presetToOptions(name) {
  845. // Accepted values: none, errors-only, minimal, normal, detailed, verbose
  846. // Any other falsy value will behave as 'none', truthy values as 'normal'
  847. const pn = (typeof name === "string") && name.toLowerCase() || name || "none";
  848. switch(pn) {
  849. case "none":
  850. return {
  851. all: false
  852. };
  853. case "verbose":
  854. return {
  855. entrypoints: true,
  856. modules: false,
  857. chunks: true,
  858. chunkModules: true,
  859. chunkOrigins: true,
  860. depth: true,
  861. env: true,
  862. reasons: true,
  863. usedExports: true,
  864. providedExports: true,
  865. optimizationBailout: true,
  866. errorDetails: true,
  867. publicPath: true,
  868. exclude: () => false,
  869. maxModules: Infinity,
  870. };
  871. case "detailed":
  872. return {
  873. entrypoints: true,
  874. chunks: true,
  875. chunkModules: false,
  876. chunkOrigins: true,
  877. depth: true,
  878. usedExports: true,
  879. providedExports: true,
  880. optimizationBailout: true,
  881. errorDetails: true,
  882. publicPath: true,
  883. exclude: () => false,
  884. maxModules: Infinity,
  885. };
  886. case "minimal":
  887. return {
  888. all: false,
  889. modules: true,
  890. maxModules: 0,
  891. errors: true,
  892. warnings: true,
  893. };
  894. case "errors-only":
  895. return {
  896. all: false,
  897. errors: true,
  898. moduleTrace: true,
  899. };
  900. default:
  901. return {};
  902. }
  903. }
  904. static getChildOptions(options, idx) {
  905. let innerOptions;
  906. if(Array.isArray(options.children)) {
  907. if(idx < options.children.length)
  908. innerOptions = options.children[idx];
  909. } else if(typeof options.children === "object" && options.children) {
  910. innerOptions = options.children;
  911. }
  912. if(typeof innerOptions === "boolean" || typeof innerOptions === "string")
  913. innerOptions = Stats.presetToOptions(innerOptions);
  914. if(!innerOptions)
  915. return options;
  916. const childOptions = Object.assign({}, options);
  917. delete childOptions.children; // do not inherit children
  918. return Object.assign(childOptions, innerOptions);
  919. }
  920. }
  921. module.exports = Stats;