From fa6bce5087618f8b8bb321e0ade082019d5dd7a7 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Tue, 16 Mar 2021 20:35:55 +0100 Subject: [PATCH] LibJS: Throw RangeError on BigInt exponentiation with negative exponent https://tc39.es/ecma262/#sec-numeric-types-bigint-exponentiate --- Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 1 + Userland/Libraries/LibJS/Runtime/Value.cpp | 7 ++++++- .../Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index 58bb2f2929c..f55314261df 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/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") \ diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index e29d40aa403..328d53c9145 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/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(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(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation"); return {}; } diff --git a/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js b/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js index eb96764d4f3..eb957020bfa 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js +++ b/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"); + }); });