summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-05-31 20:27:44 +0300
committerLinus Groh <mail@linusgroh.de>2021-05-31 19:50:29 +0100
commit67a5e9f0184eac51a7451f540845e49dfdc0b34a (patch)
tree33da39ec3c07ac10ab38bc4a60a017851481e711 /Userland/Libraries
parent4ee58d36c0ac500aa1357478416723e38562995a (diff)
downloadserenity-67a5e9f0184eac51a7451f540845e49dfdc0b34a.zip
LibJS: Add left shift & right shift operator support for BigIntegers
Based on https://tc39.es/ecma262/#sec-numeric-types-bigint-leftShift (This commit also includes the matching tests)
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Value.cpp16
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js2
2 files changed, 14 insertions, 4 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp
index 98a8c0eec2..62e7c9d19d 100644
--- a/Userland/Libraries/LibJS/Runtime/Value.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Value.cpp
@@ -787,8 +787,13 @@ Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
auto rhs_u32 = rhs_numeric.to_u32(global_object);
return Value(lhs_i32 << rhs_u32);
}
- if (both_bigint(lhs_numeric, rhs_numeric))
- TODO();
+ if (both_bigint(lhs_numeric, rhs_numeric)) {
+ auto multiplier_divisor = Crypto::SignedBigInteger { Crypto::NumberTheory::Power(Crypto::UnsignedBigInteger(2), rhs_numeric.as_bigint().big_integer().unsigned_value()) };
+ if (rhs_numeric.as_bigint().big_integer().is_negative())
+ return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(multiplier_divisor).quotient);
+ else
+ return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().multiplied_by(multiplier_divisor));
+ }
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "left-shift");
return {};
}
@@ -813,8 +818,11 @@ Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
auto rhs_u32 = rhs_numeric.to_u32(global_object);
return Value(lhs_i32 >> rhs_u32);
}
- if (both_bigint(lhs_numeric, rhs_numeric))
- TODO();
+ if (both_bigint(lhs_numeric, rhs_numeric)) {
+ auto rhs_negated = rhs_numeric.as_bigint().big_integer();
+ rhs_negated.negate();
+ return left_shift(global_object, lhs, js_bigint(global_object.heap(), rhs_negated));
+ }
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "right-shift");
return {};
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js b/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js
index eb957020bf..426f92dc62 100644
--- a/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js
+++ b/Userland/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js
@@ -28,6 +28,8 @@ describe("correct behavior", () => {
expect(1n | 2n).toBe(3n);
expect(5n ^ 3n).toBe(6n);
expect(~1n).toBe(-2n);
+ expect(5n << 2n).toBe(20n);
+ expect(7n >> 1n).toBe(3n);
});
test("increment operators", () => {