1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:27:45 +00:00

LibJS: Make Number() constructor spec compliant

By using to_numeric() and adding BigInt handling, we get support for
`Number(123n)`.

Fixes #8125.
This commit is contained in:
Linus Groh 2021-06-19 01:34:17 +01:00
parent 7f8245439b
commit 8e26c7a1dd
2 changed files with 55 additions and 25 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -58,24 +58,41 @@ NumberConstructor::~NumberConstructor()
{
}
// Most of 21.1.1.1 Number ( value ) factored into a separate function for sharing between call() and construct().
static Value get_value_from_constructor_argument(GlobalObject& global_object)
{
auto& vm = global_object.vm();
Value number;
if (vm.argument_count() > 0) {
auto primitive = vm.argument(0).to_numeric(global_object);
if (vm.exception())
return {};
if (primitive.is_bigint()) {
// FIXME: How should huge values be handled here?
auto& big_integer = primitive.as_bigint().big_integer();
number = Value(static_cast<double>(big_integer.unsigned_value().to_u64()) * (big_integer.is_negative() ? -1.0 : 1.0));
} else {
number = primitive;
}
} else {
number = Value(0);
}
return number;
}
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value
Value NumberConstructor::call()
{
if (!vm().argument_count())
return Value(0);
return vm().argument(0).to_number(global_object());
return get_value_from_constructor_argument(global_object());
}
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value
Value NumberConstructor::construct(Function&)
{
double number = 0;
if (vm().argument_count()) {
number = vm().argument(0).to_double(global_object());
if (vm().exception())
return {};
}
return NumberObject::create(global_object(), number);
auto number = get_value_from_constructor_argument(global_object());
// FIXME: Use OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%")
return NumberObject::create(global_object(), number.as_double());
}
// 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite