LibWeb: Prevent infinite recursion on abspos w/ intrinsic max-size

We were incorrectly deciding that abspos elements shouldn't treat many
max-width and max-height values as `none`. My best understanding is that
this was a hack in 2023 for an issue that has been solved since then.

By removing the incorrect short-circuit, we stop at least one WPT test
from crashing due to infinite recursion and get ourselves +34 passes.
This commit is contained in:
Andreas Kling 2025-04-24 13:10:12 +02:00 committed by Andreas Kling
parent e5d62e9915
commit f7a7cd9b2b
Notes: github-actions[bot] 2025-04-24 16:28:19 +00:00
3 changed files with 372 additions and 4 deletions

View file

@ -1914,8 +1914,6 @@ bool FormattingContext::should_treat_max_width_as_none(Box const& box, Available
return true;
if (available_width.is_max_content() && max_width.is_max_content())
return true;
if (box.is_absolutely_positioned())
return false;
if (max_width.contains_percentage()) {
if (available_width.is_max_content())
return true;
@ -1942,8 +1940,6 @@ bool FormattingContext::should_treat_max_height_as_none(Box const& box, Availabl
auto const& max_height = box.computed_values().max_height();
if (max_height.is_none())
return true;
if (box.is_absolutely_positioned())
return false;
if (max_height.contains_percentage()) {
if (available_height.is_min_content())
return false;

View file

@ -0,0 +1,66 @@
Harness status: OK
Found 60 tests
34 Pass
26 Fail
Pass .test 1
Pass .test 2
Fail .test 3
Pass .test 4
Pass .test 5
Pass .test 6
Pass .test 7
Fail .test 8
Pass .test 9
Fail .test 10
Pass .test 11
Pass .test 12
Fail .test 13
Pass .test 14
Fail .test 15
Pass .test 16
Pass .test 17
Pass .test 18
Pass .test 19
Pass .test 20
Pass .test 21
Pass .test 22
Pass .test 23
Pass .test 24
Fail .test 25
Pass .test 26
Pass .test 27
Pass .test 28
Pass .test 29
Fail .test 30
Pass .test 31
Fail .test 32
Fail .test 33
Fail .test 34
Pass .test 35
Pass .test 36
Fail .test 37
Fail .test 38
Fail .test 39
Fail .test 40
Pass .test 41
Fail .test 42
Fail .test 43
Fail .test 44
Fail .test 45
Pass .test 46
Pass .test 47
Pass .test 48
Pass .test 49
Pass .test 50
Pass .test 51
Fail .test 52
Fail .test 53
Fail .test 54
Fail .test 55
Pass .test 56
Fail .test 57
Fail .test 58
Fail .test 59
Fail .test 60

View file

@ -0,0 +1,306 @@
<!DOCTYPE html>
<title>Keyword sizes on absolutely positioned box</title>
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#sizing-values">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#sizing-values">
<link rel="help" href="https://drafts.csswg.org/css-position/#abspos-layout">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11387">
<meta assert="The various keyword sizes work as expected on absolutely positioned boxes.">
<link rel="stylesheet" type="text/css" href="../../fonts/ahem.css">
<style>
.cb {
position: relative;
width: 100px;
height: 100px
}
.test {
position: absolute;
inset: 0;
margin: 5px;
border: 3px solid;
padding: 2px;
font: 20px/1 Ahem;
}
/* Set the preferred size to small amount, to test that the min size works */
.test.min-width { width: 0px }
.test.min-height { height: 0px }
/* Set the preferred size to big amount, to test that the max size works */
.test.max-width { width: 500px }
.test.max-height { height: 500px }
/* stretch isn't widely supported, fall back to vendor-prefixed alternatives */
.width.stretch { width: -moz-available; width: -webkit-fill-available; width: stretch }
.min-width.stretch { min-width: -moz-available; min-width: -webkit-fill-available; min-width: stretch }
.max-width.stretch { max-width: -moz-available; max-width: -webkit-fill-available; max-width: stretch }
.height.stretch { height: -moz-available; height: -webkit-fill-available; height: stretch }
.min-height.stretch { min-height: -moz-available; min-height: -webkit-fill-available; min-height: stretch }
.max-height.stretch { max-height: -moz-available; max-height: -webkit-fill-available; max-height: stretch }
canvas { display: block; background: currentcolor }
.test.width canvas, .test.min-width canvas, .test.max-width canvas { width: 100% }
.test.height canvas, .test.min-height canvas, .test.max-height canvas { height: 100% }
</style>
<div id="log"></div>
<div class="cb">
<div class="test width" style="width: initial" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test width" style="width: min-content" data-expected-width="50">XX XX</div>
</div>
<div class="cb">
<div class="test width" style="width: fit-content" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test width" style="width: max-content" data-expected-width="110">XX XX</div>
</div>
<div class="cb">
<div class="test width stretch" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: initial" data-expected-width="10">XX XX</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: min-content" data-expected-width="50">XX XX</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: fit-content" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: max-content" data-expected-width="110">XX XX</div>
</div>
<div class="cb">
<div class="test min-width stretch" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: initial" data-expected-width="510">XX XX</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: min-content" data-expected-width="50">XX XX</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: fit-content" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: max-content" data-expected-width="110">XX XX</div>
</div>
<div class="cb">
<div class="test max-width stretch" data-expected-width="90">XX XX</div>
</div>
<div class="cb">
<div class="test width" style="width: initial" data-expected-width="90">
<canvas width="20" height="10" data-expected-width="80" data-expected-height="40"></canvas>
</div>
</div>
<div class="cb">
<div class="test width" style="width: min-content" data-expected-width="10">
<canvas width="20" height="10" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test width" style="width: fit-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test width" style="width: max-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test width stretch" data-expected-width="90">
<canvas width="20" height="10" data-expected-width="80" data-expected-height="40"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: initial" data-expected-width="10">
<canvas width="20" height="10" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: min-content" data-expected-width="10">
<canvas width="20" height="10" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: fit-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-width" style="min-width: max-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-width stretch" data-expected-width="90">
<canvas width="20" height="10" data-expected-width="80" data-expected-height="40"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: initial" data-expected-width="510">
<canvas width="20" height="10" data-expected-width="500" data-expected-height="250"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: min-content" data-expected-width="10">
<canvas width="20" height="10" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: fit-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-width" style="max-width: max-content" data-expected-width="30">
<canvas width="20" height="10" data-expected-width="20" data-expected-height="10"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-width stretch" data-expected-width="90">
<canvas width="20" height="10" data-expected-width="80" data-expected-height="40"></canvas>
</div>
</div>
<div class="cb">
<div class="test height" style="height: initial" data-expected-height="90">XX XX</div>
</div>
<div class="cb">
<div class="test height" style="height: min-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test height" style="height: fit-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test height" style="height: max-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test height stretch" data-expected-height="90">XX XX</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: initial" data-expected-height="10">XX XX</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: min-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: fit-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: max-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test min-height stretch" data-expected-height="90">XX XX</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: initial" data-expected-height="510">XX XX</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: min-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: fit-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: max-content" data-expected-height="50">XX XX</div>
</div>
<div class="cb">
<div class="test max-height stretch" data-expected-height="90">XX XX</div>
</div>
<div class="cb">
<div class="test height" style="height: initial" data-expected-height="90">
<canvas width="10" height="20" data-expected-width="40" data-expected-height="80"></canvas>
</div>
</div>
<div class="cb">
<div class="test height" style="height: min-content" data-expected-height="30">
<canvas width="10" height="20" data-expected-width="10" data-expected-height="20"></canvas>
</div>
</div>
<div class="cb">
<div class="test height" style="height: fit-content" data-expected-height="30">
<canvas width="10" height="20" data-expected-width="10" data-expected-height="20"></canvas>
</div>
</div>
<div class="cb">
<div class="test height" style="height: max-content" data-expected-height="30">
<canvas width="10" height="20" data-expected-width="10" data-expected-height="20"></canvas>
</div>
</div>
<div class="cb">
<div class="test height stretch" data-expected-height="90">
<canvas width="10" height="20" data-expected-width="40" data-expected-height="80"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: initial" data-expected-height="10">
<canvas width="10" height="20" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: min-content" data-expected-height="10">
<canvas width="10" height="20" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: fit-content" data-expected-height="10">
<canvas width="10" height="20" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-height" style="min-height: max-content" data-expected-height="10">
<canvas width="10" height="20" data-expected-width="0" data-expected-height="0"></canvas>
</div>
</div>
<div class="cb">
<div class="test min-height stretch" data-expected-height="90">
<canvas width="10" height="20" data-expected-width="40" data-expected-height="80"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: initial" data-expected-height="510">
<canvas width="10" height="20" data-expected-width="250" data-expected-height="500"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: min-content" data-expected-height="510">
<canvas width="10" height="20" data-expected-width="250" data-expected-height="500"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: fit-content" data-expected-height="510">
<canvas width="10" height="20" data-expected-width="250" data-expected-height="500"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-height" style="max-height: max-content" data-expected-height="510">
<canvas width="10" height="20" data-expected-width="250" data-expected-height="500"></canvas>
</div>
</div>
<div class="cb">
<div class="test max-height stretch" data-expected-height="90">
<canvas width="10" height="20" data-expected-width="40" data-expected-height="80"></canvas>
</div>
</div>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../resources/check-layout-th.js"></script>
<script>
document.fonts.ready.then(() => checkLayout(".test"));
</script>