12#include <Ultralight/CAPI/CAPI_JSAPI.h>
13#include <Ultralight/CAPI/CAPI_JSRuntime.h>
17#include <Ultralight/js/detail/Coroutine.h>
111template <
typename T =
void>
114 static_assert(!detail::IsExpectedType<T>::value,
115 "co_return the value or the js::Error directly from Task<U>; Task's promise "
116 "already carries the error channel");
117 static_assert(!std::is_same_v<T, Error>,
"a Task cannot resolve with a js::Error");
120 using Handle = std::coroutine_handle<promise_type>;
125 Task(
Task&& other) noexcept : handle_(std::exchange(other.handle_, {})) {}
133 if (
this != &other) {
136 handle_ = std::exchange(other.handle_, {});
159 Handle handle = std::exchange(handle_, {});
160 assert(handle &&
"Start on an empty Task");
161 handle.promise().resolver_.emplace(std::move(resolver));
162 handle.promise().root_ = &handle.promise();
171 auto operator co_await() && {
172 assert(handle_ &&
"co_await on an empty Task");
173 return Awaiter { handle_ };
180 template <
typename U = T>
181 void operator co_await() & {
182 static_assert(detail::kAlwaysFalse<U>,
183 "co_await std::move(task): awaiting a Task runs it once and consumes it");
188 friend struct detail::TaskAccess;
192 bool await_ready() const noexcept {
return false; }
193 template <
typename P>
194 std::coroutine_handle<> await_suspend(std::coroutine_handle<P> continuation)
noexcept {
195 handle.promise().continuation_ = continuation;
197 if (detail::TaskFrame* parent = detail::FrameOf(continuation))
198 handle.promise().root_ = parent->root_;
201 Result<T> await_resume() {
return handle.promise().TakeResult(); }
204 explicit Task(Handle handle) : handle_(handle) {}
212Task<T> TaskPromise<T>::get_return_object() {
213 auto handle = std::coroutine_handle<TaskPromise<T>>::from_promise(*
this);
214 this->handle_ = handle;
218inline Task<void> TaskPromise<void>::get_return_object() {
219 auto handle = std::coroutine_handle<TaskPromise<void>>::from_promise(*
this);
262template <
typename Fn>
264 return detail::WorkerAwaitable<std::decay_t<Fn>>(std::forward<Fn>(fn));
296template <
typename T = Value>
297 requires Marshalable<T>
299 return detail::PromiseAwaitable<T>(promise);
318template <
typename T = Value,
typename R>
319 requires(Marshalable<T> && std::is_same_v<std::remove_cvref_t<R>,
Result<Value>>)
322 return detail::PromiseAwaitable<T>(std::forward<R>(call).error());
323 return detail::PromiseAwaitable<T>(std::forward<R>(call).value());
A handle that settles a JavaScript Promise.
Definition Resolver.h:97
~Task()
Destructor.
Definition Task.h:144
void Start(Resolver resolver) &&
Start the Task and send its result to resolver.
Definition Task.h:158
Task & operator=(const Task &)=delete
Task & operator=(Task &&other) noexcept
Move assignment (discards this Task if it never started, and other becomes empty).
Definition Task.h:132
std::coroutine_handle< promise_type > Handle
Definition Task.h:120
detail::TaskPromise< T > promise_type
Definition Task.h:119
Task(const Task &)=delete
Task(Task &&other) noexcept
Move constructor (other becomes empty).
Definition Task.h:125
A handle to a live JavaScript value.
Definition Value.h:210
Type-checked JavaScript bridge between C++ and web pages.
Definition JSInterop.h:141
auto RunOnWorker(Fn &&fn)
Run a function on a background thread, then resume the coroutine on the Renderer's thread with its re...
Definition Task.h:263
auto Await(const Value &promise)
Wait for a JavaScript promise from a Task:
Definition Task.h:298
Expected< T, Error > Result
The result of a JavaScript operation that can fail: a T or a js::Error.
Definition Error.h:520
Root namespace for every public Ultralight type, function, and enumeration.