Quicksand (quicksand v0.1.1)

Copy Markdown View Source

Sandboxed JavaScript execution via QuickJS-NG.

Provides eval/2 for simple evaluation and eval/3 for evaluation with pre-registered Elixir callback functions callable from JS. Each runtime runs on a dedicated OS thread with configurable memory and time limits.

Reserved JS globals

When using eval/3 in callback mode, quicksand installs four globalThis.__quicksand_* properties on the JS runtime: __quicksand_make_wrapper, __quicksand_dispatch, __quicksand_cb_args, __quicksand_cb_result. User JavaScript must not overwrite these or the callback machinery silently breaks for that runtime. See README.md for the full list and rationale.

Summary

Functions

Check if a runtime is alive.

Evaluate JavaScript code and return the result.

Evaluate JavaScript code with pre-registered Elixir callbacks.

Start a new JavaScript runtime on a dedicated OS thread.

Stop a runtime. Idempotent — safe to call multiple times.

Types

js_result()

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

Functions

alive?(runtime)

@spec alive?(runtime()) :: boolean()

Check if a runtime is alive.

eval(runtime, code)

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

Evaluate JavaScript code and return the result.

{:ok, 3} = Quicksand.eval(rt, "1 + 2")

eval(runtime, code, callbacks)

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

Evaluate JavaScript code with pre-registered Elixir callbacks.

Each callback receives its arguments as a list and must return {:ok, value} or {:error, reason}. Errors become JS exceptions.

callbacks = %{
  "add" => fn [a, b] -> {:ok, a + b} end
}
{:ok, 5} = Quicksand.eval(rt, "add(2, 3)", callbacks)

start(opts \\ [])

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

Start a new JavaScript runtime on a dedicated OS thread.

Options

  • :timeout — max eval time in milliseconds (default 30_000)
  • :memory_limit — max JS heap in bytes (default 268_435_456)
  • :max_stack_size — max JS stack in bytes (default 1_048_576)

stop(runtime)

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

Stop a runtime. Idempotent — safe to call multiple times.