6#include <Ultralight/CAPI/CAPI_JSAPI.h>
7#include <Ultralight/CAPI/CAPI_JSRuntime.h>
8#include <Ultralight/CAPI/CAPI_JSValue.h>
9#include <Ultralight/CAPI/CAPI_String.h>
11#include <Ultralight/detail/Exceptions.h>
21#include <initializer_list>
56 size_t index =
static_cast<size_t>(type);
167 explicit Context(
View* view) : handle_(view ? view->GetJSContext() : nullptr) {}
176 : handle_(value.
raw() ? ulJSValueGetContext(value.
raw()) : nullptr) {}
201 return Context(handle ? ulCreateJSContextRef(handle) :
nullptr);
208 : handle_(other.handle_ ? ulCreateJSContextRef(other.handle_) : nullptr) {}
213 Context(
Context&& other) noexcept : handle_(other.handle_) { other.handle_ =
nullptr; }
219 std::swap(handle_, other.handle_);
231 explicit operator bool()
const {
return handle_ && ulJSContextIsAlive(handle_); }
236 bool IsEmpty()
const {
return handle_ ==
nullptr; }
244 bool IsAlive()
const {
return handle_ && ulJSContextIsAlive(handle_); }
257 const char* source_url =
nullptr)
const {
259 return detail::EmptyHandleError();
260 ULString source = ulCreateStringUTF8(script.data(), script.size());
261 ULJSValue exception =
nullptr;
262 ULJSValue result = ulJSContextEvaluate(handle_, source, source_url, &exception);
263 ulDestroyString(source);
287 template <
typename T>
290 const char* source_url =
nullptr)
const {
293 return Unexpected<Error>(std::move(completion).error());
294 return completion.value().To<T>();
303 return Value::Adopt(ulJSContextGetGlobalObject(handle_));
324 ref.source_gone_ = handle_ && global.
IsEmpty();
338 template <
typename T>
340 using U = std::decay_t<T>;
341 detail::AssertInteropHeader<U>();
343 "no js::TypeTraits for T: use a supported built-in, make it a plain "
344 "aggregate struct, or specialize js::TypeTraits for it");
367 std::vector<ULJSValue>
raw(count);
368 for (
size_t i = 0; i < count; i++)
369 raw[i] = elements[i].
raw();
370 return Value::Adopt(ulCreateJSArray(handle_, count ?
raw.data() :
nullptr, count));
381 return MakeArray(elements.begin(), elements.size());
392 return MakeArray(elements.data(), elements.size());
409 return detail::EmptyHandleError();
410 ULString text = ulCreateStringUTF8(json.data(), json.length());
411 ULJSValue exception =
nullptr;
412 ULJSValue result = ulCreateJSValueFromJSON(handle_, text, &exception);
413 ulDestroyString(text);
443 template <
typename F>
445 using Fn = std::decay_t<F>;
446 static_assert(std::is_invocable_v<Fn&> || std::is_invocable_v<Fn&, Context&>,
447 "js::Context::PostTask takes a callable invocable with nothing or with "
449 ulJSContextPostTask(handle_, &TaskThunk<Fn>,
new Fn(std::forward<F>(task)),
450 &DeleteTaskCallable<Fn>);
467 ULJSPromiseResolver
raw =
nullptr;
468 ULJSValue promise = handle_ ? ulCreateJSPromise(handle_, &
raw) :
nullptr;
490 Value::Adopt(detail::WrapBufferThrough(handle_, buffer, [&](ULBuffer shared) {
491 return ulCreateJSArrayBufferFromBuffer(handle_, shared);
517 template <
typename T>
520 Value::Adopt(ulCreateJSTypedArray(handle_, detail::kTypedArrayTypeOf<T>, length)));
535 template <
typename T>
540 Value::Adopt(detail::WrapBufferThrough(handle_, buffer, [&](ULBuffer shared) {
541 return ulCreateJSTypedArrayFromBuffer(handle_, detail::kTypedArrayTypeOf<T>, shared);
569 template <
typename Fn>
571 using F = std::decay_t<Fn>;
572 using Traits = detail::CallableTraits<F>;
573 using Shape = detail::ParamShape<typename Traits::Params>;
574 static_assert(!Shape::kHasResolver
575 && !detail::kIsAsyncReturn<typename Traits::Return>,
576 "MakeFunction binds synchronous callables; bind async forms (js::Task, "
577 "trailing js::Resolver) through js::API");
578 [&]<
size_t... Is>(std::index_sequence<Is...>) {
579 (detail::ValidateParam<std::tuple_element_t<Is, typename Shape::Converted>>(), ...);
580 }(std::make_index_sequence<Shape::kCount> {});
583 auto* bound =
new detail::BoundCallable<F> { std::forward<Fn>(fn),
584 std::string(name ? name :
""), {}, {} };
585 return Value::Adopt(ulCreateJSFunction(handle_, name, &detail::SyncTrampoline<F>, bound,
586 &detail::DestroyBoundCallable<F>));
600 ULJSHandleStats raw_stats = {};
601 if (handle_ && ulJSContextGetHandleStats(handle_, &raw_stats)) {
603 for (
size_t i = 0; i < kULJSType_Count; i++)
631 template <
typename Fn>
632 static void TaskThunk(
void* user_data,
ULJSContext ctx) {
633 Fn& fn = *
static_cast<Fn*
>(user_data);
635 ultralight::detail::CallCatchingExceptions(
637 if constexpr (std::is_invocable_v<Fn&, Context&>) {
644 [](
const char* what) { detail::LogNativeException(
"js::Context::PostTask", what); });
647 template <
typename Fn>
648 static void DeleteTaskCallable(
void* user_data) {
649 delete static_cast<Fn*
>(user_data);
struct C_JSContext * ULJSContext
Opaque handle to a JavaScript execution context (one page's script world in one View).
Definition View.h:25
A nullable smart pointer.
Definition RefPtr.h:126
Web-page container rendered to an offscreen surface.
Definition View.h:483
Handle to a JavaScript ArrayBuffer for sharing raw binary memory with the page.
Definition Buffer.h:88
ArrayBuffer()=default
Create an empty ArrayBuffer wrapper.
Context context() const
Get the calling context, to create values in it or to keep it after the call:
Definition Context.h:655
JavaScript execution environment for a page.
Definition Context.h:151
Value::Ref operator[](const char *name) const
Access a property of the global object (ctx["fn"](args) is the same as ctx.GlobalObject()["fn"](args)...
Definition Context.h:320
Value MakeArray(std::span< const Value > elements) const
Create a new JavaScript Array from a range (eg, a std::vector<js::Value>).
Definition Context.h:391
TypedArray< T > MakeTypedArray(const RefPtr< ultralight::Buffer > &buffer) const
Create a typed array of elements of type T that shares a Buffer's bytes with JavaScript without copyi...
Definition Context.h:536
Value Make(T &&value) const
Convert a C++ value to a JavaScript value through js::TypeTraits.
Definition Context.h:339
Value GlobalObject() const
Get the global object.
Definition Context.h:302
ArrayBuffer MakeArrayBuffer(const RefPtr< ultralight::Buffer > &buffer) const
Create an ArrayBuffer that shares a Buffer's bytes with JavaScript without copying.
Definition Context.h:486
Value MakeArray(const Value *elements, size_t count) const
Create a new JavaScript Array.
Definition Context.h:364
Result< Value > Evaluate(std::string_view script, const char *source_url=nullptr) const
Run a script and get its completion value.
Definition Context.h:256
Value MakeArray(std::initializer_list< Value > elements) const
Create a new JavaScript Array from a brace list (eg, ctx.MakeArray({ a, b })).
Definition Context.h:380
Context(const Context &other)
Copy constructor (refers to the same context).
Definition Context.h:207
ULJSContext raw() const
Get the C API handle without transferring ownership.
Definition Context.h:615
Context()=default
Create an empty Context.
Context & operator=(Context other) noexcept
Assignment (copies or moves other into this Context).
Definition Context.h:218
Context(Context &&other) noexcept
Move constructor (other becomes empty).
Definition Context.h:213
static Context Adopt(ULJSContext handle)
Take ownership of a context handle from the C API.
Definition Context.h:190
bool IsEmpty() const
Whether or not this Context holds nothing.
Definition Context.h:236
bool IsAlive() const
Whether or not this Context's page is still alive (the same test as operator bool).
Definition Context.h:244
HandleStats GetHandleStats() const
Count the live handles on this context, for finding leaks.
Definition Context.h:598
Value MakeObject() const
Create a new empty JavaScript object.
Definition Context.h:353
PendingPromise MakePromise() const
Create a pending Promise and the Resolver that settles it, to hand a Promise to the page outside a bo...
Definition Context.h:466
Context(View *view)
Get the context of a View's main frame.
Definition Context.h:167
Value MakeFunction(const char *name, Fn &&fn) const
Create a JavaScript function backed by a C++ callable, to hand to the page (eg, as a callback).
Definition Context.h:570
Context(const Value &value)
Get the context a value belongs to.
Definition Context.h:175
~Context()
Destructor (releases this handle).
Definition Context.h:226
void PostTask(F &&task) const
Run a function with this context during a later Renderer::Update().
Definition Context.h:444
Result< T > Evaluate(std::string_view script, const char *source_url=nullptr) const
Run a script and convert its completion value to a C++ type (see Value::To()).
Definition Context.h:289
Result< Value > MakeFromJSON(std::string_view json) const
Create a value from JSON text (the reverse of Value::ToJSON()):
Definition Context.h:407
static Context FromBorrowed(ULJSContext handle)
Add a reference to a context handle the library owns (eg, the context a C API callback receives) so y...
Definition Context.h:200
ArrayBuffer MakeArrayBuffer(const void *bytes, size_t length) const
Create an ArrayBuffer holding a copy of the given bytes.
Definition Context.h:505
ULJSContext LeakRef()
Give up ownership of the C API handle and return it.
Definition Context.h:622
TypedArray< T > MakeTypedArray(size_t length) const
Create a typed array of zero-filled elements of type T (eg, MakeTypedArray<float>(4) creates a Float3...
Definition Context.h:518
static Error AdoptException(ULJSValue exception)
Create an error from a JavaScript exception, taking ownership of the handle.
Definition Error.h:131
static Error PageGone()
Create a page-gone error (is_page_gone() returns true).
Definition Error.h:122
A handle that settles a JavaScript Promise.
Definition Resolver.h:97
static Resolver Adopt(ULJSPromiseResolver handle)
Take ownership of a resolver handle from the C API.
Definition Resolver.h:120
Handle to a JavaScript typed array on a page.
Definition Buffer.h:203
TypedArray()=default
Create an empty TypedArray wrapper.
A reference to a property of a Value (returned by Value::operator[]).
Definition Value.h:906
A handle to a live JavaScript value.
Definition Value.h:210
static Value Adopt(ULJSValue handle)
Take ownership of a handle from the C API without adding a reference.
Definition Value.h:799
bool IsEmpty() const
Whether or not this Value holds nothing (see "Handle States" above).
Definition Value.h:249
Value()
Create an empty Value.
Definition Value.h:215
Whether or not js::TypeTraits can convert T (ignoring const, volatile, and references).
Definition TypeTraits.h:275
Type-checked JavaScript bridge between C++ and web pages.
Definition JSInterop.h:141
Type
The type of a JavaScript value.
Definition Value.h:95
@ Symbol
Definition Value.h:102
@ String
Definition Value.h:101
@ Object
Definition Value.h:104
@ BigInt
Definition Value.h:103
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.
Counts of the live handles on one context, for finding leaks (see Context::GetHandleStats()).
Definition Context.h:43
size_t weak_refs
Live weak references (0 once the context is gone).
Definition Context.h:46
size_t count(Type type) const
Get the number of live value handles of one type.
Definition Context.h:55
size_t ProtectedEstimate() const
Count the value handles that keep something from being garbage collected (strings,...
Definition Context.h:66
size_t total_values
Live value handles.
Definition Context.h:44
size_t values_by_type[kULJSType_Count]
Live value handles by js::Type (see count()).
Definition Context.h:45
A new pending Promise and the Resolver that settles it (see Context::MakePromise()).
Definition Context.h:75
Value promise
The Promise to hand to the page.
Definition Context.h:76
Resolver resolver
Settles promise (from any thread).
Definition Context.h:77
Type conversions between C++ and JavaScript across the bridge.
Definition TypeTraits.h:240