goja
A pure-Go ECMAScript 5.1+ engine for embedding JavaScript execution directly inside Go applications.
Repository Health
Technical Analysis
Goja is an implementation of ECMAScript 5.1 (with a growing set of ES6+ features) written entirely in Go, with no cgo dependency. It compiles JavaScript source into a custom bytecode and executes it on a register-based virtual machine, giving Go programs a way to run untrusted or user-supplied scripts, plugin logic, or tools like Babel and the TypeScript compiler without shelling out to Node or linking against V8.
The library is built around a small, ergonomic API: goja.New() creates a Runtime, RunString/RunProgram executes source, and Value.Export()/Runtime.ToValue() convert between Go and JS values automatically, including structs, maps, and slices via reflection. It supports calling JS functions from Go and vice versa, catching JS exceptions as typed Go errors, interrupting long-running scripts, and passes nearly the entire tc39 test262 conformance suite for the ECMAScript features it implements.
What You Get
- A
Runtimetype you instantiate per-goroutine (goja.New()) to compile and run ECMAScript 5.1 source, with most of ES6+ still landing incrementally - Automatic two-way conversion between Go and JS values via
ToValue()/Export()/ExportTo(), including Go structs, maps, slices, and functions - The ability to call JS functions from Go (
AssertFunction) and native Go functions from JS, including constructors viagoja.ConstructorCall - Typed error handling: JS exceptions surface as
*goja.Exceptionand script timeouts as*goja.InterruptedError, both inspectable from Go - Sourcemap support and a
FieldNameMapperinterface (with built-in JSON-tag and lowercase-first mappers) for making Go types feel idiomatic from JS - A companion
goja_nodejsproject adding Node-style globals (console, require, an event loop) for scripts that expect a more Node-like environment
Common Use Cases
- Letting end users write custom scripting/plugin logic (validation rules, workflow steps, pricing formulas) that a Go backend evaluates safely in-process
- Running JS-based build tooling — Babel, the TypeScript compiler, or bundler plugins — from a Go CLI without invoking Node as a subprocess
- Powering user-defined transformation or filter expressions inside a Go data pipeline or API gateway (e.g. request/response scripting, feature flag rules)
- Embedding a JS-based extension/automation layer in desktop or server tools written in Go, where linking cgo/V8 isn’t acceptable
- Unit-testing or simulating browser-side JS logic inside Go test suites without spinning up a headless browser
Under The Hood
Architecture
Goja is organized as a classic front-end/back-end interpreter pipeline split across dedicated packages: parser/ and ast/ turn source text into an abstract syntax tree (with token/ and file/ providing lexical tokens and source-position tracking), compiler.go/compiler_expr.go/compiler_stmt.go lower that AST into a custom bytecode representation, and vm.go (a ~120KB register/stack-based virtual machine) executes the resulting Program. The Runtime type in runtime.go owns the object graph and global environment, with each ECMAScript built-in (Object, Array, Map, Proxy, TypedArrays, RegExp, Promise, etc.) implemented in its own builtin_*.go file and object variants (object_goreflect.go, object_gomap.go, object_goslice.go) bridging Go’s reflection-based types into the JS object model. Changing the bytecode instruction set or the core Value interface (value.go) would ripple through the compiler, VM, and every builtin, since all of them operate on the same instruction/value contracts.
Tech Stack
Written in pure Go (module targets Go 1.25) with zero cgo dependencies, making it trivially cross-compilable. Direct dependencies are narrow and purposeful: dlclark/regexp2 backs regular-expression features Go’s native regexp package can’t express, Masterminds/semver and goccy/go-yaml support auxiliary tooling, go-sourcemap/sourcemap provides sourcemap parsing, and google/pprof plus golang.org/x/text support profiling and text encoding respectively. A small companion binary under goja/main.go wires in the sibling goja_nodejs project (console + CommonJS require) to run scripts from the command line, but the project’s primary interface is the importable goja package itself.
Code Quality
Around two in five of the top-level Go files are _test.go files, and CI (.github/workflows/main.yml) runs gofmt -d, go vet, staticcheck, and go test ./... across two Go versions and both 386/amd64 architectures on every push and PR. Beyond its own unit tests, the suite checks out the official ECMA tc39 test262 conformance tests and runs the engine against them, which is an unusually rigorous correctness bar for a language implementation. Errors are modeled explicitly as typed values (*Exception, *InterruptedError) rather than swallowed, and the README documents exact panic/recover semantics for native Go functions that need to raise catchable JS exceptions.
API Design
The public surface is deliberately small and consistent: create a Runtime, run source, convert values — with ToValue/Export/ExportTo covering the common Go-JS boundary cases with minimal boilerplate, and AssertFunction giving a low-level escape hatch when callers need explicit control over the JS this value. Naming mirrors the ECMAScript spec closely (constructors, prototypes, field mappers), which keeps the API predictable for anyone who already knows JS semantics, and the README backs every documented capability with a short, runnable example rather than prose alone.
Used by 5 apps in this directory
Convoy
Developer Tools · Devops
Convoy is an open-source, cloud-native webhooks gateway that ingests events over HTTP or straight from Kafka, SQS, Google Pub/Sub, and RabbitMQ, then reliably delivers them to subscriber endpoints with signed payloads, automatic retries, circuit breaking, and JavaScript-based transformations.
Formance Ledger
Invoicing Finance · Developer Tools · Databases
The programmable open source core ledger for fintech — build money-moving applications with atomic multi-posting transactions, account-based modeling, and Numscript, a built-in DSL for financial logic.
Nakama
Developer Tools · Game Development
Open-source game backend server with built-in multiplayer, matchmaking, leaderboards, chat, authentication, and storage — deploy anywhere via Docker or binary.
PocketBase
Databases · Ecommerce · Authentication
Open Source realtime backend in 1 file — embedded SQLite, auth, file storage, and admin UI as a single Go binary.
ZITADEL
Authentication
Open-source, API-first identity platform delivering multi-tenancy, Passkeys, OIDC, SAML, and SCIM without vendor lock-in.