Skip to content

Commit cc64efa

Browse files
committed
LibJS: Split out NumberToBigInt from the BigInt constructor
This is supposed to be its own AO, but since it was only used in one place, we inlined it. Now that it's also being used in the Temporal proposal (Date.prototype.toTemporalInstant() specifically), it makes sense to have it as a standalone function. A small difference is that we now construct the SignedBigInteger without casting to i32 but instead take the (known to be integral) double and cast it to i64. Not perfect, but slightly better. Also clean up the BigInt constructor a bit while we're here and sprinkle some spec comments.
1 parent 3e8574a commit cc64efa

File tree

3 files changed

+37
-17
lines changed

3 files changed

+37
-17
lines changed

Userland/Libraries/LibJS/Runtime/BigInt.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/*
2-
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
2+
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
33
*
44
* SPDX-License-Identifier: BSD-2-Clause
55
*/
66

77
#include <LibCrypto/BigInt/SignedBigInteger.h>
88
#include <LibJS/Heap/Heap.h>
99
#include <LibJS/Runtime/BigInt.h>
10+
#include <LibJS/Runtime/GlobalObject.h>
1011

1112
namespace JS {
1213

@@ -25,4 +26,20 @@ BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer)
2526
return heap.allocate_without_global_object<BigInt>(move(big_integer));
2627
}
2728

29+
// 21.2.1.1.1 NumberToBigInt ( number ), https://tc39.es/ecma262/#sec-numbertobigint
30+
BigInt* number_to_bigint(GlobalObject& global_object, Value number)
31+
{
32+
VERIFY(number.is_number());
33+
auto& vm = global_object.vm();
34+
35+
// 1. If IsIntegralNumber(number) is false, throw a RangeError exception.
36+
if (!number.is_integral_number()) {
37+
vm.throw_exception<RangeError>(global_object, ErrorType::BigIntIntArgument);
38+
return {};
39+
}
40+
41+
// 2. Return the BigInt value that represents ℝ(number).
42+
return js_bigint(vm.heap(), Crypto::SignedBigInteger::create_from((i64)number.as_double()));
43+
}
44+
2845
}

Userland/Libraries/LibJS/Runtime/BigInt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
2+
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
33
*
44
* SPDX-License-Identifier: BSD-2-Clause
55
*/
@@ -26,5 +26,6 @@ class BigInt final : public Cell {
2626
};
2727

2828
BigInt* js_bigint(Heap&, Crypto::SignedBigInteger);
29+
BigInt* number_to_bigint(GlobalObject&, Value);
2930

3031
}

Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
2+
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
33
*
44
* SPDX-License-Identifier: BSD-2-Clause
55
*/
66

77
#include <AK/String.h>
8-
#include <LibCrypto/BigInt/SignedBigInteger.h>
8+
#include <LibJS/Runtime/BigInt.h>
99
#include <LibJS/Runtime/BigIntConstructor.h>
1010
#include <LibJS/Runtime/BigIntObject.h>
1111
#include <LibJS/Runtime/Error.h>
@@ -42,20 +42,22 @@ BigIntConstructor::~BigIntConstructor()
4242
// 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value
4343
Value BigIntConstructor::call()
4444
{
45-
auto primitive = vm().argument(0).to_primitive(global_object(), Value::PreferredType::Number);
46-
if (vm().exception())
47-
return {};
48-
if (primitive.is_number()) {
49-
if (!primitive.is_integral_number()) {
50-
vm().throw_exception<RangeError>(global_object(), ErrorType::BigIntIntArgument);
51-
return {};
52-
}
53-
return js_bigint(heap(), Crypto::SignedBigInteger { primitive.as_i32() });
54-
}
55-
auto* bigint = vm().argument(0).to_bigint(global_object());
56-
if (vm().exception())
45+
auto& vm = this->vm();
46+
auto& global_object = this->global_object();
47+
48+
auto value = vm.argument(0);
49+
50+
// 2. Let prim be ? ToPrimitive(value, number).
51+
auto primitive = value.to_primitive(global_object, Value::PreferredType::Number);
52+
if (vm.exception())
5753
return {};
58-
return bigint;
54+
55+
// 3. If Type(prim) is Number, return ? NumberToBigInt(prim).
56+
if (primitive.is_number())
57+
return number_to_bigint(global_object, primitive);
58+
59+
// 4. Otherwise, return ? ToBigInt(value).
60+
return value.to_bigint(global_object);
5961
}
6062

6163
// 21.2.1.1 BigInt ( value ), https://tc39.es/ecma262/#sec-bigint-constructor-number-value

0 commit comments

Comments
 (0)