diff --git a/Userland/Libraries/LibJS/Runtime/BigInt.cpp b/Userland/Libraries/LibJS/Runtime/BigInt.cpp index 8e78e3b81a..60022cccef 100644 --- a/Userland/Libraries/LibJS/Runtime/BigInt.cpp +++ b/Userland/Libraries/LibJS/Runtime/BigInt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Linus Groh + * Copyright (c) 2020-2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,6 +7,7 @@ #include #include #include +#include namespace JS { @@ -25,4 +26,20 @@ BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer) return heap.allocate_without_global_object(move(big_integer)); } +// 21.2.1.1.1 NumberToBigInt ( number ), https://tc39.es/ecma262/#sec-numbertobigint +BigInt* number_to_bigint(GlobalObject& global_object, Value number) +{ + VERIFY(number.is_number()); + auto& vm = global_object.vm(); + + // 1. If IsIntegralNumber(number) is false, throw a RangeError exception. + if (!number.is_integral_number()) { + vm.throw_exception(global_object, ErrorType::BigIntIntArgument); + return {}; + } + + // 2. Return the BigInt value that represents ℝ(number). + return js_bigint(vm.heap(), Crypto::SignedBigInteger::create_from((i64)number.as_double())); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/BigInt.h b/Userland/Libraries/LibJS/Runtime/BigInt.h index fd1673fb5b..add9fae0c2 100644 --- a/Userland/Libraries/LibJS/Runtime/BigInt.h +++ b/Userland/Libraries/LibJS/Runtime/BigInt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Linus Groh + * Copyright (c) 2020-2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -26,5 +26,6 @@ private: }; BigInt* js_bigint(Heap&, Crypto::SignedBigInteger); +BigInt* number_to_bigint(GlobalObject&, Value); } diff --git a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp index 19e644186c..dd83b83cf7 100644 --- a/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp @@ -1,11 +1,11 @@ /* - * Copyright (c) 2020, Linus Groh + * Copyright (c) 2020-2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #include -#include +#include #include #include #include @@ -42,20 +42,22 @@ BigIntConstructor::~BigIntConstructor() // 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value Value BigIntConstructor::call() { - auto primitive = vm().argument(0).to_primitive(global_object(), Value::PreferredType::Number); - if (vm().exception()) + auto& vm = this->vm(); + auto& global_object = this->global_object(); + + auto value = vm.argument(0); + + // 2. Let prim be ? ToPrimitive(value, number). + auto primitive = value.to_primitive(global_object, Value::PreferredType::Number); + if (vm.exception()) return {}; - if (primitive.is_number()) { - if (!primitive.is_integral_number()) { - vm().throw_exception(global_object(), ErrorType::BigIntIntArgument); - return {}; - } - return js_bigint(heap(), Crypto::SignedBigInteger { primitive.as_i32() }); - } - auto* bigint = vm().argument(0).to_bigint(global_object()); - if (vm().exception()) - return {}; - return bigint; + + // 3. If Type(prim) is Number, return ? NumberToBigInt(prim). + if (primitive.is_number()) + return number_to_bigint(global_object, primitive); + + // 4. Otherwise, return ? ToBigInt(value). + return value.to_bigint(global_object); } // 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value