瀏覽代碼

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.
Linus Groh 4 年之前
父節點
當前提交
cc64efac44

+ 18 - 1
Userland/Libraries/LibJS/Runtime/BigInt.cpp

@@ -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
  */
@@ -7,6 +7,7 @@
 #include <LibCrypto/BigInt/SignedBigInteger.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Runtime/BigInt.h>
+#include <LibJS/Runtime/GlobalObject.h>
 
 namespace JS {
 
@@ -25,4 +26,20 @@ BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer)
     return heap.allocate_without_global_object<BigInt>(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<RangeError>(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()));
+}
+
 }

+ 2 - 1
Userland/Libraries/LibJS/Runtime/BigInt.h

@@ -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
  */
@@ -26,5 +26,6 @@ private:
 };
 
 BigInt* js_bigint(Heap&, Crypto::SignedBigInteger);
+BigInt* number_to_bigint(GlobalObject&, Value);
 
 }

+ 17 - 15
Userland/Libraries/LibJS/Runtime/BigIntConstructor.cpp

@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
 #include <AK/String.h>
-#include <LibCrypto/BigInt/SignedBigInteger.h>
+#include <LibJS/Runtime/BigInt.h>
 #include <LibJS/Runtime/BigIntConstructor.h>
 #include <LibJS/Runtime/BigIntObject.h>
 #include <LibJS/Runtime/Error.h>
@@ -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())
-        return {};
-    if (primitive.is_number()) {
-        if (!primitive.is_integral_number()) {
-            vm().throw_exception<RangeError>(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())
+    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 {};
-    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