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

LibJS: Convert Value::invoke and VM::call to ThrowCompletionOr

This commit is contained in:
Idan Horowitz 2021-09-23 20:56:28 +03:00
parent a90107b02a
commit ab594e5f2f
35 changed files with 196 additions and 328 deletions

View file

@ -399,8 +399,9 @@ RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook)
break; break;
case Cell::Formula: { case Cell::Formula: {
auto& interpreter = sheet->interpreter(); auto& interpreter = sheet->interpreter();
auto value = interpreter.vm().call(parse_function, json, JS::js_string(interpreter.heap(), obj.get("value").as_string())); auto value_or_error = interpreter.vm().call(parse_function, json, JS::js_string(interpreter.heap(), obj.get("value").as_string()));
cell = make<Cell>(obj.get("source").to_string(), move(value), position, *sheet); VERIFY(!value_or_error.is_error());
cell = make<Cell>(obj.get("source").to_string(), value_or_error.release_value(), position, *sheet);
break; break;
} }
} }
@ -526,8 +527,9 @@ JsonObject Sheet::to_json() const
if (it.value->kind() == Cell::Formula) { if (it.value->kind() == Cell::Formula) {
data.set("source", it.value->data()); data.set("source", it.value->data());
auto json = interpreter().global_object().get("JSON"); auto json = interpreter().global_object().get("JSON");
auto stringified = interpreter().vm().call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data()); auto stringified_or_error = interpreter().vm().call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data());
data.set("value", stringified.to_string_without_side_effects()); VERIFY(!stringified_or_error.is_error());
data.set("value", stringified_or_error.release_value().to_string_without_side_effects());
} else { } else {
data.set("value", it.value->data()); data.set("value", it.value->data());
} }

View file

@ -246,7 +246,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
return TRY_OR_DISCARD(perform_eval(script_value, global_object, vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct)); return TRY_OR_DISCARD(perform_eval(script_value, global_object, vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct));
} }
return vm.call(function, this_value, move(arg_list)); return TRY_OR_DISCARD(vm.call(function, this_value, move(arg_list)));
} }
// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
@ -976,11 +976,8 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
if (field.is_static()) { if (field.is_static()) {
Value field_value = js_undefined(); Value field_value = js_undefined();
if (initializer) { if (initializer)
field_value = interpreter.vm().call(*initializer, class_constructor_value); field_value = TRY_OR_DISCARD(interpreter.vm().call(*initializer, class_constructor_value));
if (interpreter.exception())
return {};
}
class_constructor->create_data_property_or_throw(property_key, field_value); class_constructor->create_data_property_or_throw(property_key, field_value);
if (interpreter.exception()) if (interpreter.exception())
@ -2280,7 +2277,7 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& glo
raw_strings->indexed_properties().append(value); raw_strings->indexed_properties().append(value);
} }
strings->define_direct_property(vm.names.raw, raw_strings, 0); strings->define_direct_property(vm.names.raw, raw_strings, 0);
return vm.call(tag_function, js_undefined(), move(arguments)); return TRY_OR_DISCARD(vm.call(tag_function, js_undefined(), move(arguments)));
} }
void TryStatement::dump(int indent) const void TryStatement::dump(int indent) const

View file

@ -295,16 +295,21 @@ void Call::execute_impl(Bytecode::Interpreter& interpreter) const
Value return_value; Value return_value;
if (m_argument_count == 0 && m_type == CallType::Call) { if (m_argument_count == 0 && m_type == CallType::Call) {
return_value = interpreter.vm().call(function, this_value); auto return_value_or_error = interpreter.vm().call(function, this_value);
if (!return_value_or_error.is_error())
return_value = return_value_or_error.release_value();
} else { } else {
MarkedValueList argument_values { interpreter.vm().heap() }; MarkedValueList argument_values { interpreter.vm().heap() };
for (size_t i = 0; i < m_argument_count; ++i) { for (size_t i = 0; i < m_argument_count; ++i) {
argument_values.append(interpreter.reg(m_arguments[i])); argument_values.append(interpreter.reg(m_arguments[i]));
} }
if (m_type == CallType::Call) if (m_type == CallType::Call) {
return_value = interpreter.vm().call(function, this_value, move(argument_values)); auto return_value_or_error = interpreter.vm().call(function, this_value, move(argument_values));
else if (!return_value_or_error.is_error())
return_value = return_value_or_error.release_value();
} else {
return_value = interpreter.vm().construct(function, function, move(argument_values)); return_value = interpreter.vm().construct(function, function, move(argument_values));
}
} }
interpreter.accumulator() = return_value; interpreter.accumulator() = return_value;

View file

@ -35,7 +35,7 @@ public:
{ {
if (!m_getter) if (!m_getter)
return js_undefined(); return js_undefined();
return vm().call(*m_getter, this_value); return TRY_OR_DISCARD(vm().call(*m_getter, this_value));
} }
void call_setter(Value this_value, Value setter_value) void call_setter(Value this_value, Value setter_value)

View file

@ -151,7 +151,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
Value mapped_value; Value mapped_value;
if (map_fn) { if (map_fn) {
mapped_value = vm.call(*map_fn, this_arg, next_value, Value(k)); mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, next_value, Value(k)));
if (vm.exception()) { if (vm.exception()) {
iterator_close(*iterator); iterator_close(*iterator);
return {}; return {};
@ -192,13 +192,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
for (size_t k = 0; k < length; ++k) { for (size_t k = 0; k < length; ++k) {
auto k_value = array_like->get(k); auto k_value = array_like->get(k);
Value mapped_value; Value mapped_value;
if (map_fn) { if (map_fn)
mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k)));
if (vm.exception()) else
return {};
} else {
mapped_value = k_value; mapped_value = k_value;
}
array_object.create_data_property_or_throw(k, mapped_value); array_object.create_data_property_or_throw(k, mapped_value);
} }

View file

@ -206,12 +206,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
return {}; return {};
// ii. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)). // ii. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto selected = vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object); auto selected = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
if (vm.exception())
return {};
// iii. If selected is true, then // iii. If selected is true, then
if (selected.to_boolean()) { if (selected) {
// 1. Perform ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(to)), kValue). // 1. Perform ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(to)), kValue).
array->create_data_property_or_throw(to, k_value); array->create_data_property_or_throw(to, k_value);
@ -322,9 +320,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map)
return {}; return {};
// ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »). // ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object); auto mapped_value = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object));
if (vm.exception())
return {};
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
array->create_data_property_or_throw(property_name, mapped_value); array->create_data_property_or_throw(property_name, mapped_value);
@ -495,7 +491,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
return {}; return {};
if (!join_function.is_function()) if (!join_function.is_function())
return ObjectPrototype::to_string(vm, global_object); return ObjectPrototype::to_string(vm, global_object);
return vm.call(join_function.as_function(), this_object); return TRY_OR_DISCARD(vm.call(join_function.as_function(), this_object));
} }
// 23.1.3.29 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-array.prototype.tolocalestring // 23.1.3.29 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-array.prototype.tolocalestring
@ -524,9 +520,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
return {}; return {};
if (value.is_nullish()) if (value.is_nullish())
continue; continue;
auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString); auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
if (vm.exception())
return {};
auto string = locale_string_result.to_string(global_object); auto string = locale_string_result.to_string(global_object);
if (vm.exception()) if (vm.exception())
return {}; return {};
@ -912,9 +906,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
return {}; return {};
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »). // ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value(k), object); accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value(k), object));
if (vm.exception())
return {};
} }
// d. Set k to k + 1. // d. Set k to k + 1.
@ -1012,9 +1004,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
return {}; return {};
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »). // ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value((size_t)k), object); accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value((size_t)k), object));
if (vm.exception())
return {};
} }
// d. Set k to k - 1. // d. Set k to k - 1.
@ -1128,9 +1118,10 @@ static void array_merge_sort(VM& vm, GlobalObject& global_object, FunctionObject
} else if (y.is_undefined()) { } else if (y.is_undefined()) {
comparison_result = -1; comparison_result = -1;
} else if (compare_func) { } else if (compare_func) {
auto call_result = vm.call(*compare_func, js_undefined(), left[left_index], right[right_index]); auto call_result_or_error = vm.call(*compare_func, js_undefined(), left[left_index], right[right_index]);
if (vm.exception()) if (call_result_or_error.is_error())
return; return;
auto call_result = call_result_or_error.release_value();
auto number = call_result.to_number(global_object); auto number = call_result.to_number(global_object);
if (vm.exception()) if (vm.exception())
@ -1393,12 +1384,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find)
return {}; return {};
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)). // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(predicate.as_function(), this_arg, k_value, Value(k), object); auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
if (vm.exception())
return {};
// d. If testResult is true, return kValue. // d. If testResult is true, return kValue.
if (test_result.to_boolean()) if (test_result)
return k_value; return k_value;
// e. Set k to k + 1. // e. Set k to k + 1.
@ -1440,12 +1429,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
return {}; return {};
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)). // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(predicate.as_function(), this_arg, k_value, Value(k), object); auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
if (vm.exception())
return {};
// d. If testResult is true, return 𝔽(k). // d. If testResult is true, return 𝔽(k).
if (test_result.to_boolean()) if (test_result)
return Value(k); return Value(k);
// e. Set k to k + 1. // e. Set k to k + 1.
@ -1487,12 +1474,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last)
return {}; return {};
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)). // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object); auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
if (vm.exception())
return {};
// d. If testResult is true, return kValue. // d. If testResult is true, return kValue.
if (test_result.to_boolean()) if (test_result)
return k_value; return k_value;
// e. Set k to k - 1. // e. Set k to k - 1.
@ -1534,12 +1519,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last_index)
return {}; return {};
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)). // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object); auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
if (vm.exception())
return {};
// d. If testResult is true, return 𝔽(k). // d. If testResult is true, return 𝔽(k).
if (test_result.to_boolean()) if (test_result)
return Value((double)k); return Value((double)k);
// e. Set k to k - 1. // e. Set k to k - 1.
@ -1588,12 +1571,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
return {}; return {};
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)). // ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object); auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
if (vm.exception())
return {};
// iii. If testResult is true, return true. // iii. If testResult is true, return true.
if (test_result.to_boolean()) if (test_result)
return Value(true); return Value(true);
} }
@ -1643,12 +1624,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
return {}; return {};
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)). // ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object); auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
if (vm.exception())
return {};
// iii. If testResult is false, return false. // iii. If testResult is false, return false.
if (!test_result.to_boolean()) if (!test_result)
return Value(false); return Value(false);
} }
@ -1887,11 +1866,8 @@ static size_t flatten_into_array(GlobalObject& global_object, Object& new_array,
if (vm.exception()) if (vm.exception())
return {}; return {};
if (mapper_func) { if (mapper_func)
value = vm.call(*mapper_func, this_arg, value, Value(j), &array); value = TRY_OR_DISCARD(vm.call(*mapper_func, this_arg, value, Value(j), &array));
if (vm.exception())
return {};
}
if (depth > 0 && TRY_OR_DISCARD(value.is_array(global_object))) { if (depth > 0 && TRY_OR_DISCARD(value.is_array(global_object))) {
if (vm.did_reach_stack_space_limit()) { if (vm.did_reach_stack_space_limit()) {

View file

@ -842,7 +842,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_json)
if (time_value.is_number() && !time_value.is_finite_number()) if (time_value.is_number() && !time_value.is_finite_number())
return js_null(); return js_null();
return this_value.invoke(global_object, vm.names.toISOString); return TRY_OR_DISCARD(this_value.invoke(global_object, vm.names.toISOString));
} }
// 14.1.1 Date.prototype.toTemporalInstant ( ), https://tc39.es/proposal-temporal/#sec-date.prototype.totemporalinstant // 14.1.1 Date.prototype.toTemporalInstant ( ), https://tc39.es/proposal-temporal/#sec-date.prototype.totemporalinstant

View file

@ -76,9 +76,10 @@ void FunctionObject::InstanceField::define_field(VM& vm, Object& receiver) const
{ {
Value init_value = js_undefined(); Value init_value = js_undefined();
if (initializer) { if (initializer) {
init_value = vm.call(*initializer, receiver.value_of()); auto init_value_or_error = vm.call(*initializer, receiver.value_of());
if (vm.exception()) if (init_value_or_error.is_error())
return; return;
init_value = init_value_or_error.release_value();
} }
receiver.create_data_property_or_throw(name, init_value); receiver.create_data_property_or_throw(name, init_value);
} }

View file

@ -56,9 +56,9 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
auto this_arg = vm.argument(0); auto this_arg = vm.argument(0);
auto arg_array = vm.argument(1); auto arg_array = vm.argument(1);
if (arg_array.is_nullish()) if (arg_array.is_nullish())
return vm.call(function, this_arg); return TRY_OR_DISCARD(vm.call(function, this_arg));
auto arguments = TRY_OR_DISCARD(create_list_from_array_like(global_object, arg_array)); auto arguments = TRY_OR_DISCARD(create_list_from_array_like(global_object, arg_array));
return vm.call(function, this_arg, move(arguments)); return TRY_OR_DISCARD(vm.call(function, this_arg, move(arguments)));
} }
// 20.2.3.2 Function.prototype.bind ( thisArg, ...args ), https://tc39.es/ecma262/#sec-function.prototype.bind // 20.2.3.2 Function.prototype.bind ( thisArg, ...args ), https://tc39.es/ecma262/#sec-function.prototype.bind
@ -100,7 +100,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call)
for (size_t i = 1; i < vm.argument_count(); ++i) for (size_t i = 1; i < vm.argument_count(); ++i)
arguments.append(vm.argument(i)); arguments.append(vm.argument(i));
} }
return vm.call(function, this_arg, move(arguments)); return TRY_OR_DISCARD(vm.call(function, this_arg, move(arguments)));
} }
// 20.2.3.5 Function.prototype.toString ( ), https://tc39.es/ecma262/#sec-function.prototype.tostring // 20.2.3.5 Function.prototype.toString ( ), https://tc39.es/ecma262/#sec-function.prototype.tostring

View file

@ -160,7 +160,7 @@ template<>
inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); } inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); }
template<typename... Args> template<typename... Args>
[[nodiscard]] ALWAYS_INLINE Value Value::invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args) [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> Value::invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args)
{ {
if constexpr (sizeof...(Args) > 0) { if constexpr (sizeof...(Args) > 0) {
MarkedValueList arglist { global_object.vm().heap() }; MarkedValueList arglist { global_object.vm().heap() };

View file

@ -29,9 +29,7 @@ Object* get_iterator(GlobalObject& global_object, Value value, IteratorHint hint
vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects()); vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects());
return nullptr; return nullptr;
} }
auto iterator = vm.call(method.as_function(), value); auto iterator = TRY_OR_DISCARD(vm.call(method.as_function(), value));
if (vm.exception())
return {};
if (!iterator.is_object()) { if (!iterator.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects()); vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects());
return nullptr; return nullptr;
@ -56,12 +54,10 @@ Object* iterator_next(Object& iterator, Value value)
Value result; Value result;
if (value.is_empty()) if (value.is_empty())
result = vm.call(next_method.as_function(), &iterator); result = TRY_OR_DISCARD(vm.call(next_method.as_function(), &iterator));
else else
result = vm.call(next_method.as_function(), &iterator, value); result = TRY_OR_DISCARD(vm.call(next_method.as_function(), &iterator, value));
if (vm.exception())
return {};
if (!result.is_object()) { if (!result.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::IterableNextBadReturn); vm.throw_exception<TypeError>(global_object, ErrorType::IterableNextBadReturn);
return nullptr; return nullptr;
@ -132,11 +128,12 @@ void iterator_close(Object& iterator)
if (!return_method) if (!return_method)
return restore_completion(); // If return is undefined, return Completion(completion). return restore_completion(); // If return is undefined, return Completion(completion).
auto result = vm.call(*return_method, &iterator); auto result_or_error = vm.call(*return_method, &iterator);
if (completion_exception) if (completion_exception)
return restore_completion(); // If completion.[[Type]] is throw, return Completion(completion). return restore_completion(); // If completion.[[Type]] is throw, return Completion(completion).
if (vm.exception()) if (result_or_error.is_error())
return; // If innerResult.[[Type]] is throw, return Completion(innerResult). return; // If innerResult.[[Type]] is throw, return Completion(innerResult).
auto result = result_or_error.release_value();
if (!result.is_object()) { if (!result.is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::IterableReturnBadReturn); vm.throw_exception<TypeError>(global_object, ErrorType::IterableReturnBadReturn);
return; // If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. return; // If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.

View file

@ -152,18 +152,12 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif
auto to_json = value_object->get(vm.names.toJSON); auto to_json = value_object->get(vm.names.toJSON);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (to_json.is_function()) { if (to_json.is_function())
value = vm.call(to_json.as_function(), value, js_string(vm, key.to_string())); value = TRY_OR_DISCARD(vm.call(to_json.as_function(), value, js_string(vm, key.to_string())));
if (vm.exception())
return {};
}
} }
if (state.replacer_function) { if (state.replacer_function)
value = vm.call(*state.replacer_function, holder, js_string(vm, key.to_string()), value); value = TRY_OR_DISCARD(vm.call(*state.replacer_function, holder, js_string(vm, key.to_string()), value));
if (vm.exception())
return {};
}
if (value.is_object()) { if (value.is_object()) {
auto& value_object = value.as_object(); auto& value_object = value.as_object();
@ -507,7 +501,7 @@ Value JSONObject::internalize_json_property(GlobalObject& global_object, Object*
} }
} }
return vm.call(reviver, Value(holder), js_string(vm, name.to_string()), value); return TRY_OR_DISCARD(vm.call(reviver, Value(holder), js_string(vm, name.to_string()), value));
} }
} }

View file

@ -28,7 +28,7 @@ template<typename... Args>
{ {
VERIFY(job_callback.callback); VERIFY(job_callback.callback);
auto& callback = *job_callback.callback; auto& callback = *job_callback.callback;
return vm.call(callback, this_value, args...); return TRY_OR_DISCARD(vm.call(callback, this_value, args...));
} }
} }

View file

@ -703,7 +703,7 @@ Value Object::internal_get(PropertyName const& property_name, Value receiver) co
return js_undefined(); return js_undefined();
// 8. Return ? Call(getter, Receiver). // 8. Return ? Call(getter, Receiver).
return vm.call(*getter, receiver); return TRY_OR_DISCARD(vm.call(*getter, receiver));
} }
static bool ordinary_set_with_own_descriptor(Object&, PropertyName const&, Value, Value, Optional<PropertyDescriptor>); static bool ordinary_set_with_own_descriptor(Object&, PropertyName const&, Value, Value, Optional<PropertyDescriptor>);
@ -1199,7 +1199,7 @@ Value Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
if (vm.exception()) if (vm.exception())
return {}; return {};
if (method.is_function()) { if (method.is_function()) {
auto result = vm.call(method.as_function(), const_cast<Object*>(this)); auto result = TRY_OR_DISCARD(vm.call(method.as_function(), const_cast<Object*>(this)));
if (!result.is_object()) if (!result.is_object())
return result; return result;
} }

View file

@ -144,7 +144,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string) JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
{ {
auto this_value = vm.this_value(global_object); auto this_value = vm.this_value(global_object);
return this_value.invoke(global_object, vm.names.toString); return TRY_OR_DISCARD(this_value.invoke(global_object, vm.names.toString));
} }
// 20.1.3.7 Object.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-object.prototype.valueof // 20.1.3.7 Object.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-object.prototype.valueof

View file

@ -32,9 +32,7 @@ Object* promise_resolve(GlobalObject& global_object, Object& constructor, Value
auto promise_capability = new_promise_capability(global_object, &constructor); auto promise_capability = new_promise_capability(global_object, &constructor);
if (vm.exception()) if (vm.exception())
return nullptr; return nullptr;
[[maybe_unused]] auto result = vm.call(*promise_capability.resolve, js_undefined(), value); [[maybe_unused]] auto result = TRY_OR_DISCARD(vm.call(*promise_capability.resolve, js_undefined(), value));
if (vm.exception())
return nullptr;
return promise_capability.promise; return promise_capability.promise;
} }

View file

@ -113,9 +113,7 @@ static Value perform_promise_common(GlobalObject& global_object, Object& iterato
values->values().append(js_undefined()); values->values().append(js_undefined());
auto next_promise = vm.call(promise_resolve.as_function(), constructor, next_value); auto next_promise = TRY_OR_DISCARD(vm.call(promise_resolve.as_function(), constructor, next_value));
if (vm.exception())
return {};
++remaining_elements_count->value; ++remaining_elements_count->value;
@ -410,7 +408,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::reject)
if (vm.exception()) if (vm.exception())
return {}; return {};
auto reason = vm.argument(0); auto reason = vm.argument(0);
[[maybe_unused]] auto result = vm.call(*promise_capability.reject, js_undefined(), reason); [[maybe_unused]] auto result = TRY_OR_DISCARD(vm.call(*promise_capability.reject, js_undefined(), reason));
return promise_capability.promise; return promise_capability.promise;
} }

View file

@ -62,11 +62,11 @@ Value PromiseReactionJob::call()
vm.stop_unwind(); vm.stop_unwind();
auto* reject_function = promise_capability.value().reject; auto* reject_function = promise_capability.value().reject;
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's reject function @ {}", this, reject_function); dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's reject function @ {}", this, reject_function);
return vm.call(*reject_function, js_undefined(), handler_result); return TRY_OR_DISCARD(vm.call(*reject_function, js_undefined(), handler_result));
} else { } else {
auto* resolve_function = promise_capability.value().resolve; auto* resolve_function = promise_capability.value().resolve;
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's resolve function @ {}", this, resolve_function); dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob @ {}]: Calling PromiseCapability's resolve function @ {}", this, resolve_function);
return vm.call(*resolve_function, js_undefined(), handler_result); return TRY_OR_DISCARD(vm.call(*resolve_function, js_undefined(), handler_result));
} }
} }

View file

@ -55,7 +55,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::catch_)
{ {
auto this_value = vm.this_value(global_object); auto this_value = vm.this_value(global_object);
auto on_rejected = vm.argument(0); auto on_rejected = vm.argument(0);
return this_value.invoke(global_object, vm.names.then, js_undefined(), on_rejected); return TRY_OR_DISCARD(this_value.invoke(global_object, vm.names.then, js_undefined(), on_rejected));
} }
// 27.2.5.3 Promise.prototype.finally ( onFinally ), https://tc39.es/ecma262/#sec-promise.prototype.finally // 27.2.5.3 Promise.prototype.finally ( onFinally ), https://tc39.es/ecma262/#sec-promise.prototype.finally
@ -77,16 +77,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell()); auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell());
auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell()); auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell());
auto value = vm.argument(0); auto value = vm.argument(0);
auto result = vm.call(on_finally, js_undefined()); auto result = TRY_OR_DISCARD(vm.call(on_finally, js_undefined()));
if (vm.exception())
return {};
auto* promise = promise_resolve(global_object, constructor, result); auto* promise = promise_resolve(global_object, constructor, result);
if (vm.exception()) if (vm.exception())
return {}; return {};
auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> Value { auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> Value {
return value; return value;
}); });
return Value(promise).invoke(global_object, vm.names.then, value_thunk); return TRY_OR_DISCARD(Value(promise).invoke(global_object, vm.names.then, value_thunk));
}); });
then_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable); then_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
@ -95,9 +93,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell()); auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell());
auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell()); auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell());
auto reason = vm.argument(0); auto reason = vm.argument(0);
auto result = vm.call(on_finally, js_undefined()); auto result = TRY_OR_DISCARD(vm.call(on_finally, js_undefined()));
if (vm.exception())
return {};
auto* promise = promise_resolve(global_object, constructor, result); auto* promise = promise_resolve(global_object, constructor, result);
if (vm.exception()) if (vm.exception())
return {}; return {};
@ -105,14 +101,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
vm.throw_exception(global_object, reason); vm.throw_exception(global_object, reason);
return {}; return {};
}); });
return Value(promise).invoke(global_object, vm.names.then, thrower); return TRY_OR_DISCARD(Value(promise).invoke(global_object, vm.names.then, thrower));
}); });
catch_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable); catch_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
then_finally = Value(then_finally_function); then_finally = Value(then_finally_function);
catch_finally = Value(catch_finally_function); catch_finally = Value(catch_finally_function);
} }
return Value(promise).invoke(global_object, vm.names.then, then_finally, catch_finally); return TRY_OR_DISCARD(Value(promise).invoke(global_object, vm.names.then, then_finally, catch_finally));
} }
} }

View file

@ -67,7 +67,7 @@ Value PromiseAllResolveElementFunction::resolve_element()
if (--m_remaining_elements.value == 0) { if (--m_remaining_elements.value == 0) {
auto values_array = Array::create_from(global_object, m_values.values()); auto values_array = Array::create_from(global_object, m_values.values());
return vm.call(*m_capability.resolve, js_undefined(), values_array); return TRY_OR_DISCARD(vm.call(*m_capability.resolve, js_undefined(), values_array));
} }
return js_undefined(); return js_undefined();
@ -96,7 +96,7 @@ Value PromiseAllSettledResolveElementFunction::resolve_element()
if (--m_remaining_elements.value == 0) { if (--m_remaining_elements.value == 0) {
auto values_array = Array::create_from(global_object, m_values.values()); auto values_array = Array::create_from(global_object, m_values.values());
return vm.call(*m_capability.resolve, js_undefined(), values_array); return TRY_OR_DISCARD(vm.call(*m_capability.resolve, js_undefined(), values_array));
} }
return js_undefined(); return js_undefined();
@ -125,7 +125,7 @@ Value PromiseAllSettledRejectElementFunction::resolve_element()
if (--m_remaining_elements.value == 0) { if (--m_remaining_elements.value == 0) {
auto values_array = Array::create_from(global_object, m_values.values()); auto values_array = Array::create_from(global_object, m_values.values());
return vm.call(*m_capability.resolve, js_undefined(), values_array); return TRY_OR_DISCARD(vm.call(*m_capability.resolve, js_undefined(), values_array));
} }
return js_undefined(); return js_undefined();
@ -154,7 +154,7 @@ Value PromiseAnyRejectElementFunction::resolve_element()
auto* error = AggregateError::create(global_object); auto* error = AggregateError::create(global_object);
error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }); error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true });
return vm.call(*m_capability.reject, js_undefined(), error); return TRY_OR_DISCARD(vm.call(*m_capability.reject, js_undefined(), error));
} }
return js_undefined(); return js_undefined();

View file

@ -73,9 +73,7 @@ Object* ProxyObject::internal_get_prototype_of() const
} }
// 7. Let handlerProto be ? Call(trap, handler, « target »). // 7. Let handlerProto be ? Call(trap, handler, « target »).
auto handler_proto = vm.call(*trap, &m_handler, &m_target); auto handler_proto = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target));
if (vm.exception())
return {};
// 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception.
if (!handler_proto.is_object() && !handler_proto.is_null()) { if (!handler_proto.is_object() && !handler_proto.is_null()) {
@ -137,12 +135,10 @@ bool ProxyObject::internal_set_prototype_of(Object* prototype)
} }
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)). // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target, prototype); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, prototype)).to_boolean();
if (vm.exception())
return {};
// 9. If booleanTrapResult is false, return false. // 9. If booleanTrapResult is false, return false.
if (!trap_result.to_boolean()) if (!trap_result)
return false; return false;
// 10. Let extensibleTarget be ? IsExtensible(target). // 10. Let extensibleTarget be ? IsExtensible(target).
@ -198,9 +194,7 @@ bool ProxyObject::internal_is_extensible() const
} }
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)). // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)).to_boolean();
if (vm.exception())
return {};
// 8. Let targetResult be ? IsExtensible(target). // 8. Let targetResult be ? IsExtensible(target).
auto target_result = m_target.is_extensible(); auto target_result = m_target.is_extensible();
@ -208,13 +202,13 @@ bool ProxyObject::internal_is_extensible() const
return {}; return {};
// 9. If SameValue(booleanTrapResult, targetResult) is false, throw a TypeError exception. // 9. If SameValue(booleanTrapResult, targetResult) is false, throw a TypeError exception.
if (trap_result.to_boolean() != target_result) { if (trap_result != target_result) {
vm.throw_exception<TypeError>(global_object, ErrorType::ProxyIsExtensibleReturn); vm.throw_exception<TypeError>(global_object, ErrorType::ProxyIsExtensibleReturn);
return {}; return {};
} }
// 10. Return booleanTrapResult. // 10. Return booleanTrapResult.
return trap_result.to_boolean(); return trap_result;
} }
// 10.5.4 [[PreventExtensions]] ( ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-preventextensions // 10.5.4 [[PreventExtensions]] ( ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-preventextensions
@ -246,12 +240,10 @@ bool ProxyObject::internal_prevent_extensions()
} }
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)). // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)).to_boolean();
if (vm.exception())
return {};
// 8. If booleanTrapResult is true, then // 8. If booleanTrapResult is true, then
if (trap_result.to_boolean()) { if (trap_result) {
// a. Let extensibleTarget be ? IsExtensible(target). // a. Let extensibleTarget be ? IsExtensible(target).
auto extensible_target = m_target.is_extensible(); auto extensible_target = m_target.is_extensible();
if (vm.exception()) if (vm.exception())
@ -265,7 +257,7 @@ bool ProxyObject::internal_prevent_extensions()
} }
// 9. Return booleanTrapResult. // 9. Return booleanTrapResult.
return trap_result.to_boolean(); return trap_result;
} }
// 10.5.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p // 10.5.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p
@ -300,9 +292,7 @@ Optional<PropertyDescriptor> ProxyObject::internal_get_own_property(const Proper
} }
// 8. Let trapResultObj be ? Call(trap, handler, « target, P »). // 8. Let trapResultObj be ? Call(trap, handler, « target, P »).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)));
if (vm.exception())
return {};
// 9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception.
if (!trap_result.is_object() && !trap_result.is_undefined()) { if (!trap_result.is_object() && !trap_result.is_undefined()) {
@ -421,12 +411,10 @@ bool ProxyObject::internal_define_own_property(PropertyName const& property_name
auto descriptor_object = from_property_descriptor(global_object, property_descriptor); auto descriptor_object = from_property_descriptor(global_object, property_descriptor);
// 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)). // 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), descriptor_object); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), descriptor_object)).to_boolean();
if (vm.exception())
return {};
// 10. If booleanTrapResult is false, return false. // 10. If booleanTrapResult is false, return false.
if (!trap_result.to_boolean()) if (!trap_result)
return false; return false;
// 11. Let targetDesc be ? target.[[GetOwnProperty]](P). // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
@ -519,12 +507,10 @@ bool ProxyObject::internal_has_property(PropertyName const& property_name) const
} }
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean();
if (vm.exception())
return {};
// 9. If booleanTrapResult is false, then // 9. If booleanTrapResult is false, then
if (!trap_result.to_boolean()) { if (!trap_result) {
// a. Let targetDesc be ? target.[[GetOwnProperty]](P). // a. Let targetDesc be ? target.[[GetOwnProperty]](P).
auto target_descriptor = m_target.internal_get_own_property(property_name); auto target_descriptor = m_target.internal_get_own_property(property_name);
if (vm.exception()) if (vm.exception())
@ -552,7 +538,7 @@ bool ProxyObject::internal_has_property(PropertyName const& property_name) const
} }
// 10. Return booleanTrapResult. // 10. Return booleanTrapResult.
return trap_result.to_boolean(); return trap_result;
} }
// 10.5.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver // 10.5.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver
@ -607,9 +593,7 @@ Value ProxyObject::internal_get(PropertyName const& property_name, Value receive
} }
// 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »). // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), receiver); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), receiver));
if (vm.exception())
return {};
// 9. Let targetDesc be ? target.[[GetOwnProperty]](P). // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
auto target_descriptor = m_target.internal_get_own_property(property_name); auto target_descriptor = m_target.internal_get_own_property(property_name);
@ -675,12 +659,10 @@ bool ProxyObject::internal_set(PropertyName const& property_name, Value value, V
} }
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)). // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), value, receiver); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), value, receiver)).to_boolean();
if (vm.exception())
return {};
// 9. If booleanTrapResult is false, return false. // 9. If booleanTrapResult is false, return false.
if (!trap_result.to_boolean()) if (!trap_result)
return false; return false;
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P). // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
@ -744,12 +726,10 @@ bool ProxyObject::internal_delete(PropertyName const& property_name)
} }
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)); auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean();
if (vm.exception())
return {};
// 9. If booleanTrapResult is false, return false. // 9. If booleanTrapResult is false, return false.
if (!trap_result.to_boolean()) if (!trap_result)
return false; return false;
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P). // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
@ -811,9 +791,10 @@ MarkedValueList ProxyObject::internal_own_property_keys() const
} }
// 7. Let trapResultArray be ? Call(trap, handler, « target »). // 7. Let trapResultArray be ? Call(trap, handler, « target »).
auto trap_result_array = vm.call(*trap, &m_handler, &m_target); auto trap_result_array_or_error = vm.call(*trap, &m_handler, &m_target);
if (vm.exception()) if (trap_result_array_or_error.is_error())
return MarkedValueList { heap() }; return MarkedValueList { heap() };
auto trap_result_array = trap_result_array_or_error.release_value();
// 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »). // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »).
HashTable<StringOrSymbol> unique_keys; HashTable<StringOrSymbol> unique_keys;
@ -967,7 +948,7 @@ Value ProxyObject::call()
}); });
// 8. Return ? Call(trap, handler, « target, thisArgument, argArray »). // 8. Return ? Call(trap, handler, « target, thisArgument, argArray »).
return vm.call(*trap, &m_handler, &m_target, this_argument, arguments_array); return TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, this_argument, arguments_array));
} }
// 10.5.13 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget // 10.5.13 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
@ -1012,7 +993,7 @@ Value ProxyObject::construct(FunctionObject& new_target)
}); });
// 9. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »). // 9. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
auto result = vm.call(*trap, &m_handler, &m_target, arguments_array, &new_target); auto result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, arguments_array, &new_target));
// 10. If Type(newObj) is not Object, throw a TypeError exception. // 10. If Type(newObj) is not Object, throw a TypeError exception.
if (!result.is_object()) { if (!result.is_object()) {

View file

@ -65,7 +65,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::apply)
// 3. Perform PrepareForTailCall(). // 3. Perform PrepareForTailCall().
// 4. Return ? Call(target, thisArgument, args). // 4. Return ? Call(target, thisArgument, args).
return vm.call(target.as_function(), this_argument, move(args)); return TRY_OR_DISCARD(vm.call(target.as_function(), this_argument, move(args)));
} }
// 28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] ), https://tc39.es/ecma262/#sec-reflect.construct // 28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] ), https://tc39.es/ecma262/#sec-reflect.construct

View file

@ -292,9 +292,7 @@ Value regexp_exec(GlobalObject& global_object, Object& regexp_object, Utf16Strin
return {}; return {};
if (exec.is_function()) { if (exec.is_function()) {
auto result = vm.call(exec.as_function(), &regexp_object, js_string(vm, move(string))); auto result = TRY_OR_DISCARD(vm.call(exec.as_function(), &regexp_object, js_string(vm, move(string))));
if (vm.exception())
return {};
if (!result.is_object() && !result.is_null()) if (!result.is_object() && !result.is_null())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObjectOrNull, result.to_string_without_side_effects()); vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObjectOrNull, result.to_string_without_side_effects());
@ -685,9 +683,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
replacer_args.append(move(named_captures)); replacer_args.append(move(named_captures));
} }
auto replace_result = vm.call(replace_value.as_function(), js_undefined(), move(replacer_args)); auto replace_result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), move(replacer_args)));
if (vm.exception())
return {};
replacement = replace_result.to_string(global_object); replacement = replace_result.to_string(global_object);
if (vm.exception()) if (vm.exception())

View file

@ -714,7 +714,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
if (vm.exception()) if (vm.exception())
return {}; return {};
if (splitter) if (splitter)
return vm.call(*splitter, separator_argument, object, limit_argument); return TRY_OR_DISCARD(vm.call(*splitter, separator_argument, object, limit_argument));
} }
auto string = object.to_utf16_string(global_object); auto string = object.to_utf16_string(global_object);
@ -861,7 +861,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match)
auto regexp = vm.argument(0); auto regexp = vm.argument(0);
if (!regexp.is_nullish()) { if (!regexp.is_nullish()) {
if (auto* matcher = regexp.get_method(global_object, *vm.well_known_symbol_match())) if (auto* matcher = regexp.get_method(global_object, *vm.well_known_symbol_match()))
return vm.call(*matcher, regexp, this_object); return TRY_OR_DISCARD(vm.call(*matcher, regexp, this_object));
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
@ -873,7 +873,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match)
auto rx = regexp_create(global_object, regexp, js_undefined()); auto rx = regexp_create(global_object, regexp, js_undefined());
if (!rx) if (!rx)
return {}; return {};
return Value(rx).invoke(global_object, *vm.well_known_symbol_match(), js_string(vm, move(string))); return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_match(), js_string(vm, move(string))));
} }
// 22.1.3.12 String.prototype.matchAll ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.matchall // 22.1.3.12 String.prototype.matchAll ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.matchall
@ -897,7 +897,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
} }
} }
if (auto* matcher = regexp.get_method(global_object, *vm.well_known_symbol_match_all())) if (auto* matcher = regexp.get_method(global_object, *vm.well_known_symbol_match_all()))
return vm.call(*matcher, regexp, this_object); return TRY_OR_DISCARD(vm.call(*matcher, regexp, this_object));
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
@ -909,7 +909,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
auto rx = regexp_create(global_object, regexp, js_string(vm, "g")); auto rx = regexp_create(global_object, regexp, js_string(vm, "g"));
if (!rx) if (!rx)
return {}; return {};
return Value(rx).invoke(global_object, *vm.well_known_symbol_match_all(), js_string(vm, move(string))); return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_match_all(), js_string(vm, move(string))));
} }
// 22.1.3.17 String.prototype.replace ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replace // 22.1.3.17 String.prototype.replace ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replace
@ -921,7 +921,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
if (!search_value.is_nullish()) { if (!search_value.is_nullish()) {
if (auto* replacer = search_value.get_method(global_object, *vm.well_known_symbol_replace())) if (auto* replacer = search_value.get_method(global_object, *vm.well_known_symbol_replace()))
return vm.call(*replacer, search_value, this_object, replace_value); return TRY_OR_DISCARD(vm.call(*replacer, search_value, this_object, replace_value));
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
@ -950,9 +950,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
String replacement; String replacement;
if (replace_value.is_function()) { if (replace_value.is_function()) {
auto result = vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position.value()), js_string(vm, string)); auto result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position.value()), js_string(vm, string)));
if (vm.exception())
return {};
replacement = result.to_string(global_object); replacement = result.to_string(global_object);
if (vm.exception()) if (vm.exception())
@ -996,12 +994,8 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
auto* replacer = search_value.get_method(global_object, *vm.well_known_symbol_replace()); auto* replacer = search_value.get_method(global_object, *vm.well_known_symbol_replace());
if (vm.exception()) if (vm.exception())
return {}; return {};
if (replacer) { if (replacer)
auto result = vm.call(*replacer, search_value, this_object, replace_value); return TRY_OR_DISCARD(vm.call(*replacer, search_value, this_object, replace_value));
if (vm.exception())
return {};
return result;
}
} }
auto string = this_object.to_utf16_string(global_object); auto string = this_object.to_utf16_string(global_object);
@ -1040,9 +1034,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
String replacement; String replacement;
if (replace_value.is_function()) { if (replace_value.is_function()) {
auto result = vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position), js_string(vm, string)); auto result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position), js_string(vm, string)));
if (vm.exception())
return {};
replacement = result.to_string(global_object); replacement = result.to_string(global_object);
if (vm.exception()) if (vm.exception())
@ -1070,7 +1062,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search)
auto regexp = vm.argument(0); auto regexp = vm.argument(0);
if (!regexp.is_nullish()) { if (!regexp.is_nullish()) {
if (auto* searcher = regexp.get_method(global_object, *vm.well_known_symbol_search())) if (auto* searcher = regexp.get_method(global_object, *vm.well_known_symbol_search()))
return vm.call(*searcher, regexp, this_object); return TRY_OR_DISCARD(vm.call(*searcher, regexp, this_object));
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
@ -1082,7 +1074,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search)
auto rx = regexp_create(global_object, regexp, js_undefined()); auto rx = regexp_create(global_object, regexp, js_undefined());
if (!rx) if (!rx)
return {}; return {};
return Value(rx).invoke(global_object, *vm.well_known_symbol_search(), js_string(vm, move(string))); return TRY_OR_DISCARD(Value(rx).invoke(global_object, *vm.well_known_symbol_search(), js_string(vm, move(string))));
} }
// B.2.3.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml // B.2.3.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml

View file

@ -103,9 +103,7 @@ ThrowCompletionOr<Vector<String>> calendar_fields(GlobalObject& global_object, O
// 3. If fields is not undefined, then // 3. If fields is not undefined, then
if (fields) { if (fields) {
// a. Set fieldsArray to ? Call(fields, calendar, « fieldsArray »). // a. Set fieldsArray to ? Call(fields, calendar, « fieldsArray »).
fields_array = vm.call(*fields, &calendar, fields_array); fields_array = TRY(vm.call(*fields, &calendar, fields_array));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
} }
// 4. Return ? IterableToListOfType(fieldsArray, « String »). // 4. Return ? IterableToListOfType(fieldsArray, « String »).
@ -124,9 +122,7 @@ ThrowCompletionOr<double> calendar_year(GlobalObject& global_object, Object& cal
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "year", « dateLike »). // 2. Let result be ? Invoke(calendar, "year", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.year, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.year, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is undefined, throw a RangeError exception. // 3. If result is undefined, throw a RangeError exception.
if (result.is_undefined()) if (result.is_undefined())
@ -143,9 +139,7 @@ ThrowCompletionOr<double> calendar_month(GlobalObject& global_object, Object& ca
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "month", « dateLike »). // 2. Let result be ? Invoke(calendar, "month", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.month, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.month, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is undefined, throw a RangeError exception. // 3. If result is undefined, throw a RangeError exception.
if (result.is_undefined()) if (result.is_undefined())
@ -162,9 +156,7 @@ ThrowCompletionOr<String> calendar_month_code(GlobalObject& global_object, Objec
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "monthCode", « dateLike »). // 2. Let result be ? Invoke(calendar, "monthCode", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.monthCode, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.monthCode, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is undefined, throw a RangeError exception. // 3. If result is undefined, throw a RangeError exception.
if (result.is_undefined()) if (result.is_undefined())
@ -181,9 +173,7 @@ ThrowCompletionOr<double> calendar_day(GlobalObject& global_object, Object& cale
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "day", « dateLike »). // 2. Let result be ? Invoke(calendar, "day", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.day, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.day, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is undefined, throw a RangeError exception. // 3. If result is undefined, throw a RangeError exception.
if (result.is_undefined()) if (result.is_undefined())
@ -200,10 +190,7 @@ ThrowCompletionOr<Value> calendar_day_of_week(GlobalObject& global_object, Objec
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "dayOfWeek", « dateLike »). // 2. Return ? Invoke(calendar, "dayOfWeek", « dateLike »).
auto day_of_week = Value(&calendar).invoke(global_object, vm.names.dayOfWeek, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.dayOfWeek, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return day_of_week;
} }
// 12.1.14 CalendarDayOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofyear // 12.1.14 CalendarDayOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofyear
@ -213,10 +200,7 @@ ThrowCompletionOr<Value> calendar_day_of_year(GlobalObject& global_object, Objec
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "dayOfYear", « dateLike »). // 2. Return ? Invoke(calendar, "dayOfYear", « dateLike »).
auto day_of_year = Value(&calendar).invoke(global_object, vm.names.dayOfYear, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.dayOfYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return day_of_year;
} }
// 12.1.15 CalendarWeekOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarweekofyear // 12.1.15 CalendarWeekOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarweekofyear
@ -226,10 +210,7 @@ ThrowCompletionOr<Value> calendar_week_of_year(GlobalObject& global_object, Obje
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "weekOfYear", « dateLike »). // 2. Return ? Invoke(calendar, "weekOfYear", « dateLike »).
auto week_of_year = Value(&calendar).invoke(global_object, vm.names.weekOfYear, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.weekOfYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return week_of_year;
} }
// 12.1.16 CalendarDaysInWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinweek // 12.1.16 CalendarDaysInWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinweek
@ -239,10 +220,7 @@ ThrowCompletionOr<Value> calendar_days_in_week(GlobalObject& global_object, Obje
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "daysInWeek", « dateLike »). // 2. Return ? Invoke(calendar, "daysInWeek", « dateLike »).
auto days_in_week = Value(&calendar).invoke(global_object, vm.names.daysInWeek, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.daysInWeek, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return days_in_week;
} }
// 12.1.17 CalendarDaysInMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinmonth // 12.1.17 CalendarDaysInMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinmonth
@ -252,10 +230,7 @@ ThrowCompletionOr<Value> calendar_days_in_month(GlobalObject& global_object, Obj
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "daysInMonth", « dateLike »). // 2. Return ? Invoke(calendar, "daysInMonth", « dateLike »).
auto days_in_month = Value(&calendar).invoke(global_object, vm.names.daysInMonth, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.daysInMonth, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return days_in_month;
} }
// 12.1.18 CalendarDaysInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinyear // 12.1.18 CalendarDaysInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinyear
@ -265,10 +240,7 @@ ThrowCompletionOr<Value> calendar_days_in_year(GlobalObject& global_object, Obje
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "daysInYear", « dateLike »). // 2. Return ? Invoke(calendar, "daysInYear", « dateLike »).
auto days_in_year = Value(&calendar).invoke(global_object, vm.names.daysInYear, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.daysInYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return days_in_year;
} }
// 12.1.19 CalendarMonthsInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthsinyear // 12.1.19 CalendarMonthsInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthsinyear
@ -278,10 +250,7 @@ ThrowCompletionOr<Value> calendar_months_in_year(GlobalObject& global_object, Ob
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "monthsInYear", « dateLike »). // 2. Return ? Invoke(calendar, "monthsInYear", « dateLike »).
auto months_in_year = Value(&calendar).invoke(global_object, vm.names.monthsInYear, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.monthsInYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return months_in_year;
} }
// 12.1.20 CalendarInLeapYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarinleapyear // 12.1.20 CalendarInLeapYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarinleapyear
@ -291,10 +260,7 @@ ThrowCompletionOr<Value> calendar_in_leap_year(GlobalObject& global_object, Obje
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Return ? Invoke(calendar, "inLeapYear", « dateLike »). // 2. Return ? Invoke(calendar, "inLeapYear", « dateLike »).
auto in_leap_year = Value(&calendar).invoke(global_object, vm.names.inLeapYear, &date_like); return TRY(Value(&calendar).invoke(global_object, vm.names.inLeapYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
return in_leap_year;
} }
// 15.6.1.2 CalendarEra ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarera // 15.6.1.2 CalendarEra ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarera
@ -305,9 +271,7 @@ ThrowCompletionOr<Value> calendar_era(GlobalObject& global_object, Object& calen
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "era", « dateLike »). // 2. Let result be ? Invoke(calendar, "era", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.era, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.era, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is not undefined, set result to ? ToString(result). // 3. If result is not undefined, set result to ? ToString(result).
if (!result.is_undefined()) { if (!result.is_undefined()) {
@ -329,9 +293,7 @@ ThrowCompletionOr<Value> calendar_era_year(GlobalObject& global_object, Object&
// 1. Assert: Type(calendar) is Object. // 1. Assert: Type(calendar) is Object.
// 2. Let result be ? Invoke(calendar, "eraYear", « dateLike »). // 2. Let result be ? Invoke(calendar, "eraYear", « dateLike »).
auto result = Value(&calendar).invoke(global_object, vm.names.eraYear, &date_like); auto result = TRY(Value(&calendar).invoke(global_object, vm.names.eraYear, &date_like));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 3. If result is not undefined, set result to ? ToIntegerThrowOnInfinity(result). // 3. If result is not undefined, set result to ? ToIntegerThrowOnInfinity(result).
if (!result.is_undefined()) if (!result.is_undefined())
@ -451,9 +413,7 @@ ThrowCompletionOr<PlainDate*> date_from_fields(GlobalObject& global_object, Obje
// 2. Assert: Type(fields) is Object. // 2. Assert: Type(fields) is Object.
// 3. Let date be ? Invoke(calendar, "dateFromFields", « fields, options »). // 3. Let date be ? Invoke(calendar, "dateFromFields", « fields, options »).
auto date = Value(&calendar).invoke(global_object, vm.names.dateFromFields, &fields, &options); auto date = TRY(Value(&calendar).invoke(global_object, vm.names.dateFromFields, &fields, &options));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 4. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]). // 4. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]).
auto* date_object = date.to_object(global_object); auto* date_object = date.to_object(global_object);
@ -479,9 +439,7 @@ ThrowCompletionOr<PlainYearMonth*> year_month_from_fields(GlobalObject& global_o
// a. Assert: Type(options) is Object. // a. Assert: Type(options) is Object.
// 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). // 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »).
auto year_month = Value(&calendar).invoke(global_object, vm.names.yearMonthFromFields, &fields, options ?: js_undefined()); auto year_month = TRY(Value(&calendar).invoke(global_object, vm.names.yearMonthFromFields, &fields, options ?: js_undefined()));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 6. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). // 6. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
auto* year_month_object = year_month.to_object(global_object); auto* year_month_object = year_month.to_object(global_object);
@ -507,9 +465,7 @@ ThrowCompletionOr<PlainMonthDay*> month_day_from_fields(GlobalObject& global_obj
// a. Assert: Type(options) is Object. // a. Assert: Type(options) is Object.
// 5. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »). // 5. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »).
auto month_day = Value(&calendar).invoke(global_object, vm.names.monthDayFromFields, &fields, options ?: js_undefined()); auto month_day = TRY(Value(&calendar).invoke(global_object, vm.names.monthDayFromFields, &fields, options ?: js_undefined()));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 6. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). // 6. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
auto* month_day_object = month_day.to_object(global_object); auto* month_day_object = month_day.to_object(global_object);

View file

@ -374,9 +374,7 @@ ThrowCompletionOr<double> get_offset_nanoseconds_for(GlobalObject& global_object
get_offset_nanoseconds_for = global_object.temporal_time_zone_prototype_get_offset_nanoseconds_for_function(); get_offset_nanoseconds_for = global_object.temporal_time_zone_prototype_get_offset_nanoseconds_for_function();
// 3. Let offsetNanoseconds be ? Call(getOffsetNanosecondsFor, timeZone, « instant »). // 3. Let offsetNanoseconds be ? Call(getOffsetNanosecondsFor, timeZone, « instant »).
auto offset_nanoseconds_value = vm.call(*get_offset_nanoseconds_for, time_zone, &instant); auto offset_nanoseconds_value = TRY(vm.call(*get_offset_nanoseconds_for, time_zone, &instant));
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// 4. If Type(offsetNanoseconds) is not Number, throw a TypeError exception. // 4. If Type(offsetNanoseconds) is not Number, throw a TypeError exception.
if (!offset_nanoseconds_value.is_number()) if (!offset_nanoseconds_value.is_number())

View file

@ -94,13 +94,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
for (size_t k = 0; k < values.size(); ++k) { for (size_t k = 0; k < values.size(); ++k) {
auto k_value = values[k]; auto k_value = values[k];
Value mapped_value; Value mapped_value;
if (map_fn) { if (map_fn)
mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k)));
if (vm.exception()) else
return {};
} else {
mapped_value = k_value; mapped_value = k_value;
}
target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes); target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes);
if (vm.exception()) if (vm.exception())
return {}; return {};
@ -121,13 +118,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from)
for (size_t k = 0; k < length; ++k) { for (size_t k = 0; k < length; ++k) {
auto k_value = array_like->get(k); auto k_value = array_like->get(k);
Value mapped_value; Value mapped_value;
if (map_fn) { if (map_fn)
mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k)));
if (vm.exception()) else
return {};
} else {
mapped_value = k_value; mapped_value = k_value;
}
target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes); target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes);
if (vm.exception()) if (vm.exception())
return {}; return {};

View file

@ -122,9 +122,10 @@ static void for_each_item(VM& vm, GlobalObject& global_object, const String& nam
if (vm.exception()) if (vm.exception())
return; return;
auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array);
if (vm.exception()) if (callback_result_or_error.is_error())
return; return;
auto callback_result = callback_result_or_error.release_value();
if (callback(i, value, callback_result) == IterationDecision::Break) if (callback(i, value, callback_result) == IterationDecision::Break)
break; break;
@ -150,9 +151,10 @@ static void for_each_item_from_last(VM& vm, GlobalObject& global_object, const S
if (vm.exception()) if (vm.exception())
return; return;
auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array);
if (vm.exception()) if (callback_result_or_error.is_error())
return; return;
auto callback_result = callback_result_or_error.release_value();
if (callback(i, value, callback_result) == IterationDecision::Break) if (callback(i, value, callback_result) == IterationDecision::Break)
break; break;
@ -535,9 +537,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce)
for (; k < length; ++k) { for (; k < length; ++k) {
auto k_value = typed_array->get(k); auto k_value = typed_array->get(k);
accumulator = vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array); accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array));
if (vm.exception())
return {};
} }
return accumulator; return accumulator;
@ -573,9 +573,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right)
for (; k >= 0; --k) { for (; k >= 0; --k) {
auto k_value = typed_array->get(k); auto k_value = typed_array->get(k);
accumulator = vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array); accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array));
if (vm.exception())
return {};
} }
return accumulator; return accumulator;
@ -996,9 +994,10 @@ static void typed_array_merge_sort(GlobalObject& global_object, FunctionObject*
double comparison_result; double comparison_result;
if (compare_function) { if (compare_function) {
auto result = vm.call(*compare_function, js_undefined(), x, y); auto result_or_error = vm.call(*compare_function, js_undefined(), x, y);
if (vm.exception()) if (result_or_error.is_error())
return; return;
auto result = result_or_error.release_value();
auto value = result.to_number(global_object); auto value = result.to_number(global_object);
if (vm.exception()) if (vm.exception())
@ -1410,12 +1409,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
auto value = typed_array->get(i); auto value = typed_array->get(i);
// c. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)). // c. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); auto callback_result = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean();
if (vm.exception())
return {};
// d. If selected is true, then // d. If selected is true, then
if (callback_result.to_boolean()) { if (callback_result) {
// i. Append kValue to the end of kept. // i. Append kValue to the end of kept.
kept.append(value); kept.append(value);
@ -1483,9 +1480,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map)
auto value = typed_array->get(i); auto value = typed_array->get(i);
// c. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »). // c. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
auto mapped_value = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); auto mapped_value = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array));
if (vm.exception())
return {};
// d. Perform ? Set(A, Pk, mappedValue, true). // d. Perform ? Set(A, Pk, mappedValue, true).
return_array->set(i, mapped_value, Object::ShouldThrowExceptions::Yes); return_array->set(i, mapped_value, Object::ShouldThrowExceptions::Yes);
@ -1517,9 +1512,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
return {}; return {};
if (value.is_nullish()) if (value.is_nullish())
continue; continue;
auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString); auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString));
if (vm.exception())
return {};
auto string = locale_string_result.to_string(global_object); auto string = locale_string_result.to_string(global_object);
if (vm.exception()) if (vm.exception())
return {}; return {};

View file

@ -662,7 +662,7 @@ void VM::ordinary_call_bind_this(FunctionObject& function, ExecutionContext& cal
callee_context.this_value = this_value; callee_context.this_value = this_value;
} }
Value VM::call_internal(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments) ThrowCompletionOr<Value> VM::call_internal(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments)
{ {
VERIFY(!exception()); VERIFY(!exception());
VERIFY(!this_value.is_empty()); VERIFY(!this_value.is_empty());
@ -680,8 +680,8 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar
// This needs to be moved to NativeFunction/OrdinaryFunctionObject's construct() (10.2.2 [[Construct]]) // This needs to be moved to NativeFunction/OrdinaryFunctionObject's construct() (10.2.2 [[Construct]])
ExecutionContext callee_context(heap()); ExecutionContext callee_context(heap());
prepare_for_ordinary_call(function, callee_context, nullptr); prepare_for_ordinary_call(function, callee_context, nullptr);
if (exception()) if (auto* exception = this->exception())
return {}; return JS::throw_completion(exception->value());
ScopeGuard pop_guard = [&] { ScopeGuard pop_guard = [&] {
pop_execution_context(); pop_execution_context();
@ -696,10 +696,13 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar
if (callee_context.lexical_environment) if (callee_context.lexical_environment)
ordinary_call_bind_this(function, callee_context, this_value); ordinary_call_bind_this(function, callee_context, this_value);
if (exception()) if (auto* exception = this->exception())
return {}; return JS::throw_completion(exception->value());
return function.call(); auto result = function.call();
if (auto* exception = this->exception())
return JS::throw_completion(exception->value());
return result;
} }
bool VM::in_strict_mode() const bool VM::in_strict_mode() const

View file

@ -255,7 +255,7 @@ public:
Value get_new_target(); Value get_new_target();
template<typename... Args> template<typename... Args>
[[nodiscard]] ALWAYS_INLINE Value call(FunctionObject& function, Value this_value, Args... args) [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> call(FunctionObject& function, Value this_value, Args... args)
{ {
if constexpr (sizeof...(Args) > 0) { if constexpr (sizeof...(Args) > 0) {
MarkedValueList arglist { heap() }; MarkedValueList arglist { heap() };
@ -289,7 +289,7 @@ private:
void ordinary_call_bind_this(FunctionObject&, ExecutionContext&, Value this_argument); void ordinary_call_bind_this(FunctionObject&, ExecutionContext&, Value this_argument);
[[nodiscard]] Value call_internal(FunctionObject&, Value this_value, Optional<MarkedValueList> arguments); [[nodiscard]] ThrowCompletionOr<Value> call_internal(FunctionObject&, Value this_value, Optional<MarkedValueList> arguments);
void prepare_for_ordinary_call(FunctionObject&, ExecutionContext& callee_context, Object* new_target); void prepare_for_ordinary_call(FunctionObject&, ExecutionContext& callee_context, Object* new_target);
Exception* m_exception { nullptr }; Exception* m_exception { nullptr };
@ -327,13 +327,13 @@ private:
}; };
template<> template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(FunctionObject& function, Value this_value, MarkedValueList arguments) { return call_internal(function, this_value, move(arguments)); } [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> VM::call(FunctionObject& function, Value this_value, MarkedValueList arguments) { return call_internal(function, this_value, move(arguments)); }
template<> template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments) { return call_internal(function, this_value, move(arguments)); } [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> VM::call(FunctionObject& function, Value this_value, Optional<MarkedValueList> arguments) { return call_internal(function, this_value, move(arguments)); }
template<> template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(FunctionObject& function, Value this_value) { return call(function, this_value, Optional<MarkedValueList> {}); } [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> VM::call(FunctionObject& function, Value this_value) { return call(function, this_value, Optional<MarkedValueList> {}); }
ALWAYS_INLINE Heap& Cell::heap() const ALWAYS_INLINE Heap& Cell::heap() const
{ {

View file

@ -423,9 +423,7 @@ Value Value::to_primitive(GlobalObject& global_object, PreferredType preferred_t
return {}; return {};
if (to_primitive_method) { if (to_primitive_method) {
auto hint = get_hint_for_preferred_type(); auto hint = get_hint_for_preferred_type();
auto result = vm.call(*to_primitive_method, *this, js_string(vm, hint)); auto result = TRY_OR_DISCARD(vm.call(*to_primitive_method, *this, js_string(vm, hint)));
if (vm.exception())
return {};
if (!result.is_object()) if (!result.is_object())
return result; return result;
vm.throw_exception<TypeError>(global_object, ErrorType::ToPrimitiveReturnedObject, to_string_without_side_effects(), hint); vm.throw_exception<TypeError>(global_object, ErrorType::ToPrimitiveReturnedObject, to_string_without_side_effects(), hint);
@ -1298,9 +1296,7 @@ Value instance_of(GlobalObject& global_object, Value lhs, Value rhs)
if (vm.exception()) if (vm.exception())
return {}; return {};
if (has_instance_method) { if (has_instance_method) {
auto has_instance_result = vm.call(*has_instance_method, rhs, lhs); auto has_instance_result = TRY_OR_DISCARD(vm.call(*has_instance_method, rhs, lhs));
if (vm.exception())
return {};
return Value(has_instance_result.to_boolean()); return Value(has_instance_result.to_boolean());
} }
if (!rhs.is_function()) { if (!rhs.is_function()) {
@ -1618,16 +1614,14 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l
} }
// 7.3.20 Invoke ( V, P [ , argumentsList ] ), https://tc39.es/ecma262/#sec-invoke // 7.3.20 Invoke ( V, P [ , argumentsList ] ), https://tc39.es/ecma262/#sec-invoke
Value Value::invoke_internal(GlobalObject& global_object, JS::PropertyName const& property_name, Optional<MarkedValueList> arguments) ThrowCompletionOr<Value> Value::invoke_internal(GlobalObject& global_object, JS::PropertyName const& property_name, Optional<MarkedValueList> arguments)
{ {
auto& vm = global_object.vm(); auto& vm = global_object.vm();
auto property = get(global_object, property_name); auto property = get(global_object, property_name);
if (vm.exception()) if (auto* exception = vm.exception())
return {}; return throw_completion(exception->value());
if (!property.is_function()) { if (!property.is_function())
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects()); return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects());
return {};
}
return vm.call(property.as_function(), *this, move(arguments)); return vm.call(property.as_function(), *this, move(arguments));
} }

View file

@ -292,12 +292,12 @@ public:
bool operator==(Value const&) const; bool operator==(Value const&) const;
template<typename... Args> template<typename... Args>
[[nodiscard]] ALWAYS_INLINE Value invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args); [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args);
private: private:
Type m_type { Type::Empty }; Type m_type { Type::Empty };
[[nodiscard]] Value invoke_internal(GlobalObject& global_object, PropertyName const&, Optional<MarkedValueList> arguments); [[nodiscard]] ThrowCompletionOr<Value> invoke_internal(GlobalObject& global_object, PropertyName const&, Optional<MarkedValueList> arguments);
i32 to_i32_slow_case(GlobalObject&) const; i32 to_i32_slow_case(GlobalObject&) const;

View file

@ -72,8 +72,8 @@ Value WeakMapConstructor::construct(FunctionObject& new_target)
auto value = iterator_value.as_object().get(1); auto value = iterator_value.as_object().get(1);
if (vm.exception()) if (vm.exception())
return IterationDecision::Break; return IterationDecision::Break;
(void)vm.call(adder.as_function(), Value(weak_map), key, value); auto result = vm.call(adder.as_function(), Value(weak_map), key, value);
return vm.exception() ? IterationDecision::Break : IterationDecision::Continue; return result.is_error() ? IterationDecision::Break : IterationDecision::Continue;
}); });
if (vm.exception()) if (vm.exception())
return {}; return {};

View file

@ -64,8 +64,8 @@ Value WeakSetConstructor::construct(FunctionObject& new_target)
get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) { get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) {
if (vm.exception()) if (vm.exception())
return IterationDecision::Break; return IterationDecision::Break;
(void)vm.call(adder.as_function(), Value(weak_set), iterator_value); auto result = vm.call(adder.as_function(), Value(weak_set), iterator_value);
return vm.exception() ? IterationDecision::Break : IterationDecision::Continue; return result.is_error() ? IterationDecision::Break : IterationDecision::Continue;
}); });
if (vm.exception()) if (vm.exception())
return {}; return {};

View file

@ -190,8 +190,8 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con
for (auto& entry : arguments) for (auto& entry : arguments)
argument_values.append(to_js_value(entry, global_object)); argument_values.append(to_js_value(entry, global_object));
auto result = vm.call(function, JS::js_undefined(), move(argument_values)); auto result_or_error = vm.call(function, JS::js_undefined(), move(argument_values));
if (vm.exception()) { if (result_or_error.is_error()) {
vm.clear_exception(); vm.clear_exception();
return Wasm::Trap(); return Wasm::Trap();
} }
@ -199,7 +199,7 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con
return Wasm::Result { Vector<Wasm::Value> {} }; return Wasm::Result { Vector<Wasm::Value> {} };
if (type.results().size() == 1) { if (type.results().size() == 1) {
auto value = to_webassembly_value(result, type.results().first(), global_object); auto value = to_webassembly_value(result_or_error.release_value(), type.results().first(), global_object);
if (!value.has_value()) if (!value.has_value())
return Wasm::Trap {}; return Wasm::Trap {};