Переглянути джерело

LibJS: Throw RangeError on BigInt exponentiation with negative exponent

https://tc39.es/ecma262/#sec-numeric-types-bigint-exponentiate
Linus Groh 4 роки тому
батько
коміт
fa6bce5087

+ 1 - 0
Userland/Libraries/LibJS/Runtime/ErrorTypes.h

@@ -60,6 +60,7 @@
     M(JsonBigInt, "Cannot serialize BigInt value to JSON")                                                                              \
     M(JsonCircular, "Cannot stringify circular object")                                                                                 \
     M(JsonMalformed, "Malformed JSON string")                                                                                           \
+    M(NegativeExponent, "Exponent must be positive")                                                                                    \
     M(NotA, "Not a {} object")                                                                                                          \
     M(NotAConstructor, "{} is not a constructor")                                                                                       \
     M(NotAFunction, "{} is not a function")                                                                                             \

+ 6 - 1
Userland/Libraries/LibJS/Runtime/Value.cpp

@@ -941,8 +941,13 @@ Value exp(GlobalObject& global_object, Value lhs, Value rhs)
         return {};
     if (both_number(lhs_numeric, rhs_numeric))
         return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double()));
-    if (both_bigint(lhs_numeric, rhs_numeric))
+    if (both_bigint(lhs_numeric, rhs_numeric)) {
+        if (rhs_numeric.as_bigint().big_integer().is_negative()) {
+            vm.throw_exception<RangeError>(global_object, ErrorType::NegativeExponent);
+            return {};
+        }
         return js_bigint(vm.heap(), Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer()));
+    }
     vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation");
     return {};
 }

+ 6 - 0
Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js

@@ -96,4 +96,10 @@ describe("errors", () => {
             1n % 0n;
         }).toThrowWithMessage(RangeError, "Division by zero");
     });
+
+    test("negative exponent", () => {
+        expect(() => {
+            1n ** -1n;
+        }).toThrowWithMessage(RangeError, "Exponent must be positive");
+    });
 });