LibWeb: Handle NaN within CSS min and max functions

Gains us 10 WPT tests
This commit is contained in:
Callum Law 2025-07-31 21:02:57 +12:00 committed by Sam Atkins
commit 376b992f0e
Notes: github-actions[bot] 2025-08-08 10:45:12 +00:00
7 changed files with 31 additions and 24 deletions

View file

@ -1052,6 +1052,13 @@ static Optional<CalculatedStyleValue::CalculationResult> run_min_or_max_operatio
if (!consistent_type.has_value())
return {};
// https://drafts.csswg.org/css-values-4/#calc-ieee
// Any operation with at least one NaN argument produces NaN.
if (isnan(child_value->value()) || isnan(result->value())) {
result = CalculatedStyleValue::CalculationResult { AK::NaN<double>, consistent_type };
continue;
}
if (min_or_max == MinOrMax::Min) {
if (child_value->value() < result->value()) {
result = CalculatedStyleValue::CalculationResult { child_value->value(), consistent_type };

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 21 tests
17 Pass
4 Fail
19 Pass
2 Fail
Pass 'calc(100px * 0 / 0)' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(100px / 0)' as a specified value should serialize as 'calc(infinity * 1px)'.
Pass 'calc(100px / (0))' as a specified value should serialize as 'calc(infinity * 1px)'.
@ -19,9 +19,9 @@ Pass 'calc(1px * max(0/0, 0))' as a specified value should serialize as 'calc(Na
Pass 'calc(1px * min(0/0, 0))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * max(0/0, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * clamp(0/0, 0, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * max(0, min(10, 0/0)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * max(0, min(10, 0/0)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * clamp(0, 10, 0/0))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * max(0, min(0/0, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * max(0, min(0/0, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * clamp(0, 0/0, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * clamp(-1/0, 0, 1/0))' as a specified value should serialize as 'calc(0px)'.
Pass 'calc(1px * clamp(-1/0, 1/0, 10))' as a specified value should serialize as 'calc(10px)'.

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 45 tests
24 Pass
21 Fail
26 Pass
19 Fail
Pass Property width value 'calc(NaN * 1px)'
Pass Property width value 'calc(NaN * 1%)'
Pass Property width value 'calc(infinity * 1px)'
@ -11,11 +11,11 @@ Pass Property width value 'calc(infinity * 1%)'
Pass Property width value 'calc(infinity * 1cm)'
Pass Property width value 'calc(NaN * 1rem)'
Pass Property width value 'calc(10.135262721212548pc - 199pt / NaN)'
Fail Property width value 'max(15px, NaN * 1px)'
Pass Property width value 'max(15px, NaN * 1px)'
Pass Property width value 'max(NaN * 1px, 15px)'
Pass Property width value 'max(-15px, NaN * 1px)'
Pass Property width value 'max(NaN * 1px, -15px)'
Fail Property width value 'min(15px, NaN * 1px)'
Pass Property width value 'min(15px, NaN * 1px)'
Pass Property width value 'min(NaN * 1px, 15px)'
Pass Property width value 'min(-15px, NaN * 1px)'
Pass Property width value 'min(NaN * 1px, -15px)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 30 tests
26 Pass
4 Fail
28 Pass
2 Fail
Pass 'rotate(calc(1deg * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1rad * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1turn * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
@ -28,9 +28,9 @@ Pass 'rotate(calc(1 * min(nan*3deg, 0deg)))' as a specified value should seriali
Pass 'rotate(calc(1 * clamp(-INFINITY*20deg, 0deg, infiniTY*10deg)))' as a specified value should serialize as 'rotate(calc(0deg))'.
Pass 'rotate(calc(1deg * max(NaN, min(0,10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1deg * clamp(NaN, 0, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Fail 'rotate(calc(1deg * max(0, min(10, NaN))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1deg * max(0, min(10, NaN))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Fail 'rotate(calc(1deg * clamp(0, 10, NaN)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Fail 'rotate(calc(1deg * max(0, min(NaN, 10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1deg * max(0, min(NaN, 10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Fail 'rotate(calc(1deg * clamp(0, NaN, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
Pass 'rotate(calc(1deg * clamp(-Infinity, 0, infinity)))' as a specified value should serialize as 'rotate(calc(0deg))'.
Pass 'rotate(calc(1deg * clamp(-inFinity, infinity, 10)))' as a specified value should serialize as 'rotate(calc(10deg))'.

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 41 tests
35 Pass
6 Fail
37 Pass
4 Fail
Pass 'calc(1px * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1% * NaN)' as a specified value should serialize as 'calc(NaN * 1%)'.
Pass 'calc(1in * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.
@ -35,9 +35,9 @@ Pass 'calc(1 * min(nan*3px, 0px))' as a specified value should serialize as 'cal
Pass 'calc(1 * clamp(-INFINITY*20px, 0px, infiniTY*10px))' as a specified value should serialize as 'calc(0px)'.
Pass 'calc(1px * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'.
Fail 'calc(1px * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1px)'.
Pass 'calc(1px * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0px)'.
Pass 'calc(1px * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10px)'.

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 31 tests
27 Pass
4 Fail
29 Pass
2 Fail
Pass 'calc(NaN)' as a specified value should serialize as 'calc(NaN)'.
Pass 'calc(infinity)' as a specified value should serialize as 'calc(infinity)'.
Pass 'calc(-infinity)' as a specified value should serialize as 'calc(-infinity)'.
@ -29,9 +29,9 @@ Pass 'calc(1 * min(nan*3, 0))' as a specified value should serialize as 'calc(Na
Pass 'calc(1 * clamp(-INFINITY*20, 0, infiniTY*10))' as a specified value should serialize as 'calc(0)'.
Pass 'calc(1 * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN)'.
Pass 'calc(1 * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN)'.
Fail 'calc(1 * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN)'.
Pass 'calc(1 * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN)'.
Fail 'calc(1 * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN)'.
Fail 'calc(1 * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN)'.
Pass 'calc(1 * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN)'.
Fail 'calc(1 * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN)'.
Pass 'calc(1 * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0)'.
Pass 'calc(1 * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10)'.

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 29 tests
25 Pass
4 Fail
27 Pass
2 Fail
Pass 'calc(1s * NaN)' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1s * nan)' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1ms * NaN)' as a specified value should serialize as 'calc(NaN * 1s)'.
@ -27,9 +27,9 @@ Pass 'calc(1 * min(nan*3s, 0s))' as a specified value should serialize as 'calc(
Pass 'calc(1 * clamp(-INFINITY*20s, 0s, infiniTY*10s))' as a specified value should serialize as 'calc(0s)'.
Pass 'calc(1s * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1s * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1s)'.
Fail 'calc(1s * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1s * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1s)'.
Fail 'calc(1s * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1s)'.
Fail 'calc(1s * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1s * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1s)'.
Fail 'calc(1s * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1s)'.
Pass 'calc(1s * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0s)'.
Pass 'calc(1s * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10s)'.