Skip to content

Commit b26793d

Browse files
authored
Merge pull request #14890 from webpack/fix-space-limited
fix/refactor spaceLimited
2 parents 951dac6 + 6c86a82 commit b26793d

3 files changed

Lines changed: 274 additions & 132 deletions

File tree

lib/stats/DefaultStatsFactoryPlugin.js

Lines changed: 105 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,84 +1658,121 @@ const collapse = children => {
16581658
return newChildren;
16591659
};
16601660

1661-
const spaceLimited = (itemsAndGroups, max) => {
1661+
const spaceLimited = (
1662+
itemsAndGroups,
1663+
max,
1664+
filteredChildrenLineReserved = false
1665+
) => {
1666+
if (max < 1) {
1667+
return {
1668+
children: undefined,
1669+
filteredChildren: getTotalItems(itemsAndGroups)
1670+
};
1671+
}
16621672
/** @type {any[] | undefined} */
16631673
let children = undefined;
16641674
/** @type {number | undefined} */
16651675
let filteredChildren = undefined;
16661676
// This are the groups, which take 1+ lines each
1667-
const groups = itemsAndGroups.filter(c => c.children || c.filteredChildren);
1677+
const groups = [];
16681678
// The sizes of the groups are stored in groupSizes
1669-
const groupSizes = groups.map(g => getItemSize(g));
1679+
const groupSizes = [];
16701680
// This are the items, which take 1 line each
1671-
const items = itemsAndGroups.filter(c => !c.children && !c.filteredChildren);
1681+
const items = [];
16721682
// The total of group sizes
1673-
let groupsSize = groupSizes.reduce((a, b) => a + b, 0);
1683+
let groupsSize = 0;
1684+
1685+
for (const itemOrGroup of itemsAndGroups) {
1686+
// is item
1687+
if (!itemOrGroup.children && !itemOrGroup.filteredChildren) {
1688+
items.push(itemOrGroup);
1689+
} else {
1690+
groups.push(itemOrGroup);
1691+
const size = getItemSize(itemOrGroup);
1692+
groupSizes.push(size);
1693+
groupsSize += size;
1694+
}
1695+
}
1696+
16741697
if (groupsSize + items.length <= max) {
16751698
// The total size in the current state fits into the max
16761699
// keep all
1677-
children = groups.concat(items);
1678-
} else if (
1679-
groups.length > 0 &&
1680-
groups.length + Math.min(1, items.length) < max
1681-
) {
1682-
// If each group would take 1 line the total would be below the maximum
1683-
// collapse some groups, keep items
1684-
while (groupsSize + items.length + (filteredChildren ? 1 : 0) > max) {
1700+
children = groups.length > 0 ? groups.concat(items) : items;
1701+
} else if (groups.length === 0) {
1702+
// slice items to max
1703+
// inner space marks that lines for filteredChildren already reserved
1704+
const limit = max - (filteredChildrenLineReserved ? 0 : 1);
1705+
filteredChildren = items.length - limit;
1706+
items.length = limit;
1707+
children = items;
1708+
} else {
1709+
// limit is the size when all groups are collapsed
1710+
const limit =
1711+
groups.length +
1712+
(filteredChildrenLineReserved || items.length === 0 ? 0 : 1);
1713+
if (limit < max) {
16851714
// calculate how much we are over the size limit
16861715
// this allows to approach the limit faster
1687-
// it's always > 1
1688-
const oversize =
1689-
items.length + groupsSize + (filteredChildren ? 1 : 0) - max;
1690-
// Find the maximum group and process only this one
1691-
const maxGroupSize = Math.max(...groupSizes);
1692-
if (maxGroupSize < items.length) {
1693-
filteredChildren = items.length;
1694-
items.length = 0;
1695-
continue;
1696-
}
1697-
for (let i = 0; i < groups.length; i++) {
1698-
if (groupSizes[i] === maxGroupSize) {
1699-
const group = groups[i];
1700-
// run this algorithm recursively and limit the size of the children to
1701-
// current size - oversize / number of groups
1702-
// So it should always end up being smaller
1703-
const headerSize = !group.children
1704-
? 0
1705-
: group.filteredChildren
1706-
? 2
1707-
: 1;
1708-
const limited = spaceLimited(
1709-
group.children,
1710-
groupSizes[i] - headerSize - oversize / groups.length
1711-
);
1712-
groups[i] = {
1713-
...group,
1714-
children: limited.children,
1715-
filteredChildren:
1716-
(group.filteredChildren || 0) + limited.filteredChildren
1717-
};
1718-
const newSize = getItemSize(groups[i]);
1719-
groupsSize -= groupSizes[i] - newSize;
1720-
groupSizes[i] = newSize;
1721-
break;
1716+
let oversize;
1717+
// If each group would take 1 line the total would be below the maximum
1718+
// collapse some groups, keep items
1719+
while (
1720+
(oversize =
1721+
groupsSize +
1722+
items.length +
1723+
(filteredChildren && !filteredChildrenLineReserved ? 1 : 0) -
1724+
max) > 0
1725+
) {
1726+
// Find the maximum group and process only this one
1727+
const maxGroupSize = Math.max(...groupSizes);
1728+
if (maxGroupSize < items.length) {
1729+
filteredChildren = items.length;
1730+
items.length = 0;
1731+
continue;
1732+
}
1733+
for (let i = 0; i < groups.length; i++) {
1734+
if (groupSizes[i] === maxGroupSize) {
1735+
const group = groups[i];
1736+
// run this algorithm recursively and limit the size of the children to
1737+
// current size - oversize / number of groups
1738+
// So it should always end up being smaller
1739+
const headerSize = group.filteredChildren ? 2 : 1;
1740+
const limited = spaceLimited(
1741+
group.children,
1742+
maxGroupSize -
1743+
// we should use ceil to always feet in max
1744+
Math.ceil(oversize / groups.length) -
1745+
// we substitute size of group head
1746+
headerSize,
1747+
headerSize === 2
1748+
);
1749+
groups[i] = {
1750+
...group,
1751+
children: limited.children,
1752+
filteredChildren: limited.filteredChildren
1753+
? (group.filteredChildren || 0) + limited.filteredChildren
1754+
: group.filteredChildren
1755+
};
1756+
const newSize = getItemSize(groups[i]);
1757+
groupsSize -= maxGroupSize - newSize;
1758+
groupSizes[i] = newSize;
1759+
break;
1760+
}
17221761
}
17231762
}
1763+
children = groups.concat(items);
1764+
} else if (limit === max) {
1765+
// If we have only enough space to show one line per group and one line for the filtered items
1766+
// collapse all groups and items
1767+
children = collapse(groups);
1768+
filteredChildren = items.length;
1769+
} else {
1770+
// If we have no space
1771+
// collapse complete group
1772+
filteredChildren = getTotalItems(itemsAndGroups);
17241773
}
1725-
children = groups.concat(items);
1726-
} else if (
1727-
groups.length > 0 &&
1728-
groups.length + Math.min(1, items.length) <= max
1729-
) {
1730-
// If we have only enough space to show one line per group and one line for the filtered items
1731-
// collapse all groups and items
1732-
children = groups.length ? collapse(groups) : undefined;
1733-
filteredChildren = items.length;
1734-
} else {
1735-
// If we have no space
1736-
// collapse complete group
1737-
filteredChildren = getTotalItems(itemsAndGroups);
17381774
}
1775+
17391776
return {
17401777
children,
17411778
filteredChildren
@@ -1777,6 +1814,9 @@ const reasonGroup = (children, reasons) => {
17771814
};
17781815
};
17791816

1817+
const GROUP_EXTENSION_REGEXP = /(\.[^.]+?)(?:\?|(?: \+ \d+ modules?)?$)/;
1818+
const GROUP_PATH_REGEXP = /(.+)[/\\][^/\\]+?(?:\?|(?: \+ \d+ modules?)?$)/;
1819+
17801820
/** @type {Record<string, (groupConfigs: GroupConfig[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} */
17811821
const ASSETS_GROUPERS = {
17821822
_: (groupConfigs, context, options) => {
@@ -1825,10 +1865,10 @@ const ASSETS_GROUPERS = {
18251865
groupConfigs.push({
18261866
getKeys: asset => {
18271867
const extensionMatch =
1828-
groupAssetsByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(asset.name);
1868+
groupAssetsByExtension && GROUP_EXTENSION_REGEXP.exec(asset.name);
18291869
const extension = extensionMatch ? extensionMatch[1] : "";
18301870
const pathMatch =
1831-
groupAssetsByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(asset.name);
1871+
groupAssetsByPath && GROUP_PATH_REGEXP.exec(asset.name);
18321872
const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
18331873
const keys = [];
18341874
if (groupAssetsByPath) {
@@ -2025,10 +2065,10 @@ const MODULES_GROUPERS = type => ({
20252065
const dataUrl = /^data:[^,;]+/.exec(resource);
20262066
if (dataUrl) return [dataUrl[0]];
20272067
const extensionMatch =
2028-
groupModulesByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(resource);
2068+
groupModulesByExtension && GROUP_EXTENSION_REGEXP.exec(resource);
20292069
const extension = extensionMatch ? extensionMatch[1] : "";
20302070
const pathMatch =
2031-
groupModulesByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(resource);
2071+
groupModulesByPath && GROUP_PATH_REGEXP.exec(resource);
20322072
const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
20332073
const keys = [];
20342074
if (groupModulesByPath) {

lib/stats/DefaultStatsPrinterPlugin.js

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ const isValidId = id => {
5757
return typeof id === "number" || id;
5858
};
5959

60+
const moreCount = (list, count) => {
61+
return list && list.length > 0 ? `+ ${count}` : `${count}`;
62+
};
63+
6064
/** @type {Record<string, (thing: any, context: StatsPrinterContext, printer: StatsPrinter) => string | void>} */
6165
const SIMPLE_PRINTERS = {
6266
"compilation.summary!": (
@@ -182,13 +186,24 @@ const SIMPLE_PRINTERS = {
182186
},
183187
"compilation.assetsByChunkName": () => "",
184188

185-
"compilation.filteredModules": filteredModules =>
189+
"compilation.filteredModules": (
190+
filteredModules,
191+
{ compilation: { modules } }
192+
) =>
186193
filteredModules > 0
187-
? `${filteredModules} ${plural(filteredModules, "module", "modules")}`
194+
? `${moreCount(modules, filteredModules)} ${plural(
195+
filteredModules,
196+
"module",
197+
"modules"
198+
)}`
188199
: undefined,
189200
"compilation.filteredAssets": (filteredAssets, { compilation: { assets } }) =>
190201
filteredAssets > 0
191-
? `${filteredAssets} ${plural(filteredAssets, "asset", "assets")}`
202+
? `${moreCount(assets, filteredAssets)} ${plural(
203+
filteredAssets,
204+
"asset",
205+
"assets"
206+
)}`
192207
: undefined,
193208
"compilation.logging": (logging, context, printer) =>
194209
Array.isArray(logging)
@@ -281,15 +296,19 @@ const SIMPLE_PRINTERS = {
281296
"asset.separator!": () => "\n",
282297
"asset.filteredRelated": (filteredRelated, { asset: { related } }) =>
283298
filteredRelated > 0
284-
? `${filteredRelated} related ${plural(
299+
? `${moreCount(related, filteredRelated)} related ${plural(
285300
filteredRelated,
286301
"asset",
287302
"assets"
288303
)}`
289304
: undefined,
290-
"asset.filteredChildren": filteredChildren =>
305+
"asset.filteredChildren": (filteredChildren, { asset: { children } }) =>
291306
filteredChildren > 0
292-
? `${filteredChildren} ${plural(filteredChildren, "asset", "assets")}`
307+
? `${moreCount(children, filteredChildren)} ${plural(
308+
filteredChildren,
309+
"asset",
310+
"assets"
311+
)}`
293312
: undefined,
294313

295314
assetChunk: (id, { formatChunkId }) => formatChunkId(id),
@@ -385,21 +404,29 @@ const SIMPLE_PRINTERS = {
385404
"module.issuerPath": (issuerPath, { module }) =>
386405
module.profile ? undefined : "",
387406
"module.profile": profile => undefined,
388-
"module.filteredModules": filteredModules =>
407+
"module.filteredModules": (filteredModules, { module: { modules } }) =>
389408
filteredModules > 0
390-
? `${filteredModules} nested ${plural(
409+
? `${moreCount(modules, filteredModules)} nested ${plural(
391410
filteredModules,
392411
"module",
393412
"modules"
394413
)}`
395414
: undefined,
396-
"module.filteredReasons": filteredReasons =>
415+
"module.filteredReasons": (filteredReasons, { module: { reasons } }) =>
397416
filteredReasons > 0
398-
? `${filteredReasons} ${plural(filteredReasons, "reason", "reasons")}`
417+
? `${moreCount(reasons, filteredReasons)} ${plural(
418+
filteredReasons,
419+
"reason",
420+
"reasons"
421+
)}`
399422
: undefined,
400-
"module.filteredChildren": filteredChildren =>
423+
"module.filteredChildren": (filteredChildren, { module: { children } }) =>
401424
filteredChildren > 0
402-
? `${filteredChildren} ${plural(filteredChildren, "module", "modules")}`
425+
? `${moreCount(children, filteredChildren)} ${plural(
426+
filteredChildren,
427+
"module",
428+
"modules"
429+
)}`
403430
: undefined,
404431
"module.separator!": () => "\n",
405432

@@ -417,9 +444,16 @@ const SIMPLE_PRINTERS = {
417444
"moduleReason.active": (active, { formatFlag }) =>
418445
active ? undefined : formatFlag("inactive"),
419446
"moduleReason.resolvedModule": (module, { magenta }) => magenta(module),
420-
"moduleReason.filteredChildren": filteredChildren =>
447+
"moduleReason.filteredChildren": (
448+
filteredChildren,
449+
{ moduleReason: { children } }
450+
) =>
421451
filteredChildren > 0
422-
? `${filteredChildren} ${plural(filteredChildren, "reason", "reasons")}`
452+
? `${moreCount(children, filteredChildren)} ${plural(
453+
filteredChildren,
454+
"reason",
455+
"reasons"
456+
)}`
423457
: undefined,
424458

425459
"module.profile.total": (value, { formatTime }) => formatTime(value),
@@ -447,10 +481,21 @@ const SIMPLE_PRINTERS = {
447481
size ? formatSize(size) : undefined,
448482
"chunkGroup.auxiliaryAssetsSize": (size, { formatSize }) =>
449483
size ? `(${formatSize(size)})` : undefined,
450-
"chunkGroup.filteredAssets": n =>
451-
n > 0 ? `${n} ${plural(n, "asset", "assets")}` : undefined,
452-
"chunkGroup.filteredAuxiliaryAssets": n =>
453-
n > 0 ? `${n} auxiliary ${plural(n, "asset", "assets")}` : undefined,
484+
"chunkGroup.filteredAssets": (n, { chunkGroup: { assets } }) =>
485+
n > 0
486+
? `${moreCount(assets, n)} ${plural(n, "asset", "assets")}`
487+
: undefined,
488+
"chunkGroup.filteredAuxiliaryAssets": (
489+
n,
490+
{ chunkGroup: { auxiliaryAssets } }
491+
) =>
492+
n > 0
493+
? `${moreCount(auxiliaryAssets, n)} auxiliary ${plural(
494+
n,
495+
"asset",
496+
"assets"
497+
)}`
498+
: undefined,
454499
"chunkGroup.is!": () => "=",
455500
"chunkGroupAsset.name": (asset, { green }) => green(asset),
456501
"chunkGroupAsset.size": (size, { formatSize, chunkGroup }) =>
@@ -510,9 +555,9 @@ const SIMPLE_PRINTERS = {
510555
"chunk.recorded": (recorded, { formatFlag, green }) =>
511556
recorded ? green(formatFlag("recorded")) : undefined,
512557
"chunk.reason": (reason, { yellow }) => (reason ? yellow(reason) : undefined),
513-
"chunk.filteredModules": filteredModules =>
558+
"chunk.filteredModules": (filteredModules, { chunk: { modules } }) =>
514559
filteredModules > 0
515-
? `${filteredModules} chunk ${plural(
560+
? `${moreCount(modules, filteredModules)} chunk ${plural(
516561
filteredModules,
517562
"module",
518563
"modules"

0 commit comments

Comments
 (0)