A global JavaScript namespace for native functions and data.
A js::API gives page scripts access to your application's functions and data, much like browsers add built-in Web APIs such as console and document on top of core JavaScript.
Once attached to a View, the API provides its global namespace to your pages.
Define an API with a constant and a function, attach it to a View, and load a page:
app["version"] = "2.1.0";
app["add"] = [](double a, double b) { return a + b; };
if (app.AttachTo(view.get()))
view->LoadURL("file:///app.html");
A global JavaScript namespace for native functions and data.
Definition API.h:398
Page script accesses the namespace on window:
console.log(app.version); // "2.1.0"
app.add(2, 3); // 5
Binding Functions and Values
The C++ type you bind decides what the page gets:
| Binding | What the Page Gets |
| Callable | Function |
| Plain value | Read-only constant |
| Getter and setter | Live property |
| Async callable | Function returning a Promise |
| Bound class | Class constructible with new |
A dot in a path string (such as "fs.readFile") creates a child namespace object on the page.
Bind nested paths using dot notation and live properties using getters and setters:
app["fs.readFile"] = [](std::string path) { return ReadFile(path); };
app.BindProperty("volume", [] { return g_volume; },
[](double v) { g_volume = v; });
Attaching to a View
Call AttachTo() with a View before loading content. Every page the View loads from then on gets the API automatically, so you don't need to attach again after a navigation.
If you add, replace, or remove bindings after a page is loaded, that page keeps its current bindings until its next navigation. To adjust frame scope or mutability, pass AttachOptions to AttachTo() (see AttachFlags).
Allowed Pages and Origin Rules
By default, only local file:// pages and content loaded with View::LoadHTML() get the API.
Passing origin rules replaces the default policy completely. Only pages matching your rules get the API, so you must include "file://*" if you want local pages to retain access (see ultralight::OriginRules). For decisions origin rules can't express (such as checking a user setting at runtime), set a callback with js::SetInjectionFilter() to allow or withhold the API per page.
Specify origin rules in AttachOptions to allow a local development server alongside local pages:
if (app.AttachTo(view.get(),
{ .origin_rules = { "http://localhost:*", "file://*" } }))
view->LoadURL("http://localhost:5173/");
Emitting Events
Native code can push events to attached pages without polling. Events are delivered on the Renderer's thread during a later Renderer::Update().
Call Emit() from any thread with an event name and payload arguments:
app.Emit("saved", std::string("slot1.dat"));
Subscribe on the page using on() or once(), and remove listeners with off():
app.on("saved", (path) => refreshList(path));
Managing API Lifetime
A View keeps an API attached only while the js::API instance exists. Destroying the js::API detaches it from every View. Events stop reaching pages, and any calls to bound functions or class constructors that a page still holds throw a TypeError with code ULJS_DETACHED.
Hold the API as a class member to tie its lifetime to an owner and bind member functions with js::Bind():
class Game {
public:
explicit Game(
View* view) {
api_[
"showMenu"] =
js::Bind(
this, &Game::ShowMenu);
if (api_.AttachTo(view))
}
void ShowMenu();
private:
};
Web-page container rendered to an offscreen surface.
Definition View.h:483
virtual void LoadURL(const String &url)=0
Load a URL, the View will navigate to it as a new page.
auto Bind(T *instance, M method)
Bind a member function to an instance without writing a lambda.
Definition API.h:1435
- Note
- Once an API is attached to a View, you must bind and unbind only on the Renderer's thread.
- See also
- ultralight::OriginRules, js::SetInjectionFilter(), js::BindingGuard, js::ClassBuilder, js::TypeTraits, js::Diagnostics
|
| | API (const char *root_path, const APIOptions &options={}) |
| | Create an API rooted at a global namespace path.
|
| | ~API () |
| | Destructor (releases this handle).
|
| | API (API &&other) noexcept |
| | Move constructor (other becomes empty).
|
| API & | operator= (API &&other) noexcept |
| | Move assignment (releases the current handle, and other becomes empty).
|
| | API (const API &)=delete |
| API & | operator= (const API &)=delete |
| | operator bool () const |
| | Whether or not this API holds a handle (false if the root path was invalid or reserved, and after a move or LeakRef()).
|
| Binder | operator[] (const char *path) |
| | Get the Binder for a path relative to the root (see Binder).
|
template<typename Fn, typename... Anns>
requires (detail::Annotation<Anns> && ...) |
| void | Bind (const char *path, Fn &&fn, const Anns &... annotations) |
| | Bind a callable at a path (the explicit form of api[path] = fn, which also takes annotations).
|
template<typename T, typename M, typename... Anns>
requires (std::is_member_function_pointer_v<M> && (detail::Annotation<Anns> && ...)) |
| void | Bind (const char *path, T *receiver, M method, const Anns &... annotations) |
| | Bind a member function of an object at a path (the same as binding js::Bind(receiver, method)):
|
| template<typename T> |
| void | SetConstant (const char *path, T &&value) |
| | Set a constant at a path (the explicit form of api[path] = value).
|
| template<typename T> |
| ClassBuilder< T > | DefineClass (const char *path) |
| | Define a native class at a path, so page script can call its methods, read its properties, and construct it with new (when you declare a constructor).
|
| template<typename Getter, typename Setter = std::nullptr_t> |
| void | BindProperty (const char *path, Getter &&get, Setter &&set=nullptr) |
| | Bind a property with a getter and an optional setter.
|
template<typename... Args>
requires (Marshalable<detail::CapturedArg<Args>> && ...) |
| void | Emit (const char *event_path, Args &&... args) |
| | Emit an event to the page listeners subscribed with on or once (see Emitting Events in the class overview).
|
template<typename... Args, typename... Anns>
requires (detail::Annotation<Anns> && ...) |
| void | DefineEvent (const char *event_path, const Anns &... annotations) |
| | Declare an event and its payload types.
|
| bool | Unbind (const char *path) |
| | Remove the binding at a path, along with its metadata.
|
| std::string | schema () const |
| | Get the API's schema as JSON.
|
| bool | DumpSchema (const char *utf8_path) |
| | Write the JSON from schema() to a file.
|
| void | SetMetadata (const char *path, const char *metadata_json) |
| | Add schema metadata (eg, documentation) to the entry at a path.
|
| void | set_diagnostics (Diagnostics level) |
| | Set the diagnostics level (see Diagnostics).
|
| Diagnostics | diagnostics () const |
| | Get the effective diagnostics level.
|
| bool | AttachTo (View *view, const AttachOptions &options={}) |
| | Attach this API to a View.
|
| void | DetachFrom (View *view) |
| | Detach this API from a View.
|
| ULJSAPI | raw () const |
| | Get the underlying handle, for calls into the C API.
|
| ULJSAPI | LeakRef () |
| | Give up ownership of the underlying handle without releasing it (this API becomes empty).
|