ramune

package module
v0.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2026 License: MIT Imports: 73 Imported by: 3

README

Ramune

Ramune

Build your own Workers-style platform in Go. Cloudflare-Workers-compatible out of the box.

Three ways to use it: a self-hosted Workers-style platform foundation, a standalone JS/TS runtime (run / test / check / fmt / lint / repl / compile), or an embeddable JS engine for any Go program (ramune.New()).

Ramune is a Workers-style runtime you embed and extend. Author handlers as ES modules (export default { fetch, scheduled }), design your own env in Go - Redis, Postgres, S3, SMTP, NATS, your own gRPC service, anything - and ship it as your platform. Code written against Cloudflare Workers runs unchanged, because Ramune ships a Workers-compatible surface by default. No Cgo, no Docker required, no Node.

// worker.ts
export default {
  async fetch(request, env, ctx) {
    return Response.json({ hello: "world" });
  },
};
ramune serve worker.ts                 # dev / production serve
ramune compile worker.ts -o myworker   # or compile to a single binary you can scp

Scope. Ships today: fetch, env.KV, env.SECRETS, ctx.waitUntil, scheduled, cron, WinterCG basics. env.DB is a D1-compatible API subset (prepare/bind/all/first/run/exec; batch and raw not yet implemented, .all() meta fields not populated). "D1-compatible" and "Workers-KV-like" describe API shape only — the defaults are a single-node local SQLite file, not Cloudflare's edge-replicated D1 or globally eventually-consistent Workers KV. Swap in Postgres / Planetscale / Redis / DynamoDB via DBBackend / KVBackend if you need distributed scaling. Not shipped, but implementable as user-supplied env.* bindings (see workers/BINDINGS.md): Durable Objects, Queues, R2, AI Gateway, Service Bindings, Hyperdrive.

Why Ramune?

  • Design your own env. The env you ship to handlers is yours, not a fixed vendor surface. env.KV / env.DB are Go interfaces (KVBackend, DBBackend); swap for Redis, Postgres, DynamoDB, in-memory, anything by implementing them:

    type redisKV struct{ c *redis.Client }
    
    func (r *redisKV) Get(ns, k string) (string, bool, error) {
        v, err := r.c.Get(ctx, ns+":"+k).Result()
        if err == redis.Nil { return "", false, nil }
        return v, err == nil, err
    }
    // ...Put, Delete, List
    
    workers.Register(rt, "worker.ts", src, workers.WithKVBackend(&redisKV{c: myRedis}))
    

    Invent new bindings (env.QUEUE, env.EMAIL, env.AI, env.R2, anything your product needs) by registering a Go callback plus a tiny JS facade via WithExtraEnvJS. Handler code uses env.FOO naturally. Walkthrough with the full pattern: workers/BINDINGS.md. Runnable example: examples/workers/custom-binding/.

  • Run Workers-style handlers on your own hardware. Ramune ships a Workers-compatible default surface (within the scope above), so export default { fetch, scheduled } code written against Cloudflare runs unchanged on your VM, bare metal, or air-gapped box: ctx.waitUntil, env.KV, env.DB, env.SECRETS, streaming, and cron are all there out of the box.

  • Single-binary deploy. ramune compile worker.ts -o myworker bundles handler + runtime into one Go executable. No Kubernetes, no Wrangler, no Dockerfile required; scp ./myworker prod: and run. (QuickJS path is fully self-contained; JSC path still resolves the system JSC at run time, see next bullet.)

  • No Cgo at build; honest about runtime. go build cross-compiles to any GOOS/GOARCH without a C toolchain. JSC backend loads JavaScriptCore dynamically via purego: zero install on macOS (JSC ships with the OS), libjavascriptcoregtk-4.1 required on Linux (a bundled JSCOnly build is on the roadmap). QuickJS backend is pure Go with zero runtime dependencies and runs on FROM scratch Docker, at the cost of JIT performance.

  • Full Go interop. Workers are authored in TypeScript; everything underneath is Go. Call any Go library, including the stdlib and your existing services.

  • Also a complete JS/TS runtime and embeddable library. ramune run / test / check / fmt / lint / repl / compile with tsgo + rslint + esbuild built in. ramune.New() gives you a JS engine for any Go program.

Tri-backend: JavaScriptCore (JIT, macOS/Linux) via purego, QuickJS (pure Go, cross-platform incl. Windows) via modernc.org/quickjs, and goja (pure Go, reflect-based, ~94% ECMAScript) via github.com/dop251/goja — no Cgo required for any of them. Type checker and formatter (typescript-go), linter (rslint), bundler (esbuild), and all Node.js polyfills are built in with zero external tool dependencies.

Named after Ramune, a Japanese carbonated soft drink served in a Codd-neck bottle.

ramune serve worker.ts        # Serve Workers-style module
ramune run server.ts          # Run TypeScript (classic)
ramune test                   # Run tests
ramune check app.ts           # Type-check
ramune fmt .                  # Format
ramune lint .                 # Lint
ramune compile app.ts -o app  # Compile to standalone binary
ramune transpile main.ts -o out  # Transpile TS to Go source
ramune typegen go:fmt go:net/http -o go.d.ts  # Generate .d.ts for Go packages
ramune skills install         # Install Agent Skills for AI agents

What is Ramune?

Ramune is three things, with one narrative:

  1. A foundation for Workers-style platforms - ramune serve worker.ts runs Workers-style handlers out of the box (SQLite defaults for env.DB / env.KV, Cloudflare-compatible so CF code runs as-is), and the same runtime is the substrate you build your own platform on - your env, your backends, your bindings. Core scope: WinterCG + fetch
    • env.DB / env.KV / env.SECRETS + ctx.waitUntil + cron. Durable Objects / Queues / R2 / AI Gateway are not shipped; they are implemented as user-supplied env.* bindings so the core stays small and you aren't blocked on us.
  2. A JS/TS runtime like Bun or Deno, but built in Go — ramune run, test, check, fmt, lint, repl, compile.
  3. An embeddable JS engine for Go applications — ramune.New() in any Go program.

One runtime, three surfaces. Same Go-native core, three entry points: embed it in a Go program, run TypeScript from the CLI, or serve Workers-style handlers on it.

Three backends, same API:

JSC (default) QuickJS (-tags quickjs) goja (-tags goja)
Engine Apple JavaScriptCore via purego modernc.org/quickjs (pure Go) dop251/goja (pure Go, reflect-based)
JIT Yes No No
Platforms macOS, Linux macOS, Linux, Windows, FreeBSD macOS, Linux, Windows, FreeBSD
System deps macOS: none. Linux: libjavascriptcoregtk None None
Spec coverage ES2023 ES2023 ES2023 effective (goja native ~ES2017; esbuild lowers newer syntax transparently on Eval)
Best for Performance, HTTP servers Embedding, scripting, portability Pure-Go embedding, Windows-native, no cgo signal forwarding

All three are pure Go at build time: go build needs no C toolchain. Runtime deps differ: JSC resolves the system JavaScriptCore (zero install on macOS, libjavascriptcoregtk-4.1 on Linux); QuickJS and goja have none.

For AI coding agents: ramune skills install adds an Agent Skill that teaches Claude Code, GitHub Copilot, and similar tools how to use Ramune's APIs and CLI.

Install

macOS

JavaScriptCore is built into macOS — no extra dependencies.

go install github.com/i2y/ramune/cmd/ramune@latest
go install github.com/i2y/ramune/cmd/ramune-toolchain@latest  # for check / fmt / lint / compile / transpile / typegen
ramune setup-jit   # enable JIT (~10x faster, recommended)
Linux
sudo apt install libjavascriptcoregtk-4.1-dev   # JSC runtime (required)
go install github.com/i2y/ramune/cmd/ramune@latest
go install github.com/i2y/ramune/cmd/ramune-toolchain@latest  # for check / fmt / lint / compile / transpile / typegen

Multi-runtime (RuntimePool, worker_threads) works out of the box on x86_64. On arm64, gcc is required for cgo signal forwarding (apt install gcc).

Windows / Zero-dependency (QuickJS backend)
go install -tags quickjs github.com/i2y/ramune/cmd/ramune@latest
go install -tags quickjs github.com/i2y/ramune/cmd/ramune-toolchain@latest  # optional: check / fmt / lint / compile

The QuickJS backend uses modernc.org/quickjs (pure Go, ES2023). No shared libraries needed — works on Windows, macOS, Linux, and FreeBSD. Trade-off: no JIT, so CPU-bound code is slower (see Performance).

Goja backend (-tags goja, pure Go, reflect-based)
go install -tags goja github.com/i2y/ramune/cmd/ramune@latest

The goja backend wraps dop251/goja unchanged, so it's a drop-in for existing goja users: scripts and Go interop code that run on goja directly run on Ramune with -tags goja with no behavioral change, and can later switch to -tags quickjs or the default JSC build to gain throughput without touching the handler code. goja is a reflection-based Go JS interpreter with ~94% ECMAScript coverage. Appropriate when you want pure-Go embedding on Windows without any shared libraries and want to avoid the cgo signal-forwarding requirement that JSC needs on Linux/arm64. Modern JS syntax that goja's parser rejects (private class fields, top-level await, Object.hasOwn, logical assignment, etc.) is transparently lowered to ES2017 via esbuild on first-encounter parse failure in Runtime.Eval / Runtime.Exec — both CLI and library paths see the same effective ES2023 surface, and the lowered result is cached so repeated source is amortized.

Smaller binary
go install -tags nosqlite -ldflags="-s -w" github.com/i2y/ramune/cmd/ramune@latest

The main ramune binary above is ~30MB and holds the runtime; ramune-toolchain (~60MB) is a separate development-only binary for check / fmt / lint / compile / transpile / typegen. If you only need ramune run / serve / eval / repl / test, you can skip installing ramune-toolchain entirely.

-tags nosqlite excludes bun:sqlite. -ldflags="-s -w" strips debug info. Combine with -tags quickjs,nosqlite for the smallest possible binary.

Quick Start

Run JavaScript/TypeScript
ramune run app.ts
ramune run -p lodash -p dayjs app.ts   # with npm packages
ramune run                              # reads package.json
ramune run -w server.ts                 # watch mode
ramune run --workers 4 server.ts        # multi-worker HTTP server
ramune run --env-file .env.prod app.ts  # load env file
ramune run dev                          # run package.json script
Evaluate Expressions
ramune eval "1 + 2"
ramune eval "require('crypto').randomUUID()"
ramune eval "const x: number = 42; x"   # TypeScript works
REPL
ramune repl

Packages from package.json are automatically available:

ramune add lodash
ramune repl
> lodash.chunk([1,2,3,4,5,6], 2)
[[1,2],[3,4],[5,6]]

Features: history, tab completion, TypeScript, colors, multiline.

Test Runner
ramune test

Finds *.test.ts, *.spec.js, etc. Jest/Bun-compatible API:

describe("math", () => {
  test("addition", () => {
    expect(1 + 2).toBe(3);
  });
});

Mocking is supported via jest.fn() and jest.spyOn():

test("mock", () => {
  const fn = jest.fn().mockReturnValue(42);
  expect(fn()).toBe(42);
  expect(fn).toHaveBeenCalledTimes(1);
});
Compile to Standalone Binary
ramune compile server.ts -o myserver --http --minify
./myserver    # self-contained binary with embedded JS

The compiled binary embeds the bundled JS via go:embed. On macOS, it is automatically codesigned with the JIT entitlement.

Options: --http (Ramune.serve event loop), --minify (esbuild minification). Output binary is ~28MB (linter/formatter/checker are not included — only the runtime).

Note: The compiled binary loads JavaScriptCore dynamically at runtime. The target machine must have JSC available (macOS: built-in, Linux: libjavascriptcoregtk). Use -tags quickjs for cross-platform builds.

Native Extension Modules (Experimental)

Note: This workflow uses the TypeScript-to-Go transpiler under the hood and inherits its experimental status. Simple typed functions (primitives, structs, typed slices) work reliably; generics, decorators, and deep class inheritance may produce Go code that needs manual fixes.

Compile performance-critical TypeScript functions to native Go code and call them from JavaScript at full compiled speed:

ramune compile app.js --native math.ts -o myapp

The --native flag transpiles TypeScript to Go, making exported functions available via require('native:modulename'):

// math.ts — transpiled to Go
export function fibonacci(n: number): number {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}
// app.js — runs in JS, calls native Go code
const { fibonacci } = require('native:math');
console.log(fibonacci(35)); // runs as compiled Go, not interpreted JS

Multiple native files and inter-file imports are supported:

ramune compile app.js --native math.ts --native geometry.ts -o myapp

Native functions support rich type interop — structs, typed arrays, and class-like instances with live properties:

// counter.ts
export class Counter {
  count: number = 0;
  name: string;
  constructor(name: string) { this.name = name; }
  increment(): number { return ++this.count; }
}
export function newCounter(name: string): Counter {
  return new Counter(name);
}
const { newCounter } = require('native:counter');
const c = newCounter("hits");
c.increment();
c.increment();
console.log(c.count); // 2 — live property, reads Go struct field
c.count = 100;        // setter, writes Go struct field
c.increment();
console.log(c.count); // 101
Transpile TypeScript to Go (Experimental)

Note: The TypeScript-to-Go transpiler is experimental and under active development. Generated code may require manual adjustments for complex codebases.

Transpile TypeScript source code directly to Go:

ramune transpile main.ts -o out/                     # single file
ramune transpile main.ts utils.ts -o out/ --module myapp  # multi-file project
ramune transpile main.ts --compile -o myapp           # transpile + build binary

The transpiler converts TypeScript types, classes, interfaces, generics, async/await, and more to idiomatic Go. See TRANSPILER.md for supported features and limitations.

Type Checking
ramune check app.ts              # check files
ramune check src/                # check directory
ramune run --check app.ts        # check then run

Uses typescript-go (TypeScript 7.0-dev, backward-compatible with TS 5.x) built into Ramune — no external tools required.

Format & Lint
ramune fmt .                     # format all JS/TS files
ramune fmt --check .             # check formatting (CI)
ramune lint .                    # lint all JS/TS files
ramune lint --fix .              # lint with auto-fix

The formatter uses typescript-go's built-in formatter. The linter uses rslint (Go-based, 20-40x faster than ESLint). Both are built into Ramune — no external tools required.

If rslint.json or rslint.jsonc exists, ramune lint uses that configuration. Otherwise, all recommended rules are enabled by default.

Note: TypeScript transpilation (ramune run app.ts) uses esbuild which is also built into Ramune.

Package Manager
ramune init                      # create package.json
ramune add lodash dayjs          # add dependencies
ramune remove lodash             # remove
ramune install                   # install all
Build (esbuild)
ramune build app.ts --outdir=dist --bundle --minify
Permissions (Sandbox)
ramune run app.ts                              # default: all allowed
ramune run --sandbox app.ts                    # deny all
ramune run --sandbox --allow-read=/tmp app.ts  # selective access

Flags: --allow-read, --allow-write, --allow-net, --allow-env, --allow-run.

Docker Sandbox

Run scripts in isolated Docker containers:

ramune run --docker app.ts                          # run in default ubuntu:24.04
ramune run --docker --docker-image node:22 app.ts   # custom image
ramune run --docker --docker-memory 512 app.ts      # 512MB memory limit
ramune run --docker --docker-no-network app.ts      # no network access
ramune run --docker --docker-network mynet app.ts   # specific Docker network

The host binary is automatically mounted into the container. On macOS/Windows, a Linux binary is cross-compiled and cached. Go functions registered via SandboxRuntime.RegisterFunc are available inside the container (they are compiled into the binary).

Environment Variables

.env and .env.local files are automatically loaded (like Bun/Deno). Use --env-file to specify a custom file:

ramune run --env-file .env.production app.ts
Package.json Scripts

Run scripts defined in package.json:

ramune run dev     # runs "scripts.dev" from package.json
ramune run build   # runs "scripts.build"
Workers-style Modules (ramune serve)

The flagship command. Serve a Cloudflare-Workers-style ES-module handler — export a default object with fetch(request, env, ctx) and the CLI wires it up:

// worker.ts
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    const url = new URL(request.url);
    return Response.json({ hello: url.searchParams.get("name") ?? "world" });
  },
} satisfies WorkersHandler;
ramune serve worker.ts                    # listens on :3000
ramune serve --port 8080 worker.ts        # custom port
ramune serve --workers 4 worker.ts        # N runtimes, round-robined
ramune serve --sqlite :memory:  worker.ts # non-persistent env.DB/env.KV

ctx.waitUntil(promise) keeps the executor alive after the response goes out. env.SECRETS reads RAMUNE_SECRET_* env vars. env.DB (D1-compatible API subset, see Scope above) and env.KV (Workers-KV-like API) are backed by a single-node local SQLite file at .ramune/data.db by default — this matches the D1/Workers-KV handler surface, not their distributed storage profile. For production horizontal scaling, implement DBBackend / KVBackend against your actual database (Postgres, Redis, etc.) and bind via WithDBBackend / WithKVBackend. Works with Hono directly (export default app).

An optional ramune.toml next to the entry declares dependencies, permissions, and named KV bindings:

[dependencies]
hono = "*"

[permissions]
net = "granted"
read = "denied"

[[kv_namespaces]]
binding = "SESSIONS"
namespace = "sessions"

See examples/workers/ for hello, SSE, Hono, and a full HTML guestbook. Type declarations live in workers/workers.d.ts. For non-SQLite backends (Redis, Postgres, …) and user-defined bindings (env.QUEUE, env.EMAIL, …), see the embed API below and the custom binding guide.

Embed in Go

Ramune is also a Go library. Embed JavaScript in your Go application and expose any Go library to JS — database drivers, image processing, gRPC clients, ML inference, etc.

package main

import (
    "fmt"
    "log"

    "github.com/i2y/ramune"
)

func main() {
    rt, err := ramune.New()
    if err != nil {
        log.Fatal(err)
    }
    defer rt.Close()

    val, _ := rt.Eval("1 + 2")
    defer val.Close()
    fmt.Println(val.Float64()) // 3
}
Call Go from JavaScript
rt.RegisterFunc("greet", func(args []any) (any, error) {
    return fmt.Sprintf("Hello, %s!", args[0]), nil
})

val, _ := rt.Eval(`greet("World")`) // "Hello, World!"

Go functions registered via RegisterFunc can safely access Value methods (Attr, Call, SetAttr, etc.) — no deadlock. For typed callbacks, use Register with generics:

ramune.Register(rt, "add", func(a, b float64) float64 {
    return a + b
})
Receive JS Functions in Go

JS functions passed to Go callbacks are wrapped as *JSFunc, callable from Go:

rt.RegisterFunc("forEach", func(args []any) (any, error) {
    items := args[0].([]any)
    fn := args[1].(*ramune.JSFunc)
    defer fn.Close()
    for _, item := range items {
        fn.Call(item)
    }
    return nil, nil
})
forEach(["a", "b", "c"], function(item) { console.log(item); });
// → a, b, c
Struct Binding

Expose Go structs to JavaScript:

type User struct {
    Name string `js:"name"`
    Age  int    `js:"age"`
}
func (u *User) Greet() string { return "Hello, " + u.Name }

rt.Bind("user", &User{Name: "Alice", Age: 30})
// JS: user.name → "Alice", user.greet() → "Hello, Alice"
Plugin System

Register custom modules available via require():

rt, _ := ramune.New(ramune.NodeCompat(), ramune.WithModule(ramune.Module{
    Name: "mydb",
    Exports: map[string]ramune.GoFunc{
        "query": func(args []any) (any, error) {
            return db.Query(args[0].(string))
        },
    },
}))
// JS: const db = require('mydb'); db.query("SELECT 1")
Native Module (Go Library API)

NativeModuleFromFuncs creates a require()-able module from typed Go functions — no manual argument parsing needed:

mod := ramune.NativeModuleFromFuncs("native:math", map[string]any{
    "add":       func(a, b float64) float64 { return a + b },
    "isPrime":   func(n float64) bool { /* ... */ },
    "fibonacci": mymath.Fibonacci,  // any typed Go function
})

rt, _ := ramune.New(ramune.NodeCompat(), ramune.WithModule(mod))
rt.Eval(`require('native:math').add(3, 4)`) // 7

Supports struct parameters, struct returns with live properties, typed slices, error handling, and panic recovery:

type Point struct {
    X float64 `json:"x"`
    Y float64 `json:"y"`
}

mod := ramune.NativeModuleFromFuncs("native:geo", map[string]any{
    "distance": func(a, b Point) float64 {
        dx, dy := a.X-b.X, a.Y-b.Y
        return math.Sqrt(dx*dx + dy*dy)
    },
})
// JS: require('native:geo').distance({x:0, y:0}, {x:3, y:4}) → 5

When a function returns a struct pointer, the JS object has live getter/setter properties and callable methods — mutations in JS are reflected in Go and vice versa.

Use npm Packages
rt, _ := ramune.New(
    ramune.NodeCompat(),
    ramune.Dependencies("lodash@4"),
)
val, _ := rt.Eval(`lodash.chunk([1,2,3,4,5,6], 2)`)

Subpath imports are supported (e.g., "react-dom/server"). Use PreloadJS to inject polyfills that bundled packages may require:

rt, _ := ramune.New(
    ramune.NodeCompat(),
    ramune.PreloadJS(`globalThis.MessageChannel = class { constructor() { this.port1 = {}; this.port2 = {}; } };`),
    ramune.Dependencies("react@18", "react-dom@18", "react-dom/server"),
)
Async / Promises
val, _ := rt.EvalAsync(`
    new Promise(resolve => setTimeout(() => resolve(42), 100))
`)
HTTP Server
rt, _ := ramune.New(ramune.NodeCompat())

rt.Exec(`
    Ramune.serve({
        port: 3000,
        fetch(req) {
            return new Response("Hello!");
        }
    })
`)
rt.RunEventLoop()

Works with Hono and other frameworks. Async handlers with setTimeout/await are supported:

app.get('/slow', async (c) => {
    await new Promise(r => setTimeout(r, 100));
    return c.json({ ok: true });
});
Workers-style Modules (ramune/workers)

The Go embed API for Workers-style handlers — returns an http.Handler that slots into any Go HTTP server (net/http, chi, Echo, gRPC gateway, …):

import "github.com/i2y/ramune/workers"

rt, _ := ramune.New(ramune.NodeCompat(), ramune.WithFetch())
defer rt.Close()

src, _ := os.ReadFile("worker.ts")
handler, err := workers.Register(rt, "worker.ts", string(src),
    workers.WithSQLite(".ramune/data.db"),
    workers.WithWaitUntilTimeout(30*time.Second),
)
http.ListenAndServe(":3000", handler)

ctx.waitUntil(promise) is honoured — the HTTP response ships immediately while the executor drains pending promises. For multi-VM setups, workers.Prepare runs esbuild once and workers.AttachPrepared binds to each Runtime.

Swap env.KV / env.DB for anything. The built-in SQLite path is built on KVBackend / DBBackend Go interfaces; implement them with Redis, Postgres, DynamoDB, or an in-memory map:

// type KVBackend interface { Get/Put/Delete/List ... }
// type DBBackend interface { Query/Exec ... }
workers.Register(rt, "w.ts", src,
    workers.WithKVBackend(myRedisKV),
    workers.WithDBBackend(myPostgres),
)

Invent your own bindings. Anything a CF Workers binding does — env.QUEUE.send, env.EMAIL.send, env.R2.put, env.AI.run, env.DURABLE.get — is a few lines of Go. Register a callback with RegisterFunc, inject a small JS facade via WithExtraEnvJS, and handler code uses env.FOO naturally:

rt.RegisterFunc("__env_email_send", func(args []any) (any, error) {
    // wire up SMTP / SendGrid / SES here
    return nil, myMailer.Send(opts)
})

handler, _ := workers.Register(rt, "w.ts", src,
    workers.WithExtraEnvJS(`
        globalThis.__extraEnvBindings = function(env) {
            env.EMAIL = { send: opts => __env_email_send(opts) };
        };
    `),
)

Full walkthrough with TypeScript types and the composition pattern for stacking multiple bindings: workers/BINDINGS.md. Runnable example: examples/workers/custom-binding/.

workers.LoadRamuneTOML parses the same ramune.toml schema the CLI uses. The CLI-side wrapper is ramune serve (above).

Multi-core Parallelism

Unlike Bun/Node (single-threaded), Ramune runs multiple JSC VMs in parallel on separate OS threads:

pool, _ := ramune.NewPool(4, ramune.NodeCompat())
defer pool.Close()

pool.Eval("Math.PI * 2")                        // round-robin to one VM
pool.Broadcast("globalThis.config = {debug: true}")  // run on every VM

// Multi-worker HTTP server
pool.ListenAndServe(":3000", `
    globalThis.__poolHandle = function(req) {
        return { status: 200, body: "Hello from worker!" };
    };
`)

Worker threads are also supported:

const { Worker } = require('worker_threads');
const w = new Worker('./worker.js', { workerData: { n: 42 } });
w.on('message', msg => console.log(msg));
Ramune APIs & Bun Compatibility

Ramune provides its own API namespace. Bun.* is available as an alias for backward compatibility with existing Bun code, though compatibility is partial and will be improved over time.

API Status
Ramune.serve({port, fetch, websocket}) Supported (Go net/http backend, see Performance)
Ramune.file(path) Supported (text, json, exists, size)
Ramune.write(path, data) Supported
Ramune.password.hash/verify Supported (bcrypt)
Ramune.sleep(ms) Supported
Ramune.plugin({setup}) Supported (onLoad filters, virtual modules)
Request / Response Polyfilled with ReadableStream body
Ramune.build({entrypoints, outdir, ...}) Supported (esbuild backend, minify, splitting, sourcemap)
bun:sqlite Supported (transactions, WAL, prepared stmt cache, pure Go)
Bun.* Alias for Ramune.* (partial Bun compatibility)
WebView (Desktop)

Open native desktop webview windows from JavaScript (macOS, via glaze + purego):

// Go setup — must run on main thread (macOS requirement)
ramune.InitWebViewMain()
rt, _ := ramune.New(ramune.NodeCompat())
done := make(chan struct{})
go func() {
    rt.Exec(`
        var wv = new Ramune.WebView({ title: "My App", width: 800, height: 600 });
        wv.navigate("https://example.com");
        // or: wv.setHtml("<h1>Hello</h1>");
    `)
    rt.RunEventLoop()
    close(done)
}()
ramune.DrainWebViewMain(done)

API: navigate(url), setHtml(html), eval(js), setTitle(title), setSize(w, h), init(js), destroy(), onclose(fn).

WebView (Headless / Bun.WebView)

Headless browser automation via Chrome DevTools Protocol, compatible with Bun.WebView:

const wv = new Bun.WebView({ headless: true });
await wv.navigate("https://example.com");
console.log(await wv.evaluate("document.title")); // "Example Domain"
const screenshot = await wv.screenshot(); // PNG buffer
await wv.click(100, 200);
await wv.type("hello");
wv.close();

Requires Chrome or Chromium installed (set CHROME_PATH to override detection).

API: navigate(url), evaluate(expr), screenshot(opts), click(x, y), type(text), press(key), scroll(dx, dy), resize(w, h), back(), forward(), reload(), cdp(method, params), close(). Properties: url, title, loading.

Console Output

console.log/error/warn work out of the box in both CLI and library mode. Output goes to os.Stdout/os.Stderr by default. Use WithStdout/WithStderr to redirect:

var buf bytes.Buffer
rt, _ := ramune.New(ramune.WithStdout(&buf))
rt.Exec(`console.log("captured")`)
fmt.Println(buf.String()) // "captured\n"
GC Configuration

Ramune provides tunable GC settings for high-throughput HTTP servers:

rt, _ := ramune.New(ramune.NodeCompat(), ramune.WithGC(ramune.GCConfig{
    GCInterval: 2000,   // manual JSC GC every N requests
    GCPercent:  100,    // Go GC target % (GOGC)
}))

For most use cases (CLI, scripting, SDK), defaults work fine.

Permissions (Library API)
rt, _ := ramune.New(
    ramune.NodeCompat(),
    ramune.WithPermissions(&ramune.Permissions{
        Read:      ramune.PermGranted,
        ReadPaths: []string{"/tmp", "/var/data"},
        Write:     ramune.PermDenied,
        Net:       ramune.PermDenied,
    }),
)
Docker Sandbox (Library API)

Execute untrusted JS in Docker containers with Go function passthrough:

rt := ramune.NewSandboxRuntime(ramune.NodeCompat())

// Go functions are available inside the container
rt.RegisterFunc("multiply", func(args []any) (any, error) {
    return args[0].(float64) * args[1].(float64), nil
})

// Must be called first — handles re-exec as sandbox worker
if ramune.HandleSandboxWorker(rt) {
    return
}

result, err := rt.SandboxRun("script.js", ramune.SandboxConfig{
    Image:     "ubuntu:24.04",
    MemoryMB:  512,
    NoNetwork: true,
    Timeout:   30 * time.Second,
})
fmt.Println(result.Stdout)

SandboxEval evaluates code strings instead of files. SandboxAvailable() checks if Docker is reachable.

Docker API (dockerode)

Access Docker from JavaScript via the DockerModule() option:

rt, _ := ramune.New(ramune.NodeCompat(), ramune.DockerModule())
const Docker = require('dockerode');
const docker = new Docker();
await docker.ping();

const container = await docker.createContainer({ Image: 'alpine:latest', Cmd: ['echo', 'hello'] });
await container.start();
const { StatusCode } = await container.wait();

Supports: ping, pull, createContainer, start/stop/remove/wait/inspect/logs, createNetwork/removeNetwork.

Performance

TL;DR. Use JSC for raw single-worker throughput and latency-sensitive setups (1-3 workers). Use QuickJS for zero-dependency FROM scratch Docker and many-worker deployments where scaling factor matters. Use goja for pure-Go embedding on Windows without cgo signal forwarding. All three share the same Ramune API and the same Workers-style handler surface.

JSC backend (default)

Relative performance on Apple M4 Max with JIT enabled. Absolute numbers shift with Go toolchain, hardware, and thermal state; run make bench for numbers on your machine.

Workload Ramune vs Node.js Ramune vs Bun
Hello World startup ~1.1x faster ~2.4x slower
Fibonacci(35) CPU ~1.3x faster ~1.2x slower
JSON 10K objects ~1.2x faster ~2x slower
Crypto SHA256 x1000 comparable ~2x slower
File I/O x100 comparable ~1.7x slower
HTTP req/s (single) ~1.1x slower ~1.7x slower

Single-runtime HTTP is below Bun but competitive with Node.js. For throughput see Multi-Runtime Pool below: Ramune runs N JS VMs in parallel on separate OS threads, where Bun and Node stay single-threaded.

Raw throughput is only one axis. Ramune's edge over Bun is Go-native embedding (ramune.New() in any Go program), Workers-style compatibility out of the box, and multi-core scaling within one process; Bun offers none of these.

QuickJS backend (-tags quickjs)

Same machine, no JIT. Without a JIT compiler, QuickJS is orders of magnitude slower on CPU-heavy benchmarks (Fibonacci, JSON); I/O-bound workloads stay close because the heavy lifting happens in Go. Best suited for embedding, scripting, Windows, and FROM scratch Docker deployments where zero runtime deps matter more than raw JS execution speed.

Workload QuickJS vs JSC+JIT QuickJS vs Bun
Hello World startup ~1.3x slower ~3x slower
Fibonacci(35) CPU ~65x slower ~80x slower
JSON 10K objects ~4x slower ~7x slower
Crypto SHA256 x1000 ~1.4x slower ~2.6x slower
File I/O x100 ~1.3x slower ~2x slower
HTTP req/s (single) ~1.5x slower ~2.5x slower
Goja backend (-tags goja)

Pure-Go reflection-based interpreter. Slower on CPU-heavy JS than QuickJS but with the widest platform reach and zero system dependencies.

Multi-Runtime Pool

Ramune runs multiple JS VMs in parallel on separate OS threads (Bun/Node are single-threaded). Measured on Apple M4 Max with bench/pool/pool_bench.go (JSON generate/filter/map handler, 200 objects per request, wrk -t4 -c100 -d10s). Numbers below are the median of 3 runs per backend; reproduce with go build [-tags quickjs|-tags goja] -o pool bench/pool/pool_bench.go && ./pool 6.

JSC (default)
Workers req/s Scaling
1 16,229 1.0x
2 23,489 1.45x
3 23,645 1.46x
4 19,479 1.20x
5 15,951 0.98x
6 14,448 0.89x

JSC wins on single-worker throughput (JIT). Scaling peaks around 2-3 workers (~23.5k req/s) and regresses past 4 back to 14.4k at 6 workers. This is a property of JSC itself, not a Ramune-specific issue: the JSC VM serializes on shared JIT state (code cache, inline cache stubs) when multiple runtimes execute in the same process on separate threads, and purego FFI crossings add lock contention on top. For latency-sensitive workloads, run 1-3 workers.

QuickJS (-tags quickjs)
Workers req/s Scaling
1 1,528 1.0x
2 2,947 1.93x
3 4,271 2.79x
4 5,079 3.32x
5 5,820 3.81x
6 6,184 4.05x

Monotonic out to 6 workers thanks to the vendored libc fork in third_party/libc/ (per-TLS allocator + page-owner routing). Without the fork, contention on the global allocator flattens throughput past 1 worker. Best scaling factor of the three, but lowest single-worker absolute throughput.

goja (-tags goja)
Workers req/s Scaling
1 3,941 1.0x
2 6,425 1.63x
3 8,220 2.09x
4 9,445 2.40x
5 10,377 2.63x
6 11,166 2.83x

Pure-Go dispatch, no cgo signal forwarding or allocator contention. Monotonic out to 6 workers with a shallower slope than QuickJS, but higher absolute throughput at every worker count among pure-Go backends.

Backend selection by shape. JSC wins single-worker and peaks at 2 workers (best for latency-sensitive workloads). QuickJS has the best multiplicative scaling (best multi-core efficiency, especially for many-worker deployments). goja wins absolute multi-worker throughput among pure-Go backends. Pick the backend that matches your target shape.

vs Go JS Runtimes

Ramune with JSC+JIT vs other Go-embedded JS runtimes (absolute ms per workload, lower is better):

Test Ramune (JSC+JIT) Ramune (QuickJS) Ramune (goja) otto
Fibonacci(35) 31ms 3,122ms 1,989ms 26,413ms
JSON 10K objects 0.9ms 30ms 11ms 27ms

JSC with JIT is the fastest Go-embedded JS runtime by 1-2 orders of magnitude on CPU-heavy code. QuickJS (pure Go interpreter) is comparable to goja for JSON workloads and much slower on CPU-heavy code. otto is the slowest across all tests.

Run make bench-go to reproduce.

JIT Setup

On macOS, JIT requires a code signing entitlement:

# After go install:
ramune setup-jit

# Or when building from source:
make build-cli

Linux does not need JIT setup.

Node.js Compatibility

Module Coverage Module Coverage
path 100% zlib 75% (gzip, deflate, brotli)
fs 90% (async + sync + watch) os 85%
child_process 80% events 85%
crypto 85% (+ crypto.subtle) url 80%
stream 85% (class extends, asyncIterator, backpressure, cork/uncork) Buffer 90%
http/https 80% (createServer with streaming response) assert 80%
http2 75% (connect, createServer, trailers, multiplexing) dns basic
net/tls 70% (+ net.createServer) readline 70%
worker_threads 80% (+ SharedArrayBuffer, Atomics.waitAsync) querystring 80%
vm 70% perf_hooks basic
timers/promises 70% process 85% (stdin, signals, exit, env, tty)
util 80% (types, promisify, format, debuglog) tty 70% (isatty, WriteStream)
dgram 70% (UDP) async_hooks basic (AsyncLocalStorage)
module createRequire, file-based require with ESM-to-CJS
Stream Classes

Stream classes (Readable, Writable, Duplex, Transform, PassThrough) are ES6 classes that support class extends:

const { Transform } = require('stream');

class Upper extends Transform {
  _transform(chunk, encoding, cb) {
    this.push(String(chunk).toUpperCase());
    cb();
  }
}

Key features: Symbol.asyncIterator (for await...of), backpressure-aware pipe(), cork()/uncork(), unshift(), unpipe(), objectMode, readableFlowing/readableEnded/writableEnded/writableFinished properties, stream.pipeline(), stream.finished().

http.IncomingMessage extends Readable, so request bodies support pipe(), read(), and for await...of.

HTTP/2
const http2 = require('http2');

// Client
const session = http2.connect('http://localhost:8080');
session.on('connect', () => {
  const req = session.request({ ':method': 'POST', ':path': '/api' });
  req.on('response', (headers) => { /* ... */ });
  req.on('data', (chunk) => { /* ... */ });
  req.on('trailers', (trailers) => { /* grpc-status, grpc-message */ });
  req.end(body);
});

// Server (cleartext h2c)
const server = http2.createServer((stream, headers) => {
  stream.respond({ ':status': 200, 'content-type': 'text/plain' });
  stream.end('hello');
});
server.listen(3000);

Supports http2.connect(), createServer(), createSecureServer(), stream multiplexing, trailers (for gRPC), and http2.constants.

Web Platform APIs

Ramune implements the WinterTC Minimum Common Web API (ECMA-429), the standard API surface shared across non-browser JS runtimes (Deno, Cloudflare Workers, Bun, Node.js). The implementation is Go-side, so the Web API surface is consistent across all three backends (JSC, QuickJS, goja); only WebAssembly is JSC-only, and all other APIs below behave identically regardless of the backend.

API Status
fetch / Headers / Request / Response Supported (Go net/http backend, ReadableStream body)
ReadableStream / WritableStream / TransformStream Supported (pipeTo, pipeThrough, tee, BYOB, async iterator)
ReadableStreamBYOBReader / ReadableByteStreamController Supported
CompressionStream / DecompressionStream Supported (gzip, deflate, deflate-raw, brotli)
TextEncoder / TextDecoder Supported (UTF-8)
TextEncoderStream / TextDecoderStream Supported
crypto.subtle Supported (digest, sign/verify, encrypt/decrypt, importKey/exportKey, deriveBits/deriveKey)
crypto.getRandomValues / randomUUID Supported
Blob / File / FormData Supported (stream, bytes, slice, MIME normalization)
AbortController / AbortSignal Supported (timeout, abort, any)
EventTarget / Event / CustomEvent Supported (addEventListener, once, signal, handleEvent)
ErrorEvent / PromiseRejectionEvent / MessageEvent Supported
MessageChannel / MessagePort Supported
DOMException Supported (all legacy error codes)
URL / URLSearchParams / URLPattern Supported
WebSocket Supported (server-side via Ramune.serve)
Performance / performance.now Supported (mark, measure, timeOrigin)
SharedArrayBuffer / Atomics Supported (Go []byte backed, wait/notify/waitAsync)
structuredClone Supported (circular refs, Map, Set, Date, RegExp, TypedArray)
atob / btoa Supported
setTimeout / setInterval / queueMicrotask Supported
navigator.userAgent Supported
reportError / onerror / onunhandledrejection Supported
CountQueuingStrategy / ByteLengthQueuingStrategy Supported
WebAssembly Supported (JSC backend; compile, instantiate, validate, streaming)
console Supported (log, error, warn, info, debug, time, table, trace)
WPT Conformance

Ramune's Web API implementations are validated against the Web Platform Tests (WPT) suite:

make test-wpt   # run WPT conformance tests

Pass rates measure coverage against the full WPT subtest corpus, which includes browser-only edge cases irrelevant to a non-browser runtime (layout, DOM mutation, cross-window postMessage, etc.). Mainstream Workers patterns like fetch, Response.json, basic streaming readers/writers, and compression round-trips work reliably in practice; the unmet percentages are dominated by those browser-specific subtests and a handful of obscure stream-controller races. Run make test-wpt for the exact failing subtests per category.

Most categories pass at identical rates across all three backends because the Web APIs are Go-side polyfills:

Category Pass Rate
timers 100%
atob/btoa 99%
hr-time 86%
FileAPI/blob 82%
microtask-queuing 80%
dom/abort 61%

Backend-sensitive categories (differ because the underlying JS engine affects behavior or the polyfill interacts with engine-specific scheduling):

Category JSC QuickJS goja
compression 63% 55% 53%
streams 53% 53% 51%
dom/events 46% 53%† 53%†
webmessaging 33% 18% 33%

†QuickJS and goja skip AddEventListenerOptions-signal.any.js which hangs on both engines; goja additionally skips gb18030-decoder.any.js which triggers a goja parser panic on \u{10FFFF} string literals. Skip list lives in wpt_test.go.

WPT checkout is required (test/wpt/). See make test-wpt output for setup instructions.

File-based require() with ESM Support

require() loads files from the filesystem with automatic ESM-to-CJS conversion:

const { hello } = require('./lib.mjs');     // ESM -> CJS transform
const data = require('./config.json');       // JSON parsing
const utils = require('./utils.ts');         // TypeScript stripping
const pkg = require('some-package');         // node_modules resolution

ESM detection: .mjs extension, package.json "type": "module", or import/export keywords. TypeScript ESM files (.ts with import/export) are processed in a single esbuild pass. Modules are cached by resolved absolute path. Per-module require functions ensure correct relative path resolution in nested imports.

Ramune also supports package.json "exports" field resolution (conditional exports with require/import/default and subpath exports).

TypeScript-to-Go Transpiler (Experimental)

Ramune ships a built-in TypeScript-to-Go transpiler that converts TS source to idiomatic Go: numberfloat64, classes → structs with methods, Promise<T>*promise.Promise[T], generics, enums, discriminated unions. A go: prefix lets you import any Go package from TypeScript, and ramune compile --native turns TS modules into require('native:name')-able Go native modules.

Status is experimental; generated code may need manual fixes for complex codebases. Full feature list, type mapping, native module workflow, go: imports, and limitations: TRANSPILER.md.

Known Limitations

  • N-API / Native addons: Not supported. Packages that require .node native binaries (e.g., bcrypt, sharp, better-sqlite3) will not work. Use pure JS alternatives instead.
  • HTTP self-fetch: Ramune.serve() handlers cannot fetch their own server (same JS context deadlock).
  • Windows: JSC backend not available. Use -tags quickjs for Windows support.
  • Linux multi-runtime (JSC): Architecture-dependent signal handling. On arm64, CGO_ENABLED=1 and gcc are required for multi-runtime (cgo's signal forwarding is needed for JSC's GC). On x86_64, multi-runtime works without cgo (CGO_ENABLED=0).
  • Multi-worker scaling (JSC): Scaling flattens around 3-4 workers on macOS due to JSC JIT contention and purego FFI overhead. Linux (libjavascriptcoregtk) may differ.
  • QuickJS backend: No JIT; CPU-bound JS is orders of magnitude slower than JSC (see Performance). Error stack traces not available. Best for embedding/scripting, not compute-heavy workloads.
  • goja backend: No WebAssembly (JSC-only). Post-ES2017 syntax (private class fields, top-level await, etc.) is auto-lowered to ES2017 via esbuild at Runtime.Eval/Exec time on first parse failure and cached, so user code rarely hits goja's native parser limits in practice. Some subsystems are stubbed (WebSocket upgrade path). No JS error stack traces exposed to Go.
  • Native module instance lifecycle: Struct instances returned to JS are not automatically freed when the JS object is garbage collected. Instances are cleaned up when Runtime.Close() is called. For long-running servers creating many short-lived struct instances, this may cause increased memory usage.

Requirements

JSC backend (default) QuickJS backend (-tags quickjs) goja backend (-tags goja)
Go 1.26+ 1.26+ 1.26+
Platforms macOS, Linux macOS, Linux, Windows, FreeBSD macOS, Linux, Windows, FreeBSD
System deps macOS: none. Linux: apt install libjavascriptcoregtk-4.1-dev None None

All tools are built in — no external dependencies needed for check, fmt, lint, or TypeScript transpilation. npm packages are fetched directly from the npm registry — no npm or bun CLI required.

Developing Ramune

Make targets for working on Ramune itself (contributor setup):

make ci          # fmt + build + vet + test
make test-wpt    # WPT conformance tests (requires test/wpt checkout)
make build-cli   # build with JIT entitlement (macOS)
make bench       # CLI benchmarks vs Bun/Node (hyperfine + wrk)
make bench-go    # compare vs goja / otto (Go-embedded runtimes)
make sync        # sync typescript-go & rslint from submodules

License

MIT

Third-Party Licenses

Ramune includes code from the following projects:

Project License Usage Inclusion
microsoft/typescript-go Apache-2.0 Type checker, formatter (TS 7.0-dev) Source copy (internal/tsgo/)
web-infra-dev/rslint MIT Linter Source copy (internal/rslint/)
modernc.org/libc BSD-3-Clause Pure-Go libc for QuickJS/SQLite multi-worker scaling (fork with per-TLS allocator + page-owner routing; see third_party/libc/pageowner.go and the local patches to mem.go / pthread.go / libc_darwin.go / mem_musl.go / libc_musl.go) Source copy (third_party/libc/) via replace directive
modernc.org/quickjs BSD-3-Clause QuickJS backend (-tags quickjs) Go module dependency
dop251/goja MIT goja backend (-tags goja) Go module dependency
evanw/esbuild MIT TypeScript transpilation, bundling Go module dependency

License texts for source-copied projects are in internal/tsgo/LICENSE, internal/rslint/LICENSE, internal/rslint/tsgo_pinned/LICENSE (a separate tsgo copy pinned to rslint's version for its shim bindings), and third_party/libc/LICENSE (together with AUTHORS, CONTRIBUTORS, and LICENSE-3RD-PARTY.md preserved from upstream).

The Ramune logo includes the Go Gopher, originally designed by Renée French, licensed under Creative Commons Attribution 4.0.

Documentation

Overview

Package ramune provides Go bindings for JavaScriptCore via purego — no Cgo required. The JSC runtime is dynamically loaded at startup and works with the system framework on macOS and libjavascriptcoregtk on Linux.

Basic Usage

Evaluate JavaScript and read results:

rt, err := ramune.New()
if err != nil {
    log.Fatal(err)
}
defer rt.Close()

val, err := rt.Eval("1 + 2")
if err != nil {
    log.Fatal(err)
}
defer val.Close()
fmt.Println(val.Float64()) // 3

Constructing Objects

Create JS objects and arrays directly from Go:

obj, _ := rt.NewObject(map[string]any{"name": "Alice", "age": 30})
arr, _ := rt.NewArray(1, "two", true)
obj.SetAttr("tags", arr)

Go Callbacks

Register Go functions callable from JavaScript:

rt.RegisterFunc("add", func(args []any) (any, error) {
    return args[0].(float64) + args[1].(float64), nil
})
val, _ := rt.Eval("add(3, 4)") // 7

npm Packages

Use npm packages via automatic esbuild bundling:

rt, _ := ramune.New(
    ramune.NodeCompat(),
    ramune.Dependencies("lodash@4"),
)
val, _ := rt.Eval(`lodash.chunk([1,2,3,4,5,6], 2)`)

Event Loop and Async

setTimeout, setInterval, and Promises work with the built-in event loop:

val, _ := rt.EvalAsync(`
    new Promise(resolve => setTimeout(() => resolve(42), 100))
`)
fmt.Println(val.Float64()) // 42

Fetch

HTTP requests via globalThis.fetch backed by Go's net/http:

rt, _ := ramune.New(ramune.WithFetch())
val, _ := rt.EvalAsync(`
    fetch("https://api.example.com/data").then(r => r.json())
`)

Index

Constants

This section is empty.

Variables

View Source
var ErrAlreadyClosed = errors.New("ramune: runtime already closed")

ErrAlreadyClosed is returned when operations are attempted on a closed Runtime.

View Source
var ErrJSCNotFound = errors.New("ramune: shared library not found")

ErrJSCNotFound is returned when no suitable JavaScriptCore shared library can be located on the system.

View Source
var ErrNilValue = errors.New("ramune: operation on nil Value")

ErrNilValue is returned when an operation is attempted on a nil Value.

View Source
var NodeBuiltins = []string{
	"child_process", "fs", "path", "os", "net", "http", "https", "tls",
	"stream", "events", "util", "buffer", "crypto", "url", "querystring",
	"zlib", "string_decoder", "assert", "readline", "dns", "worker_threads",
	"dgram", "module", "process", "tty", "timers", "timers/promises",
	"perf_hooks", "node:*",
}

NodeBuiltins lists Node.js built-in modules that are provided by the NodeCompat polyfill layer and should be marked as external during bundling.

Functions

func ClearCache

func ClearCache() error

ClearCache removes all cached JS bundles created by Dependencies().

func DrainWebViewMain added in v0.8.0

func DrainWebViewMain(done <-chan struct{})

DrainWebViewMain processes WebView operations on the main thread. Blocks until done is closed or all work is complete. Must be called from the main goroutine (pinned to thread 0 via runtime.LockOSThread in init).

func HandleSandboxWorker added in v0.8.0

func HandleSandboxWorker(s *SandboxRuntime) bool

HandleSandboxWorker checks if the current process is a sandbox worker and returns true if so. The caller should pass the SandboxRuntime that was set up with RegisterFunc calls, then exit.

Usage:

rt := ramune.NewSandboxRuntime(ramune.NodeCompat())
rt.RegisterFunc("add", func(a, b float64) float64 { return a + b })
if ramune.HandleSandboxWorker(rt) {
    return
}

func InitWebViewMain added in v0.8.0

func InitWebViewMain()

InitWebViewMain enables WebView support by creating the main-thread dispatch channel. Must be called before any WebView is created. The caller must drain the channel on the main goroutine, e.g.:

ramune.InitWebViewMain()
go func() { /* run engine */ }()
ramune.DrainWebViewMain(done)

func InstallNpmPackages added in v0.5.0

func InstallNpmPackages(specs []string, destDir string) error

InstallNpmPackages downloads npm packages to destDir/node_modules/. Packages are specified as "name" or "name@version" (e.g., "preact", "lodash@4"). Packages are fetched directly from the npm registry — no npm or bun required.

func Register

func Register[F any](rt *Runtime, name string, fn F) error

Register registers a typed Go function as a global JavaScript function. Unlike RegisterFunc, which requires manual args[]any casting, Register uses reflection to automatically convert JS arguments to the function's parameter types and convert return values back.

Supported parameter types: float64, float32, int, int8/16/32/64, uint, uint8/16/32/64, string, bool, map[string]any, []any.

Supported return signatures:

  • func(...) → no return value
  • func(...) T → single return value (non-error)
  • func(...) error → single error return
  • func(...) (T, error) → value + error

Example:

ramune.Register(rt, "add", func(a, b float64) float64 {
    return a + b
})

func SandboxAvailable added in v0.8.0

func SandboxAvailable() bool

SandboxAvailable checks whether Docker is reachable.

Types

type CallbackContext

type CallbackContext struct {
	// contains filtered or unexported fields
}

CallbackContext provides safe access to the JS engine from within a GoFunc. Value methods like Attr() and Call() dispatch to the engine goroutine, which deadlocks inside a callback (already on the engine goroutine). CallbackContext calls engine functions directly and returns Go values.

func (*CallbackContext) Eval

func (cc *CallbackContext) Eval(code string) (any, error)

Eval evaluates JS code and returns the result as any (Go value).

func (*CallbackContext) EvalBool

func (cc *CallbackContext) EvalBool(code string) (bool, error)

EvalBool evaluates JS code and returns the result as bool.

func (*CallbackContext) EvalFloat64

func (cc *CallbackContext) EvalFloat64(code string) (float64, error)

EvalFloat64 evaluates JS code and returns the result as float64.

func (*CallbackContext) EvalString

func (cc *CallbackContext) EvalString(code string) (string, error)

EvalString evaluates JS code and returns the result as string.

func (*CallbackContext) Exec

func (cc *CallbackContext) Exec(code string) error

Exec executes JavaScript code, discarding the result.

func (*CallbackContext) GetProperty

func (cc *CallbackContext) GetProperty(name string) (any, error)

GetProperty reads a property from the global object.

func (*CallbackContext) SetProperty

func (cc *CallbackContext) SetProperty(name string, value any) error

SetProperty sets a property on the global object.

type GCConfig

type GCConfig struct {
	// GCInterval is the number of HTTP requests between manual JSC GC cycles.
	// Lower values use more CPU but prevent JS memory growth.
	// Default: 2000. Set to 0 to disable manual JSC GC.
	GCInterval int

	// GCPercent sets the Go GC target percentage (same as GOGC env var).
	// Applied when the HTTP server starts. Default: 100 (Go's default).
	GCPercent int
}

GCConfig configures garbage collection behavior for a Runtime.

func DefaultGCConfig

func DefaultGCConfig() GCConfig

DefaultGCConfig returns the default GC configuration.

type GoFunc

type GoFunc func(args []any) (any, error)

GoFunc is a Go function that can be called from JavaScript. Arguments are converted to Go types: bool, float64, string, nil, map[string]any (for objects), []any (for arrays), or *JSFunc (for functions).

type GoFuncWithContext

type GoFuncWithContext func(ctx *CallbackContext, args []any) (any, error)

GoFuncWithContext is a callback that receives a CallbackContext for safe engine access. Use RegisterFuncWithContext to register these.

type JSError

type JSError struct {
	Context string
	Message string
	Stack   string // JavaScript stack trace, if available
}

JSError represents an error that originated in the JavaScript runtime.

func (*JSError) Error

func (e *JSError) Error() string

type JSFunc added in v0.4.0

type JSFunc struct {
	// contains filtered or unexported fields
}

JSFunc wraps a JavaScript function reference, allowing it to be called from Go. Created automatically when a JS function is passed as an argument to a GoFunc callback. Call Close() when done to release the JS reference.

func (*JSFunc) Call added in v0.4.0

func (f *JSFunc) Call(args ...any) (any, error)

Call invokes the JavaScript function with the given arguments. Returns the result converted to a Go value (bool, float64, string, nil, map[string]any, or []any). Safe to call from any goroutine and from within GoFunc callbacks.

func (*JSFunc) Close added in v0.4.0

func (f *JSFunc) Close() error

Close releases the JavaScript function reference. Safe to call multiple times or on nil.

type LibraryNotFoundError

type LibraryNotFoundError struct {
	Searched []string
}

LibraryNotFoundError provides detailed information about which paths were searched when JavaScriptCore could not be found.

func (*LibraryNotFoundError) Error

func (e *LibraryNotFoundError) Error() string

func (*LibraryNotFoundError) Unwrap

func (e *LibraryNotFoundError) Unwrap() error

type Module

type Module struct {
	// Name is the module name used with require('name').
	Name string

	// Exports maps JS property names to Go functions.
	// Each function becomes a property on the module object.
	Exports map[string]GoFunc

	// Init is called after exports are registered, allowing
	// additional setup such as evaluating JS code.
	// The Runtime's JSC lock is held — use execLocked/evalLocked only.
	Init func(rt *Runtime) error
}

Module defines a custom module that can be loaded via require() in JS.

func NativeModuleFromFuncs added in v0.4.0

func NativeModuleFromFuncs(name string, funcs map[string]any) Module

NativeModuleFromFuncs creates a Module from a map of typed Go functions. Each function is automatically wrapped with reflection-based argument conversion, similar to Register[F]. This is used to expose transpiled Go code as a JS module.

Example:

mod := ramune.NativeModuleFromFuncs("native:math", map[string]any{
    "fibonacci": mymath.Fibonacci,  // func(float64) float64
    "isPrime":   mymath.IsPrime,    // func(float64) bool
})
rt, _ := ramune.New(ramune.WithModule(mod))
rt.Eval(`require('native:math').fibonacci(10)`) // 55

type Option

type Option func(*config)

Option configures a Runtime.

func Dependencies

func Dependencies(pkgs ...string) Option

Dependencies declares npm package dependencies that are automatically installed, bundled with esbuild, and evaluated in the JSC context. Packages are specified as "name" or "name@version" (e.g., "lodash@4"). Subpath imports are also supported (e.g., "react-dom/server"); the base package is installed and the subpath is imported separately in the bundle. The bundle is cached in ~/.cache/ramune/jsbundles/<hash>/. Packages are fetched directly from the npm registry — no npm or bun required.

func DockerModule added in v0.8.0

func DockerModule() Option

DockerModule returns an Option that installs the Docker native module. The module is lazy-initialized on first require('dockerode').

func NodeCompat

func NodeCompat() Option

NodeCompat installs a minimal Node.js compatibility layer into the JSC context. This enables npm packages that depend on Node.js built-ins to run in JSC with Go providing the native functionality.

Supported polyfills:

  • require() — returns polyfilled modules
  • process.env, process.cwd(), process.platform, process.arch
  • child_process.spawnSync / execSync (synchronous only)
  • fs.readFileSync, fs.existsSync, fs.writeFileSync, fs.mkdirSync
  • path.join, path.resolve, path.dirname, path.basename, path.sep
  • Buffer.from (basic)
  • console.log, console.error, console.warn
  • setTimeout (immediate execution, no real delay)

func PreloadJS added in v0.6.0

func PreloadJS(code string) Option

PreloadJS sets JavaScript code that will be executed before loading dependency bundles. This is useful for providing polyfills required by bundled packages (e.g., MessageChannel for React).

func WithFetch

func WithFetch() Option

WithFetch installs a globalThis.fetch polyfill backed by Go's net/http. This is also automatically enabled when NodeCompat() is used.

func WithGC

func WithGC(gc GCConfig) Option

WithGC configures garbage collection behavior. See GCConfig for details on each setting.

func WithLibraryPath

func WithLibraryPath(path string) Option

WithLibraryPath sets an explicit path to the JavaScriptCore shared library. Ignored when using the QuickJS backend.

func WithModule

func WithModule(m Module) Option

WithModule returns an Option that registers a module during Runtime creation. The module is available via require('name') if NodeCompat is enabled.

func WithPermissions

func WithPermissions(p *Permissions) Option

WithPermissions sets the permission policy for the Runtime.

func WithStderr added in v0.8.0

func WithStderr(w io.Writer) Option

WithStderr sets the writer for console.error/warn output. Defaults to os.Stderr if not set.

func WithStdout added in v0.8.0

func WithStdout(w io.Writer) Option

WithStdout sets the writer for console.log/info/debug output. Defaults to os.Stdout if not set.

func WithTickManager added in v0.8.0

func WithTickManager(m TickManager) Option

WithTickManager registers a custom event loop manager. The manager's ProcessEvents method is called during each event loop tick, and HasActive is checked to determine if the event loop should keep running.

func WithWinterTC added in v0.10.0

func WithWinterTC() Option

WithWinterTC installs the WinterTC (ECMA-429) Minimum Common Web API surface. This includes CompressionStream, DecompressionStream, MessageChannel, MessagePort, MessageEvent, ErrorEvent, PromiseRejectionEvent, and URLPattern.

When used with NodeCompat(), these APIs are installed automatically. Use WithWinterTC() for standalone WinterTC compliance without the full Node.js compatibility layer.

type PermissionState

type PermissionState int

PermissionState represents the state of a permission.

const (
	PermGranted PermissionState = iota
	PermDenied
)

type Permissions

type Permissions struct {
	Read  PermissionState
	Write PermissionState
	Net   PermissionState
	Env   PermissionState
	Run   PermissionState

	ReadPaths  []string // allowed read paths (empty = all if granted)
	WritePaths []string // allowed write paths
	NetHosts   []string // allowed network hosts
	EnvVars    []string // allowed env var names
	RunCmds    []string // allowed commands
}

Permissions controls access to system resources. Default is all granted (Bun-compatible). Use WithSandbox() to deny by default.

func AllPermissions

func AllPermissions() *Permissions

AllPermissions returns permissions with everything granted.

func SandboxPermissions

func SandboxPermissions() *Permissions

SandboxPermissions returns permissions with everything denied.

func (*Permissions) CheckEnv

func (p *Permissions) CheckEnv(name string) error

CheckEnv checks if accessing the given env var is allowed.

func (*Permissions) CheckNet

func (p *Permissions) CheckNet(host string) error

CheckNet checks if network access to the given host is allowed.

func (*Permissions) CheckRead

func (p *Permissions) CheckRead(path string) error

CheckRead checks if reading the given path is allowed.

func (*Permissions) CheckRun

func (p *Permissions) CheckRun(cmd string) error

CheckRun checks if running the given command is allowed.

func (*Permissions) CheckWrite

func (p *Permissions) CheckWrite(path string) error

CheckWrite checks if writing to the given path is allowed.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime holds a loaded JavaScriptCore library and a global JS context. Multiple Runtimes can coexist in the same process — each gets a dedicated OS thread for JSC access. All JSC operations are dispatched to this thread via a channel, ensuring thread identity across calls (required by JSC). The Runtime is safe for concurrent use from multiple goroutines.

func New

func New(opts ...Option) (*Runtime, error)

New creates a new JavaScriptCore runtime with a fresh global context. Each Runtime gets a dedicated OS thread for all JSC operations, ensuring thread identity across calls. Multiple Runtimes can coexist safely.

func (*Runtime) Bind

func (r *Runtime) Bind(name string, v any) error

Bind exposes a Go struct as a JavaScript object on globalThis. Exported struct fields become JS properties (read from current Go state), and methods on the pointer receiver become callable JS functions.

Field naming: if a field has a `js:"name"` tag, that name is used; otherwise the first letter is lowercased (e.g. Name → name).

Method naming: Go method names are converted to camelCase (e.g. Greet → greet, SetAge → setAge).

Fields are backed by the Go struct: reading a property in JS always returns the current Go value. Setting a property in JS updates the Go struct. Methods that mutate the struct are reflected on subsequent property reads.

func (*Runtime) Close

func (r *Runtime) Close() error

Close releases the JS global context and stops the dedicated JSC goroutine.

func (*Runtime) Engine added in v0.2.0

func (r *Runtime) Engine() string

Engine returns the name of the JS engine backend.

func (*Runtime) Eval

func (r *Runtime) Eval(code string) (*Value, error)

Eval evaluates JavaScript code and returns the result.

func (*Runtime) EvalAsync

func (r *Runtime) EvalAsync(code string) (*Value, error)

EvalAsync evaluates JavaScript code that may return a Promise, runs the event loop until the Promise resolves, and returns the result.

func (*Runtime) EvalAsyncWithContext

func (r *Runtime) EvalAsyncWithContext(ctx context.Context, code string) (*Value, error)

EvalAsyncWithContext evaluates JavaScript code that may return a Promise, runs the event loop until the Promise resolves or the context is cancelled/expired, and returns the result.

func (*Runtime) EvalWithContext

func (r *Runtime) EvalWithContext(ctx context.Context, code string) (*Value, error)

EvalWithContext evaluates JavaScript code and returns the result, respecting the provided context for cancellation and deadlines. Since JSC cannot be interrupted mid-execution, the context is checked before evaluation begins. For timeout control over async operations, use EvalAsyncWithContext instead.

func (*Runtime) Exec

func (r *Runtime) Exec(code string) error

Exec executes JavaScript code, discarding the result.

func (*Runtime) GlobalObject

func (r *Runtime) GlobalObject() *Value

GlobalObject returns the global object for this context.

func (*Runtime) LoadModule

func (r *Runtime) LoadModule(m Module) error

LoadModule registers a module on an existing Runtime.

func (*Runtime) NativeInstanceCount added in v0.4.0

func (r *Runtime) NativeInstanceCount() int

NativeInstanceCount returns the number of live native struct instances. Useful for testing and debugging instance lifecycle.

func (*Runtime) NewArray

func (r *Runtime) NewArray(items ...any) (*Value, error)

NewArray creates a new JavaScript array with the given items.

func (*Runtime) NewObject

func (r *Runtime) NewObject(props map[string]any) (*Value, error)

NewObject creates a new JavaScript object with the given properties.

func (*Runtime) NewUint8Array

func (r *Runtime) NewUint8Array(data []byte) (*Value, error)

NewUint8Array creates a JavaScript Uint8Array containing a copy of the given bytes.

func (*Runtime) RegisterFunc

func (r *Runtime) RegisterFunc(name string, fn GoFunc) error

RegisterFunc registers a Go function as a global JavaScript function.

func (*Runtime) RegisterFuncWithContext

func (r *Runtime) RegisterFuncWithContext(name string, fn GoFuncWithContext) error

RegisterFuncWithContext registers a Go function that receives a CallbackContext, allowing safe JSC access from within the callback without deadlocking.

func (*Runtime) RunEventLoop

func (r *Runtime) RunEventLoop() error

RunEventLoop processes the event loop until all pending operations complete. For short-lived scripts (timers, promises), the default timeout is 30 seconds. If an HTTP server (Ramune.serve) is active, the loop runs indefinitely.

func (*Runtime) RunEventLoopFor

func (r *Runtime) RunEventLoopFor(timeout time.Duration) error

RunEventLoopFor processes the event loop until all timers complete or the timeout is reached.

func (*Runtime) RunEventLoopWithContext

func (r *Runtime) RunEventLoopWithContext(ctx context.Context) error

RunEventLoopWithContext processes the event loop until all timers complete or the context is cancelled/expired.

func (*Runtime) Tick

func (r *Runtime) Tick() (bool, error)

Tick processes one round of the event loop (immediates + ready timers). Returns true if there are still pending timers or immediates.

func (*Runtime) Wake

func (r *Runtime) Wake()

Wake signals the event loop to process events immediately. Safe to call from any goroutine. Non-blocking.

type RuntimePool

type RuntimePool struct {
	// contains filtered or unexported fields
}

RuntimePool manages multiple Runtimes for parallel JS execution. Each Runtime has its own dedicated OS thread and independent JSC VM.

func NewPool

func NewPool(n int, opts ...Option) (*RuntimePool, error)

NewPool creates a pool of n Runtimes, each configured with the given options.

func (*RuntimePool) Addr

func (p *RuntimePool) Addr() string

Addr returns the listener address, or "" if not listening.

func (*RuntimePool) Broadcast

func (p *RuntimePool) Broadcast(code string) error

Broadcast executes JavaScript code on all workers in parallel.

func (*RuntimePool) Close

func (p *RuntimePool) Close() error

Close stops the HTTP server (if running) and closes all Runtimes.

func (*RuntimePool) Eval

func (p *RuntimePool) Eval(code string) (*Value, error)

Eval evaluates JavaScript code on the next available worker.

func (*RuntimePool) Exec

func (p *RuntimePool) Exec(code string) error

Exec executes JavaScript code on the next available worker, discarding the result.

func (*RuntimePool) ListenAndServe

func (p *RuntimePool) ListenAndServe(addr string, jsHandler string) error

ListenAndServe starts an HTTP server that dispatches requests round-robin across pool workers via per-worker channels.

func (*RuntimePool) Size

func (p *RuntimePool) Size() int

Size returns the number of workers in the pool.

func (*RuntimePool) StopHTTP

func (p *RuntimePool) StopHTTP()

StopHTTP stops the HTTP server and drains in-flight requests.

type SandboxConfig added in v0.8.0

type SandboxConfig struct {
	// Image is the Docker image to use. Default: "ubuntu:24.04".
	Image string
	// Mounts are additional bind mounts in "host:container[:ro]" format.
	Mounts []string
	// Env is additional environment variables for the container.
	Env map[string]string
	// Timeout is the maximum execution time. Default: 60s.
	Timeout time.Duration
	// SocketPath overrides the Docker socket path.
	SocketPath string
	// Network is the Docker network to connect the container to.
	// Use this to give the sandbox access to other services on the same network.
	Network string
	// ExtraHosts adds custom host-to-IP mappings (like --add-host).
	// Format: "hostname:ip" (e.g. "api-server:192.168.1.100").
	ExtraHosts []string
	// MemoryMB sets the container memory limit in megabytes. 0 = unlimited.
	MemoryMB int
	// CPUs sets the CPU limit (e.g. 1.5 = 1.5 cores). 0 = unlimited.
	CPUs float64
	// NoNetwork disables all network access from the container.
	NoNetwork bool
}

SandboxConfig configures Docker sandbox execution.

type SandboxResult added in v0.8.0

type SandboxResult struct {
	ExitCode int
	Stdout   string
	Stderr   string
}

SandboxResult holds the result of a sandboxed execution.

func SandboxEval added in v0.8.0

func SandboxEval(code string, cfg SandboxConfig) (*SandboxResult, error)

SandboxEval evaluates a JS expression inside a Docker container.

func SandboxRun added in v0.8.0

func SandboxRun(scriptPath string, cfg SandboxConfig) (*SandboxResult, error)

SandboxRun executes a ramune script inside a Docker container.

type SandboxRuntime added in v0.8.0

type SandboxRuntime struct {
	// contains filtered or unexported fields
}

SandboxRuntime holds Go function registrations for sandbox execution. When the binary is re-invoked inside Docker, the same functions are available because they are compiled into the binary.

func NewSandboxRuntime added in v0.8.0

func NewSandboxRuntime(opts ...Option) *SandboxRuntime

NewSandboxRuntime creates a new SandboxRuntime with the given options.

func (*SandboxRuntime) RegisterFunc added in v0.8.0

func (s *SandboxRuntime) RegisterFunc(name string, fn GoFunc)

RegisterFunc registers a Go function that will be available to JS code in the sandbox. The function is compiled into the binary, so it works both on the host and inside the Docker container.

func (*SandboxRuntime) SandboxEval added in v0.8.0

func (s *SandboxRuntime) SandboxEval(code string, cfg SandboxConfig) (*SandboxResult, error)

SandboxEval evaluates JS code inside a Docker container.

func (*SandboxRuntime) SandboxRun added in v0.8.0

func (s *SandboxRuntime) SandboxRun(scriptPath string, cfg SandboxConfig) (*SandboxResult, error)

SandboxRun executes a ramune script inside a Docker container.

type TickManager added in v0.8.0

type TickManager interface {
	// ProcessEvents drains pending events and delivers them to JavaScript.
	// Called on the dedicated engine goroutine during each event loop tick.
	ProcessEvents(r *Runtime)

	// HasActive returns true if there are pending operations that should
	// keep the event loop running.
	HasActive() bool

	// Close releases resources held by the manager.
	Close()
}

TickManager is the interface for custom event loop managers. External packages implement this to integrate async I/O with ramune's event loop.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value wraps a JavaScriptCore JSValueRef with lifecycle management. Call Close() to unprotect the value.

func (*Value) Attr

func (v *Value) Attr(name string) *Value

Attr returns a property by name from the JS object. Returns nil if this is not an object or the property doesn't exist.

func (*Value) AttrErr

func (v *Value) AttrErr(name string) (*Value, error)

AttrErr returns a property by name or an error.

func (*Value) Bool

func (v *Value) Bool() (bool, error)

Bool returns the value as a bool.

func (*Value) Bytes

func (v *Value) Bytes() ([]byte, error)

Bytes returns the contents of a TypedArray or ArrayBuffer as a Go byte slice.

func (*Value) Call

func (v *Value) Call(args ...any) (*Value, error)

Call calls this value as a function with the given arguments.

func (*Value) Close

func (v *Value) Close() error

Close queues the JSValueRef for unprotection at the next safe point. Uses the unprotectQueue to avoid deadlock when called from GoFunc callbacks (which already run on the dedicated JSC goroutine). Safe to call multiple times or on nil.

func (*Value) Delete

func (v *Value) Delete(name string) error

Delete removes a property from the JS object.

func (*Value) Float64

func (v *Value) Float64() (float64, error)

Float64 returns the value as a float64.

func (*Value) GoString

func (v *Value) GoString() (string, error)

GoString returns the JavaScript string value as a Go string.

func (*Value) Has

func (v *Value) Has(name string) bool

Has reports whether the JS object has the named property.

func (*Value) Index

func (v *Value) Index(i int) *Value

Index returns the value at the given array index.

func (*Value) Int64

func (v *Value) Int64() (int64, error)

Int64 returns the value as an int64 (truncated from float64, since JS has no integer type).

func (*Value) IsArray

func (v *Value) IsArray() bool

IsArray reports whether this value is a JavaScript array.

func (*Value) IsFunction

func (v *Value) IsFunction() bool

IsFunction reports whether this value is a JavaScript function.

func (*Value) IsNull

func (v *Value) IsNull() bool

IsNull reports whether this value is JavaScript null.

func (*Value) IsUndefined

func (v *Value) IsUndefined() bool

IsUndefined reports whether this value is JavaScript undefined.

func (*Value) Keys

func (v *Value) Keys() ([]string, error)

Keys returns all enumerable property names of the JS object.

func (*Value) Len

func (v *Value) Len() (int, error)

Len returns the "length" property as an integer. Works for arrays, strings, and any object with a length property.

func (*Value) Ptr

func (v *Value) Ptr() uintptr

Ptr returns the raw JSValueRef pointer.

func (*Value) SetAttr

func (v *Value) SetAttr(name string, val any) error

SetAttr sets a property on the JS object.

func (*Value) String

func (v *Value) String() string

String returns the JavaScript string representation.

func (*Value) ToMap

func (v *Value) ToMap() (map[string]any, error)

ToMap converts a JS object to a Go map via JSON serialization. Returns an error if the value is not a JSON-serializable object.

func (*Value) ToSlice

func (v *Value) ToSlice() ([]any, error)

ToSlice converts a JS array to a Go slice via JSON serialization.

Directories

Path Synopsis
bench
pool command
cmd
ramune command
Command ramune is a JavaScript runtime powered by JavaScriptCore via purego.
Command ramune is a JavaScript runtime powered by JavaScriptCore via purego.
ramune-toolchain command
Command ramune-toolchain is the development toolchain for ramune: check, fmt, lint, transpile, typegen, compile.
Command ramune-toolchain is the development toolchain for ramune: check, fmt, lint, transpile, typegen, compile.
examples
workers/custom-binding command
A runnable demonstration of a custom env binding.
A runnable demonstration of a custom env binding.
internal
gotranspiler
Package gotranspiler implements TypeScript to Go source code transpilation.
Package gotranspiler implements TypeScript to Go source code transpilation.
rslint/tsgo_pinned/bundled
Package bundled provides access to files bundled with TypeScript.
Package bundled provides access to files bundled with TypeScript.
rslint/tsgo_pinned/compiler
Package compiler implements the TypeScript compiler.
Package compiler implements the TypeScript compiler.
rslint/tsgo_pinned/diagnostics
Package diagnostics contains generated localizable diagnostic messages.
Package diagnostics contains generated localizable diagnostic messages.
rslint/tsgo_pinned/jsnum
Package jsnum provides JS-like number handling.
Package jsnum provides JS-like number handling.
rslint/tsgo_pinned/nodebuilder
Exports interfaces and types defining the node builder - concrete implementations are on top of the checker, but these types and interfaces are used by the emit resolver in the printer
Exports interfaces and types defining the node builder - concrete implementations are on top of the checker, but these types and interfaces are used by the emit resolver in the printer
rslint/tsgo_pinned/printer
Package printer exports a Printer for pretty-printing TS ASTs and writer interfaces and implementations for using them Intended ultimate usage:
Package printer exports a Printer for pretty-printing TS ASTs and writer interfaces and implementations for using them Intended ultimate usage:
rslint/tsgo_pinned/stringutil
Package stringutil Exports common rune utilities for parsing and emitting javascript
Package stringutil Exports common rune utilities for parsing and emitting javascript
tsgo/bundled
Package bundled provides access to files bundled with TypeScript.
Package bundled provides access to files bundled with TypeScript.
tsgo/compiler
Package compiler implements the TypeScript compiler.
Package compiler implements the TypeScript compiler.
tsgo/diagnostics
Package diagnostics contains generated localizable diagnostic messages.
Package diagnostics contains generated localizable diagnostic messages.
tsgo/jsnum
Package jsnum provides JS-like number handling.
Package jsnum provides JS-like number handling.
tsgo/nodebuilder
Exports interfaces and types defining the node builder - concrete implementations are on top of the checker, but these types and interfaces are used by the emit resolver in the printer
Exports interfaces and types defining the node builder - concrete implementations are on top of the checker, but these types and interfaces are used by the emit resolver in the printer
tsgo/printer
Package printer exports a Printer for pretty-printing TS ASTs and writer interfaces and implementations for using them Intended ultimate usage:
Package printer exports a Printer for pretty-printing TS ASTs and writer interfaces and implementations for using them Intended ultimate usage:
tsgo/pseudochecker
pseudochecker is a limited "checker" that returns pseudo-"types" of expressions - mostly those which trivially have type nodes
pseudochecker is a limited "checker" that returns pseudo-"types" of expressions - mostly those which trivially have type nodes
tsgo/stringutil
Package stringutil Exports common rune utilities for parsing and emitting javascript
Package stringutil Exports common rune utilities for parsing and emitting javascript
Package jsrt provides runtime support for TypeScript-to-Go transpiled code.
Package jsrt provides runtime support for TypeScript-to-Go transpiled code.
array
Package array provides JavaScript Array.prototype method equivalents using Go generics.
Package array provides JavaScript Array.prototype method equivalents using Go generics.
compat/lodash
Package lodash provides Go adapters for commonly used lodash/lodash-es functions.
Package lodash provides Go adapters for commonly used lodash/lodash-es functions.
compat/uuid
Package uuid provides a Go adapter for the npm "uuid" package.
Package uuid provides a Go adapter for the npm "uuid" package.
compat/zod
Package zod provides a Go adapter for the npm "zod" schema validation library.
Package zod provides a Go adapter for the npm "zod" schema validation library.
console
Package console provides console.log/error/warn for transpiled TypeScript code.
Package console provides console.log/error/warn for transpiled TypeScript code.
fetch
Package fetch provides the fetch() API for transpiled TypeScript code.
Package fetch provides the fetch() API for transpiled TypeScript code.
node/crypto
Package crypto provides Node.js crypto module equivalents for transpiled TypeScript code.
Package crypto provides Node.js crypto module equivalents for transpiled TypeScript code.
node/fs
Package fs provides Node.js fs module equivalents for transpiled TypeScript code.
Package fs provides Node.js fs module equivalents for transpiled TypeScript code.
node/http
Package http provides Node.js http module equivalents for transpiled TypeScript code.
Package http provides Node.js http module equivalents for transpiled TypeScript code.
node/path
Package path provides Node.js path module equivalents for transpiled TypeScript code.
Package path provides Node.js path module equivalents for transpiled TypeScript code.
promise
Package promise provides a Promise[T] type for transpiled async/await TypeScript code.
Package promise provides a Promise[T] type for transpiled async/await TypeScript code.
web
Package web provides Go struct definitions for Web API types used by transpiled TypeScript code.
Package web provides Go struct definitions for Web API types used by transpiled TypeScript code.
Package workers provides a Cloudflare-Workers-style handler runtime on top of Ramune.
Package workers provides a Cloudflare-Workers-style handler runtime on top of Ramune.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL