quickjs-rs
Sandboxed JavaScript and TypeScript execution for Python, running QuickJS inside a WebAssembly sandbox.
Repository Health
Technical Analysis
quickjs-rs lets Python code execute untrusted JavaScript (and inline TypeScript) inside a WebAssembly sandbox. It compiles quickjs-ng, a maintained QuickJS fork, to wasm32-wasip1 via rquickjs and drives it with wasmtime, so the guest runs fully isolated from the host with no ambient filesystem or network access.
The package ships as a single universal pure-Python wheel that bundles the guest .wasm artifacts, with wasmtime as its only runtime dependency. It exposes an ergonomic Runtime and Context API, supports registering Python callables as JS globals, async evaluation with top-level await, ES module loading through host callbacks, and OXC-backed TypeScript type stripping.
What You Get
- A Runtime and Context API for evaluating JavaScript from Python
- WebAssembly-based isolation with no ambient host access
- Registration of Python callables (sync and async) as JavaScript globals
- Async evaluation with support for top-level await
- ES module loading through host normalize/load callbacks and inline TypeScript type stripping
- A single universal pure-Python wheel with wasmtime as the only runtime dependency
Common Use Cases
- Running untrusted or user-supplied JavaScript safely from a Python service
- Executing agent- or LLM-generated JS/TS code in an isolated sandbox
- Embedding a JavaScript scripting layer inside a Python application
- Evaluating small JS snippets with controlled resource limits
Under The Hood
Architecture — The Python package (quickjs_rs/) is a thin, well-factored host layer over a WebAssembly guest. runtime.py and context.py expose the Runtime/Context objects; _wasmtime.py and _engine.py bridge into the wasmtime-executed guest; globals.py and handle.py marshal Python callables and values across the host/guest boundary via handles; _transform.py/transforms.py drive a separate OXC-backed WASM module that strips TypeScript types before QuickJS sees the code. The guest itself is built from Rust crates under crates/quickjs-wasm (rquickjs + quickjs-ng) and crates/quickjs-wasm-transform, compiled to wasm32-wasip1.
Tech Stack — Python 3.11+ with a single runtime dependency, wasmtime>=45. Built with hatchling and a custom hatch_build.py hook that produces and force-includes the .wasm guest artifacts. The guest is Rust compiled to WebAssembly. Dev tooling includes pytest, pytest-asyncio, pytest-cov, ruff, and mypy, plus codspeed/matplotlib for benchmarks.
Code Quality — The test suite is thorough for an alpha project, with dedicated files for async execution, host functions, exceptions, isolation, resource limits, globals, and handles. The package ships py.typed and is type-checked with mypy and linted with ruff. Isolation and limits are explicitly tested, reflecting the security-sensitive nature of the sandbox.
API Design — The public API is context-manager oriented and reads naturally: open a Runtime, open a Context, call ctx.eval(...) or await ctx.eval_async(...), and decorate Python functions with @ctx.function to expose them as JS globals. Module resolution is delegated to host normalize/load callbacks so the caller owns all policy, keeping the core API small while remaining flexible.