LibWeb: Fix infinite loop in GFC growth limit distribution

This change is bd85e1b30b ported from
base size to growth limit distribution.

Fixes https://github.com/SerenityOS/serenity/issues/21056
This commit is contained in:
Aliaksandr Kalenik 2023-09-14 17:15:11 +02:00 committed by Andreas Kling
parent 9b4ddff6a9
commit 693d602b2f
Notes: sideshowbarker 2024-07-17 08:34:29 +09:00
3 changed files with 45 additions and 11 deletions

View File

@ -0,0 +1,16 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x33.46875 [BFC] children: not-inline
Box <body> at (8,8) content-size 784x17.46875 [GFC] children: not-inline
BlockContainer <div#item> at (8,8) content-size 784x17.46875 [BFC] children: not-inline
BlockContainer <div#block> at (8,8) content-size 784x17.46875 children: inline
line 0 width: 210.484375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 0, length: 26, rect: [8,8 210.484375x17.46875]
"Taika Waititi's Best Roles"
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33.46875]
PaintableBox (Box<BODY>) [8,8 784x17.46875]
PaintableWithLines (BlockContainer<DIV>#item) [8,8 784x17.46875]
PaintableWithLines (BlockContainer<DIV>#block) [8,8 784x17.46875]
TextPaintable (TextNode<#text>)

View File

@ -0,0 +1,17 @@
<!doctype html><style>
* {
outline: 1px solid black;
}
html {
font: inherit;
}
body {
display: grid;
}
#item {
grid-column: span 4 / auto;
}
#block {
min-width: 0px;
}
</style><body><div id="item"><div id="block">Taika Waititi's Best Roles

View File

@ -935,7 +935,7 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_
auto extra_space = max(CSSPixels(0), item_size_contribution - spanned_tracks_sizes_sum);
// 2. Distribute space up to limits:
while (true) {
while (extra_space > 0) {
auto all_frozen = all_of(affected_tracks, [](auto const& track) { return track.growth_limit_frozen; });
if (all_frozen)
break;
@ -943,23 +943,24 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_
// Find the item-incurred increase for each spanned track with an affected size by: distributing the space
// equally among such tracks, freezing a tracks item-incurred increase as its affected size + item-incurred
// increase reaches its limit
CSSPixels increase_per_track = extra_space / affected_tracks.size();
if (increase_per_track == 0)
break;
CSSPixels increase_per_track = max(CSSPixels::smallest_positive_value(), extra_space / affected_tracks.size());
for (auto& track : affected_tracks) {
if (track.growth_limit_frozen)
continue;
auto increase = min(increase_per_track, extra_space);
// For growth limits, the limit is infinity if it is marked as infinitely growable, and equal to the
// growth limit otherwise.
if (track.infinitely_growable || !track.growth_limit.has_value()) {
track.item_incurred_increase += increase_per_track;
extra_space -= increase_per_track;
} else if (track.growth_limit.has_value() && increase_per_track >= track.growth_limit.value()) {
track.growth_limit_frozen = true;
track.item_incurred_increase = track.growth_limit.value();
extra_space -= track.growth_limit.value();
if (!track.infinitely_growable && track.growth_limit.has_value()) {
auto maximum_increase = track.growth_limit.value() - track.base_size;
if (track.item_incurred_increase + increase >= maximum_increase) {
track.growth_limit_frozen = true;
increase = maximum_increase - track.item_incurred_increase;
}
}
track.item_incurred_increase += increase;
extra_space -= increase;
}
}