ramune

package module
v0.0.0-...-b1675e3 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2026 License: MIT Imports: 54 Imported by: 0

README

Ramune

Ramune

A JavaScript/TypeScript runtime for Go — powered by JavaScriptCore, no Cgo required. Pure Go except for JSC: 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 run server.ts          # Run TypeScript
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

What is Ramune?

Ramune is two things:

  1. A JS/TS runtime like Bun or Deno, but built in Go
  2. An embeddable JS engine for Go applications

It loads Apple's JavaScriptCore dynamically via purego — no C compiler, no Cgo, just go build.

Install

macOS

JavaScriptCore is built into macOS — no extra dependencies.

go install github.com/i2y/ramune/cmd/ramune@latest
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

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).

Minimal install (12MB)
go install -tags nosqlite -ldflags="-s -w" github.com/i2y/ramune/cmd/ramune@latest
Build Size Excludes
Default 44MB
-tags nosqlite 39MB bun:sqlite
-tags nosqlite -ldflags="-s -w" 29MB bun:sqlite + debug info

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
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);
  });
});
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 ~21MB (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).

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.

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
})
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")
Use npm Packages
rt, _ := ramune.New(
    ramune.NodeCompat(),
    ramune.Dependencies("lodash@4"),
)
val, _ := rt.Eval(`lodash.chunk([1,2,3,4,5,6], 2)`)
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 });
});
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("computeHeavy()")                     // round-robin dispatch
pool.Broadcast("globalThis.config = {debug: true}")  // run on all

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

With CPU-heavy handlers, 3 workers achieve 2.7x throughput vs single-threaded Bun.

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, 101K req/s)
Ramune.file(path) Supported (text, json, exists, size)
Ramune.write(path, data) Supported
Ramune.password.hash/verify Supported (bcrypt)
Ramune.sleep(ms) Supported
Request / Response Polyfilled (enables Hono etc.)
bun:sqlite Supported (pure Go, modernc.org/sqlite)
Bun.* Alias for Ramune.* (partial Bun compatibility)
GC Configuration

Go's garbage collector can interfere with JavaScriptCore under high load. Ramune provides tunable GC settings:

rt, _ := ramune.New(ramune.NodeCompat(), ramune.WithGC(ramune.GCConfig{
    DisableAutoGC: true,   // disable Go's auto GC during HTTP serving
    GCInterval:    2000,   // manual GC every N requests
    GCPercent:     100,    // Go GC target %
}))

For most use cases (CLI, scripting, SDK), defaults work fine. Tuning is only needed for high-throughput HTTP servers.

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,
    }),
)

Performance

Benchmarks on Apple M4 Max (macOS, JIT enabled):

Test Ramune Bun Node.js
Hello World startup 10.5ms 6.2ms 17.4ms
Fibonacci(35) 42.9ms 39.4ms 63.5ms
JSON 10K objects 14.2ms 8.9ms 22.2ms
Crypto SHA256 x1000 16.6ms 10.3ms 19.6ms
File I/O x100 17.2ms 11.9ms 23.0ms
HTTP req/s (single) 101K 170K 114K
HTTP req/s (3 workers) 87 req/s 31 req/s 22 req/s

The last row shows CPU-heavy handlers (fib(35) per request) — Ramune's multi-runtime pool scales linearly while Bun/Node are single-threaded.

vs Go JS Runtimes
Test Ramune (JSC+JIT) goja otto
Fibonacci(35) 43ms 1,945ms (45x slower) 23,760ms (559x slower)
JSON 10K objects 1.5ms 12ms (8x slower) 26ms (17x slower)

Ramune uses Apple's JavaScriptCore with JIT compilation. goja and otto are pure Go interpreters.

Run make bench 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 70%
fs 85% os 85%
child_process 80% events 85%
crypto 80% url 80%
stream 70% Buffer 60%
http/https 70% assert 80%
net/tls 60% dns basic
worker_threads 70% readline 70%

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 JSC context deadlock).
  • Windows: No JavaScriptCore available.
  • Linux multi-runtime: 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 limit: 2-3 workers recommended for sustained high-throughput; 4+ may trigger JSC JIT contention.

Requirements

Dependency Required Purpose
Go 1.26+ Yes Build and install
macOS or Linux Yes macOS: JSC built-in. Linux: apt install libjavascriptcoregtk-4.1-dev

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.

Development

make ci          # fmt + build + vet + test
make build-cli   # build with JIT entitlement (macOS)
make bench       # benchmark vs Bun/Node
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/)
evanw/esbuild MIT TypeScript transpilation, bundling Go module dependency

License texts for source-copied projects are in internal/tsgo/LICENSE and internal/rslint/LICENSE.

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.

Functions

func ClearCache

func ClearCache() error

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

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
})

Types

type CallbackContext

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

CallbackContext provides safe access to JSC from within a GoFunc. Value methods like Attr() and Call() dispatch to the JSC goroutine, which deadlocks inside a callback (already on the JSC goroutine). CallbackContext calls JSC 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 {
	// DisableAutoGC disables Go's automatic GC while the HTTP server is
	// running. Manual GC is triggered every GCInterval requests.
	// Default: true (for HTTP server stability).
	DisableAutoGC bool

	// GCInterval is the number of HTTP requests between manual GC cycles.
	// Lower values use more CPU but prevent memory growth.
	// Default: 5000. Set to 0 to disable manual GC.
	GCInterval int

	// GCPercent sets the Go GC target percentage (same as GOGC env var).
	// Only used when DisableAutoGC is false.
	// Default: 100 (Go's default). Set to -1 to disable GC entirely.
	GCPercent int
}

GCConfig controls garbage collection behavior for JSC interoperability. Go's concurrent GC can corrupt JSC's internal structures under high load. These settings allow tuning the tradeoff between performance and stability.

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), or []any (for arrays).

type GoFuncWithContext

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

GoFuncWithContext is a callback that receives a CallbackContext for safe JSC 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 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.

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"). The bundle is cached in ~/.cache/ramune/jsbundles/<hash>/. Packages are fetched directly from the npm registry — no npm or bun required.

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 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.

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.

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) 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) 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 timers complete. Default timeout is 30 seconds.

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 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.
internal
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/stringutil
Package stringutil Exports common rune utilities for parsing and emitting javascript
Package stringutil Exports common rune utilities for parsing and emitting javascript

Jump to

Keyboard shortcuts

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