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

LibJS: Convert Value operator AOs to ThrowCompletionOr

This commit is contained in:
Idan Horowitz 2021-10-19 00:13:29 +03:00 committed by Linus Groh
parent 48ac15758e
commit 545d403f6b
5 changed files with 204 additions and 220 deletions

View file

@ -909,17 +909,17 @@ Value BinaryExpression::execute(Interpreter& interpreter, GlobalObject& global_o
switch (m_op) { switch (m_op) {
case BinaryOp::Addition: case BinaryOp::Addition:
return add(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(add(global_object, lhs_result, rhs_result));
case BinaryOp::Subtraction: case BinaryOp::Subtraction:
return sub(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(sub(global_object, lhs_result, rhs_result));
case BinaryOp::Multiplication: case BinaryOp::Multiplication:
return mul(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(mul(global_object, lhs_result, rhs_result));
case BinaryOp::Division: case BinaryOp::Division:
return div(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(div(global_object, lhs_result, rhs_result));
case BinaryOp::Modulo: case BinaryOp::Modulo:
return mod(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(mod(global_object, lhs_result, rhs_result));
case BinaryOp::Exponentiation: case BinaryOp::Exponentiation:
return exp(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(exp(global_object, lhs_result, rhs_result));
case BinaryOp::StrictlyEquals: case BinaryOp::StrictlyEquals:
return Value(is_strictly_equal(lhs_result, rhs_result)); return Value(is_strictly_equal(lhs_result, rhs_result));
case BinaryOp::StrictlyInequals: case BinaryOp::StrictlyInequals:
@ -929,29 +929,29 @@ Value BinaryExpression::execute(Interpreter& interpreter, GlobalObject& global_o
case BinaryOp::LooselyInequals: case BinaryOp::LooselyInequals:
return Value(!TRY_OR_DISCARD(is_loosely_equal(global_object, lhs_result, rhs_result))); return Value(!TRY_OR_DISCARD(is_loosely_equal(global_object, lhs_result, rhs_result)));
case BinaryOp::GreaterThan: case BinaryOp::GreaterThan:
return greater_than(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(greater_than(global_object, lhs_result, rhs_result));
case BinaryOp::GreaterThanEquals: case BinaryOp::GreaterThanEquals:
return greater_than_equals(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(greater_than_equals(global_object, lhs_result, rhs_result));
case BinaryOp::LessThan: case BinaryOp::LessThan:
return less_than(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(less_than(global_object, lhs_result, rhs_result));
case BinaryOp::LessThanEquals: case BinaryOp::LessThanEquals:
return less_than_equals(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(less_than_equals(global_object, lhs_result, rhs_result));
case BinaryOp::BitwiseAnd: case BinaryOp::BitwiseAnd:
return bitwise_and(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(bitwise_and(global_object, lhs_result, rhs_result));
case BinaryOp::BitwiseOr: case BinaryOp::BitwiseOr:
return bitwise_or(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(bitwise_or(global_object, lhs_result, rhs_result));
case BinaryOp::BitwiseXor: case BinaryOp::BitwiseXor:
return bitwise_xor(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(bitwise_xor(global_object, lhs_result, rhs_result));
case BinaryOp::LeftShift: case BinaryOp::LeftShift:
return left_shift(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(left_shift(global_object, lhs_result, rhs_result));
case BinaryOp::RightShift: case BinaryOp::RightShift:
return right_shift(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(right_shift(global_object, lhs_result, rhs_result));
case BinaryOp::UnsignedRightShift: case BinaryOp::UnsignedRightShift:
return unsigned_right_shift(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(unsigned_right_shift(global_object, lhs_result, rhs_result));
case BinaryOp::In: case BinaryOp::In:
return in(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(in(global_object, lhs_result, rhs_result));
case BinaryOp::InstanceOf: case BinaryOp::InstanceOf:
return instance_of(global_object, lhs_result, rhs_result); return TRY_OR_DISCARD(instance_of(global_object, lhs_result, rhs_result));
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
@ -1134,13 +1134,13 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
switch (m_op) { switch (m_op) {
case UnaryOp::BitwiseNot: case UnaryOp::BitwiseNot:
return bitwise_not(global_object, lhs_result); return TRY_OR_DISCARD(bitwise_not(global_object, lhs_result));
case UnaryOp::Not: case UnaryOp::Not:
return Value(!lhs_result.to_boolean()); return Value(!lhs_result.to_boolean());
case UnaryOp::Plus: case UnaryOp::Plus:
return unary_plus(global_object, lhs_result); return TRY_OR_DISCARD(unary_plus(global_object, lhs_result));
case UnaryOp::Minus: case UnaryOp::Minus:
return unary_minus(global_object, lhs_result); return TRY_OR_DISCARD(unary_minus(global_object, lhs_result));
case UnaryOp::Typeof: case UnaryOp::Typeof:
return js_string(vm, lhs_result.typeof()); return js_string(vm, lhs_result.typeof());
case UnaryOp::Void: case UnaryOp::Void:
@ -1987,40 +1987,40 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob
switch (m_op) { switch (m_op) {
case AssignmentOp::AdditionAssignment: case AssignmentOp::AdditionAssignment:
rhs_result = add(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(add(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::SubtractionAssignment: case AssignmentOp::SubtractionAssignment:
rhs_result = sub(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(sub(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::MultiplicationAssignment: case AssignmentOp::MultiplicationAssignment:
rhs_result = mul(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(mul(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::DivisionAssignment: case AssignmentOp::DivisionAssignment:
rhs_result = div(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(div(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::ModuloAssignment: case AssignmentOp::ModuloAssignment:
rhs_result = mod(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(mod(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::ExponentiationAssignment: case AssignmentOp::ExponentiationAssignment:
rhs_result = exp(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(exp(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::BitwiseAndAssignment: case AssignmentOp::BitwiseAndAssignment:
rhs_result = bitwise_and(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(bitwise_and(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::BitwiseOrAssignment: case AssignmentOp::BitwiseOrAssignment:
rhs_result = bitwise_or(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(bitwise_or(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::BitwiseXorAssignment: case AssignmentOp::BitwiseXorAssignment:
rhs_result = bitwise_xor(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(bitwise_xor(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::LeftShiftAssignment: case AssignmentOp::LeftShiftAssignment:
rhs_result = left_shift(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(left_shift(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::RightShiftAssignment: case AssignmentOp::RightShiftAssignment:
rhs_result = right_shift(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(right_shift(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::UnsignedRightShiftAssignment: case AssignmentOp::UnsignedRightShiftAssignment:
rhs_result = unsigned_right_shift(global_object, lhs_result, rhs_result); rhs_result = TRY_OR_DISCARD(unsigned_right_shift(global_object, lhs_result, rhs_result));
break; break;
case AssignmentOp::Assignment: case AssignmentOp::Assignment:
case AssignmentOp::AndAssignment: case AssignmentOp::AndAssignment:

View file

@ -55,58 +55,64 @@ void Store::execute_impl(Bytecode::Interpreter& interpreter) const
interpreter.reg(m_dst) = interpreter.accumulator(); interpreter.reg(m_dst) = interpreter.accumulator();
} }
static Value abstract_inequals(GlobalObject& global_object, Value src1, Value src2) static ThrowCompletionOr<Value> abstract_inequals(GlobalObject& global_object, Value src1, Value src2)
{ {
return Value(!TRY_OR_DISCARD(is_loosely_equal(global_object, src1, src2))); return Value(!TRY(is_loosely_equal(global_object, src1, src2)));
} }
static Value abstract_equals(GlobalObject& global_object, Value src1, Value src2) static ThrowCompletionOr<Value> abstract_equals(GlobalObject& global_object, Value src1, Value src2)
{ {
return Value(TRY_OR_DISCARD(is_loosely_equal(global_object, src1, src2))); return Value(TRY(is_loosely_equal(global_object, src1, src2)));
} }
static Value typed_inequals(GlobalObject&, Value src1, Value src2) static ThrowCompletionOr<Value> typed_inequals(GlobalObject&, Value src1, Value src2)
{ {
return Value(!is_strictly_equal(src1, src2)); return Value(!is_strictly_equal(src1, src2));
} }
static Value typed_equals(GlobalObject&, Value src1, Value src2) static ThrowCompletionOr<Value> typed_equals(GlobalObject&, Value src1, Value src2)
{ {
return Value(is_strictly_equal(src1, src2)); return Value(is_strictly_equal(src1, src2));
} }
#define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \ #define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \ void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
{ \ { \
auto lhs = interpreter.reg(m_lhs_reg); \ auto lhs = interpreter.reg(m_lhs_reg); \
auto rhs = interpreter.accumulator(); \ auto rhs = interpreter.accumulator(); \
interpreter.accumulator() = op_snake_case(interpreter.global_object(), lhs, rhs); \ auto result_or_error = op_snake_case(interpreter.global_object(), lhs, rhs); \
} \ if (result_or_error.is_error()) \
String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \ return; \
{ \ interpreter.accumulator() = result_or_error.release_value(); \
return String::formatted(#OpTitleCase " {}", m_lhs_reg); \ } \
String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
{ \
return String::formatted(#OpTitleCase " {}", m_lhs_reg); \
} }
JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP) JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP)
static Value not_(GlobalObject&, Value value) static ThrowCompletionOr<Value> not_(GlobalObject&, Value value)
{ {
return Value(!value.to_boolean()); return Value(!value.to_boolean());
} }
static Value typeof_(GlobalObject& global_object, Value value) static ThrowCompletionOr<Value> typeof_(GlobalObject& global_object, Value value)
{ {
return js_string(global_object.vm(), value.typeof()); return Value(js_string(global_object.vm(), value.typeof()));
} }
#define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \ #define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \ void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
{ \ { \
interpreter.accumulator() = op_snake_case(interpreter.global_object(), interpreter.accumulator()); \ auto result_or_error = op_snake_case(interpreter.global_object(), interpreter.accumulator()); \
} \ if (result_or_error.is_error()) \
String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \ return; \
{ \ interpreter.accumulator() = result_or_error.release_value(); \
return #OpTitleCase; \ } \
String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
{ \
return #OpTitleCase; \
} }
JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP) JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP)
@ -218,7 +224,10 @@ void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpre
void ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const void ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const
{ {
interpreter.reg(m_lhs) = add(interpreter.global_object(), interpreter.reg(m_lhs), interpreter.accumulator()); auto result_or_error = add(interpreter.global_object(), interpreter.reg(m_lhs), interpreter.accumulator());
if (result_or_error.is_error())
return;
interpreter.reg(m_lhs) = result_or_error.release_value();
} }
void GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const void GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const

View file

@ -151,7 +151,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string)
// 20.2.3.6 Function.prototype [ @@hasInstance ] ( V ), https://tc39.es/ecma262/#sec-function.prototype-@@hasinstance // 20.2.3.6 Function.prototype [ @@hasInstance ] ( V ), https://tc39.es/ecma262/#sec-function.prototype-@@hasinstance
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::symbol_has_instance) JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::symbol_has_instance)
{ {
return ordinary_has_instance(global_object, vm.argument(0), vm.this_value(global_object)); return TRY_OR_DISCARD(ordinary_has_instance(global_object, vm.argument(0), vm.this_value(global_object)));
} }
} }

View file

@ -769,64 +769,63 @@ ThrowCompletionOr<FunctionObject*> Value::get_method(GlobalObject& global_object
} }
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators // 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value greater_than(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> greater_than(GlobalObject& global_object, Value lhs, Value rhs)
{ {
TriState relation = TRY_OR_DISCARD(is_less_than(global_object, false, lhs, rhs)); TriState relation = TRY(is_less_than(global_object, false, lhs, rhs));
if (relation == TriState::Unknown) if (relation == TriState::Unknown)
return Value(false); return Value(false);
return Value(relation == TriState::True); return Value(relation == TriState::True);
} }
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators // 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value greater_than_equals(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> greater_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
{ {
TriState relation = TRY_OR_DISCARD(is_less_than(global_object, true, lhs, rhs)); TriState relation = TRY(is_less_than(global_object, true, lhs, rhs));
if (relation == TriState::Unknown || relation == TriState::True) if (relation == TriState::Unknown || relation == TriState::True)
return Value(false); return Value(false);
return Value(true); return Value(true);
} }
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators // 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value less_than(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> less_than(GlobalObject& global_object, Value lhs, Value rhs)
{ {
TriState relation = TRY_OR_DISCARD(is_less_than(global_object, true, lhs, rhs)); TriState relation = TRY(is_less_than(global_object, true, lhs, rhs));
if (relation == TriState::Unknown) if (relation == TriState::Unknown)
return Value(false); return Value(false);
return Value(relation == TriState::True); return Value(relation == TriState::True);
} }
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators // 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value less_than_equals(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> less_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
{ {
TriState relation = TRY_OR_DISCARD(is_less_than(global_object, false, lhs, rhs)); TriState relation = TRY(is_less_than(global_object, false, lhs, rhs));
if (relation == TriState::Unknown || relation == TriState::True) if (relation == TriState::Unknown || relation == TriState::True)
return Value(false); return Value(false);
return Value(true); return Value(true);
} }
// 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) ThrowCompletionOr<Value> bitwise_and(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
return Value(TRY_OR_DISCARD(lhs_numeric.to_i32(global_object)) & TRY_OR_DISCARD(rhs_numeric.to_i32(global_object))); return Value(TRY(lhs_numeric.to_i32(global_object)) & TRY(rhs_numeric.to_i32(global_object)));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise AND");
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) ThrowCompletionOr<Value> bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
@ -834,20 +833,19 @@ Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
return rhs_numeric; return rhs_numeric;
if (!rhs_numeric.is_finite_number()) if (!rhs_numeric.is_finite_number())
return lhs_numeric; return lhs_numeric;
return Value(TRY_OR_DISCARD(lhs_numeric.to_i32(global_object)) | TRY_OR_DISCARD(rhs_numeric.to_i32(global_object))); return Value(TRY(lhs_numeric.to_i32(global_object)) | TRY(rhs_numeric.to_i32(global_object)));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise OR");
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) ThrowCompletionOr<Value> bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
@ -855,56 +853,55 @@ Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
return rhs_numeric; return rhs_numeric;
if (!rhs_numeric.is_finite_number()) if (!rhs_numeric.is_finite_number())
return lhs_numeric; return lhs_numeric;
return Value(TRY_OR_DISCARD(lhs_numeric.to_i32(global_object)) ^ TRY_OR_DISCARD(rhs_numeric.to_i32(global_object))); return Value(TRY(lhs_numeric.to_i32(global_object)) ^ TRY(rhs_numeric.to_i32(global_object)));
} }
if (both_bigint(lhs_numeric, rhs_numeric)) if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise XOR");
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) ThrowCompletionOr<Value> bitwise_not(GlobalObject& global_object, Value lhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
if (lhs_numeric.is_number()) if (lhs_numeric.is_number())
return Value(~TRY_OR_DISCARD(lhs_numeric.to_i32(global_object))); return Value(~TRY(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(vm, big_integer_bitwise_not); return Value(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
Value unary_plus(GlobalObject& global_object, Value lhs) ThrowCompletionOr<Value> unary_plus(GlobalObject& global_object, Value lhs)
{ {
return TRY_OR_DISCARD(lhs.to_number(global_object)); return TRY(lhs.to_number(global_object));
} }
// 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) ThrowCompletionOr<Value> unary_minus(GlobalObject& global_object, Value lhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
if (lhs_numeric.is_number()) { if (lhs_numeric.is_number()) {
if (lhs_numeric.is_nan()) if (lhs_numeric.is_nan())
return js_nan(); return js_nan();
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(vm, BIGINT_ZERO); return Value(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(vm, big_integer_negated); return Value(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) ThrowCompletionOr<Value> left_shift(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
@ -918,20 +915,19 @@ 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(vm, lhs_numeric.as_bigint().big_integer().divided_by(multiplier_divisor).quotient); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().divided_by(multiplier_divisor).quotient));
else else
return js_bigint(vm, lhs_numeric.as_bigint().big_integer().multiplied_by(multiplier_divisor)); return Value(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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "left-shift");
return {};
} }
// 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) ThrowCompletionOr<Value> right_shift(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
@ -946,15 +942,15 @@ Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
rhs_negated.negate(); rhs_negated.negate();
return left_shift(global_object, lhs, js_bigint(vm, 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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "right-shift");
return {};
} }
// 13.9.3 The Unsigned Right Shift Operator ( >>> ), https://tc39.es/ecma262/#sec-unsigned-right-shift-operator // 13.9.3 The Unsigned Right Shift Operator ( >>> ), https://tc39.es/ecma262/#sec-unsigned-right-shift-operator
Value unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto& vm = global_object.vm();
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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())
return Value(0); return Value(0);
@ -965,12 +961,11 @@ Value unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs)
auto rhs_u32 = MUST(rhs_numeric.to_u32(global_object)) % 32; auto rhs_u32 = MUST(rhs_numeric.to_u32(global_object)) % 32;
return Value(lhs_u32 >> rhs_u32); return Value(lhs_u32 >> rhs_u32);
} }
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperator, "unsigned right-shift"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperator, "unsigned right-shift");
return {};
} }
// 13.8.1 The Addition Operator ( + ), https://tc39.es/ecma262/#sec-addition-operator-plus // 13.8.1 The Addition Operator ( + ), https://tc39.es/ecma262/#sec-addition-operator-plus
Value add(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> add(GlobalObject& global_object, Value lhs, Value rhs)
{ {
if (both_number(lhs, rhs)) { if (both_number(lhs, rhs)) {
if (lhs.type() == Value::Type::Int32 && rhs.type() == Value::Type::Int32) { if (lhs.type() == Value::Type::Int32 && rhs.type() == Value::Type::Int32) {
@ -983,8 +978,8 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
return Value(lhs.as_double() + rhs.as_double()); return Value(lhs.as_double() + rhs.as_double());
} }
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_primitive = TRY_OR_DISCARD(lhs.to_primitive(global_object)); auto lhs_primitive = TRY(lhs.to_primitive(global_object));
auto rhs_primitive = TRY_OR_DISCARD(rhs.to_primitive(global_object)); auto rhs_primitive = TRY(rhs.to_primitive(global_object));
if (lhs_primitive.is_string() && rhs_primitive.is_string()) { if (lhs_primitive.is_string() && rhs_primitive.is_string()) {
auto const& lhs_string = lhs_primitive.as_string(); auto const& lhs_string = lhs_primitive.as_string();
@ -998,81 +993,75 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
combined.ensure_capacity(lhs_utf16_string.length_in_code_units() + rhs_utf16_string.length_in_code_units()); combined.ensure_capacity(lhs_utf16_string.length_in_code_units() + rhs_utf16_string.length_in_code_units());
combined.extend(lhs_utf16_string.string()); combined.extend(lhs_utf16_string.string());
combined.extend(rhs_utf16_string.string()); combined.extend(rhs_utf16_string.string());
return js_string(vm.heap(), Utf16String(move(combined))); return Value(js_string(vm.heap(), Utf16String(move(combined))));
} }
} }
if (lhs_primitive.is_string() || rhs_primitive.is_string()) { if (lhs_primitive.is_string() || rhs_primitive.is_string()) {
auto lhs_string = TRY_OR_DISCARD(lhs_primitive.to_string(global_object)); auto lhs_string = TRY(lhs_primitive.to_string(global_object));
auto rhs_string = TRY_OR_DISCARD(rhs_primitive.to_string(global_object)); auto rhs_string = TRY(rhs_primitive.to_string(global_object));
StringBuilder builder(lhs_string.length() + rhs_string.length()); StringBuilder builder(lhs_string.length() + rhs_string.length());
builder.append(lhs_string); builder.append(lhs_string);
builder.append(rhs_string); builder.append(rhs_string);
return js_string(vm, builder.to_string()); return Value(js_string(vm, builder.to_string()));
} }
auto lhs_numeric = TRY_OR_DISCARD(lhs_primitive.to_numeric(global_object)); auto lhs_numeric = TRY(lhs_primitive.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs_primitive.to_numeric(global_object)); auto rhs_numeric = TRY(rhs_primitive.to_numeric(global_object));
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, lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer())); return Value(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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "addition");
return {};
} }
// 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) ThrowCompletionOr<Value> sub(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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, lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "subtraction"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "subtraction");
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) ThrowCompletionOr<Value> mul(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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, lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())); return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "multiplication"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "multiplication");
return {};
} }
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators // 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value div(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> div(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
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)) {
if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) { if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO)
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); return vm.throw_completion<RangeError>(global_object, ErrorType::DivisionByZero);
return {}; return Value(js_bigint(vm, 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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "division");
return {};
} }
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators // 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value mod(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> mod(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
// 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder // 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder
@ -1107,67 +1096,55 @@ Value mod(GlobalObject& global_object, Value lhs, Value rhs)
return Value(index - trunc * period); return Value(index - trunc * period);
} }
if (both_bigint(lhs_numeric, rhs_numeric)) { if (both_bigint(lhs_numeric, rhs_numeric)) {
if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) { if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO)
vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); return vm.throw_completion<RangeError>(global_object, ErrorType::DivisionByZero);
return {}; return Value(js_bigint(vm, 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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "modulo");
return {};
} }
// 13.6 Exponentiation Operator, https://tc39.es/ecma262/#sec-exp-operator // 13.6 Exponentiation Operator, https://tc39.es/ecma262/#sec-exp-operator
Value exp(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> exp(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto lhs_numeric = TRY_OR_DISCARD(lhs.to_numeric(global_object)); auto lhs_numeric = TRY(lhs.to_numeric(global_object));
auto rhs_numeric = TRY_OR_DISCARD(rhs.to_numeric(global_object)); auto rhs_numeric = TRY(rhs.to_numeric(global_object));
if (both_number(lhs_numeric, rhs_numeric)) if (both_number(lhs_numeric, rhs_numeric))
return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double())); 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()) { if (rhs_numeric.as_bigint().big_integer().is_negative())
vm.throw_exception<RangeError>(global_object, ErrorType::NegativeExponent); return vm.throw_completion<RangeError>(global_object, ErrorType::NegativeExponent);
return {}; return Value(js_bigint(vm, 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"); return vm.throw_completion<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation");
return {};
} }
Value in(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> in(GlobalObject& global_object, Value lhs, Value rhs)
{ {
if (!rhs.is_object()) { if (!rhs.is_object())
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::InOperatorWithObject); return global_object.vm().throw_completion<TypeError>(global_object, ErrorType::InOperatorWithObject);
return {}; auto lhs_property_key = TRY(lhs.to_property_key(global_object));
} return Value(TRY(rhs.as_object().has_property(lhs_property_key)));
auto lhs_property_key = TRY_OR_DISCARD(lhs.to_property_key(global_object));
return Value(TRY_OR_DISCARD(rhs.as_object().has_property(lhs_property_key)));
} }
// 13.10.2 InstanceofOperator ( V, target ), https://tc39.es/ecma262/#sec-instanceofoperator // 13.10.2 InstanceofOperator ( V, target ), https://tc39.es/ecma262/#sec-instanceofoperator
Value instance_of(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> instance_of(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
if (!rhs.is_object()) { if (!rhs.is_object())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, rhs.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, rhs.to_string_without_side_effects());
return {}; auto has_instance_method = TRY(rhs.get_method(global_object, *vm.well_known_symbol_has_instance()));
}
auto has_instance_method = TRY_OR_DISCARD(rhs.get_method(global_object, *vm.well_known_symbol_has_instance()));
if (has_instance_method) { if (has_instance_method) {
auto has_instance_result = TRY_OR_DISCARD(vm.call(*has_instance_method, rhs, lhs)); auto has_instance_result = TRY(vm.call(*has_instance_method, rhs, lhs));
return Value(has_instance_result.to_boolean()); return Value(has_instance_result.to_boolean());
} }
if (!rhs.is_function()) { if (!rhs.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, rhs.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, rhs.to_string_without_side_effects());
return {}; return TRY(ordinary_has_instance(global_object, lhs, rhs));
}
return ordinary_has_instance(global_object, lhs, rhs);
} }
// 7.3.21 OrdinaryHasInstance ( C, O ), https://tc39.es/ecma262/#sec-ordinaryhasinstance // 7.3.21 OrdinaryHasInstance ( C, O ), https://tc39.es/ecma262/#sec-ordinaryhasinstance
Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs) ThrowCompletionOr<Value> ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
if (!rhs.is_function()) if (!rhs.is_function())
@ -1183,13 +1160,11 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
return Value(false); return Value(false);
Object* lhs_object = &lhs.as_object(); Object* lhs_object = &lhs.as_object();
auto rhs_prototype = TRY_OR_DISCARD(rhs_function.get(vm.names.prototype)); auto rhs_prototype = TRY(rhs_function.get(vm.names.prototype));
if (!rhs_prototype.is_object()) { if (!rhs_prototype.is_object())
vm.throw_exception<TypeError>(global_object, ErrorType::InstanceOfOperatorBadPrototype, rhs.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::InstanceOfOperatorBadPrototype, rhs.to_string_without_side_effects());
return {};
}
while (true) { while (true) {
lhs_object = TRY_OR_DISCARD(lhs_object->internal_get_prototype_of()); lhs_object = TRY(lhs_object->internal_get_prototype_of());
if (!lhs_object) if (!lhs_object)
return Value(false); return Value(false);
if (same_value(rhs_prototype, lhs_object)) if (same_value(rhs_prototype, lhs_object))

View file

@ -399,28 +399,28 @@ inline void Cell::Visitor::visit(Value value)
visit_impl(value.as_cell()); visit_impl(value.as_cell());
} }
Value greater_than(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> greater_than(GlobalObject&, Value lhs, Value rhs);
Value greater_than_equals(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> greater_than_equals(GlobalObject&, Value lhs, Value rhs);
Value less_than(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> less_than(GlobalObject&, Value lhs, Value rhs);
Value less_than_equals(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> less_than_equals(GlobalObject&, Value lhs, Value rhs);
Value bitwise_and(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> bitwise_and(GlobalObject&, Value lhs, Value rhs);
Value bitwise_or(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> bitwise_or(GlobalObject&, Value lhs, Value rhs);
Value bitwise_xor(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> bitwise_xor(GlobalObject&, Value lhs, Value rhs);
Value bitwise_not(GlobalObject&, Value); ThrowCompletionOr<Value> bitwise_not(GlobalObject&, Value);
Value unary_plus(GlobalObject&, Value); ThrowCompletionOr<Value> unary_plus(GlobalObject&, Value);
Value unary_minus(GlobalObject&, Value); ThrowCompletionOr<Value> unary_minus(GlobalObject&, Value);
Value left_shift(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> left_shift(GlobalObject&, Value lhs, Value rhs);
Value right_shift(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> right_shift(GlobalObject&, Value lhs, Value rhs);
Value unsigned_right_shift(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> unsigned_right_shift(GlobalObject&, Value lhs, Value rhs);
Value add(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> add(GlobalObject&, Value lhs, Value rhs);
Value sub(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> sub(GlobalObject&, Value lhs, Value rhs);
Value mul(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> mul(GlobalObject&, Value lhs, Value rhs);
Value div(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> div(GlobalObject&, Value lhs, Value rhs);
Value mod(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> mod(GlobalObject&, Value lhs, Value rhs);
Value exp(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> exp(GlobalObject&, Value lhs, Value rhs);
Value in(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> in(GlobalObject&, Value lhs, Value rhs);
Value instance_of(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> instance_of(GlobalObject&, Value lhs, Value rhs);
Value ordinary_has_instance(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<Value> ordinary_has_instance(GlobalObject&, Value lhs, Value rhs);
ThrowCompletionOr<bool> is_loosely_equal(GlobalObject&, Value lhs, Value rhs); ThrowCompletionOr<bool> is_loosely_equal(GlobalObject&, Value lhs, Value rhs);
bool is_strictly_equal(Value lhs, Value rhs); bool is_strictly_equal(Value lhs, Value rhs);