From 191e0a782ed7022a35a3d43ea0b857e53bc6a6b8 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 27 Jun 2023 10:25:58 +0200 Subject: [PATCH] LibJS: Have AsyncFunctionDriverWrapper unwrap promises before returning 24 new passes on test262. :^) --- .../Runtime/AsyncFunctionDriverWrapper.cpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp b/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp index e3f2ad5476fbf9..70d2219e31fd0d 100644 --- a/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp +++ b/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.cpp @@ -72,12 +72,26 @@ void AsyncFunctionDriverWrapper::continue_async_execution(VM& vm, Value value, b auto promise_value = TRY(result.get(vm, vm.names.value)); if (TRY(result.get(vm, vm.names.done)).to_boolean()) { - // We hit a `return value;` - m_top_level_promise->fulfill(promise_value); - // We should not execute anymore, so we are safe to allow our selfs to be GC'd + // We should not execute anymore, so we are safe to allow ourselves to be GC'd. m_self_handle = {}; + // When returning a promise, we need to unwrap it. + if (promise_value.is_object() && is(promise_value.as_object())) { + auto& returned_promise = static_cast(promise_value.as_object()); + if (returned_promise.state() == Promise::State::Fulfilled) { + m_top_level_promise->fulfill(returned_promise.result()); + return {}; + } + if (returned_promise.state() == Promise::State::Rejected) + return throw_completion(returned_promise.result()); + + // The promise is still pending but there's nothing more to do here. + return {}; + } + + // We hit a `return value;` + m_top_level_promise->fulfill(promise_value); return {}; }