OnchainJs.Runtime (onchain_js v0.2.0)

Copy Markdown View Source

Thin wrapper over QuickBEAM providing supervised JavaScript runtimes for onchain_js.

Each runtime is a GenServer holding a persistent QuickJS-NG context. Functions, modules, and globals survive across eval/2 and call/3 calls, so the typical pattern is to start a runtime once, load a JS bundle, then invoke library functions on demand.

Defaults to the :browser API surface (fetch, crypto, WebSocket, URL, TextEncoder, document) since the npm packages this project targets — solc-js, Uniswap SDK, DeFiSaver, merkletreejs — ship browser bundles and assume those globals exist. Callers may override any option by passing them through to start_link/1.

Browser-bundle stubs

Browser bundles routinely reference self, window, navigator, and location. The :browser API surface does NOT define these — they must be stubbed before the bundle is loaded. apply_browser_stubs/1 performs the standard QuickBEAM-recommended stub sequence in one call.

Example

{:ok, rt} = OnchainJs.Runtime.start_link()
:ok = OnchainJs.Runtime.apply_browser_stubs(rt)
{:ok, 2} = OnchainJs.Runtime.eval(rt, "1 + 1")
:ok = OnchainJs.Runtime.stop(rt)

Supervision

Runtimes are typically spawned dynamically via OnchainJs.RuntimeSupervisor:

{:ok, pid} =
  DynamicSupervisor.start_child(
    OnchainJs.RuntimeSupervisor,
    {OnchainJs.Runtime, []}
  )

Summary

Functions

Apply the standard browser-global stub sequence to runtime.

Call a global JavaScript function by name.

Call a global JavaScript function by name with options.

Evaluate JavaScript source in runtime.

Evaluate JavaScript source in runtime with options.

Start a new supervised QuickBEAM runtime.

Stop runtime and free its resources.

Types

js_result()

@type js_result() :: {:ok, term()} | {:error, QuickBEAM.JSError.t()}

runtime()

@type runtime() :: GenServer.server()

Functions

apply_browser_stubs(runtime)

@spec apply_browser_stubs(runtime()) :: :ok | {:error, term()}

Apply the standard browser-global stub sequence to runtime.

Stubs:

  • globalThis.self = globalThis;
  • globalThis.window = globalThis;
  • navigator = %{"userAgent" => "OnchainJs"}
  • location = %{"protocol" => "https:"}

self and window MUST literally BE globalThis (not the string "globalThis"), so they're set via eval/2 rather than set_global/3 — the latter would convert the atom value to a string and break libraries that perform self === globalThis identity checks.

Returns :ok on success, {:error, reason} on failure.

call(runtime, fn_name, args)

@spec call(runtime(), String.t(), [term()]) :: js_result()

Call a global JavaScript function by name.

Equivalent to QuickBEAM.call/3. Promise-returning functions are awaited automatically.

call(runtime, fn_name, args, opts)

@spec call(runtime(), String.t(), [term()], keyword()) :: js_result()

Call a global JavaScript function by name with options.

Equivalent to QuickBEAM.call/4. Supports :timeout (ms).

eval(runtime, code)

@spec eval(runtime(), String.t()) :: js_result()

Evaluate JavaScript source in runtime.

Equivalent to QuickBEAM.eval/2. Top-level await is supported; the promise is awaited before returning.

eval(runtime, code, opts)

@spec eval(runtime(), String.t(), keyword()) :: js_result()

Evaluate JavaScript source in runtime with options.

Equivalent to QuickBEAM.eval/3. Supports :timeout (ms) and :vars (map of globals injected for the duration of the evaluation).

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Start a new supervised QuickBEAM runtime.

Defaults apis: :browser. Callers may override any QuickBEAM option by including it in opts (the caller's value wins).

See QuickBEAM.start/1 for the full list of options (:name, :script, :handlers, :define, :memory_limit, :max_stack_size, etc.).

stop(runtime)

@spec stop(runtime()) :: :ok

Stop runtime and free its resources.

Equivalent to QuickBEAM.stop/1. Returns :ok.