Documentation
¶
Overview ¶
Package moejs embeds the moejs JavaScript engine in a Go host that runs ES modules as plugins: compile a module once, evaluate it in any number of runtimes, call its exported functions with Go data and read their results back as Go data or JSON bytes.
mod, err := moejs.Compile("plugin.js", source)
hook, err := mod.Hook("protocols", "openai", "decodeRequest")
rt := moejs.NewRuntime(moejs.Options{})
err = rt.SetGlobal("utils", map[string]any{"now": moejs.NativeFunc(now)})
err = rt.Load(mod)
arg, err := rt.ParseJSON(body)
res, err := rt.Call(hook, arg)
out, err := rt.AppendJSON(nil, res)
Values are engine values (package engine) under their own names, so host functions and the host share one representation and nothing is wrapped on the way in or out. Errors are returned, never panicked: a JavaScript throw is an *Exception, an interrupt an *InterruptedError, bad source a *SyntaxError.
The jobs JavaScript queues (promise reactions, queueMicrotask callbacks) run before the method that ran it returns, getters and proxy traps included (Load, Call, Has, Get, ToGo, AppendJSON, SetGlobal, the settlers of NewPromise): the first exception a callback throws is the method's error when it succeeded otherwise, and an interrupt drops the jobs left.
A Module is immutable and may be loaded by many runtimes concurrently. A Runtime is one global environment with one loaded module; it must be used from one goroutine at a time, except Interrupt and ClearInterrupt.
Index ¶
- Constants
- Variables
- func PromiseResult(p Value) (state PromiseState, result Value, ok bool)
- type Exception
- type Hook
- type InternalError
- type InterruptedError
- type Module
- type NativeFunc
- type Object
- type Options
- type PromiseRejectionOperation
- type PromiseState
- type Realm
- type Runtime
- func (rt *Runtime) AppendJSON(dst []byte, v Value) (out []byte, err error)
- func (rt *Runtime) Call(h Hook, args ...Value) (res Value, err error)
- func (rt *Runtime) ClearInterrupt()
- func (rt *Runtime) Export(name string) (v Value, ok bool)
- func (rt *Runtime) FromGo(v any) (Value, error)
- func (rt *Runtime) Function(name string, length int, fn NativeFunc) Value
- func (rt *Runtime) Get(v Value, key string) (res Value, err error)
- func (rt *Runtime) Has(h Hook) (ok bool, err error)
- func (rt *Runtime) Interrupt(v any)
- func (rt *Runtime) Load(m *Module) (err error)
- func (rt *Runtime) Module() *Module
- func (rt *Runtime) NewPromise() (p Value, resolve, reject func(v Value) error)
- func (rt *Runtime) ParseJSON(b []byte) (Value, error)
- func (rt *Runtime) Realm() *Realm
- func (rt *Runtime) SetGlobal(name string, v any) (err error)
- func (rt *Runtime) SetPromiseRejectionTracker(f func(p Value, op PromiseRejectionOperation))
- func (rt *Runtime) StackTrace(exc *Exception) string
- func (rt *Runtime) ToGo(v Value) (out any, err error)
- type SyntaxError
- type Value
Constants ¶
const ( PromisePending = engine.PromisePending PromiseFulfilled = engine.PromiseFulfilled PromiseRejected = engine.PromiseRejected )
Promise states.
const ( // PromiseRejectionReject: the promise was rejected with no handler. PromiseRejectionReject = engine.PromiseRejectionReject // PromiseRejectionHandle: the first handler was added to the promise, // rejected earlier with none. PromiseRejectionHandle = engine.PromiseRejectionHandle )
Rejection tracker operations.
Variables ¶
var ( Undefined = engine.Undefined Null = engine.Null Bool = engine.Bool Number = engine.NumberValue Int = engine.Int64Value )
Value constructors, for host functions. None allocates except String.
var ( // ErrHookNotFound is returned when a hook's export or one of its members // is missing, undefined or null. ErrHookNotFound = errors.New("moejs: hook not found") // ErrNotCallable is returned when a hook names a value that is not a // function. ErrNotCallable = errors.New("moejs: hook is not a function") // ErrModulePending is Load's error for a module with top-level await // whose evaluation still awaits once no job is left. ErrModulePending = engine.ErrModulePending )
var Arg = engine.Arg
Arg returns args[i], or undefined when there are fewer arguments.
Functions ¶
func PromiseResult ¶
func PromiseResult(p Value) (state PromiseState, result Value, ok bool)
PromiseResult reports the state of the promise p and its result: the fulfillment value or the rejection reason, undefined while pending. ok is false when p is not a promise. No user code runs, so a promise a Call returned is read as the jobs that Call ran left it.
Types ¶
type Hook ¶
type Hook struct {
// contains filtered or unexported fields
}
Hook is a resolved path to a function in a module (Module.Hook). The zero Hook names nothing.
type InternalError ¶
type InternalError struct {
Value any // the recovered panic value
Stack []byte // the goroutine stack at the panic
}
InternalError is a Go panic that escaped the engine: an engine bug or a host function that panicked. The runtime's call state is restored, but the host should drop the runtime.
func (*InternalError) Error ¶
func (e *InternalError) Error() string
func (*InternalError) Unwrap ¶
func (e *InternalError) Unwrap() error
Unwrap returns the panic value when it is an error.
type InterruptedError ¶
type InterruptedError = engine.InterruptedError
InterruptedError is returned when Interrupt stopped running code.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module is a compiled ES module. It is immutable: any number of runtimes may load it, concurrently.
func Compile ¶
Compile parses and compiles an ES module. Bad source, including features the engine does not support yet, is a *SyntaxError. Modules cannot import.
func (*Module) Hook ¶
Hook names an exported function, or a function below an exported object reached through own properties (members "openai", "decodeRequest" of export "protocols"). The export slot and the property keys are resolved here, once; the bindings stay live, so each Call reads the export and walks the members in the runtime at hand. An export the module does not declare is ErrHookNotFound.
type NativeFunc ¶
type NativeFunc = engine.NativeFunc
NativeFunc is a host function. Returning an error throws: an *Exception or *InterruptedError as is, any other error as an Error whose message is err.Error() and which unwraps to err.
type Options ¶
type Options struct {
// MutableIntrinsics gives the runtime its own mutable copy of the
// builtins (prototypes, constructors, Math, JSON). By default they are
// built once per process, deeply frozen and shared by every runtime, and
// writing to them throws a TypeError.
MutableIntrinsics bool
// TimeZone is the local time zone of Date; nil means time.Local.
TimeZone *time.Location
}
Options configures NewRuntime.
type PromiseRejectionOperation ¶
type PromiseRejectionOperation = engine.PromiseRejectionOperation
PromiseRejectionOperation is what a rejection tracker is told (see SetPromiseRejectionTracker).
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime is one JavaScript global environment with at most one loaded module. It must be used from one goroutine at a time; only Interrupt and ClearInterrupt may be called concurrently.
func (*Runtime) AppendJSON ¶
AppendJSON appends JSON.stringify(v) to dst as UTF-8. A value with no JSON form (undefined, a function, a symbol) appends null. A proxy is serialized as JSON.stringify does it: its traps run.
func (*Runtime) Call ¶
Call invokes the function h names with this = undefined. A path that does not lead to a value is ErrHookNotFound, one that leads to a value that is not a function ErrNotCallable; a throw is an *Exception, an interrupt an *InterruptedError. The hooks of a module whose top level failed return Load's error.
func (*Runtime) ClearInterrupt ¶
func (rt *Runtime) ClearInterrupt()
ClearInterrupt drops a pending interrupt.
func (*Runtime) Export ¶
Export returns the current value of the loaded module's export name. ok is false when there is no such export or the binding is not initialized yet.
func (*Runtime) FromGo ¶
FromGo converts a Go value: nil, bool, the integer and float kinds, string, json.Number, *big.Int (a bigint), Value, NativeFunc, and the JSON-shaped containers map[string]any, map[string]string, map[string][]string, []any, []string and []map[string]any. Containers convert lazily, one level when first touched, so a large argument the hook reads little of costs little; the Go value must not change while the result is in use, and JavaScript writes never reach it. Maps enumerate their keys sorted. A []byte becomes an ArrayBuffer over the same bytes, not a copy: JavaScript writes reach them, and the host must not modify them while JavaScript may read them. Other types (structs, named map types) are an error: marshal them and use ParseJSON.
func (*Runtime) Function ¶
func (rt *Runtime) Function(name string, length int, fn NativeFunc) Value
Function creates a host function with a name and a length, the values of its `name` and `length` properties.
func (*Runtime) Get ¶
Get reads property key of v, running a getter and walking the prototype chain; undefined and null have no properties and read as undefined.
func (*Runtime) Has ¶
Has reports whether h names a function in this runtime now. A getter on the path that throws is returned as the error, and so is Load's for the hooks of a module whose top level failed.
func (*Runtime) Interrupt ¶
Interrupt stops running code: the pending Call (or Load, ToGo, ...) returns an *InterruptedError carrying v. It may be called from any goroutine. An interrupt that arrives while nothing runs stops the next Call, whatever the function it names, or Load, and any other method once it runs JavaScript, so a host calls ClearInterrupt before reusing the runtime.
func (*Runtime) Load ¶
Load evaluates m's top level in this runtime. A runtime loads one module once, and a Load made while the top level runs is refused too. When the top level throws or is interrupted before it ends or first awaits, the error is returned and the module stays loaded: Export reads the bindings initialized before the failure (none when an interrupt stopped the top level before it started), and Call and Has return the error for the module's hooks, whose functions could find the others uninitialized. The jobs the top level queued run after it, when Export and the module's hooks find its bindings; while the top level itself runs they find none. A module with top-level await evaluates asynchronously: its top level resumes from those jobs, with the bindings found, and Load returns once none is left, with what the evaluation rejected with (an interrupt of those jobs wins), or ErrModulePending when it still awaits; an exported function called while it awaits throws a ReferenceError for a binding it has not initialized yet.
func (*Runtime) NewPromise ¶
NewPromise creates a pending promise, for a host function to return, and the functions that settle it. resolve does what the promise's resolve function does in JavaScript: it adopts a thenable and fulfills with any other value; reject rejects. The first call of either decides and later calls do nothing. Both may be called after the host function returned, from the goroutine that uses the runtime: called outside a Call, they run the jobs they queue before returning, as the end of a Call does, and return what a Call would for those (an *InterruptedError, or the first exception a queueMicrotask callback threw).
func (*Runtime) Realm ¶
Realm returns the runtime's engine state, for host functions and tests that need the engine API directly.
func (*Runtime) SetGlobal ¶
SetGlobal assigns the global variable name. v is converted by FromGo, so a host installs a namespace of functions as a map[string]any with NativeFunc values.
func (*Runtime) SetPromiseRejectionTracker ¶
func (rt *Runtime) SetPromiseRejectionTracker(f func(p Value, op PromiseRejectionOperation))
SetPromiseRejectionTracker registers f to be called when a promise is rejected with no handler (PromiseRejectionReject) and when a promise so rejected gets its first handler (PromiseRejectionHandle), ECMAScript's HostPromiseRejectionTracker. A promise told Reject and not Handle when a Call returns has an unhandled rejection. f runs synchronously, in the reject or then that caused the operation. nil removes the tracker.
func (*Runtime) StackTrace ¶
StackTrace returns the `stack` of an Error thrown in this runtime: "Name: message" and one " at ..." line per frame. It is "" when the thrown value is not an Error or its stack was replaced by a non-string. No user code runs.
func (*Runtime) ToGo ¶
ToGo exports v: undefined and null become nil, booleans bool, strings string, integral numbers in int64 range int64 (except -0), other numbers float64, arrays []any, other objects map[string]any of their own enumerable string-keyed properties, Date time.Time, bigint *big.Int, and functions and symbols the engine value itself (*Object, *engine.Symbol). An ArrayBuffer or SharedArrayBuffer exports a copy of its bytes as a []byte, and a typed array or DataView a copy of the bytes it views (so a Uint16Array of 2 elements gives 4 bytes, little-endian); a detached buffer and a view out of its buffer's bounds give a nil []byte, and a zero-length buffer or view a non-nil empty one. A proxy exports through its traps (see engine.Realm.ToGo): []any when its target is an array, the map of its enumerable keys otherwise, the *Object when it is callable. A getter or trap that throws, or a revoked proxy, is returned as the error.
type SyntaxError ¶
type SyntaxError struct {
File string
Line int // 1-based
Column int // 1-based, in code points
Message string
}
SyntaxError is a parse or early error in module source.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
Error formats as "file:line:col: SyntaxError: message".
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bytecode defines the moejs instruction set and the compiled-function template shared between the compiler and the engine's interpreter.
|
Package bytecode defines the moejs instruction set and the compiled-function template shared between the compiler and the engine's interpreter. |
|
Package compiler translates the annotated AST produced by package syntax into bytecode.Function templates.
|
Package compiler translates the annotated AST produced by package syntax into bytecode.Function templates. |
|
internal
|
|
|
gen/decomp
command
Command decomp generates engine/decomp_tables.go, the character decomposition data of String.prototype.localeCompare: the Decomposition_Mapping field of UnicodeData.txt (canonical and compatibility mappings, one level each, with the compatibility tag) and the non-zero Canonical_Combining_Class values.
|
Command decomp generates engine/decomp_tables.go, the character decomposition data of String.prototype.localeCompare: the Decomposition_Mapping field of UnicodeData.txt (canonical and compatibility mappings, one level each, with the compatibility tag) and the non-zero Canonical_Combining_Class values. |
|
gen/ucd
command
Command ucd generates internal/regexpsyntax/unicode_tables.go, the Unicode Character Database tables of the regular-expression engine: General_Category, Script and Script_Extensions values, the binary properties of ECMA-262 table 67, the properties of strings of the v flag, simple case folding and the non-u Canonicalize mapping.
|
Command ucd generates internal/regexpsyntax/unicode_tables.go, the Unicode Character Database tables of the regular-expression engine: General_Category, Script and Script_Extensions values, the binary properties of ECMA-262 table 67, the properties of strings of the v flag, simple case folding and the non-u Canonicalize mapping. |
|
regexpsyntax
Package regexpsyntax parses ECMAScript regular expression patterns.
|
Package regexpsyntax parses ECMAScript regular expression patterns. |
|
Package syntax implements the moejs front end: a hand-written lexer, a recursive-descent parser producing a compact AST, strict-mode early errors, and a scope-resolution pass whose annotations the compiler consumes directly.
|
Package syntax implements the moejs front end: a hand-written lexer, a recursive-descent parser producing a compact AST, strict-mode early errors, and a scope-resolution pass whose annotations the compiler consumes directly. |