The JavaScript execution engine for JetCrab - our Bun engine equivalent.
Chitin is the core JS engine that powers JetCrab. Like Bun uses JavaScriptCore, JetCrab uses Chitin: a fast, portable, WASM-based engine for parsing and executing JavaScript.
| Component | Status | Notes |
|---|---|---|
| Architecture | ✅ Complete | Modular bindings/, Builder Config, wasmtime integration. |
| CLI Integration | ✅ Complete | repl, run, eval fully wired to JetCrabRuntime. |
| Host Bindings | ✅ Implemented | fs: read file, canonicalize (write to guest buffer). net: fetch HTTP(S), _host_fetch_result(id, buf, cap) for body. Prelude runs on first evaluate(). |
| WASM Binary | Optional | Use quickjs.wasm (or stub) that exports the Guest ABI. Without it, evaluate() returns placeholder. |
| Memory Model | OK | Host writes source at offset 0; guest writes result at RESULT_OFFSET; host reads via get_result. |
Chitin is the core execution engine for the JetCrab Runtime. It is designed as a lightweight, embeddable library that wraps a WebAssembly (WASM) runtime to execute JavaScript code.
Unlike traditional JavaScript runtimes that bind directly to C++ engines like V8 or JavaScriptCore, Chitin leverages wasmtime to run a JavaScript engine (such as QuickJS) compiled to WASM. This architecture provides several key benefits:
- Sandboxing: JavaScript code executes within a secure WASM sandbox, isolating it from the host system.
- Portability: The engine runs anywhere
wasmtimeis supported, without requiring complex build chains or platform-specific linkers. - Modularity: The underlying JavaScript engine can be swapped by changing the WASM binary.
Chitin exposes a high-level API for initializing the engine, managing configuration, and executing code.
- JetCrabEngine: The main entry point. It manages the WASM
Store,Linker, andModule. - EngineConfig: Configuration options for memory limits, execution time, and available features.
Add chitin to your Cargo.toml:
[dependencies]
chitin = { path = "path/to/chitin" }Initialize and use the engine:
use chitin::{JetCrabEngine, EngineConfig};
#[tokio::main]
async fn main() -> Result<(), String> {
let mut engine = JetCrabEngine::new();
engine.init()?;
let result = engine.evaluate("2 + 2").await?;
println!("Result: {}", result);
Ok(())
}Chitin is built on a "Dual-Standard" architecture:
-
Host Compliance (WebAssembly Core):
- Powered by
wasmtime(v22.0). - Fully compliant with the W3C WebAssembly Core Specification.
- Supports WASI (WebAssembly System Interface) for secure system access.
- Powered by
-
Guest Compliance (ECMAScript/JavaScript):
-
Compliance depends on the loaded WASM engine (e.g., QuickJS, SpiderMonkey).
-
Goal: 100% ECMA-262 (ES2025) compliance.
-
Strategy: Chitin injects a
prelude.jspolyfill at startup to add bleeding-edge features (likeSet.prototype.union) that the raw engine might lack. -
Strategy: Chitin injects a
prelude.jspolyfill at startup to add bleeding-edge features (likeSet.prototype.union) that the raw engine might lack.
-
| Category | Status | Provider | Examples |
|---|---|---|---|
| Syntax | ✅ 100% | WASM Engine | async/await, class, let/const, ?. |
| Standard Lib | ✅ 100% | WASM Engine | Map, Set, Promise, JSON, Math |
| ESNext | 🚧 90% | Chitin Polyfill | Set.union, Temporal (planned), Decorators |
| System I/O | 🚧 Partial | Chitin Host | fs.read (mapped), console.log (mapped) |
| Browser APIs | ❌ N/A | N/A | window, document, DOM (This is a Server Runtime) |
To build the library:
cargo build --releaseGuests that link against Chitin's env module can use:
-
_host_fs_read(path_ptr, path_len, buf_ptr, buf_cap) -> i32
Reads file at path from guest memory. Writes file content into guest buffer atbuf_ptr(maxbuf_capbytes). Returns bytes written, or-1on error. -
_host_fs_canonicalize(path_ptr, path_len, buf_ptr, buf_cap) -> i32
Canonicalizes path. Writes result path (UTF-8) into buffer atbuf_ptr. Returns bytes written, or-1on error. -
_host_fs_write(path_ptr, path_len, data_ptr, data_len) -> i32
Writes data to file. Returns0on success or-1on error. -
_host_fs_exists(path_ptr, path_len) -> i32
Returns1if path exists,0otherwise. -
_host_fs_mkdir(path_ptr, path_len) -> i32
Creates directory. Returns0on success or-1on error. -
_host_fs_readdir(path_ptr, path_len, buf_ptr, buf_cap) -> i32
Reads directory entries (newline-separated names). Returns bytes written or-1on error. -
_host_fs_unlink(path_ptr, path_len) -> i32
Removes file. Returns0on success or-1on error. -
_host_fs_rmdir(path_ptr, path_len) -> i32
Removes empty directory. Returns0on success or-1on error. -
_host_fetch(url_ptr, url_len, opt_ptr, opt_len) -> i32
Performs HTTP(S) GET. Returns a fetch id (non-negative). Use_host_fetch_resultto retrieve the body. -
_host_fetch_result(id, buf_ptr, buf_cap) -> i32
Copies the response body for fetchidinto buffer atbuf_ptr. Returns bytes written, or-1if id is invalid or buffer too small.
For evaluate(source) to run code and return the result string, the WASM module (e.g. quickjs.wasm) must export:
-
memory(WebAssembly Memory)
Linear memory. Host writes the JS source at offset0(UTF-8 bytes). Guest may write the evaluation result at offset0x10000(RESULT_OFFSET) forget_resultto read. -
eval(ptr: i32, len: i32) -> i32
Evaluates the JavaScript code in memory at[ptr, ptr+len). Returns0on success or non-zero on error. The guest should write the result (e.g. string representation) into the result area soget_resultcan return it. -
get_result(ptr: i32, max_len: i32) -> i32
Writes the last evaluation result into memory at[ptr, ptr+max_len). Returns the number of bytes written. Host calls this withptr = 0x10000,max_len = 32768and then reads from memory.
A minimal stub that echoes the input as the result is in tests/fixtures/quickjs_stub.wat. Compile it to WASM and place as quickjs.wasm (or set EngineConfig::wasm_binary_path) to test the full path without a real JS engine.
This project is licensed under the MIT License.