Skip to Content
How-To GuidesGeneralGolem JavaScript Runtime (QuickJS)

Golem JavaScript Runtime (QuickJS)

Both TypeScript and Scala (via Scala.js) Golem agents compile to JavaScript and run inside a QuickJS -based WebAssembly runtime provided by wasm-rquickjs .

Language Support

The runtime supports ES2020 including modules, async/await, async generators, Proxies, BigInt, WeakRef, FinalizationRegistry, and all standard built-ins (Array, Map, Set, Promise, RegExp, Date, JSON, Math, typed arrays, etc.).

Available Web Platform APIs

The following browser/web APIs are available out of the box — no imports needed:

  • HTTP: fetch, Headers, Request, Response, FormData
  • Files/Blobs: Blob, File
  • URLs: URL, URLSearchParams
  • Console: console
  • Timers: setTimeout/clearTimeout, setInterval/clearInterval, setImmediate
  • Abort: AbortController, AbortSignal
  • Encoding: TextEncoder, TextDecoder, TextEncoderStream, TextDecoderStream
  • Streams: ReadableStream, WritableStream, TransformStream
  • Structured clone: structuredClone
  • Crypto: crypto.randomUUID, crypto.getRandomValues
  • Events: Event, EventTarget, CustomEvent
  • Messaging: MessageChannel, MessagePort
  • Errors: DOMException
  • Internationalization: Intl (DateTimeFormat, NumberFormat, Collator, PluralRules)

Available Node.js Modules

These Node.js-compatible modules can be imported:

ModuleDescription
node:bufferBuffer API
node:child_processConstrained in-runtime JavaScript execution; no host processes or general shell
node:cryptoHashes, HMAC, ciphers, key generation, sign/verify, DH, ECDH, X509, etc.
node:eventsEventEmitter
node:fs, node:fs/promisesComprehensive filesystem API (read, write, stat, mkdir, readdir, etc.)
node:http, node:httpsHTTP client; socket-free servers through custom HTTP routers (see below)
node:moduleModule utilities
node:osOS information
node:pathPath manipulation
node:perf_hooksPerformance measurement
node:processProcess information
node:punycodePunycode encoding
node:querystringQuery string parsing
node:readlineReadline interface
node:sqliteEmbedded SQLite (requires feature flag)
node:stream, node:stream/promisesStream API
node:string_decoderString decoding
node:testTest runner
node:timersTimer APIs
node:urlURL parsing
node:utilUtility functions
node:v8V8 compatibility shim
node:vmScript evaluation
node:zlibCompression (gzip, deflate, brotli)

Stub Modules (Throw or No-op)

These modules exist for compatibility but will throw or no-op when used:

  • node:cluster
  • node:http2
  • node:inspector
  • node:tls
  • node:worker_threads

Unsupported Network Modules

Golem does not support node:net, node:dgram and node:dns. The modules load, but the worker executor refuses WASI sockets by default, so every TCP connect, UDP send, bind and DNS lookup fails. Only an operator can turn WASI sockets on, with the executor setting agent_sockets.enabled.

Do not use these modules, or npm packages that open raw TCP connections through them (for example pg, mysql2 or ioredis). Use these instead:

  • fetch or the node:http / node:https client for HTTP requests
  • the Golem WebSocket API for WebSocket connections
  • golem:rdbms for PostgreSQL and MySQL

Socket-backed servers (net.createServer, or http.createServer with a port listen()) do not work. To serve HTTP with an http.createServer request listener, mount the server as a custom HTTP router with nodeHttpHandler from @golemcloud/golem-ts-sdk/http-router.

npm Package Compatibility

Additional npm packages can be installed with npm install (TypeScript) or added as Scala.js-compatible dependencies (Scala). Most packages targeting browsers or using the Node.js APIs listed above will work. Packages that depend on native C/C++ bindings or JVM-specific APIs will not work.

The runtime’s node:child_process adapter can run JavaScript targets, supported Node shebang files, and npm’s simple node <script> command form. It cannot create host processes, run a general shell, or execute native binaries. Unsupported commands fail explicitly.

Fresh JavaScript Execution

wasm-rquickjs:execution runs asynchronous JavaScript jobs in fresh QuickJS runtimes for both TypeScript and Scala agents. Use startJavaScript for live output and cancellation, or runJavaScript for collected output. Entry files ending in .ts, .mts, or .cts are transformed at runtime, and inline TypeScript is accepted with language: 'typescript'. The same transformation applies to import() and require() of TypeScript files and to stripTypeScriptTypes from node:module. The transformation transpiles syntax but does not type-check or read tsconfig.json. Scala agents use the typed golem.host.JavaScriptExecution facade: run and start take Options(Code.Source(source, Language.TypeScript)) or Options(Code.Entry(path)) with optional cwd, argv, env, timeoutMs, maxBytes, and overflow.

Each job receives an explicit environment allowlist and fresh globals, process state, timers, and module caches. Jobs still share the component filesystem and host capabilities, so this is not a security sandbox. Always provide a positive timeout for untrusted or potentially CPU-bound code.

File I/O

Use node:fs or node:fs/promises for filesystem operations. This is the standard way to read/write files in both TypeScript and Scala agents.

TypeScript

import * as fs from 'node:fs'; // Synchronous const content = fs.readFileSync('/data/config.json', 'utf-8'); // Async import * as fsp from 'node:fs/promises'; const data = await fsp.readFile('/data/config.json', 'utf-8');

Scala (via Scala.js interop)

import scala.scalajs.js import scala.scalajs.js.annotation.JSImport @js.native @JSImport("node:fs", JSImport.Namespace) private object Fs extends js.Object { def readFileSync(path: String, encoding: String): String = js.native def writeFileSync(path: String, data: String): Unit = js.native def existsSync(path: String): Boolean = js.native } // Usage val content = Fs.readFileSync("/data/config.json", "utf-8")

Important (Scala.js): WASI modules like node:fs are not available during the build-time pre-initialization (wizer) phase — they are only available at runtime. If you import node:fs at the top level of a Scala.js module, the import executes during pre-initialization and will fail. Use lazy initialization (lazy val) or defer the import to method bodies to ensure the module is loaded at runtime:

// ✅ CORRECT — lazy val defers initialization to first use at runtime private lazy val fs: Fs.type = Fs // ❌ WRONG — top-level val triggers import during pre-initialization private val fs: Fs.type = Fs

Reference

Check the wasm-rquickjs README  for the most up-to-date list of available APIs.

Looking up Golem SDK signatures

The full TypeScript type definitions for the Golem SDK live at:

node_modules/@golemcloud/golem-ts-sdk/dist/index.d.mts

Grep there (and in the dist/host/ and dist/lib/ subdirectories under the same package) when you need the exact signature of a helper such as durable, withRetryPolicy, Duration, Predicate, Policy, NamedPolicy, etc. The shipped dist/index.mjs is a single-line minified bundle and is not a useful reference; always read the .d.mts instead.