1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 04:47:34 +00:00

LibJS: Add a js_bigint(VM&, ...) overload and use it

We already have js_string(VM&, ...) and js_symbol(VM&, ...) overloads,
so feels very familiar.
This commit is contained in:
Linus Groh 2021-08-03 00:14:48 +01:00
parent dc9f516339
commit f58891ed42
8 changed files with 67 additions and 50 deletions

View file

@ -26,6 +26,11 @@ BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer)
return heap.allocate_without_global_object<BigInt>(move(big_integer)); return heap.allocate_without_global_object<BigInt>(move(big_integer));
} }
BigInt* js_bigint(VM& vm, Crypto::SignedBigInteger big_integer)
{
return js_bigint(vm.heap(), move(big_integer));
}
// 21.2.1.1.1 NumberToBigInt ( number ), https://tc39.es/ecma262/#sec-numbertobigint // 21.2.1.1.1 NumberToBigInt ( number ), https://tc39.es/ecma262/#sec-numbertobigint
BigInt* number_to_bigint(GlobalObject& global_object, Value number) BigInt* number_to_bigint(GlobalObject& global_object, Value number)
{ {
@ -39,7 +44,7 @@ BigInt* number_to_bigint(GlobalObject& global_object, Value number)
} }
// 2. Return the BigInt value that represents (number). // 2. Return the BigInt value that represents (number).
return js_bigint(vm.heap(), Crypto::SignedBigInteger::create_from((i64)number.as_double())); return js_bigint(vm, Crypto::SignedBigInteger::create_from((i64)number.as_double()));
} }
} }

View file

@ -26,6 +26,7 @@ private:
}; };
BigInt* js_bigint(Heap&, Crypto::SignedBigInteger); BigInt* js_bigint(Heap&, Crypto::SignedBigInteger);
BigInt* js_bigint(VM&, Crypto::SignedBigInteger);
BigInt* number_to_bigint(GlobalObject&, Value); BigInt* number_to_bigint(GlobalObject&, Value);
} }

View file

@ -873,7 +873,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_temporal_instant)
auto* ns = number_to_bigint(global_object, t); auto* ns = number_to_bigint(global_object, t);
if (vm.exception()) if (vm.exception())
return {}; return {};
ns = js_bigint(vm.heap(), ns->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 })); ns = js_bigint(vm, ns->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }));
// 3. Return ! CreateTemporalInstant(ns). // 3. Return ! CreateTemporalInstant(ns).
return Temporal::create_temporal_instant(global_object, *ns); return Temporal::create_temporal_instant(global_object, *ns);

View file

@ -142,7 +142,7 @@ BigInt* parse_temporal_instant(GlobalObject& global_object, String const& iso_st
return {}; return {};
// 8. Return utc offsetNanoseconds. // 8. Return utc offsetNanoseconds.
return js_bigint(vm.heap(), utc->big_integer().minus(Crypto::SignedBigInteger::create_from(offset_nanoseconds))); return js_bigint(vm, utc->big_integer().minus(Crypto::SignedBigInteger::create_from(offset_nanoseconds)));
} }
// 8.5.5 CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo ) // 8.5.5 CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo )

View file

@ -78,7 +78,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from)
// 1. If Type(item) is Object and item has an [[InitializedTemporalInstant]] internal slot, then // 1. If Type(item) is Object and item has an [[InitializedTemporalInstant]] internal slot, then
if (item.is_object() && is<Instant>(item.as_object())) { if (item.is_object() && is<Instant>(item.as_object())) {
// a. Return ! CreateTemporalInstant(item.[[Nanoseconds]]). // a. Return ! CreateTemporalInstant(item.[[Nanoseconds]]).
return create_temporal_instant(global_object, *js_bigint(vm.heap(), static_cast<Instant&>(item.as_object()).nanoseconds().big_integer())); return create_temporal_instant(global_object, *js_bigint(vm, static_cast<Instant&>(item.as_object()).nanoseconds().big_integer()));
} }
// 2. Return ? ToTemporalInstant(item). // 2. Return ? ToTemporalInstant(item).
@ -99,7 +99,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_seconds)
return {}; return {};
// 3. Let epochNanoseconds be epochSeconds × 10^9. // 3. Let epochNanoseconds be epochSeconds × 10^9.
auto* epoch_nanoseconds = js_bigint(vm.heap(), epoch_seconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000'000 })); auto* epoch_nanoseconds = js_bigint(vm, epoch_seconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000'000 }));
// 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. // 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
@ -125,7 +125,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_milliseconds)
return {}; return {};
// 3. Let epochNanoseconds be epochMilliseconds × 10^6. // 3. Let epochNanoseconds be epochMilliseconds × 10^6.
auto* epoch_nanoseconds = js_bigint(vm.heap(), epoch_milliseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 })); auto* epoch_nanoseconds = js_bigint(vm, epoch_milliseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }));
// 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. // 4. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {
@ -146,7 +146,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantConstructor::from_epoch_microseconds)
return {}; return {};
// 2. Let epochNanoseconds be epochMicroseconds × 1000. // 2. Let epochNanoseconds be epochMicroseconds × 1000.
auto* epoch_nanoseconds = js_bigint(vm.heap(), epoch_microseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000 })); auto* epoch_nanoseconds = js_bigint(vm, epoch_microseconds->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000 }));
// 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception. // 3. If ! IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) { if (!is_valid_epoch_nanoseconds(*epoch_nanoseconds)) {

View file

@ -106,7 +106,7 @@ JS_DEFINE_NATIVE_FUNCTION(InstantPrototype::epoch_microseconds_getter)
auto [us, _] = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000 }); auto [us, _] = ns.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000 });
// 5. Return (µs). // 5. Return (µs).
return js_bigint(vm.heap(), move(us)); return js_bigint(vm, move(us));
} }
// 8.3.6 get Temporal.Instant.prototype.epochNanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochnanoseconds // 8.3.6 get Temporal.Instant.prototype.epochNanoseconds, https://tc39.es/proposal-temporal/#sec-get-temporal.instant.prototype.epochnanoseconds

View file

@ -61,7 +61,7 @@ BigInt* get_epoch_from_iso_parts(GlobalObject& global_object, i32 year, u8 month
VERIFY(ms.is_finite_number()); VERIFY(ms.is_finite_number());
// 8. Return (ms) × 10^6 + microsecond × 10^3 + nanosecond. // 8. Return (ms) × 10^6 + microsecond × 10^3 + nanosecond.
return js_bigint(vm.heap(), Crypto::SignedBigInteger::create_from(static_cast<i64>(ms.as_double())).multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }).plus(Crypto::SignedBigInteger::create_from((i64)microsecond * 1000)).plus(Crypto::SignedBigInteger(nanosecond))); return js_bigint(vm, Crypto::SignedBigInteger::create_from(static_cast<i64>(ms.as_double())).multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }).plus(Crypto::SignedBigInteger::create_from((i64)microsecond * 1000)).plus(Crypto::SignedBigInteger(nanosecond)));
} }
// -864 * 10^19 - 864 * 10^14 // -864 * 10^19 - 864 * 10^14

View file

@ -540,7 +540,7 @@ BigInt* Value::to_bigint(GlobalObject& global_object) const
return nullptr; return nullptr;
case Type::Boolean: { case Type::Boolean: {
auto value = primitive.as_bool() ? 1 : 0; auto value = primitive.as_bool() ? 1 : 0;
return js_bigint(vm.heap(), Crypto::SignedBigInteger { value }); return js_bigint(vm, Crypto::SignedBigInteger { value });
} }
case Type::BigInt: case Type::BigInt:
return &primitive.as_bigint(); return &primitive.as_bigint();
@ -554,7 +554,7 @@ BigInt* Value::to_bigint(GlobalObject& global_object) const
vm.throw_exception<SyntaxError>(global_object, ErrorType::BigIntInvalidValue, string); vm.throw_exception<SyntaxError>(global_object, ErrorType::BigIntInvalidValue, string);
return {}; return {};
} }
return js_bigint(vm.heap(), Crypto::SignedBigInteger::from_base(10, string.trim_whitespace())); return js_bigint(vm, Crypto::SignedBigInteger::from_base(10, string.trim_whitespace()));
} }
case Type::Symbol: case Type::Symbol:
vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "BigInt"); vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "BigInt");
@ -883,11 +883,12 @@ Value less_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators // 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs) Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
if (!lhs_numeric.is_finite_number() || !rhs_numeric.is_finite_number()) if (!lhs_numeric.is_finite_number() || !rhs_numeric.is_finite_number())
@ -895,19 +896,20 @@ Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs)
return Value(lhs_numeric.to_i32(global_object) & rhs_numeric.to_i32(global_object)); return Value(lhs_numeric.to_i32(global_object) & rhs_numeric.to_i32(global_object));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer()));
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise AND");
return {}; return {};
} }
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators // 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs) Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number()) if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number())
@ -919,19 +921,20 @@ Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
return Value(lhs_numeric.to_i32(global_object) | rhs_numeric.to_i32(global_object)); return Value(lhs_numeric.to_i32(global_object) | rhs_numeric.to_i32(global_object));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer()));
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise OR");
return {}; return {};
} }
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators // 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs) Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number()) if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number())
@ -943,23 +946,24 @@ Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
return Value(lhs_numeric.to_i32(global_object) ^ rhs_numeric.to_i32(global_object)); return Value(lhs_numeric.to_i32(global_object) ^ rhs_numeric.to_i32(global_object));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer()));
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise XOR");
return {}; return {};
} }
// 13.5.6 Bitwise NOT Operator ( ~ ), https://tc39.es/ecma262/#sec-bitwise-not-operator // 13.5.6 Bitwise NOT Operator ( ~ ), https://tc39.es/ecma262/#sec-bitwise-not-operator
Value bitwise_not(GlobalObject& global_object, Value lhs) Value bitwise_not(GlobalObject& global_object, Value lhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (lhs_numeric.is_number()) if (lhs_numeric.is_number())
return Value(~lhs_numeric.to_i32(global_object)); return Value(~lhs_numeric.to_i32(global_object));
auto big_integer_bitwise_not = lhs_numeric.as_bigint().big_integer(); auto big_integer_bitwise_not = lhs_numeric.as_bigint().big_integer();
big_integer_bitwise_not = big_integer_bitwise_not.plus(Crypto::SignedBigInteger { 1 }); big_integer_bitwise_not = big_integer_bitwise_not.plus(Crypto::SignedBigInteger { 1 });
big_integer_bitwise_not.negate(); big_integer_bitwise_not.negate();
return js_bigint(global_object.heap(), big_integer_bitwise_not); return js_bigint(vm, big_integer_bitwise_not);
} }
// 13.5.4 Unary + Operator, https://tc39.es/ecma262/#sec-unary-plus-operator // 13.5.4 Unary + Operator, https://tc39.es/ecma262/#sec-unary-plus-operator
@ -971,8 +975,9 @@ Value unary_plus(GlobalObject& global_object, Value lhs)
// 13.5.5 Unary - Operator, https://tc39.es/ecma262/#sec-unary-minus-operator // 13.5.5 Unary - Operator, https://tc39.es/ecma262/#sec-unary-minus-operator
Value unary_minus(GlobalObject& global_object, Value lhs) Value unary_minus(GlobalObject& global_object, Value lhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (lhs_numeric.is_number()) { if (lhs_numeric.is_number()) {
if (lhs_numeric.is_nan()) if (lhs_numeric.is_nan())
@ -980,20 +985,21 @@ Value unary_minus(GlobalObject& global_object, Value lhs)
return Value(-lhs_numeric.as_double()); return Value(-lhs_numeric.as_double());
} }
if (lhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) if (lhs_numeric.as_bigint().big_integer() == BIGINT_ZERO)
return js_bigint(global_object.heap(), BIGINT_ZERO); return js_bigint(vm, BIGINT_ZERO);
auto big_integer_negated = lhs_numeric.as_bigint().big_integer(); auto big_integer_negated = lhs_numeric.as_bigint().big_integer();
big_integer_negated.negate(); big_integer_negated.negate();
return js_bigint(global_object.heap(), big_integer_negated); return js_bigint(vm, big_integer_negated);
} }
// 13.9.1 The Left Shift Operator ( << ), https://tc39.es/ecma262/#sec-left-shift-operator // 13.9.1 The Left Shift Operator ( << ), https://tc39.es/ecma262/#sec-left-shift-operator
Value left_shift(GlobalObject& global_object, Value lhs, Value rhs) Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
if (!lhs_numeric.is_finite_number()) if (!lhs_numeric.is_finite_number())
@ -1008,9 +1014,9 @@ Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
if (both_bigint(lhs_numeric, rhs_numeric)) { 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()) }; 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()) 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); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().divided_by(multiplier_divisor).quotient);
else else
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().multiplied_by(multiplier_divisor)); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().multiplied_by(multiplier_divisor));
} }
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "left-shift"); global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "left-shift");
return {}; return {};
@ -1019,11 +1025,12 @@ Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
// 13.9.2 The Signed Right Shift Operator ( >> ), https://tc39.es/ecma262/#sec-signed-right-shift-operator // 13.9.2 The Signed Right Shift Operator ( >> ), https://tc39.es/ecma262/#sec-signed-right-shift-operator
Value right_shift(GlobalObject& global_object, Value lhs, Value rhs) Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
if (!lhs_numeric.is_finite_number()) if (!lhs_numeric.is_finite_number())
@ -1037,7 +1044,7 @@ Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
if (both_bigint(lhs_numeric, rhs_numeric)) { if (both_bigint(lhs_numeric, rhs_numeric)) {
auto rhs_negated = rhs_numeric.as_bigint().big_integer(); auto rhs_negated = rhs_numeric.as_bigint().big_integer();
rhs_negated.negate(); rhs_negated.negate();
return left_shift(global_object, lhs, js_bigint(global_object.heap(), rhs_negated)); return left_shift(global_object, lhs, js_bigint(vm, rhs_negated));
} }
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "right-shift"); global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "right-shift");
return {}; return {};
@ -1109,7 +1116,7 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
if (both_number(lhs_numeric, rhs_numeric)) if (both_number(lhs_numeric, rhs_numeric))
return Value(lhs_numeric.as_double() + rhs_numeric.as_double()); return Value(lhs_numeric.as_double() + rhs_numeric.as_double());
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(vm.heap(), lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer()));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "addition"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "addition");
return {}; return {};
} }
@ -1117,34 +1124,36 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
// 13.8.2 The Subtraction Operator ( - ), https://tc39.es/ecma262/#sec-subtraction-operator-minus // 13.8.2 The Subtraction Operator ( - ), https://tc39.es/ecma262/#sec-subtraction-operator-minus
Value sub(GlobalObject& global_object, Value lhs, Value rhs) Value sub(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) if (both_number(lhs_numeric, rhs_numeric))
return Value(lhs_numeric.as_double() - rhs_numeric.as_double()); return Value(lhs_numeric.as_double() - rhs_numeric.as_double());
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer()));
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "subtraction"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "subtraction");
return {}; return {};
} }
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators // 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value mul(GlobalObject& global_object, Value lhs, Value rhs) Value mul(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object); auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(global_object); auto rhs_numeric = rhs.to_numeric(global_object);
if (global_object.vm().exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) if (both_number(lhs_numeric, rhs_numeric))
return Value(lhs_numeric.as_double() * rhs_numeric.as_double()); return Value(lhs_numeric.as_double() * rhs_numeric.as_double());
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer()));
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "multiplication"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "multiplication");
return {}; return {};
} }
@ -1165,7 +1174,7 @@ Value div(GlobalObject& global_object, Value lhs, Value rhs)
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero);
return {}; return {};
} }
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient);
} }
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "division"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "division");
return {}; return {};
@ -1194,7 +1203,7 @@ Value mod(GlobalObject& global_object, Value lhs, Value rhs)
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero);
return {}; return {};
} }
return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder); return js_bigint(vm, lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder);
} }
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "modulo"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "modulo");
return {}; return {};
@ -1217,7 +1226,7 @@ Value exp(GlobalObject& global_object, Value lhs, Value rhs)
vm.throw_exception<RangeError>(global_object, ErrorType::NegativeExponent); vm.throw_exception<RangeError>(global_object, ErrorType::NegativeExponent);
return {}; return {};
} }
return js_bigint(vm.heap(), Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer())); return js_bigint(vm, Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer()));
} }
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation");
return {}; return {};
@ -1386,6 +1395,8 @@ bool strict_eq(Value lhs, Value rhs)
// 7.2.14 IsLooselyEqual ( x, y ), https://tc39.es/ecma262/#sec-islooselyequal // 7.2.14 IsLooselyEqual ( x, y ), https://tc39.es/ecma262/#sec-islooselyequal
bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs) bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm();
if (same_type_for_equality(lhs, rhs)) if (same_type_for_equality(lhs, rhs))
return strict_eq(lhs, rhs); return strict_eq(lhs, rhs);
@ -1408,7 +1419,7 @@ bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs)
auto& rhs_string = rhs.as_string().string(); auto& rhs_string = rhs.as_string().string();
if (!is_valid_bigint_value(rhs_string)) if (!is_valid_bigint_value(rhs_string))
return false; return false;
return abstract_eq(global_object, lhs, js_bigint(global_object.heap(), Crypto::SignedBigInteger::from_base(10, rhs_string))); return abstract_eq(global_object, lhs, js_bigint(vm, Crypto::SignedBigInteger::from_base(10, rhs_string)));
} }
if (lhs.is_string() && rhs.is_bigint()) if (lhs.is_string() && rhs.is_bigint())
@ -1422,14 +1433,14 @@ bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs)
if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object()) { if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object()) {
auto rhs_primitive = rhs.to_primitive(global_object); auto rhs_primitive = rhs.to_primitive(global_object);
if (global_object.vm().exception()) if (vm.exception())
return false; return false;
return abstract_eq(global_object, lhs, rhs_primitive); return abstract_eq(global_object, lhs, rhs_primitive);
} }
if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || lhs.is_bigint() || rhs.is_symbol())) { if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || lhs.is_bigint() || rhs.is_symbol())) {
auto lhs_primitive = lhs.to_primitive(global_object); auto lhs_primitive = lhs.to_primitive(global_object);
if (global_object.vm().exception()) if (vm.exception())
return false; return false;
return abstract_eq(global_object, lhs_primitive, rhs); return abstract_eq(global_object, lhs_primitive, rhs);
} }