mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 17:49:40 +00:00
LibWeb: Set numeric type of asin, acos, atan calculation results
Previously we were omitting the numeric type which meant these functions weren't valid in some cases e.g. within rotate() functions.
This commit is contained in:
parent
4e747f525a
commit
536f8c395c
Notes:
github-actions[bot]
2025-06-25 04:20:13 +00:00
Author: https://github.com/Calme1709
Commit: 536f8c395c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5205
Reviewed-by: https://github.com/tcl3 ✅
5 changed files with 254 additions and 1 deletions
|
@ -1702,7 +1702,7 @@ static Optional<CalculatedStyleValue::CalculationResult> run_asin_acos_or_atan_o
|
|||
break;
|
||||
}
|
||||
|
||||
return CalculatedStyleValue::CalculationResult { result, CSSNumericType {}.made_consistent_with(child.numeric_type().value()) };
|
||||
return CalculatedStyleValue::CalculationResult { result, CSSNumericType { CSSNumericType::BaseType::Angle, 1 }.made_consistent_with(child.numeric_type().value()) };
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-values-4/#funcdef-asin
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 45 tests
|
||||
|
||||
34 Pass
|
||||
11 Fail
|
||||
Pass acos(1) should be used-value-equivalent to 0deg
|
||||
Pass atan(0) should be used-value-equivalent to 0deg
|
||||
Pass asin(0) should be used-value-equivalent to 0deg
|
||||
Pass atan2(0,0) should be used-value-equivalent to 0deg
|
||||
Pass calc(asin(sin(pi/2))) should be used-value-equivalent to 90deg
|
||||
Pass calc(acos(cos(pi - 3.14159265358979323846))) should be used-value-equivalent to 0deg
|
||||
Pass calc(atan(e - 2.7182818284590452354) ) should be used-value-equivalent to 0deg
|
||||
Pass calc(asin(sin(30deg + 1.0471967rad ) )) should be used-value-equivalent to 90deg
|
||||
Pass calc(acos(cos(30deg - 0.523599rad ) )) should be used-value-equivalent to 0deg
|
||||
Pass calc(asin(sin(3.14159 / 2 + 1 - 1) )) should be used-value-equivalent to 90deg
|
||||
Pass calc(asin(sin(100grad) )) should be used-value-equivalent to 90deg
|
||||
Pass calc(acos(cos(0 / 2 + 1 - 1) )) should be used-value-equivalent to 0deg
|
||||
Pass calc(atan(tan(30deg + 0.261799rad ) )) should be used-value-equivalent to 45deg
|
||||
Pass calc(atan(tan(0.7853975rad ) )) should be used-value-equivalent to 45deg
|
||||
Pass calc(atan(tan(3.14159 / 4 + 1 - 1) )) should be used-value-equivalent to 45deg
|
||||
Pass calc(asin(sin(0.25turn)) ) should be used-value-equivalent to 90deg
|
||||
Pass calc(atan2(0,1)) should be used-value-equivalent to 0deg
|
||||
Pass calc(atan2(0,-1) / 4) should be used-value-equivalent to 45deg
|
||||
Pass calc(atan2(1,-1)) should be used-value-equivalent to 135deg
|
||||
Pass calc(atan2(-1,1)) should be used-value-equivalent to -45deg
|
||||
Fail calc(asin(sin(180deg * sibling-index()))) should be used-value-equivalent to 0deg
|
||||
Fail calc(acos(cos(180deg * sibling-index()))) should be used-value-equivalent to 180deg
|
||||
Fail calc(atan(tan(180deg * sibling-index()))) should be used-value-equivalent to 0deg
|
||||
Pass calc(cos(sin(acos(cos(pi))))) should be used-value-equivalent to 1
|
||||
Pass atan2(1px, -1px) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1cm, -1cm) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1mm, -1mm) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1Q, -1Q) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1in, -1in) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1pc, -1pc) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1pt, -1pt) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1em, -1em) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1ex, -1ex) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1ch, -1ch) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1rem, -1rem) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1rem + 1px - 1px, -1rem) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1vh, -1vh) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1vh + 0px, -1vh + 0px) should be used-value-equivalent to 135deg
|
||||
Fail atan2(1vw, -1vw) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1deg, -1deg) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1grad, -1grad) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1turn, -1turn) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1rad, -1rad) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1s, -1s) should be used-value-equivalent to 135deg
|
||||
Pass atan2(1ms, -1ms) should be used-value-equivalent to 135deg
|
|
@ -0,0 +1,68 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 62 tests
|
||||
|
||||
50 Pass
|
||||
12 Fail
|
||||
Pass 'rotate(acos(1))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(calc(acos(1)))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(acos(-1))' as a specified value should serialize as 'rotate(calc(180deg))'.
|
||||
Pass 'rotate(calc(acos(-1)))' as a specified value should serialize as 'rotate(calc(180deg))'.
|
||||
Pass 'rotate(acos(-1.5))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(acos(-1.5)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(acos(1.5))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(acos(1.5)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(acos(2))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(acos(2)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Fail 'rotate(acos(0.5))' as a specified value should serialize as 'rotate(calc(60deg))'.
|
||||
Fail 'rotate(calc(acos(0.5)))' as a specified value should serialize as 'rotate(calc(60deg))'.
|
||||
Fail 'rotate(acos(1 - 0.5))' as a specified value should serialize as 'rotate(calc(60deg))'.
|
||||
Fail 'rotate(calc(acos(1 - 0.5)))' as a specified value should serialize as 'rotate(calc(60deg))'.
|
||||
Pass 'rotate(acos(0))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(acos(0)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(asin(1))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(asin(1)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(asin(-1))' as a specified value should serialize as 'rotate(calc(-90deg))'.
|
||||
Pass 'rotate(calc(asin(-1)))' as a specified value should serialize as 'rotate(calc(-90deg))'.
|
||||
Pass 'rotate(asin(-1.5))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(asin(-1.5)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(asin(1.5))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(asin(1.5)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(asin(2))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(asin(2)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Fail 'rotate(asin(0.5))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Fail 'rotate(calc(asin(0.5)))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Fail 'rotate(asin(1 - 0.5))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Fail 'rotate(calc(asin(1 - 0.5)))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Pass 'rotate(asin(0))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(calc(asin(0)))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(acos(pi - pi))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(acos(pi - pi)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(asin(pi - pi + 1))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(asin(pi - pi + 1)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(atan(1))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Pass 'rotate(calc(atan(1)))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Fail 'rotate(atan(0.577350269))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Fail 'rotate(calc(atan(0.577350269)))' as a specified value should serialize as 'rotate(calc(30deg))'.
|
||||
Pass 'rotate(atan(0))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(calc(atan(0)))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(atan(infinity))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(atan(infinity)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Fail 'rotate(atan2(37.320508075, 10))' as a specified value should serialize as 'rotate(calc(75deg))'.
|
||||
Fail 'rotate(calc(atan2(37.320508075, 10)))' as a specified value should serialize as 'rotate(calc(75deg))'.
|
||||
Pass 'rotate(atan2(1s, 1000ms))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Pass 'rotate(calc(atan2(1s, 1000ms)))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Pass 'rotate(atan2(infinity, infinity))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Pass 'rotate(calc(atan2(infinity, infinity)))' as a specified value should serialize as 'rotate(calc(45deg))'.
|
||||
Pass 'rotate(atan2(-infinity, -infinity))' as a specified value should serialize as 'rotate(calc(-135deg))'.
|
||||
Pass 'rotate(calc(atan2(-infinity, -infinity)))' as a specified value should serialize as 'rotate(calc(-135deg))'.
|
||||
Pass 'rotate(atan2(infinity, 10))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(calc(atan2(infinity, 10)))' as a specified value should serialize as 'rotate(calc(90deg))'.
|
||||
Pass 'rotate(atan2(10, infinity))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(calc(atan2(10, infinity)))' as a specified value should serialize as 'rotate(calc(0deg))'.
|
||||
Pass 'rotate(atan2(NaN, 10))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(atan2(NaN, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(atan2(10, NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(atan2(10, NaN)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(atan2(NaN, NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
||||
Pass 'rotate(calc(atan2(NaN, NaN)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#trig-funcs">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking">
|
||||
<link rel="author" title="Apple Inc">
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../support/numeric-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
function test_angle_equals(value, expected) {
|
||||
test_math_used(value, expected, {type: "angle"});
|
||||
}
|
||||
// Simple tests
|
||||
test_angle_equals('acos(1)', '0deg');
|
||||
test_angle_equals('atan(0)', '0deg');
|
||||
test_angle_equals('asin(0)', '0deg');
|
||||
test_angle_equals('atan2(0,0)', '0deg');
|
||||
|
||||
// Test pi
|
||||
test_math_used('calc(asin(sin(pi/2)))', '90deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(acos(cos(pi - 3.14159265358979323846)))', '0deg', {type:'angle', approx:0.1});
|
||||
|
||||
// Test e
|
||||
test_math_used('calc(atan(e - 2.7182818284590452354) )', '0deg', {type:'angle', approx:0.1});
|
||||
|
||||
// General calculations
|
||||
test_math_used('calc(asin(sin(30deg + 1.0471967rad ) ))', '90deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(acos(cos(30deg - 0.523599rad ) ))', '0deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(asin(sin(3.14159 / 2 + 1 - 1) ))', '90deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(asin(sin(100grad) ))', '90deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(acos(cos(0 / 2 + 1 - 1) ))', '0deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan(tan(30deg + 0.261799rad ) ))', '45deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan(tan(0.7853975rad ) ))', '45deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan(tan(3.14159 / 4 + 1 - 1) ))', '45deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(asin(sin(0.25turn)) )', '90deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan2(0,1))', '0deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan2(0,-1) / 4)', '45deg', {type:'angle', approx:0.1}); // atan2(0,-1) equals 180deg, result is divided to avoid ambiguity with -180deg
|
||||
test_math_used('calc(atan2(1,-1))', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan2(-1,1))', '-45deg', {type:'angle', approx:0.1});
|
||||
|
||||
// Test unresolved at parse time
|
||||
test_math_used('calc(asin(sin(180deg * sibling-index())))', '0deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(acos(cos(180deg * sibling-index())))', '180deg', {type:'angle', approx:0.1});
|
||||
test_math_used('calc(atan(tan(180deg * sibling-index())))', '0deg', {type:'angle', approx:0.1});
|
||||
|
||||
// Test nesting
|
||||
test_math_used('calc(cos(sin(acos(cos(pi)))))', '1', {type:'number', approx:0.1});
|
||||
|
||||
// Test types for atan2
|
||||
test_math_used('atan2(1px, -1px)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1cm, -1cm)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1mm, -1mm)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1Q, -1Q)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1in, -1in)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1pc, -1pc)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1pt, -1pt)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1em, -1em)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1ex, -1ex)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1ch, -1ch)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1rem, -1rem)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1rem + 1px - 1px, -1rem)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1vh, -1vh)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1vh + 0px, -1vh + 0px)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1vw, -1vw)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1deg, -1deg)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1grad, -1grad)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1turn, -1turn)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1rad, -1rad)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1s, -1s)', '135deg', {type:'angle', approx:0.1});
|
||||
test_math_used('atan2(1ms, -1ms)', '135deg', {type:'angle', approx:0.1});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#trig-funcs">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#angles">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-serialize">
|
||||
<link rel="author" title="Apple Inc">
|
||||
<link rel="author" title="Seokho Song" href="seokho@chromium.org">
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../support/serialize-testcommon.js"></script>
|
||||
<div id=target></div>
|
||||
<script>
|
||||
|
||||
function test_serialization(specified, expected, {prop="transform"}={}) {
|
||||
|
||||
// We only test the specified serialization,
|
||||
// and not the computed or used serialization,
|
||||
// since we'd need to do that by retrieving the rotation matrix,
|
||||
// and that isn't perfectly interoperable in corner cases.
|
||||
// Plus the point of this test is to check the trig functions themselves.
|
||||
test_specified_serialization(prop, `rotate(${specified})`, `rotate(${expected})`)
|
||||
}
|
||||
//TEST CASE | EXPECTED
|
||||
var test_map = {
|
||||
"acos(1)" :"calc(0deg)",
|
||||
"acos(-1)" :"calc(180deg)",
|
||||
"acos(-1.5)" :"calc(NaN * 1deg)",
|
||||
"acos(1.5)" :"calc(NaN * 1deg)",
|
||||
"acos(2)" :"calc(NaN * 1deg)",
|
||||
"acos(0.5)" :"calc(60deg)",
|
||||
"acos(1 - 0.5)" :"calc(60deg)",
|
||||
"acos(0)" :"calc(90deg)",
|
||||
"asin(1)" :"calc(90deg)",
|
||||
"asin(-1)" :"calc(-90deg)",
|
||||
"asin(-1.5)" :"calc(NaN * 1deg)",
|
||||
"asin(1.5)" :"calc(NaN * 1deg)",
|
||||
"asin(2)" :"calc(NaN * 1deg)",
|
||||
"asin(0.5)" :"calc(30deg)",
|
||||
"asin(1 - 0.5)" :"calc(30deg)",
|
||||
"asin(0)" :"calc(0deg)",
|
||||
"acos(pi - pi)" :"calc(90deg)",
|
||||
"asin(pi - pi + 1)" :"calc(90deg)",
|
||||
"atan(1)" :"calc(45deg)",
|
||||
"atan(0.577350269)" :"calc(30deg)",
|
||||
"atan(0)" :"calc(0deg)",
|
||||
"atan(infinity)" :"calc(90deg)",
|
||||
"atan2(37.320508075, 10)" :"calc(75deg)",
|
||||
"atan2(1s, 1000ms)" :"calc(45deg)",
|
||||
"atan2(infinity, infinity)" :"calc(45deg)",
|
||||
"atan2(-infinity, -infinity)" :"calc(-135deg)",
|
||||
"atan2(infinity, 10)" :"calc(90deg)",
|
||||
"atan2(10, infinity)" :"calc(0deg)",
|
||||
"atan2(NaN, 10)" :"calc(NaN * 1deg)",
|
||||
"atan2(10, NaN)" :"calc(NaN * 1deg)",
|
||||
"atan2(NaN, NaN)" :"calc(NaN * 1deg)",
|
||||
};
|
||||
|
||||
for (var exp in test_map) {
|
||||
test_serialization(exp, test_map[exp]);
|
||||
test_serialization(`calc(${exp})`, test_map[exp]);
|
||||
}
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue