Embedding

Embedding cookbook.

The preview API is synchronous, creator-thread-only and explicit about owned handles. These patterns show the intended host shape without inventing authority for files, networks or timers.

Evaluate and inspect failure

js_runtime *runtime = js_runtime_new();
js_value *result = NULL;
js_status status = js_eval(runtime, "throw new Error('boom')", &result);

if (status != JS_STATUS_OK) {
    const char *message = js_runtime_error(runtime);
    /* log or copy message before the next API operation */
    js_runtime_clear_error(runtime);
}

js_value_free(runtime, result);
js_runtime_free(runtime);

Inject structured host data

js_value *config = js_object_new(runtime);
js_value *port = js_number_new(runtime, 8080);
js_object_set(runtime, config, "port", port);
js_runtime_set_global(runtime, "config", config);

js_value_free(runtime, port);
js_value_free(runtime, config);

Returned handles are owned and tied to one runtime. Inputs must be live handles from that runtime; values never outlive it.

Install a native callback

static js_status add(js_runtime *runtime,
                     js_value *receiver,
                     const js_value *const *args,
                     size_t argc,
                     void *host_data,
                     js_value **result) {
    double left = 0, right = 0;
    if (argc != 2 ||
        js_value_get_number(runtime, args[0], &left) != JS_STATUS_OK ||
        js_value_get_number(runtime, args[1], &right) != JS_STATUS_OK) {
        return JS_STATUS_TYPE_ERROR;
    }
    *result = js_number_new(runtime, left + right);
    return *result ? JS_STATUS_OK : JS_STATUS_OUT_OF_MEMORY;
}

Callback receiver and arguments are borrowed for the invocation. A successful callback transfers one owned result handle to the engine. Same-thread re-entry is supported; asynchronous and cross-thread callbacks are not.

Contain untrusted work and recover

js_runtime_set_instruction_limit(runtime, 10000);
js_runtime_set_call_stack_limit(runtime, 128);
js_runtime_set_allocation_limit(runtime, 4 * 1024 * 1024);

js_status status = js_eval(runtime, "while (true) {}", &result);
if (status == JS_STATUS_LIMIT_EXCEEDED) {
    js_runtime_clear_error(runtime);
    js_runtime_set_instruction_limit(runtime, 20000);
    status = js_eval(runtime, "40 + 2", &result);
}
Containment is not a sandbox. JS++ grants no I/O authority itself, but a host callback can grant authority. Resource limits are deterministic synchronous execution controls, not process isolation or asynchronous cancellation.