docs
Loading...
Searching...
No Matches
Task< T >

#include <Ultralight/js/Task.h>

Overview

template<typename T = void>
class ultralight::js::Task< T >

A coroutine that returns a JavaScript Promise to the page.

A Task is a C++20 coroutine. Returning one from a bound function gives the page a JavaScript Promise that settles during a later Renderer::Update() after the coroutine finishes.

The coroutine executes sequentially from top to bottom, pausing at each co_await without blocking the Renderer's thread.

Return a Task from a bound function to perform background work and return a Promise:

app["loadSave"] = [](std::string slot) -> js::Task<SaveData> {
SaveData data =
co_await js::RunOnWorker([slot] { return ReadSaveFromDisk(slot); });
if (!data.valid)
co_return js::Error::Make(js::ErrorType::Error, "save is corrupt")
.WithCode("BAD_SAVE");
co_return data;
};
static Error Make(ErrorType type, std::string message)
Create a native error of any type.
Definition Error.h:168
Error WithCode(std::string code) &&
Add a code that page script gets as the error's code property when it's thrown.
Definition Error.h:234
A coroutine that returns a JavaScript Promise to the page.
Definition Task.h:112
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
@ Error
A plain Error, or an error type with no dedicated constant.
Definition Error.h:55

Page script awaits the returned Promise normally:

const save = await app.loadSave("slot1");

JavaScript Equivalents

Task maps standard JavaScript asynchronous syntax directly to C++ coroutine keywords:

JavaScript C++
async function [](...) -> js::Task<T>
return value; co_return value;
throw new Error() co_return js::Error::Make(...)
await promise co_await js::Await<T>(promise)

Awaiting Page Promises

Pass a call to a page function to Await() to invoke it and await its returned Promise:

app["confirm"] = [](js::Value ask) -> js::Task<bool> {
js::Result<bool> answer = co_await js::Await<bool>(ask("Overwrite?"));
co_return answer ? *answer : false;
};
A handle to a live JavaScript value.
Definition Value.h:210
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

The returned Result holds the resolved value converted to the requested type, or an Error holding the rejection reason, a type conversion failure, or a page-gone error if the page navigates away first.

Threads and Timing

Coroutines follow these execution and threading rules:

  • The coroutine body runs on the Renderer's thread. It starts synchronously inside the page's call up to the first co_await, and resumes on the Renderer's thread after each await.
  • Worker threads must not touch JavaScript. Use RunOnWorker() to run background operations on the worker pool, passing plain C++ data in and out without touching Value or Context.
  • The Promise settles during a later Renderer::Update(). Completions arrive on the Renderer's thread when your frame loop updates the renderer.
  • Parameters stay valid for the entire Task. Arguments, references, and views like std::string_view and std::span remain valid across every co_await until the task completes.

Page Navigation and API Teardown

Waiting tasks handle navigation and destruction safely:

  • A navigating page lets waiting tasks resume. Awaiting a Promise from that page yields a page-gone error, operations on its values fail safely, and the library discards the task's final result when it completes.
  • Destroying the API cancels waiting tasks. Once the last owning handle to the API is destroyed, waiting tasks don't resume after their next co_await, and their Promises reject with a TypeError whose code is "ULJS_DETACHED".
Note
A Task<void> can't co_return an error. Return Task<bool> instead or use a Resolver to report failures from a void operation.
See also
Resolver, RunOnWorker(), Await()

Public Types

using promise_type = detail::TaskPromise<T>
using Handle = std::coroutine_handle<promise_type>

Public Member Functions

 Task (Task &&other) noexcept
 Move constructor (other becomes empty).
 Task (const Task &)=delete
Task & operator= (const Task &)=delete
Task & operator= (Task &&other) noexcept
 Move assignment (discards this Task if it never started, and other becomes empty).
 ~Task ()
 Destructor.
void Start (Resolver resolver) &&
 Start the Task and send its result to resolver.
auto operator co_await () &&
 Run this Task from another Task and wait for it (eg, co_await std::move(task)).
template<typename U = T>
void operator co_await () &
 Awaiting a Task by name is a compile error: a Task runs once, so write co_await std::move(task).

Member Typedef Documentation

◆ Handle

template<typename T = void>
using Handle = std::coroutine_handle<promise_type>

◆ promise_type

template<typename T = void>
using promise_type = detail::TaskPromise<T>

Constructor & Destructor Documentation

◆ Task() [1/2]

template<typename T = void>
Task ( Task< T > && other)
inlinenoexcept

Move constructor (other becomes empty).

◆ Task() [2/2]

template<typename T = void>
Task ( const Task< T > & )
delete

◆ ~Task()

template<typename T = void>
~Task ( )
inline

Destructor.

A Task that never started is discarded without running its body.

Member Function Documentation

◆ operator co_await() [1/2]

template<typename T = void>
template<typename U = T>
void operator co_await ( ) &
inline

Awaiting a Task by name is a compile error: a Task runs once, so write co_await std::move(task).

◆ operator co_await() [2/2]

template<typename T = void>
auto operator co_await ( ) &&
inline

Run this Task from another Task and wait for it (eg, co_await std::move(task)).

Returns
Returns an awaitable that yields a Result<T>.

◆ operator=() [1/2]

template<typename T = void>
Task & operator= ( const Task< T > & )
delete

◆ operator=() [2/2]

template<typename T = void>
Task & operator= ( Task< T > && other)
inlinenoexcept

Move assignment (discards this Task if it never started, and other becomes empty).

◆ Start()

template<typename T = void>
void Start ( Resolver resolver) &&
inline

Start the Task and send its result to resolver.

This Task becomes empty, and the coroutine frees itself when it finishes.

Parameters
resolverThe Resolver that settles with the result.
Precondition
Must be called on the Renderer's thread.

The documentation for this class was generated from the following file: