1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 19:17:41 +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;
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());
}

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 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

View file

@ -295,17 +295,22 @@ 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;
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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()) {

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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() };

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());
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.

View file

@ -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));
}
}

View file

@ -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...));
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}
}

View file

@ -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));
}
}

View file

@ -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();

View file

@ -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()) {

View file

@ -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

View file

@ -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(), &regexp_object, js_string(vm, move(string)));
if (vm.exception())
return {};
auto result = TRY_OR_DISCARD(vm.call(exec.as_function(), &regexp_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())

View file

@ -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

View file

@ -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);

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();
// 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())

View file

@ -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 {};

View file

@ -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 {};

View file

@ -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

View file

@ -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
{

View file

@ -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));
}

View file

@ -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;

View file

@ -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 {};

View file

@ -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 {};

View file

@ -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 {};