Put JavaScript inside a native application.
The embedding surface is deliberately small and C-compatible. The bounded preview now makes lifetime, errors, roots, callbacks, re-entry and resource limits explicit.
js.h.#include <js.h>
js_runtime *runtime = js_runtime_new();
if (!runtime) {
return 1;
}
js_value *result = NULL;
js_status status = js_eval(runtime, "40 + 2", &result);
js_value_free(runtime, result);
js_runtime_free(runtime);
Lifecycle rules
- Public values are owning handles tied to exactly one runtime.
- Values cannot outlive their runtime or cross into another runtime.
- Errors are runtime-owned, retrievable and explicitly clearable.
- Native callback arguments and receiver are borrowed for that invocation.
- A successful callback transfers one owned result handle to the engine.
- Same-thread re-entry is supported; operations remain creator-thread-only.
- No C++ exception or private C++ type crosses the public C boundary.
Host responsibilities
Filesystems, networking, timers, environment variables and module loading policy belong to the embedding host. JS++ supplies language/runtime machinery and explicit hooks; it does not silently become an operating-system framework.
Native functions
Native callbacks, arguments, properties, exceptions, host data, same-thread re-entry and runtime-rooted handles are implemented through the ordinary VM call path. See the embedding cookbook for concrete patterns and C API reference for the ownership boundary.
Embedded preview contract
The qualified milestone is deliberately narrower than general ECMAScript compatibility: a C or C++ host can exchange values, install and call native functions, inspect exceptions, enforce resource limits and tear down safely through a packaged public ABI.
The definition campaign is EP0 contract inventory, EP1 host values, EP2 calls and callbacks, EP3 containment, EP4 packaging/ABI and EP5 preview-candidate evidence. Promises, modules, browser APIs and Node APIs are outside the initial contract unless independently promoted.
EP0 complete: the machine-readable contract targets Linux C11/C++17 consumers and names one frozen public-header-only C demonstration. EP1-EP5 have now closed its host-value, callback, containment, packaging and candidate-evidence gates.
EP1 host values
The C API now creates undefined, null, boolean, number, string, object and array values. Hosts can read and write bounded own-data object properties and array elements, including sparse length. Every returned value is an owning handle tied to one runtime; inputs must be live handles from that same runtime.
Calls, native callbacks, accessors through the host boundary and callback re-entry remain EP2 rather than being implied by data access.
EP2 calls and callbacks
The host can now call JavaScript functions and install native callbacks with host data. Callback receiver and arguments are borrowed for that invocation; a successful callback transfers one owned result handle to the engine. Same-thread re-entry is supported without allowing nested collection to invalidate the outer VM.
Native failures become JavaScript TypeErrors, while uncaught JavaScript errors expose located stack text and a retrievable thrown value. This is synchronous and creator-thread-only; async and cross-thread callbacks are not implied.
EP3 containment
Hosts can configure per-runtime instruction and call-stack limits plus a cumulative engine-allocation limit. Instruction or stack exhaustion returns JS_STATUS_LIMIT_EXCEEDED; allocation exhaustion returns JS_STATUS_OUT_OF_MEMORY. Raising or disabling the relevant limit allows the same runtime to evaluate successfully afterward.
The preview API is synchronous, so it does not claim asynchronous cancellation. It also grants no filesystem, network, timer, environment or module-loading authority.
EP5 candidate
The bounded Linux candidate is qualified at 171/171. Hosts can install and retrieve globals, including structured values and native callbacks. The frozen C host exercises closures, an array callback, a located Error, containment recovery and 250 repeated evaluations.
Static and shared consumers, ASan/UBSan and 400 deterministic malformed mutations pass. LeakSanitizer remains an external confirmation because it cannot start under the managed ptrace runner. Promises, jobs, modules, proxies, typed arrays, weak references, Intl and browser/Node APIs remain excluded.