I’ve just released MquickjsEx, an Elixir library for embedding JavaScript execution directly in your BEAM process using MQuickJS. It’s a new project that got a huge attention on hackernews.
Why?
I built this to let LLMs execute JavaScript code securely with minimal overhead. When an LLM generates JS code for data transformation or custom logic, I wanted to run it in a sandbox where I control exactly what functions are available - no filesystem, no network, just the tools I expose.
I will be also experimenting if it would be possible to create a very fast Server Side Renderer for my other library, LiveVue.
What is it?
MquickjsEx wraps MQuickJS (Fabrice Bellard’s minimal JS engine) via NIFs. Similar to what pythonx does for Python, but the API is inspired by tv-labs/lua.
Key points:
- No external runtime - no Node.js, Bun, or Deno installation
- In-process - runs inside the BEAM via NIFs, no subprocess spawning
- Tiny footprint - MQuickJS can run in as little as 10KB RAM (default 64KB)
- Sandboxed - no filesystem or network access by default
- Bidirectional - call JS from Elixir and Elixir from JS
Usage
# Create context and evaluate code
{:ok, ctx} = MquickjsEx.new()
{:ok, 3} = MquickjsEx.eval(ctx, "1 + 2")
# Expose Elixir functions to JavaScript
ctx = MquickjsEx.set!(ctx, :fetch_data, fn [table] -> MyApp.Repo.all(table) end)
{result, _ctx} = MquickjsEx.eval!(ctx, "fetch_data('users').length")
# Define reusable API modules
defmodule MathAPI do
use MquickjsEx.API, scope: "math"
defjs add(a, b), do: a + b
end
{:ok, ctx} = MquickjsEx.new()
{:ok, ctx} = MquickjsEx.load_api(ctx, MathAPI)
{:ok, 5} = MquickjsEx.eval(ctx, "math.add(2, 3)")
Important Limitations
MQuickJS implements a subset of JavaScript close to ES5 with a stricter mode. You need to know these:
Arrays cannot have holes:
a = []
a[10] = 1; // TypeError - can only extend at end
[1, , 3] // SyntaxError
No direct eval:
eval('1 + 2'); // Forbidden
(1, eval)('1 + 2'); // OK (indirect eval)
No value boxing:
new Number(1) // Not supported
Limited Date support:
Only Date.now() works.
ASCII-only for some string ops:
toLowerCase() / toUpperCase() only handle ASCII.
Re-execution pattern for callbacks:
When JS calls an Elixir function, execution pauses, Elixir runs the callback, then JS re-executes from the start with cached results. This means your JS code should be idempotent - no side effects that accumulate on replay.
Installation
def deps do
[{:mquickjs_ex, "~> 0.1.0"}]
end
Full docs and more examples: GitHub - Valian/mquickjs_ex: Embedded JS runtime for Elixir based on MQuickJS.
I need to disclose, it was created by collaborating closely with Claude Code Opus 4.5, otherwise it would be not possible.
Feedback welcome - this is the first release. Hope you’ll like it!






















