diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-10-19 22:53:27 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-10-20 12:27:19 +0100 |
commit | ca27e5eff56ebdaf7f990296c6429f1b3afaa057 (patch) | |
tree | c8a33d4d2c3419d5844dac57cf78534c4b13d011 | |
parent | 20163c058485dc524402c46f21bbe65a860bf9c5 (diff) | |
download | serenity-ca27e5eff56ebdaf7f990296c6429f1b3afaa057.zip |
LibJS: Convert NativeFunction callback to ThrowCompletionOr
13 files changed, 91 insertions, 65 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp index 8b8410495d..9c2e8c6147 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -201,8 +201,7 @@ void GlobalObject::initialize_global_object() // 10.2.4.1 %ThrowTypeError% ( ), https://tc39.es/ecma262/#sec-%throwtypeerror% m_throw_type_error_function = NativeFunction::create(global_object(), {}, [](VM& vm, GlobalObject& global_object) { - vm.throw_exception<TypeError>(global_object, ErrorType::RestrictedFunctionPropertiesAccess); - return Value(); + return vm.throw_completion<TypeError>(global_object, ErrorType::RestrictedFunctionPropertiesAccess); }); m_throw_type_error_function->define_direct_property(vm.names.length, Value(0), 0); m_throw_type_error_function->define_direct_property(vm.names.name, js_string(vm, ""), 0); diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp index 1759fd22c8..ada146e147 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -13,7 +13,7 @@ namespace JS { -NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyString& name, Function<Value(VM&, GlobalObject&)> function) +NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyString& name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> function) { return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype()); } @@ -28,7 +28,7 @@ NativeFunction::NativeFunction(Object& prototype) { } -NativeFunction::NativeFunction(FlyString name, Function<Value(VM&, GlobalObject&)> native_function, Object& prototype) +NativeFunction::NativeFunction(FlyString name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> native_function, Object& prototype) : FunctionObject(prototype) , m_name(move(name)) , m_native_function(move(native_function)) @@ -186,7 +186,7 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedValueList ar Value NativeFunction::call() { - return m_native_function(vm(), global_object()); + return TRY_OR_DISCARD(m_native_function(vm(), global_object())); } Value NativeFunction::construct(FunctionObject&) diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.h b/Userland/Libraries/LibJS/Runtime/NativeFunction.h index d88d388ce8..05b1002d40 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.h @@ -15,9 +15,9 @@ class NativeFunction : public FunctionObject { JS_OBJECT(NativeFunction, FunctionObject); public: - static NativeFunction* create(GlobalObject&, const FlyString& name, Function<Value(VM&, GlobalObject&)>); + static NativeFunction* create(GlobalObject&, const FlyString& name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>); - explicit NativeFunction(FlyString name, Function<Value(VM&, GlobalObject&)>, Object& prototype); + explicit NativeFunction(FlyString name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, Object& prototype); virtual void initialize(GlobalObject&) override { } virtual ~NativeFunction() override; @@ -42,7 +42,7 @@ private: virtual bool is_native_function() const final { return true; } FlyString m_name; - Function<Value(VM&, GlobalObject&)> m_native_function; + Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> m_native_function; Realm* m_realm { nullptr }; }; diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 700d93318f..dde9beb577 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -952,6 +952,29 @@ void Object::set_prototype(Object* new_prototype) void Object::define_native_accessor(PropertyName const& property_name, Function<Value(VM&, GlobalObject&)> getter, Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attribute) { + Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> completion_getter = {}; + if (getter) { + completion_getter = [getter = move(getter)](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { + auto result = getter(vm, global_object); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return result; + }; + } + Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> completion_setter = {}; + if (setter) { + completion_setter = [setter = move(setter)](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { + auto result = setter(vm, global_object); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return result; + }; + } + define_new_native_accessor(property_name, move(completion_getter), move(completion_setter), attribute); +} + +void Object::define_new_native_accessor(PropertyName const& property_name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> getter, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> setter, PropertyAttributes attribute) +{ auto& vm = this->vm(); String formatted_property_name; if (property_name.is_number()) { @@ -1018,6 +1041,17 @@ Value Object::get_without_side_effects(const PropertyName& property_name) const void Object::define_native_function(PropertyName const& property_name, Function<Value(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute) { + auto completion_native_function = [native_function = move(native_function), property_name](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { + auto result = native_function(vm, global_object); + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + return result; + }; + define_new_native_function(property_name, move(completion_native_function), length, attribute); +} + +void Object::define_new_native_function(PropertyName const& property_name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute) +{ auto& vm = this->vm(); String function_name; if (property_name.is_string()) { diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index 1e96267579..2c19851251 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -128,9 +128,13 @@ public: void define_direct_property(PropertyName const& property_name, Value value, PropertyAttributes attributes) { storage_set(property_name, { value, attributes }); }; void define_direct_accessor(PropertyName const&, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes); + // Legacy methods - Remove once JS_DECLARE_OLD_NATIVE_FUNCTION is removed void define_native_function(PropertyName const&, Function<Value(VM&, GlobalObject&)>, i32 length, PropertyAttributes attributes); void define_native_accessor(PropertyName const&, Function<Value(VM&, GlobalObject&)> getter, Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes); + void define_new_native_function(PropertyName const&, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, i32 length, PropertyAttributes attributes); + void define_new_native_accessor(PropertyName const&, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> getter, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> setter, PropertyAttributes attributes); + virtual bool is_function() const { return false; } virtual bool is_typed_array() const { return false; } virtual bool is_string_object() const { return false; } diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index a17c4befb5..1a1829f6ea 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -72,7 +72,7 @@ static void set_iterator_record_complete(GlobalObject& global_object, Object& it MUST(iterator_record.set(vm.names.done, Value(true), Object::ShouldThrowExceptions::No)); } -using EndOfElementsCallback = Function<Value(PromiseValueList&)>; +using EndOfElementsCallback = Function<ThrowCompletionOr<Value>(PromiseValueList&)>; using InvokeElementFunctionCallback = Function<void(PromiseValueList&, RemainingElements&, Value, size_t)>; static Value perform_promise_common(GlobalObject& global_object, Object& iterator_record, Value constructor, PromiseCapability result_capability, Value promise_resolve, EndOfElementsCallback end_of_list, InvokeElementFunctionCallback invoke_element_function) @@ -99,7 +99,7 @@ static Value perform_promise_common(GlobalObject& global_object, Object& iterato return {}; if (--remaining_elements_count->value == 0) - return end_of_list(*values); + return TRY_OR_DISCARD(end_of_list(*values)); return result_capability.promise; } @@ -130,14 +130,12 @@ static Value perform_promise_all(GlobalObject& global_object, Object& iterator_r return perform_promise_common( global_object, iterator_record, constructor, result_capability, promise_resolve, - [&](PromiseValueList& values) -> Value { + [&](PromiseValueList& values) -> ThrowCompletionOr<Value> { auto values_array = Array::create_from(global_object, values.values()); - (void)vm.call(*result_capability.resolve, js_undefined(), values_array); - if (vm.exception()) - return {}; + TRY(vm.call(*result_capability.resolve, js_undefined(), values_array)); - return result_capability.promise; + return Value(result_capability.promise); }, [&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) { auto* on_fulfilled = PromiseAllResolveElementFunction::create(global_object, index, values, result_capability, remaining_elements_count); @@ -154,14 +152,12 @@ static Value perform_promise_all_settled(GlobalObject& global_object, Object& it return perform_promise_common( global_object, iterator_record, constructor, result_capability, promise_resolve, - [&](PromiseValueList& values) -> Value { + [&](PromiseValueList& values) -> ThrowCompletionOr<Value> { auto values_array = Array::create_from(global_object, values.values()); - (void)vm.call(*result_capability.resolve, js_undefined(), values_array); - if (vm.exception()) - return {}; + TRY(vm.call(*result_capability.resolve, js_undefined(), values_array)); - return result_capability.promise; + return Value(result_capability.promise); }, [&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) { auto* on_fulfilled = PromiseAllSettledResolveElementFunction::create(global_object, index, values, result_capability, remaining_elements_count); @@ -181,14 +177,14 @@ static Value perform_promise_any(GlobalObject& global_object, Object& iterator_r return perform_promise_common( global_object, iterator_record, constructor, result_capability, promise_resolve, - [&](PromiseValueList& errors) -> Value { + [&](PromiseValueList& errors) -> ThrowCompletionOr<Value> { auto errors_array = Array::create_from(global_object, errors.values()); auto* error = AggregateError::create(global_object); MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true })); vm.throw_exception(global_object, error); - return {}; + return throw_completion(error); }, [&](PromiseValueList& errors, RemainingElements& remaining_elements_count, Value next_promise, size_t index) { auto* on_rejected = PromiseAnyRejectElementFunction::create(global_object, index, errors, result_capability, remaining_elements_count); @@ -205,8 +201,8 @@ static Value perform_promise_race(GlobalObject& global_object, Object& iterator_ return perform_promise_common( global_object, iterator_record, constructor, result_capability, promise_resolve, - [&](PromiseValueList&) -> Value { - return result_capability.promise; + [&](PromiseValueList&) -> ThrowCompletionOr<Value> { + return Value(result_capability.promise); }, [&](PromiseValueList&, RemainingElements&, Value next_promise, size_t) { (void)next_promise.invoke(global_object, vm.names.then, result_capability.resolve, result_capability.reject); diff --git a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp index 711add5389..1dac15c036 100644 --- a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp @@ -69,35 +69,35 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(PromisePrototype::finally) catch_finally = on_finally; } else { // 27.2.5.3.1 Then Finally Functions, https://tc39.es/ecma262/#sec-thenfinallyfunctions - auto* then_finally_function = NativeFunction::create(global_object, "", [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm, auto& global_object) -> Value { + auto* then_finally_function = NativeFunction::create(global_object, "", [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { 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 = TRY_OR_DISCARD(vm.call(on_finally, js_undefined())); + auto result = TRY(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 { + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> ThrowCompletionOr<Value> { return value; }); - return TRY_OR_DISCARD(Value(promise).invoke(global_object, vm.names.then, value_thunk)); + return TRY(Value(promise).invoke(global_object, vm.names.then, value_thunk)); }); then_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable); // 27.2.5.3.2 Catch Finally Functions, https://tc39.es/ecma262/#sec-catchfinallyfunctions - auto* catch_finally_function = NativeFunction::create(global_object, "", [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm, auto& global_object) -> Value { + auto* catch_finally_function = NativeFunction::create(global_object, "", [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { 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 = TRY_OR_DISCARD(vm.call(on_finally, js_undefined())); + auto result = TRY(vm.call(on_finally, js_undefined())); auto* promise = promise_resolve(global_object, constructor, result); - if (vm.exception()) - return {}; - auto* thrower = NativeFunction::create(global_object, "", [reason](auto& vm, auto& global_object) -> Value { + if (auto* exception = vm.exception()) + return throw_completion(exception->value()); + auto* thrower = NativeFunction::create(global_object, "", [reason](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { vm.throw_exception(global_object, reason); - return {}; + return throw_completion(reason); }); - return TRY_OR_DISCARD(Value(promise).invoke(global_object, vm.names.then, thrower)); + return TRY(Value(promise).invoke(global_object, vm.names.then, thrower)); }); catch_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable); diff --git a/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp b/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp index ac5729011d..c7fd18af34 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseReaction.cpp @@ -26,17 +26,15 @@ PromiseCapability new_promise_capability(GlobalObject& global_object, Value cons } promise_capability_functions; // 27.2.1.5.1 GetCapabilitiesExecutor Functions, https://tc39.es/ecma262/#sec-getcapabilitiesexecutor-functions - auto* executor = NativeFunction::create(global_object, "", [&promise_capability_functions](auto& vm, auto& global_object) -> Value { + auto* executor = NativeFunction::create(global_object, "", [&promise_capability_functions](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { auto resolve = vm.argument(0); auto reject = vm.argument(1); // No idea what other engines say here. if (!promise_capability_functions.resolve.is_undefined()) { - vm.template throw_exception<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes); - return {}; + return vm.template throw_completion<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes); } if (!promise_capability_functions.reject.is_undefined()) { - vm.template throw_exception<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes); - return {}; + return vm.template throw_completion<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes); } promise_capability_functions.resolve = resolve; promise_capability_functions.reject = reject; diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp index e6553c92c9..87264a9c1a 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.cpp @@ -32,7 +32,7 @@ void PromiseResolvingFunction::initialize(GlobalObject& global_object) Value PromiseResolvingFunction::call() { - return m_native_function(vm(), global_object(), m_promise, m_already_resolved); + return TRY_OR_DISCARD(m_native_function(vm(), global_object(), m_promise, m_already_resolved)); } void PromiseResolvingFunction::visit_edges(Cell::Visitor& visitor) diff --git a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h index f15fc6efea..ceb11e7315 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h +++ b/Userland/Libraries/LibJS/Runtime/PromiseResolvingFunction.h @@ -25,7 +25,7 @@ class PromiseResolvingFunction final : public NativeFunction { JS_OBJECT(PromiseResolvingFunction, NativeFunction); public: - using FunctionType = Function<Value(VM&, GlobalObject&, Promise&, AlreadyResolved&)>; + using FunctionType = Function<ThrowCompletionOr<Value>(VM&, GlobalObject&, Promise&, AlreadyResolved&)>; static PromiseResolvingFunction* create(GlobalObject&, Promise&, AlreadyResolved&, FunctionType); diff --git a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp index e2a3e25aac..ada40fab71 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyConstructor.cpp @@ -70,7 +70,7 @@ JS_DEFINE_OLD_NATIVE_FUNCTION(ProxyConstructor::revocable) return {}; // 28.2.2.1.1 Proxy Revocation Functions, https://tc39.es/ecma262/#sec-proxy-revocation-functions - auto* revoker = NativeFunction::create(global_object, "", [proxy_handle = make_handle(proxy)](auto&, auto&) -> Value { + auto* revoker = NativeFunction::create(global_object, "", [proxy_handle = make_handle(proxy)](auto&, auto&) -> ThrowCompletionOr<Value> { auto& proxy = const_cast<ProxyObject&>(*proxy_handle.cell()); if (proxy.is_revoked()) return js_undefined(); diff --git a/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp b/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp index c9369ae74f..02ec8a3ab5 100644 --- a/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp +++ b/Userland/Libraries/LibJS/Runtime/ShadowRealm.cpp @@ -184,11 +184,11 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object, // FinishDynamicImport, 5. Perform ! PerformPromiseThen(innerPromise, onFulfilled, onRejected). promise->perform_then( - NativeFunction::create(global_object, "", [](auto&, auto&) -> Value { + NativeFunction::create(global_object, "", [](auto&, auto&) -> ThrowCompletionOr<Value> { // Not called because we hardcoded a rejection above. TODO(); }), - NativeFunction::create(global_object, "", [reject = make_handle(inner_capability.reject)](auto& vm, auto& global_object) -> Value { + NativeFunction::create(global_object, "", [reject = make_handle(inner_capability.reject)](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { auto error = vm.argument(0); // a. Perform ! Call(promiseCapability.[[Reject]], undefined, ยซ error ยป). @@ -214,7 +214,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object, auto* on_fulfilled = NativeFunction::create( global_object, "", - [string = move(export_name_string)](auto& vm, auto& global_object) -> Value { + [string = move(export_name_string)](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { // 1. Assert: exports is a module namespace exotic object. auto& exports = vm.argument(0).as_object(); @@ -225,23 +225,21 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object, // 4. Assert: Type(string) is String. // 5. Let hasOwn be ? HasOwnProperty(exports, string). - auto has_own = TRY_OR_DISCARD(exports.has_own_property(string)); + auto has_own = TRY(exports.has_own_property(string)); // 6. If hasOwn is false, throw a TypeError exception. - if (!has_own) { - vm.template throw_exception<TypeError>(global_object, ErrorType::MissingRequiredProperty, string); - return {}; - } + if (!has_own) + return vm.template throw_completion<TypeError>(global_object, ErrorType::MissingRequiredProperty, string); // 7. Let value be ? Get(exports, string). - auto value = TRY_OR_DISCARD(exports.get(string)); + auto value = TRY(exports.get(string)); // 8. Let realm be f.[[Realm]]. auto* realm = function->realm(); VERIFY(realm); // 9. Return ? GetWrappedValue(realm, value). - return TRY_OR_DISCARD(get_wrapped_value(global_object, *realm, value)); + return get_wrapped_value(global_object, *realm, value); }); on_fulfilled->define_direct_property(vm.names.length, Value(1), Attribute::Configurable); on_fulfilled->define_direct_property(vm.names.name, js_string(vm, String::empty()), Attribute::Configurable); @@ -252,9 +250,8 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object, // NOTE: Even though the spec tells us to use %ThrowTypeError%, it's not observable if we actually do. // Throw a nicer TypeError forwarding the import error message instead (we know the argument is an Error object). - auto* throw_type_error = NativeFunction::create(global_object, {}, [](auto& vm, auto& global_object) -> Value { - vm.template throw_exception<TypeError>(global_object, vm.argument(0).as_object().get_without_side_effects(vm.names.message).as_string().string()); - return {}; + auto* throw_type_error = NativeFunction::create(global_object, {}, [](auto& vm, auto& global_object) -> ThrowCompletionOr<Value> { + return vm.template throw_completion<TypeError>(global_object, vm.argument(0).as_object().get_without_side_effects(vm.names.message).as_string().string()); }); // 17. Return ! PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability). diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 1c4b72c4c2..de5ed754e7 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -442,7 +442,7 @@ JS::NativeFunction* create_native_function(Wasm::FunctionAddress address, String auto function = JS::NativeFunction::create( global_object, name, - [address, type = type.release_value()](JS::VM& vm, JS::GlobalObject& global_object) -> JS::Value { + [address, type = type.release_value()](JS::VM& vm, JS::GlobalObject& global_object) -> JS::ThrowCompletionOr<JS::Value> { Vector<Wasm::Value> values; values.ensure_capacity(type.parameters().size()); @@ -453,15 +453,13 @@ JS::NativeFunction* create_native_function(Wasm::FunctionAddress address, String if (result.has_value()) values.append(result.release_value()); else - return {}; + return JS::throw_completion(vm.exception()->value()); } auto result = WebAssemblyObject::s_abstract_machine.invoke(address, move(values)); // FIXME: Use the convoluted mapping of errors defined in the spec. - if (result.is_trap()) { - vm.throw_exception<JS::TypeError>(global_object, String::formatted("Wasm execution trapped (WIP): {}", result.trap().reason)); - return {}; - } + if (result.is_trap()) + return vm.throw_completion<JS::TypeError>(global_object, String::formatted("Wasm execution trapped (WIP): {}", result.trap().reason)); if (result.values().is_empty()) return JS::js_undefined(); @@ -473,7 +471,7 @@ JS::NativeFunction* create_native_function(Wasm::FunctionAddress address, String for (auto& entry : result.values()) result_values.append(to_js_value(entry, global_object)); - return JS::Array::create_from(global_object, result_values); + return JS::Value(JS::Array::create_from(global_object, result_values)); }); WebAssemblyObject::s_global_cache.function_instances.set(address, function); |