mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:37:35 +00:00
LibJS: Rewrite Math.{max, min} to handle exceptions and NaNs properly
The specification requires that we immediately return a NaN during the iteration over the arguments if one is encountered. It also requires all arguments to be coerced into numbers before the operation starts, or else a number conversion exception could be missed due to the NaN early return.
This commit is contained in:
parent
24ffe91b16
commit
7507999230
1 changed files with 26 additions and 22 deletions
|
@ -153,38 +153,42 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::round)
|
|||
|
||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::max)
|
||||
{
|
||||
if (!vm.argument_count())
|
||||
return js_negative_infinity();
|
||||
|
||||
auto max = vm.argument(0).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
for (size_t i = 1; i < vm.argument_count(); ++i) {
|
||||
auto cur = vm.argument(i).to_number(global_object);
|
||||
Vector<Value> coerced;
|
||||
for (size_t i = 0; i < vm.argument_count(); ++i) {
|
||||
auto number = vm.argument(i).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if ((max.is_negative_zero() && cur.is_positive_zero()) || cur.as_double() > max.as_double())
|
||||
max = cur;
|
||||
coerced.append(number);
|
||||
}
|
||||
return max;
|
||||
|
||||
auto highest = js_negative_infinity();
|
||||
for (auto& number : coerced) {
|
||||
if (number.is_nan())
|
||||
return js_nan();
|
||||
if ((number.is_positive_zero() && highest.is_negative_zero()) || number.as_double() > highest.as_double())
|
||||
highest = number;
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
|
||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::min)
|
||||
{
|
||||
if (!vm.argument_count())
|
||||
return js_infinity();
|
||||
|
||||
auto min = vm.argument(0).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
for (size_t i = 1; i < vm.argument_count(); ++i) {
|
||||
auto cur = vm.argument(i).to_number(global_object);
|
||||
Vector<Value> coerced;
|
||||
for (size_t i = 0; i < vm.argument_count(); ++i) {
|
||||
auto number = vm.argument(i).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if ((min.is_positive_zero() && cur.is_negative_zero()) || cur.as_double() < min.as_double())
|
||||
min = cur;
|
||||
coerced.append(number);
|
||||
}
|
||||
return min;
|
||||
|
||||
auto lowest = js_infinity();
|
||||
for (auto& number : coerced) {
|
||||
if (number.is_nan())
|
||||
return js_nan();
|
||||
if ((number.is_negative_zero() && lowest.is_positive_zero()) || number.as_double() < lowest.as_double())
|
||||
lowest = number;
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
JS_DEFINE_NATIVE_FUNCTION(MathObject::trunc)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue