Embedding ES Runtime

ES Runtime ships as an embeddable Rust library (es-runtime) in addition to the standalone esrun CLI. The library is built for hosts that need to run untrusted or third-party JavaScript inside their own process — with explicit control over what that code can reach.

Embedder API — not finalized

The Rust embedding API is still being shaped. This page explains the model and what to expect; a full guide with code examples, capability wiring, and provider injection will replace it soon.

Two shapes, one core

Both the CLI and the library share the same V8 engine, runtime: modules, and Web-standard globals. The difference is who grants access:

ShapeWho grants capabilitiesTypical use
esrun CLIGrants all capabilities automaticallyScripts, local tools, servers you trust
Embeddable libraryThe host (your Rust code) grants exactly what guest code needsPlugins, sandboxes, policy-driven execution

See the Security model for how capabilities and the filesystem root jail work in practice.

What embedding looks like

At a high level, a host application:

  1. Creates a Runtime with injected providers (filesystem, network, timers, …).

  2. Grants capabilities — only the powers guest code is allowed to use.

  3. Loads and evaluates guest modules (ESM only).

  4. Drives the event loop by calling tick() on a schedule the host owns — no background thread is started for you.

That driven model is intentional: your application keeps control of scheduling, threading, and lifetime. Guest async work (Promises, timers, I/O) advances when you tick the runtime.

Layer A today, Layer B tomorrow

The current library is Layer A — a single isolate the host ticks. Layer B (the "es-vm" multi-isolate layer, including Workers) is on the roadmap and will build on the same capability model. See Scope & non-goals.

Deny-by-default

Unlike the CLI, the embeddable library starts with no host access. Guest code can compute, but importing runtime:fs or calling fetch throws NotAllowedError until the host grants the matching capability.

The host also controls:

  • Which providers back each capability (real disk, in-memory vfs, mocked net, …)

  • The filesystem root jail — where module resolution and file I/O are confined

  • The environment view — what runtime:process exposes to guest code

For the mental model and capability table, start with Security model and Module system.

Extending the host

Guest code cannot load native addons or call FFI. The supported extension path is Rust-side providers: implement the provider traits, wire them into the runtime, and gate them with capabilities. That keeps the trusted surface small and auditable.

Until the full guide lands

Use these pages to understand the JavaScript side of embedding (what guest code sees and how it behaves):

For Rust crate layout and dependency direction, see the ARCHITECTURE.md and README in the repository.

Stay tuned

The upcoming embedder guide will cover Runtime construction, granting capabilities, custom providers, snapshot boot, and a minimal end-to-end Rust + JavaScript example. This page will be updated in place — the URL will not change.

Last updated on
Edit this page