Lightweight JavaScript runtime for serverless workers, built on QuickJS.
It implements openworkers_core::Worker, so it plugs into the runner the same way the other engines do.
use openworkers_runtime_quickjs::{Event, HttpMethod, HttpRequest, RequestBody, Script, Worker};
use std::collections::HashMap;
let script = Script::new(r#"
addEventListener('fetch', event => {
event.respondWith(new Response('Hello from QuickJS!'));
});
"#);
let mut worker = Worker::new(script, None).await?;
let req = HttpRequest {
method: HttpMethod::Get,
url: "http://localhost/".to_string(),
headers: HashMap::new(),
body: RequestBody::None,
};
let (task, rx) = Event::fetch(req);
worker.exec(task).await?;
let response = rx.await?;Worker::new uses DefaultOps, which stubs fetch() out and prints logs to stderr.
Pass your own OperationsHandler to Worker::new_with_ops to serve outbound requests
and collect logs. A runnable version of the above is cargo run --example hello_world.
fetchandscheduledevents viaaddEventListener- console, Headers, Request, Response, TextEncoder/TextDecoder,
atob/btoa URLandURLSearchParams, backed by theurlcrateFormData, andformData()onRequest/Responsefor urlencoded bodiessetTimeout/setInterval, awaitable from inside a handlerfetch()and console delegated to the runner throughOperationsHandlercrypto.getRandomValues,crypto.randomUUID,crypto.subtle.digest(SHA-1/256/384/512)- ReadableStream response bodies, collected in the runtime before the response is sent
A task ends when its response or result is out. exec then settles the promises
passed to event.waitUntil() and cancels every timer still armed, so nothing a
request left behind runs inside the next one. waitUntil therefore keeps the
worker busy after the client has its response, and a setTimeout that outlives
the response never fires. There is no deadline on that drain: a waitUntil
promise that never settles keeps exec pending, so the host has to bound it.
It renders the SvelteKit SSR bundle of openworkers-website byte for byte like V8:
cargo run --release --example ssr_bench -- <bundle.js> times the wake, serve and
sleep cycle.
- ES modules (
export default { fetch() {} }) - Streaming request bodies (rejected with an error) and WebSocket
- AbortController, Blob, structuredClone,
queueMicrotask multipart/form-data:formData()throws on it, a file part needs Blob and File- KV, storage, database and worker bindings
RuntimeLimits: the parameter is accepted and ignored
cargo testSee TODO.md for current limitations and roadmap.
MIT