From 48ac6ba3723df477aab449c6b1866db77c5eca44 Mon Sep 17 00:00:00 2001 From: davidot Date: Thu, 25 Aug 2022 18:02:49 +0200 Subject: [PATCH] LibJS: Use the proper to_double method in NumberConstructor --- .../LibJS/Runtime/NumberConstructor.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp index bbff170620..b1f6ed14f7 100644 --- a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp @@ -60,16 +60,23 @@ void NumberConstructor::initialize(Realm& realm) static ThrowCompletionOr get_value_from_constructor_argument(VM& vm) { Value number; + // 1. If value is present, then if (vm.argument_count() > 0) { + // a. Let prim be ? ToNumeric(value). auto primitive = TRY(vm.argument(0).to_numeric(vm)); + + // b. If Type(prim) is BigInt, let n be 𝔽(ℝ(prim)). if (primitive.is_bigint()) { - // FIXME: How should huge values be handled here? - auto& big_integer = primitive.as_bigint().big_integer(); - number = Value(static_cast(big_integer.unsigned_value().to_u64()) * (big_integer.is_negative() ? -1.0 : 1.0)); - } else { + number = Value(primitive.as_bigint().big_integer().to_double(Crypto::UnsignedBigInteger::RoundingMode::ECMAScriptNumberValueFor)); + } + // c. Otherwise, let n be prim. + else { number = primitive; } - } else { + } + // 2. Else, + else { + // a. Let n be +0𝔽. number = Value(0); } return number; @@ -78,6 +85,8 @@ static ThrowCompletionOr get_value_from_constructor_argument(VM& vm) // 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value ThrowCompletionOr NumberConstructor::call() { + // NOTE: get_value_from_constructor_argument performs steps 1 and 2 and returns n. + // 3. If NewTarget is undefined, return n. return get_value_from_constructor_argument(vm()); } @@ -85,8 +94,12 @@ ThrowCompletionOr NumberConstructor::call() ThrowCompletionOr NumberConstructor::construct(FunctionObject& new_target) { auto& vm = this->vm(); - + // NOTE: get_value_from_constructor_argument performs steps 1 and 2 and returns n. auto number = TRY(get_value_from_constructor_argument(vm)); + + // 4. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »). + // 5. Set O.[[NumberData]] to n. + // 6. Return O. return TRY(ordinary_create_from_constructor(vm, new_target, &GlobalObject::number_prototype, number.as_double())); }