From 5074355f2990b20102d9656a8933bfa7598c7e46 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 9 Apr 2025 11:46:54 -0400 Subject: [PATCH] LibWeb: Implement an AO to get a promise to wait for promises to settle --- Libraries/LibWeb/WebIDL/Promise.cpp | 32 +++++++++++++++++++++++++++++ Libraries/LibWeb/WebIDL/Promise.h | 1 + 2 files changed, 33 insertions(+) diff --git a/Libraries/LibWeb/WebIDL/Promise.cpp b/Libraries/LibWeb/WebIDL/Promise.cpp index cf1180e5d0c..c2bbb0ccbb6 100644 --- a/Libraries/LibWeb/WebIDL/Promise.cpp +++ b/Libraries/LibWeb/WebIDL/Promise.cpp @@ -7,11 +7,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include namespace Web::WebIDL { @@ -290,6 +292,36 @@ void wait_for_all(JS::Realm& realm, Vector> const& promises, Fu } } +// https://webidl.spec.whatwg.org/#waiting-for-all-promise +GC::Ref get_promise_for_wait_for_all(JS::Realm& realm, Vector> const& promises) +{ + // 1. Let promise be a new promise of type Promise> in realm. + auto promise = create_promise(realm); + + // 2. Let successSteps be the following steps, given results: + auto success_steps = [&realm, promise](Vector const& results) { + HTML::TemporaryExecutionContext execution_context { realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes }; + + // 1. Resolve promise with results. + auto sequence = JS::Array::create_from(realm, results); + resolve_promise(realm, promise, sequence); + }; + + // 3. Let failureSteps be the following steps, given reason: + auto failure_steps = [&realm, promise](JS::Value reason) { + HTML::TemporaryExecutionContext execution_context { realm, HTML::TemporaryExecutionContext::CallbacksEnabled::Yes }; + + // 1. Reject promise with reason. + reject_promise(realm, promise, reason); + }; + + // 4. Wait for all with promises, given successSteps and failureSteps. + wait_for_all(realm, promises, move(success_steps), move(failure_steps)); + + // 5. Return promise. + return promise; +} + GC::Ref create_rejected_promise_from_exception(JS::Realm& realm, Exception exception) { auto throw_completion = Bindings::exception_to_throw_completion(realm.vm(), move(exception)); diff --git a/Libraries/LibWeb/WebIDL/Promise.h b/Libraries/LibWeb/WebIDL/Promise.h index 555c6f31c3b..82e2fa30b5d 100644 --- a/Libraries/LibWeb/WebIDL/Promise.h +++ b/Libraries/LibWeb/WebIDL/Promise.h @@ -30,6 +30,7 @@ GC::Ref upon_fulfillment(Promise const&, GC::Ref); GC::Ref upon_rejection(Promise const&, GC::Ref); void mark_promise_as_handled(Promise const&); void wait_for_all(JS::Realm&, Vector> const& promises, Function const&)> success_steps, Function failure_steps); +GC::Ref get_promise_for_wait_for_all(JS::Realm&, Vector> const& promises); // Non-spec, convenience method. GC::Ref create_rejected_promise_from_exception(JS::Realm&, Exception);