mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-03 08:08:43 +00:00
LibWeb: Avoid premature creation of CSSPixels in calc simplification
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Previously we were converting lengths to CSSPixels values when we didn't need to, this had a couple of effects in that: - We rounded to CSSPixel resolution prematurely (sometimes giving incorrect results) - We converted NaN to 0 when we shouldn't have. We now avoid prematurely converting lengths to CSSPixels values in two places: - `CalculationResult::from_value` - `CalculatedStyleValue::resolve_length_deprecated` (the new method already avoided rounding). Gains us 16 WPT tests.
This commit is contained in:
parent
3fa7bc1919
commit
a44e28fd56
Notes:
github-actions[bot]
2025-08-06 14:01:09 +00:00
Author: https://github.com/Calme1709
Commit: a44e28fd56
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5714
Reviewed-by: https://github.com/AtkinsSJ ✅
4 changed files with 74 additions and 17 deletions
|
@ -197,24 +197,30 @@ public:
|
|||
}
|
||||
|
||||
ALWAYS_INLINE CSSPixels absolute_length_to_px() const
|
||||
{
|
||||
return CSSPixels::nearest_value_for(absolute_length_to_px_without_rounding());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE double absolute_length_to_px_without_rounding() const
|
||||
{
|
||||
constexpr double inch_pixels = 96.0;
|
||||
constexpr double centimeter_pixels = (inch_pixels / 2.54);
|
||||
|
||||
switch (m_type) {
|
||||
case Type::Cm:
|
||||
return CSSPixels::nearest_value_for(m_value * centimeter_pixels); // 1cm = 96px/2.54
|
||||
return m_value * centimeter_pixels; // 1cm = 96px/2.54
|
||||
case Type::In:
|
||||
return CSSPixels::nearest_value_for(m_value * inch_pixels); // 1in = 2.54 cm = 96px
|
||||
return m_value * inch_pixels; // 1in = 2.54 cm = 96px
|
||||
case Type::Px:
|
||||
return CSSPixels::nearest_value_for(m_value); // 1px = 1/96th of 1in
|
||||
return m_value; // 1px = 1/96th of 1in
|
||||
case Type::Pt:
|
||||
return CSSPixels::nearest_value_for(m_value * ((1.0 / 72.0) * inch_pixels)); // 1pt = 1/72th of 1in
|
||||
return m_value * ((1.0 / 72.0) * inch_pixels); // 1pt = 1/72th of 1in
|
||||
case Type::Pc:
|
||||
return CSSPixels::nearest_value_for(m_value * ((1.0 / 6.0) * inch_pixels)); // 1pc = 1/6th of 1in
|
||||
return m_value * ((1.0 / 6.0) * inch_pixels); // 1pc = 1/6th of 1in
|
||||
case Type::Mm:
|
||||
return CSSPixels::nearest_value_for(m_value * ((1.0 / 10.0) * centimeter_pixels)); // 1mm = 1/10th of 1cm
|
||||
return m_value * ((1.0 / 10.0) * centimeter_pixels); // 1mm = 1/10th of 1cm
|
||||
case Type::Q:
|
||||
return CSSPixels::nearest_value_for(m_value * ((1.0 / 40.0) * centimeter_pixels)); // 1Q = 1/40th of 1cm
|
||||
return m_value * ((1.0 / 40.0) * centimeter_pixels); // 1Q = 1/40th of 1cm
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
|
|
@ -2600,7 +2600,7 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult:
|
|||
return 0.0;
|
||||
|
||||
if (length.is_absolute())
|
||||
return length.absolute_length_to_px().to_double();
|
||||
return length.absolute_length_to_px_without_rounding();
|
||||
|
||||
// If we don't have a context, we cant resolve the length, so return NAN
|
||||
if (!context.length_resolution_context.has_value()) {
|
||||
|
@ -2751,7 +2751,7 @@ Optional<Length> CalculatedStyleValue::resolve_length_deprecated(CalculationReso
|
|||
{
|
||||
auto result = m_calculation->resolve(context);
|
||||
if (result.type().has_value() && result.type()->matches_length(m_context.percentages_resolve_as))
|
||||
return Length::make_px(CSSPixels { result.value() });
|
||||
return Length::make_px(result.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 45 tests
|
||||
|
||||
33 Pass
|
||||
12 Fail
|
||||
Pass Property width value 'calc(NaN * 1px)'
|
||||
Pass Property width value 'calc(NaN * 1%)'
|
||||
Pass Property width value 'calc(infinity * 1px)'
|
||||
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)'
|
||||
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)'
|
||||
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)'
|
||||
Pass Property width value 'calc(infinity * 1px - infinity * 1%)'
|
||||
Pass Property width value 'calc(infinity * 1px + infinity * 1%)'
|
||||
Pass Property width value 'calc(min(NaN * 1px, infinity * 1px) + max(infinity * 1px, -infinity * 1px))'
|
||||
Pass Property width value 'calc(infinity * 1px - max(infinity * 1%, 0%))'
|
||||
Pass Property width value 'calc(max(infinity * 1px, 10px))'
|
||||
Pass Property margin-left value 'calc(-infinity * 1px)'
|
||||
Pass Property margin-left value 'calc(min(1px, -infinity * 1%))'
|
||||
Pass Property margin-left value 'calc(-infinity * 1%)'
|
||||
Pass Property margin-left value 'calc(max(10000px, 0px) + min(-infinity * 1px, infinity * 1px))'
|
||||
Pass Property margin-left value 'calc(-infinity * 1px - infinity * 1px)'
|
||||
Pass Property margin-left value 'calc(min(-infinity * 1px, 10px))'
|
||||
Pass Property animation-duration value 'calc(NaN * 1s)'
|
||||
Pass Property animation-duration value 'calc(infinity * 1s)'
|
||||
Pass Property animation-duration value 'calc(1 / 0 * 1s)'
|
||||
Pass Property animation-duration value 'calc(max(infinity * 1s, 10s)'
|
||||
Pass Property transition-delay value 'calc(-infinity* 1s)'
|
||||
Pass Property transition-delay value 'calc(max(10000s, 0s) + min(-infinity * 1s, infinity * 1s))'
|
||||
Pass Property transition-delay value 'calc(min(-infinity * 1s, 10s))'
|
||||
Fail Property rotate(calc(infinity * 1deg)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(-infinity * 1deg)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(NaN * 1deg)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(infinity * 1turn)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(-infinity * 1turn)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(NaN * 1turn)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(infinity * 1rad)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(-infinity * 1rad)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(NaN * 1rad)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(infinity * 1grad)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(-infinity * 1grad)) value expected same with rotate(0deg) in +/-0.0001
|
||||
Fail Property rotate(calc(NaN * 1grad)) value expected same with rotate(0deg) in +/-0.0001
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 41 tests
|
||||
|
||||
29 Pass
|
||||
12 Fail
|
||||
35 Pass
|
||||
6 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)'.
|
||||
|
@ -13,7 +13,7 @@ Pass 'calc(1q * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'
|
|||
Pass 'calc(1pt * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1pc * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1px * nan)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Fail 'calc(1px * infinity / infinity)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1px * infinity / infinity)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1px * 0 * infinity)' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1px * (infinity + -infinity))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1px * (-infinity + infinity))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
|
@ -28,10 +28,10 @@ Pass 'calc(1px * (-infinity + -infinity))' as a specified value should serialize
|
|||
Pass 'calc(1px * 1/infinity)' as a specified value should serialize as 'calc(0px)'.
|
||||
Pass 'calc(1px * infinity * infinity)' as a specified value should serialize as 'calc(infinity * 1px)'.
|
||||
Pass 'calc(1px * -infinity * -infinity)' as a specified value should serialize as 'calc(infinity * 1px)'.
|
||||
Fail 'calc(1 * max(INFinity*3px, 0px))' as a specified value should serialize as 'calc(infinity * 1px)'.
|
||||
Pass 'calc(1 * max(INFinity*3px, 0px))' as a specified value should serialize as 'calc(infinity * 1px)'.
|
||||
Pass 'calc(1 * min(inFInity*4px, 0px))' as a specified value should serialize as 'calc(0px)'.
|
||||
Fail 'calc(1 * max(nAn*2px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Fail 'calc(1 * min(nan*3px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1 * max(nAn*2px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1 * min(nan*3px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
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)'.
|
||||
|
@ -41,7 +41,7 @@ Fail 'calc(1px * max(0, min(NaN, 10)))' as a specified value should serialize as
|
|||
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)'.
|
||||
Fail 'calc(1 * min(NaN * 1pt, NaN * 1cm))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Fail 'calc(1 * max(NaN * 1cm, NaN * 2Q))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1 * min(NaN * 1pt, NaN * 1cm))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Pass 'calc(1 * max(NaN * 1cm, NaN * 2Q))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Fail 'calc(1 * min(NaN * 2px, NaN * 4em))' as a specified value should serialize as 'calc(NaN * 1px)'.
|
||||
Fail 'calc(1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt))' as a specified value should serialize as 'clamp(NaN * 1em, NaN * 1px, NaN * 1px)'.
|
Loading…
Add table
Add a link
Reference in a new issue