diff options
35 files changed, 196 insertions, 328 deletions
diff --git a/Userland/Applications/Spreadsheet/Spreadsheet.cpp b/Userland/Applications/Spreadsheet/Spreadsheet.cpp index 47c73b73d2..2d8aa751c5 100644 --- a/Userland/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Userland/Applications/Spreadsheet/Spreadsheet.cpp @@ -399,8 +399,9 @@ RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook) break; case Cell::Formula: { auto& interpreter = sheet->interpreter(); - auto value = 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); + auto value_or_error = interpreter.vm().call(parse_function, json, JS::js_string(interpreter.heap(), obj.get("value").as_string())); + VERIFY(!value_or_error.is_error()); + cell = make<Cell>(obj.get("source").to_string(), value_or_error.release_value(), position, *sheet); break; } } @@ -526,8 +527,9 @@ JsonObject Sheet::to_json() const if (it.value->kind() == Cell::Formula) { data.set("source", it.value->data()); auto json = interpreter().global_object().get("JSON"); - auto stringified = interpreter().vm().call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data()); - data.set("value", stringified.to_string_without_side_effects()); + auto stringified_or_error = interpreter().vm().call(json.as_object().get("stringify").as_function(), json, it.value->evaluated_data()); + VERIFY(!stringified_or_error.is_error()); + data.set("value", stringified_or_error.release_value().to_string_without_side_effects()); } else { data.set("value", it.value->data()); } diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index d0d5ad88a4..70a6a9c59b 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -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 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 @@ -976,11 +976,8 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob if (field.is_static()) { Value field_value = js_undefined(); - if (initializer) { - field_value = interpreter.vm().call(*initializer, class_constructor_value); - if (interpreter.exception()) - return {}; - } + if (initializer) + field_value = TRY_OR_DISCARD(interpreter.vm().call(*initializer, class_constructor_value)); class_constructor->create_data_property_or_throw(property_key, field_value); if (interpreter.exception()) @@ -2280,7 +2277,7 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& glo raw_strings->indexed_properties().append(value); } 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 diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 15e03fca86..fd25bb3ab8 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -295,16 +295,21 @@ void Call::execute_impl(Bytecode::Interpreter& interpreter) const Value return_value; 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 { MarkedValueList argument_values { interpreter.vm().heap() }; for (size_t i = 0; i < m_argument_count; ++i) { argument_values.append(interpreter.reg(m_arguments[i])); } - if (m_type == CallType::Call) - return_value = interpreter.vm().call(function, this_value, move(argument_values)); - else + if (m_type == CallType::Call) { + auto return_value_or_error = interpreter.vm().call(function, this_value, move(argument_values)); + 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)); + } } interpreter.accumulator() = return_value; diff --git a/Userland/Libraries/LibJS/Runtime/Accessor.h b/Userland/Libraries/LibJS/Runtime/Accessor.h index 5dfed111a7..9f30ba0be4 100644 --- a/Userland/Libraries/LibJS/Runtime/Accessor.h +++ b/Userland/Libraries/LibJS/Runtime/Accessor.h @@ -35,7 +35,7 @@ public: { if (!m_getter) 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) diff --git a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp index 4956552fee..4660d78eec 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -151,7 +151,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from) Value mapped_value; 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()) { iterator_close(*iterator); return {}; @@ -192,13 +192,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from) for (size_t k = 0; k < length; ++k) { auto k_value = array_like->get(k); Value mapped_value; - if (map_fn) { - mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); - if (vm.exception()) - return {}; - } else { + if (map_fn) + mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k))); + else mapped_value = k_value; - } array_object.create_data_property_or_throw(k, mapped_value); } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp index 7e4718d84f..6c44484aa3 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -206,12 +206,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter) return {}; // 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); - if (vm.exception()) - return {}; + auto selected = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean(); // iii. If selected is true, then - if (selected.to_boolean()) { + if (selected) { // 1. Perform ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(to)), kValue). array->create_data_property_or_throw(to, k_value); @@ -322,9 +320,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map) return {}; // 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); - if (vm.exception()) - return {}; + auto mapped_value = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)); // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). array->create_data_property_or_throw(property_name, mapped_value); @@ -495,7 +491,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string) return {}; if (!join_function.is_function()) 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 @@ -524,9 +520,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string) return {}; if (value.is_nullish()) continue; - auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString); - if (vm.exception()) - return {}; + auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString)); auto string = locale_string_result.to_string(global_object); if (vm.exception()) return {}; @@ -912,9 +906,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce) return {}; // 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); - if (vm.exception()) - return {}; + accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value(k), object)); } // d. Set k to k + 1. @@ -1012,9 +1004,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right) return {}; // 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); - if (vm.exception()) - return {}; + accumulator = TRY_OR_DISCARD(vm.call(callback_function.as_function(), js_undefined(), accumulator, k_value, Value((size_t)k), object)); } // 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()) { comparison_result = -1; } else if (compare_func) { - auto call_result = vm.call(*compare_func, js_undefined(), left[left_index], right[right_index]); - if (vm.exception()) + auto call_result_or_error = vm.call(*compare_func, js_undefined(), left[left_index], right[right_index]); + if (call_result_or_error.is_error()) return; + auto call_result = call_result_or_error.release_value(); auto number = call_result.to_number(global_object); if (vm.exception()) @@ -1393,12 +1384,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean(); // d. If testResult is true, return kValue. - if (test_result.to_boolean()) + if (test_result) return k_value; // e. Set k to k + 1. @@ -1440,12 +1429,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean(); // d. If testResult is true, return 𝔽(k). - if (test_result.to_boolean()) + if (test_result) return Value(k); // e. Set k to k + 1. @@ -1487,12 +1474,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean(); // d. If testResult is true, return kValue. - if (test_result.to_boolean()) + if (test_result) return k_value; // e. Set k to k - 1. @@ -1534,12 +1519,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last_index) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean(); // d. If testResult is true, return 𝔽(k). - if (test_result.to_boolean()) + if (test_result) return Value((double)k); // e. Set k to k - 1. @@ -1588,12 +1571,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean(); // iii. If testResult is true, return true. - if (test_result.to_boolean()) + if (test_result) return Value(true); } @@ -1643,12 +1624,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every) return {}; // 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); - if (vm.exception()) - return {}; + auto test_result = TRY_OR_DISCARD(vm.call(callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean(); // iii. If testResult is false, return false. - if (!test_result.to_boolean()) + if (!test_result) return Value(false); } @@ -1887,11 +1866,8 @@ static size_t flatten_into_array(GlobalObject& global_object, Object& new_array, if (vm.exception()) return {}; - if (mapper_func) { - value = vm.call(*mapper_func, this_arg, value, Value(j), &array); - if (vm.exception()) - return {}; - } + if (mapper_func) + value = TRY_OR_DISCARD(vm.call(*mapper_func, this_arg, value, Value(j), &array)); if (depth > 0 && TRY_OR_DISCARD(value.is_array(global_object))) { if (vm.did_reach_stack_space_limit()) { diff --git a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp index d7240a7406..d348b2851c 100644 --- a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -842,7 +842,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_json) if (time_value.is_number() && !time_value.is_finite_number()) 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 diff --git a/Userland/Libraries/LibJS/Runtime/FunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/FunctionObject.cpp index 341ac80169..872542be61 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/FunctionObject.cpp @@ -76,9 +76,10 @@ void FunctionObject::InstanceField::define_field(VM& vm, Object& receiver) const { Value init_value = js_undefined(); if (initializer) { - init_value = vm.call(*initializer, receiver.value_of()); - if (vm.exception()) + auto init_value_or_error = vm.call(*initializer, receiver.value_of()); + if (init_value_or_error.is_error()) return; + init_value = init_value_or_error.release_value(); } receiver.create_data_property_or_throw(name, init_value); } diff --git a/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp index 75b0a34ab2..295dd1b3c2 100644 --- a/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp @@ -56,9 +56,9 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply) auto this_arg = vm.argument(0); auto arg_array = vm.argument(1); 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)); - 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 @@ -100,7 +100,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call) for (size_t i = 1; i < vm.argument_count(); ++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 diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.h b/Userland/Libraries/LibJS/Runtime/GlobalObject.h index b2d47bfc4c..b03340ec86 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.h @@ -160,7 +160,7 @@ template<> inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); } 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) { MarkedValueList arglist { global_object.vm().heap() }; diff --git a/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp b/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp index afdf4d2f13..9dccef24ac 100644 --- a/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/IteratorOperations.cpp @@ -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()); return nullptr; } - auto iterator = vm.call(method.as_function(), value); - if (vm.exception()) - return {}; + auto iterator = TRY_OR_DISCARD(vm.call(method.as_function(), value)); if (!iterator.is_object()) { vm.throw_exception<TypeError>(global_object, ErrorType::NotIterable, value.to_string_without_side_effects()); return nullptr; @@ -56,12 +54,10 @@ Object* iterator_next(Object& iterator, Value value) Value result; if (value.is_empty()) - result = vm.call(next_method.as_function(), &iterator); + result = TRY_OR_DISCARD(vm.call(next_method.as_function(), &iterator)); 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()) { vm.throw_exception<TypeError>(global_object, ErrorType::IterableNextBadReturn); return nullptr; @@ -132,11 +128,12 @@ void iterator_close(Object& iterator) if (!return_method) 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) 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). + auto result = result_or_error.release_value(); if (!result.is_object()) { vm.throw_exception<TypeError>(global_object, ErrorType::IterableReturnBadReturn); return; // If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. diff --git a/Userland/Libraries/LibJS/Runtime/JSONObject.cpp b/Userland/Libraries/LibJS/Runtime/JSONObject.cpp index 568037eeff..0a64678feb 100644 --- a/Userland/Libraries/LibJS/Runtime/JSONObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/JSONObject.cpp @@ -152,18 +152,12 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif auto to_json = value_object->get(vm.names.toJSON); if (vm.exception()) return {}; - if (to_json.is_function()) { - value = vm.call(to_json.as_function(), value, js_string(vm, key.to_string())); - if (vm.exception()) - return {}; - } + if (to_json.is_function()) + value = TRY_OR_DISCARD(vm.call(to_json.as_function(), value, js_string(vm, key.to_string()))); } - if (state.replacer_function) { - value = vm.call(*state.replacer_function, holder, js_string(vm, key.to_string()), value); - if (vm.exception()) - return {}; - } + if (state.replacer_function) + value = TRY_OR_DISCARD(vm.call(*state.replacer_function, holder, js_string(vm, key.to_string()), value)); if (value.is_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)); } } diff --git a/Userland/Libraries/LibJS/Runtime/JobCallback.h b/Userland/Libraries/LibJS/Runtime/JobCallback.h index 8be1854abd..a9d95607b3 100644 --- a/Userland/Libraries/LibJS/Runtime/JobCallback.h +++ b/Userland/Libraries/LibJS/Runtime/JobCallback.h @@ -28,7 +28,7 @@ template<typename... Args> { VERIFY(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...)); } } diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 1d5e2bb54b..438382d06f 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -703,7 +703,7 @@ Value Object::internal_get(PropertyName const& property_name, Value receiver) co return js_undefined(); // 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>); @@ -1199,7 +1199,7 @@ Value Object::ordinary_to_primitive(Value::PreferredType preferred_type) const if (vm.exception()) return {}; 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()) return result; } diff --git a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp index fef4b6992b..b1547f138d 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -144,7 +144,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string) JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string) { 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 diff --git a/Userland/Libraries/LibJS/Runtime/Promise.cpp b/Userland/Libraries/LibJS/Runtime/Promise.cpp index 126acfb3f0..f9d93b97f7 100644 --- a/Userland/Libraries/LibJS/Runtime/Promise.cpp +++ b/Userland/Libraries/LibJS/Runtime/Promise.cpp @@ -32,9 +32,7 @@ Object* promise_resolve(GlobalObject& global_object, Object& constructor, Value auto promise_capability = new_promise_capability(global_object, &constructor); if (vm.exception()) return nullptr; - [[maybe_unused]] auto result = vm.call(*promise_capability.resolve, js_undefined(), value); - if (vm.exception()) - return nullptr; + [[maybe_unused]] auto result = TRY_OR_DISCARD(vm.call(*promise_capability.resolve, js_undefined(), value)); return promise_capability.promise; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index 630afddb29..8fc64ade9f 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -113,9 +113,7 @@ static Value perform_promise_common(GlobalObject& global_object, Object& iterato values->values().append(js_undefined()); - auto next_promise = vm.call(promise_resolve.as_function(), constructor, next_value); - if (vm.exception()) - return {}; + auto next_promise = TRY_OR_DISCARD(vm.call(promise_resolve.as_function(), constructor, next_value)); ++remaining_elements_count->value; @@ -410,7 +408,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::reject) if (vm.exception()) return {}; 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; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp index 4aef8c5753..e5074f5ec0 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp @@ -62,11 +62,11 @@ Value PromiseReactionJob::call() vm.stop_unwind(); auto* reject_function = promise_capability.value().reject; 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 { auto* resolve_function = promise_capability.value().resolve; 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)); } } diff --git a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp index 8efcb6e85e..3774cce9cc 100644 --- a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp @@ -55,7 +55,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::catch_) { auto this_value = vm.this_value(global_object); 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 @@ -77,16 +77,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally) auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell()); auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell()); auto value = vm.argument(0); - auto result = vm.call(on_finally, js_undefined()); - if (vm.exception()) - return {}; + auto result = TRY_OR_DISCARD(vm.call(on_finally, js_undefined())); auto* promise = promise_resolve(global_object, constructor, result); if (vm.exception()) return {}; auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> 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); @@ -95,9 +93,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally) auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell()); auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell()); auto reason = vm.argument(0); - auto result = vm.call(on_finally, js_undefined()); - if (vm.exception()) - return {}; + auto result = TRY_OR_DISCARD(vm.call(on_finally, js_undefined())); auto* promise = promise_resolve(global_object, constructor, result); if (vm.exception()) return {}; @@ -105,14 +101,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally) vm.throw_exception(global_object, reason); 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); then_finally = Value(then_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)); } } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp index 22019a1eb2..83dd7cd8c2 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingElementFunctions.cpp @@ -67,7 +67,7 @@ Value PromiseAllResolveElementFunction::resolve_element() if (--m_remaining_elements.value == 0) { 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(); @@ -96,7 +96,7 @@ Value PromiseAllSettledResolveElementFunction::resolve_element() if (--m_remaining_elements.value == 0) { 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(); @@ -125,7 +125,7 @@ Value PromiseAllSettledRejectElementFunction::resolve_element() if (--m_remaining_elements.value == 0) { 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(); @@ -154,7 +154,7 @@ Value PromiseAnyRejectElementFunction::resolve_element() auto* error = AggregateError::create(global_object); 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(); diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp index 39d99f6017..ac2d9628f2 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -73,9 +73,7 @@ Object* ProxyObject::internal_get_prototype_of() const } // 7. Let handlerProto be ? Call(trap, handler, « target »). - auto handler_proto = vm.call(*trap, &m_handler, &m_target); - if (vm.exception()) - return {}; + auto handler_proto = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)); // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. 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 »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target, prototype); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, prototype)).to_boolean(); // 9. If booleanTrapResult is false, return false. - if (!trap_result.to_boolean()) + if (!trap_result) return false; // 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 »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)).to_boolean(); // 8. Let targetResult be ? IsExtensible(target). auto target_result = m_target.is_extensible(); @@ -208,13 +202,13 @@ bool ProxyObject::internal_is_extensible() const return {}; // 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); return {}; } // 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 @@ -246,12 +240,10 @@ bool ProxyObject::internal_prevent_extensions() } // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target)).to_boolean(); // 8. If booleanTrapResult is true, then - if (trap_result.to_boolean()) { + if (trap_result) { // a. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = m_target.is_extensible(); if (vm.exception()) @@ -265,7 +257,7 @@ bool ProxyObject::internal_prevent_extensions() } // 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 @@ -300,9 +292,7 @@ Optional<PropertyDescriptor> ProxyObject::internal_get_own_property(const Proper } // 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)); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name))); // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. 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); // 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); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), descriptor_object)).to_boolean(); // 10. If booleanTrapResult is false, return false. - if (!trap_result.to_boolean()) + if (!trap_result) return false; // 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 »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean(); // 9. If booleanTrapResult is false, then - if (!trap_result.to_boolean()) { + if (!trap_result) { // a. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = m_target.internal_get_own_property(property_name); if (vm.exception()) @@ -552,7 +538,7 @@ bool ProxyObject::internal_has_property(PropertyName const& property_name) const } // 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 @@ -607,9 +593,7 @@ Value ProxyObject::internal_get(PropertyName const& property_name, Value receive } // 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); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), receiver)); // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). 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 »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), value, receiver); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name), value, receiver)).to_boolean(); // 9. If booleanTrapResult is false, return false. - if (!trap_result.to_boolean()) + if (!trap_result) return false; // 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 »)). - auto trap_result = vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name)); - if (vm.exception()) - return {}; + auto trap_result = TRY_OR_DISCARD(vm.call(*trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean(); // 9. If booleanTrapResult is false, return false. - if (!trap_result.to_boolean()) + if (!trap_result) return false; // 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 »). - auto trap_result_array = vm.call(*trap, &m_handler, &m_target); - if (vm.exception()) + auto trap_result_array_or_error = vm.call(*trap, &m_handler, &m_target); + if (trap_result_array_or_error.is_error()) return MarkedValueList { heap() }; + auto trap_result_array = trap_result_array_or_error.release_value(); // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »). HashTable<StringOrSymbol> unique_keys; @@ -967,7 +948,7 @@ Value ProxyObject::call() }); // 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 @@ -1012,7 +993,7 @@ Value ProxyObject::construct(FunctionObject& new_target) }); // 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. if (!result.is_object()) { diff --git a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp index b15131a6d4..ed2694fdee 100644 --- a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -65,7 +65,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::apply) // 3. Perform PrepareForTailCall(). // 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 diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp index c848fc28cb..340dfc492e 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp @@ -292,9 +292,7 @@ Value regexp_exec(GlobalObject& global_object, Object& regexp_object, Utf16Strin return {}; if (exec.is_function()) { - auto result = vm.call(exec.as_function(), ®exp_object, js_string(vm, move(string))); - if (vm.exception()) - return {}; + auto result = TRY_OR_DISCARD(vm.call(exec.as_function(), ®exp_object, js_string(vm, move(string)))); if (!result.is_object() && !result.is_null()) 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)); } - auto replace_result = vm.call(replace_value.as_function(), js_undefined(), move(replacer_args)); - if (vm.exception()) - return {}; + auto replace_result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), move(replacer_args))); replacement = replace_result.to_string(global_object); if (vm.exception()) diff --git a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp index 5f52af546d..e22ef1f45d 100644 --- a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -714,7 +714,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split) if (vm.exception()) return {}; 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); @@ -861,7 +861,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match) auto regexp = vm.argument(0); if (!regexp.is_nullish()) { 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()) return {}; } @@ -873,7 +873,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match) auto rx = regexp_create(global_object, regexp, js_undefined()); if (!rx) 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 @@ -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())) - return vm.call(*matcher, regexp, this_object); + return TRY_OR_DISCARD(vm.call(*matcher, regexp, this_object)); if (vm.exception()) return {}; } @@ -909,7 +909,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all) auto rx = regexp_create(global_object, regexp, js_string(vm, "g")); if (!rx) 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 @@ -921,7 +921,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace) if (!search_value.is_nullish()) { 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()) return {}; } @@ -950,9 +950,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace) String replacement; 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)); - if (vm.exception()) - return {}; + 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))); replacement = result.to_string(global_object); 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()); if (vm.exception()) return {}; - if (replacer) { - auto result = vm.call(*replacer, search_value, this_object, replace_value); - if (vm.exception()) - return {}; - return result; - } + if (replacer) + return TRY_OR_DISCARD(vm.call(*replacer, search_value, this_object, replace_value)); } auto string = this_object.to_utf16_string(global_object); @@ -1040,9 +1034,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all) String replacement; 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)); - if (vm.exception()) - return {}; + auto result = TRY_OR_DISCARD(vm.call(replace_value.as_function(), js_undefined(), js_string(vm, search_string), Value(position), js_string(vm, string))); replacement = result.to_string(global_object); if (vm.exception()) @@ -1070,7 +1062,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search) auto regexp = vm.argument(0); if (!regexp.is_nullish()) { 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()) return {}; } @@ -1082,7 +1074,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search) auto rx = regexp_create(global_object, regexp, js_undefined()); if (!rx) 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 diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp index 69698655bf..b691651ba2 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp @@ -103,9 +103,7 @@ ThrowCompletionOr<Vector<String>> calendar_fields(GlobalObject& global_object, O // 3. If fields is not undefined, then if (fields) { // a. Set fieldsArray to ? Call(fields, calendar, « fieldsArray »). - fields_array = vm.call(*fields, &calendar, fields_array); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + fields_array = TRY(vm.call(*fields, &calendar, fields_array)); } // 4. Return ? IterableToListOfType(fieldsArray, « String »). @@ -124,9 +122,7 @@ ThrowCompletionOr<double> calendar_year(GlobalObject& global_object, Object& cal // 1. Assert: Type(calendar) is Object. // 2. Let result be ? Invoke(calendar, "year", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.year, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.year, &date_like)); // 3. If result is undefined, throw a RangeError exception. if (result.is_undefined()) @@ -143,9 +139,7 @@ ThrowCompletionOr<double> calendar_month(GlobalObject& global_object, Object& ca // 1. Assert: Type(calendar) is Object. // 2. Let result be ? Invoke(calendar, "month", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.month, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.month, &date_like)); // 3. If result is undefined, throw a RangeError exception. if (result.is_undefined()) @@ -162,9 +156,7 @@ ThrowCompletionOr<String> calendar_month_code(GlobalObject& global_object, Objec // 1. Assert: Type(calendar) is Object. // 2. Let result be ? Invoke(calendar, "monthCode", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.monthCode, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.monthCode, &date_like)); // 3. If result is undefined, throw a RangeError exception. if (result.is_undefined()) @@ -181,9 +173,7 @@ ThrowCompletionOr<double> calendar_day(GlobalObject& global_object, Object& cale // 1. Assert: Type(calendar) is Object. // 2. Let result be ? Invoke(calendar, "day", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.day, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.day, &date_like)); // 3. If result is undefined, throw a RangeError exception. if (result.is_undefined()) @@ -200,10 +190,7 @@ ThrowCompletionOr<Value> calendar_day_of_week(GlobalObject& global_object, Objec // 1. Assert: Type(calendar) is Object. // 2. Return ? Invoke(calendar, "dayOfWeek", « dateLike »). - auto day_of_week = Value(&calendar).invoke(global_object, vm.names.dayOfWeek, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return day_of_week; + return TRY(Value(&calendar).invoke(global_object, vm.names.dayOfWeek, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "dayOfYear", « dateLike »). - auto day_of_year = Value(&calendar).invoke(global_object, vm.names.dayOfYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return day_of_year; + return TRY(Value(&calendar).invoke(global_object, vm.names.dayOfYear, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "weekOfYear", « dateLike »). - auto week_of_year = Value(&calendar).invoke(global_object, vm.names.weekOfYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return week_of_year; + return TRY(Value(&calendar).invoke(global_object, vm.names.weekOfYear, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "daysInWeek", « dateLike »). - auto days_in_week = Value(&calendar).invoke(global_object, vm.names.daysInWeek, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return days_in_week; + return TRY(Value(&calendar).invoke(global_object, vm.names.daysInWeek, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "daysInMonth", « dateLike »). - auto days_in_month = Value(&calendar).invoke(global_object, vm.names.daysInMonth, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return days_in_month; + return TRY(Value(&calendar).invoke(global_object, vm.names.daysInMonth, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "daysInYear", « dateLike »). - auto days_in_year = Value(&calendar).invoke(global_object, vm.names.daysInYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return days_in_year; + return TRY(Value(&calendar).invoke(global_object, vm.names.daysInYear, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "monthsInYear", « dateLike »). - auto months_in_year = Value(&calendar).invoke(global_object, vm.names.monthsInYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return months_in_year; + return TRY(Value(&calendar).invoke(global_object, vm.names.monthsInYear, &date_like)); } // 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. // 2. Return ? Invoke(calendar, "inLeapYear", « dateLike »). - auto in_leap_year = Value(&calendar).invoke(global_object, vm.names.inLeapYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); - return in_leap_year; + return TRY(Value(&calendar).invoke(global_object, vm.names.inLeapYear, &date_like)); } // 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. // 2. Let result be ? Invoke(calendar, "era", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.era, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.era, &date_like)); // 3. If result is not undefined, set result to ? ToString(result). if (!result.is_undefined()) { @@ -329,9 +293,7 @@ ThrowCompletionOr<Value> calendar_era_year(GlobalObject& global_object, Object& // 1. Assert: Type(calendar) is Object. // 2. Let result be ? Invoke(calendar, "eraYear", « dateLike »). - auto result = Value(&calendar).invoke(global_object, vm.names.eraYear, &date_like); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto result = TRY(Value(&calendar).invoke(global_object, vm.names.eraYear, &date_like)); // 3. If result is not undefined, set result to ? ToIntegerThrowOnInfinity(result). if (!result.is_undefined()) @@ -451,9 +413,7 @@ ThrowCompletionOr<PlainDate*> date_from_fields(GlobalObject& global_object, Obje // 2. Assert: Type(fields) is Object. // 3. Let date be ? Invoke(calendar, "dateFromFields", « fields, options »). - auto date = Value(&calendar).invoke(global_object, vm.names.dateFromFields, &fields, &options); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto date = TRY(Value(&calendar).invoke(global_object, vm.names.dateFromFields, &fields, &options)); // 4. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]). 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. // 5. Let yearMonth be ? Invoke(calendar, "yearMonthFromFields", « fields, options »). - auto year_month = Value(&calendar).invoke(global_object, vm.names.yearMonthFromFields, &fields, options ?: js_undefined()); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto year_month = TRY(Value(&calendar).invoke(global_object, vm.names.yearMonthFromFields, &fields, options ?: js_undefined())); // 6. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]). 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. // 5. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »). - auto month_day = Value(&calendar).invoke(global_object, vm.names.monthDayFromFields, &fields, options ?: js_undefined()); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto month_day = TRY(Value(&calendar).invoke(global_object, vm.names.monthDayFromFields, &fields, options ?: js_undefined())); // 6. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]). auto* month_day_object = month_day.to_object(global_object); diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp index 1c677f4a2c..6c91304ec8 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp @@ -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(); // 3. Let offsetNanoseconds be ? Call(getOffsetNanosecondsFor, timeZone, « instant »). - auto offset_nanoseconds_value = vm.call(*get_offset_nanoseconds_for, time_zone, &instant); - if (auto* exception = vm.exception()) - return throw_completion(exception->value()); + auto offset_nanoseconds_value = TRY(vm.call(*get_offset_nanoseconds_for, time_zone, &instant)); // 4. If Type(offsetNanoseconds) is not Number, throw a TypeError exception. if (!offset_nanoseconds_value.is_number()) diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp index f2f09b50f2..35567fb22e 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp @@ -94,13 +94,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from) for (size_t k = 0; k < values.size(); ++k) { auto k_value = values[k]; Value mapped_value; - if (map_fn) { - mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); - if (vm.exception()) - return {}; - } else { + if (map_fn) + mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k))); + else mapped_value = k_value; - } target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes); if (vm.exception()) return {}; @@ -121,13 +118,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::from) for (size_t k = 0; k < length; ++k) { auto k_value = array_like->get(k); Value mapped_value; - if (map_fn) { - mapped_value = vm.call(*map_fn, this_arg, k_value, Value(k)); - if (vm.exception()) - return {}; - } else { + if (map_fn) + mapped_value = TRY_OR_DISCARD(vm.call(*map_fn, this_arg, k_value, Value(k))); + else mapped_value = k_value; - } target_object->set(k, mapped_value, Object::ShouldThrowExceptions::Yes); if (vm.exception()) return {}; diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp index 6ad432e772..379f76db72 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -122,9 +122,10 @@ static void for_each_item(VM& vm, GlobalObject& global_object, const String& nam if (vm.exception()) return; - auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); - if (vm.exception()) + auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); + if (callback_result_or_error.is_error()) return; + auto callback_result = callback_result_or_error.release_value(); if (callback(i, value, callback_result) == IterationDecision::Break) break; @@ -150,9 +151,10 @@ static void for_each_item_from_last(VM& vm, GlobalObject& global_object, const S if (vm.exception()) return; - auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); - if (vm.exception()) + auto callback_result_or_error = vm.call(*callback_function, this_value, value, Value((i32)i), typed_array); + if (callback_result_or_error.is_error()) return; + auto callback_result = callback_result_or_error.release_value(); if (callback(i, value, callback_result) == IterationDecision::Break) break; @@ -535,9 +537,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce) for (; k < length; ++k) { auto k_value = typed_array->get(k); - accumulator = vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array); - if (vm.exception()) - return {}; + accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array)); } return accumulator; @@ -573,9 +573,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::reduce_right) for (; k >= 0; --k) { auto k_value = typed_array->get(k); - accumulator = vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array); - if (vm.exception()) - return {}; + accumulator = TRY_OR_DISCARD(vm.call(*callback_function, js_undefined(), accumulator, k_value, Value(k), typed_array)); } return accumulator; @@ -996,9 +994,10 @@ static void typed_array_merge_sort(GlobalObject& global_object, FunctionObject* double comparison_result; if (compare_function) { - auto result = vm.call(*compare_function, js_undefined(), x, y); - if (vm.exception()) + auto result_or_error = vm.call(*compare_function, js_undefined(), x, y); + if (result_or_error.is_error()) return; + auto result = result_or_error.release_value(); auto value = result.to_number(global_object); if (vm.exception()) @@ -1410,12 +1409,10 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter) auto value = typed_array->get(i); // 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); - if (vm.exception()) - return {}; + auto callback_result = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean(); // d. If selected is true, then - if (callback_result.to_boolean()) { + if (callback_result) { // i. Append kValue to the end of kept. kept.append(value); @@ -1483,9 +1480,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::map) auto value = typed_array->get(i); // 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); - if (vm.exception()) - return {}; + auto mapped_value = TRY_OR_DISCARD(vm.call(*callback_function, this_value, value, Value((i32)i), typed_array)); // d. Perform ? Set(A, Pk, mappedValue, true). return_array->set(i, mapped_value, Object::ShouldThrowExceptions::Yes); @@ -1517,9 +1512,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string) return {}; if (value.is_nullish()) continue; - auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString); - if (vm.exception()) - return {}; + auto locale_string_result = TRY_OR_DISCARD(value.invoke(global_object, vm.names.toLocaleString)); auto string = locale_string_result.to_string(global_object); if (vm.exception()) return {}; diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 9902b57612..55d7b7e53a 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -662,7 +662,7 @@ void VM::ordinary_call_bind_this(FunctionObject& function, ExecutionContext& cal 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(!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]]) ExecutionContext callee_context(heap()); prepare_for_ordinary_call(function, callee_context, nullptr); - if (exception()) - return {}; + if (auto* exception = this->exception()) + return JS::throw_completion(exception->value()); ScopeGuard pop_guard = [&] { pop_execution_context(); @@ -696,10 +696,13 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar if (callee_context.lexical_environment) ordinary_call_bind_this(function, callee_context, this_value); - if (exception()) - return {}; + if (auto* exception = this->exception()) + 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 diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index f666344b7c..4fa6d89e48 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -255,7 +255,7 @@ public: Value get_new_target(); 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) { MarkedValueList arglist { heap() }; @@ -289,7 +289,7 @@ private: 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); Exception* m_exception { nullptr }; @@ -327,13 +327,13 @@ private: }; 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<> -[[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<> -[[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 { diff --git a/Userland/Libraries/LibJS/Runtime/Value.cpp b/Userland/Libraries/LibJS/Runtime/Value.cpp index 0016c75c50..4c98b30faa 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.cpp +++ b/Userland/Libraries/LibJS/Runtime/Value.cpp @@ -423,9 +423,7 @@ Value Value::to_primitive(GlobalObject& global_object, PreferredType preferred_t return {}; if (to_primitive_method) { auto hint = get_hint_for_preferred_type(); - auto result = vm.call(*to_primitive_method, *this, js_string(vm, hint)); - if (vm.exception()) - return {}; + auto result = TRY_OR_DISCARD(vm.call(*to_primitive_method, *this, js_string(vm, hint))); if (!result.is_object()) return result; 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()) return {}; if (has_instance_method) { - auto has_instance_result = vm.call(*has_instance_method, rhs, lhs); - if (vm.exception()) - return {}; + auto has_instance_result = TRY_OR_DISCARD(vm.call(*has_instance_method, rhs, lhs)); return Value(has_instance_result.to_boolean()); } 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 -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 property = get(global_object, property_name); - if (vm.exception()) - return {}; - if (!property.is_function()) { - vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects()); - return {}; - } + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + if (!property.is_function()) + return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects()); return vm.call(property.as_function(), *this, move(arguments)); } diff --git a/Userland/Libraries/LibJS/Runtime/Value.h b/Userland/Libraries/LibJS/Runtime/Value.h index a3dd6ca38b..c8e4528795 100644 --- a/Userland/Libraries/LibJS/Runtime/Value.h +++ b/Userland/Libraries/LibJS/Runtime/Value.h @@ -292,12 +292,12 @@ public: bool operator==(Value const&) const; 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: 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; diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp index 83af5b3e6c..23655100e7 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp @@ -72,8 +72,8 @@ Value WeakMapConstructor::construct(FunctionObject& new_target) auto value = iterator_value.as_object().get(1); if (vm.exception()) return IterationDecision::Break; - (void)vm.call(adder.as_function(), Value(weak_map), key, value); - return vm.exception() ? IterationDecision::Break : IterationDecision::Continue; + auto result = vm.call(adder.as_function(), Value(weak_map), key, value); + return result.is_error() ? IterationDecision::Break : IterationDecision::Continue; }); if (vm.exception()) return {}; diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp index 803db74d88..d095528abc 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -64,8 +64,8 @@ Value WeakSetConstructor::construct(FunctionObject& new_target) get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) { if (vm.exception()) return IterationDecision::Break; - (void)vm.call(adder.as_function(), Value(weak_set), iterator_value); - return vm.exception() ? IterationDecision::Break : IterationDecision::Continue; + auto result = vm.call(adder.as_function(), Value(weak_set), iterator_value); + return result.is_error() ? IterationDecision::Break : IterationDecision::Continue; }); if (vm.exception()) return {}; diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 1f1459ef9a..8511d69aaa 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -190,8 +190,8 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con for (auto& entry : arguments) argument_values.append(to_js_value(entry, global_object)); - auto result = vm.call(function, JS::js_undefined(), move(argument_values)); - if (vm.exception()) { + auto result_or_error = vm.call(function, JS::js_undefined(), move(argument_values)); + if (result_or_error.is_error()) { vm.clear_exception(); return Wasm::Trap(); } @@ -199,7 +199,7 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con return Wasm::Result { Vector<Wasm::Value> {} }; 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()) return Wasm::Trap {}; |