LibJS: Rewrite Math.hypot to handle exceptions, NaNs, Infinity properly

The specification requires that we immediately return Infinity during
the iteration over the arguments if positive or negative infinity is
encountered, and return a NaN if it is encountered and no Infinity was
found. The specification 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 Infinity/NaN early return.
This commit is contained in:
Idan Horowitz 2021-06-05 03:20:00 +03:00 committed by Linus Groh
parent 03255c1c53
commit 57a52094d1
Notes: sideshowbarker 2024-07-18 16:50:42 +09:00

View file

@ -473,20 +473,33 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::fround)
JS_DEFINE_NATIVE_FUNCTION(MathObject::hypot)
{
if (!vm.argument_count())
return Value(0);
auto hypot = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
hypot = Value(hypot.as_double() * hypot.as_double());
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 {};
hypot = Value(hypot.as_double() + cur.as_double() * cur.as_double());
coerced.append(number);
}
return Value(::sqrt(hypot.as_double()));
for (auto& number : coerced) {
if (number.is_positive_infinity() || number.is_negative_infinity())
return js_infinity();
}
auto only_zero = true;
double sum_of_squares = 0;
for (auto& number : coerced) {
if (number.is_nan() || number.is_positive_infinity())
return number;
if (number.is_negative_infinity())
return js_infinity();
if (!number.is_positive_zero() && !number.is_negative_zero())
only_zero = false;
sum_of_squares += number.as_double() * number.as_double();
}
if (only_zero)
return Value(0);
return Value(::sqrt(sum_of_squares));
}
JS_DEFINE_NATIVE_FUNCTION(MathObject::imul)