Skip to content

Latest commit

 

History

History
83 lines (60 loc) · 2.81 KB

File metadata and controls

83 lines (60 loc) · 2.81 KB

OpenWorkers Runtime QuickJS

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.

Quick Start

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.

Implemented

  • fetch and scheduled events via addEventListener
  • console, Headers, Request, Response, TextEncoder/TextDecoder, atob/btoa
  • URL and URLSearchParams, backed by the url crate
  • FormData, and formData() on Request/Response for urlencoded bodies
  • setTimeout/setInterval, awaitable from inside a handler
  • fetch() and console delegated to the runner through OperationsHandler
  • crypto.getRandomValues, crypto.randomUUID, crypto.subtle.digest (SHA-1/256/384/512)
  • ReadableStream response bodies, collected in the runtime before the response is sent

Pending work

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.

Not implemented

  • 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

Testing

cargo test

Status

See TODO.md for current limitations and roadmap.

License

MIT