Documentation
¶
Overview ¶
Package quickjs is a pure Go embeddable Javascript engine. It supports the ECMA script 14 (ES2023) specification including modules, asynchronous generators, proxies and BigInt.
See also the original C QuickJS library.
Internationalization ¶
The engine has no Intl. ECMA-402 is not implemented by the C library this package wraps, so a page or bundle reaching for Intl.DateTimeFormat gets a ReferenceError, and the toLocale* methods it ships ignore both their locale and their timeZone argument. Package github.com/liustack/quickjs/intl adds Intl.DateTimeFormat, Intl.NumberFormat and Intl.PluralRules, with CLDR data for every locale Chromium has, and replaces those toLocale* methods, for a VM that opts in by calling its Register. With no locale argument the locale is en-US, and with no timeZone option the zone is UTC.
Performance ¶
Geomeans of time/op over a set of benchmarks, relative to CCGO, lower number is better. Detailed results available in the testdata/benchmarks directory.
CCGO: github.com/liustack/quickjs/lib GOJA: github.com/dop251/goja@v0.0.0-20260723142020-b4aef50fa347 QJS: github.com/fastschema/qjs@v0.0.6 CCGO GOJA QJS ----------------------------------------------- darwin/amd64 1.000 1.575 1.300 darwin/arm64 1.000 1.069 1.080 freebsd/amd64 1.000 1.943 1.472 (qemu) freebsd/arm64 1.000 1.803 1.030 (qemu) linux/386 1.000 3.082 95.312 (qemu) linux/amd64 1.000 1.419 1.213 linux/arm 1.000 3.859 139.339 linux/arm64 1.000 1.611 1.267 linux/loong64 1.000 1.555 85.539 linux/ppc64le 1.000 2.286 75.183 linux/riscv64 1.000 1.656 76.609 linux/s390x 1.000 2.016 68.871 (qemu) windows/amd64 1.000 2.254 1.438 windows/arm64 1.000 2.002 1.610 ----------------------------------------------- CCGO GOJA QJS
Notes ¶
Parts of the documentation were copied from the quickjs documentation, see LICENSE-QUICKJS for details.
Supported platforms and architectures ¶
These combinations of GOOS and GOARCH are currently supported
OS Arch ------------- darwin amd64 darwin arm64 freebsd amd64 freebsd arm64 linux 386 linux amd64 linux arm linux arm64 linux loong64 linux ppc64le linux riscv64 linux s390x windows amd64 windows arm64
Builders ¶
Builder results are available here.
Change Log ¶
2026-07-27: Upgrade to QuickJS release 2026-06-04. The bytecode format changed, code produced by VM.Compile using an older release will no longer load.
2025-10-10: Upgrade to QuickJS release 2025-09-13.
Example (Ping) ¶
Multiple concurrent Javascript virtual machines communicating via Go channels.
package main // import "github.com/liustack/quickjs"
import (
"fmt"
)
// Multiple concurrent Javascript virtual machines communicating via Go channels.
func main() {
tx := make(chan string, 1)
rx := make(chan string, 1)
client, _ := NewVM()
defer client.Close()
registerFuncs(client, tx, rx)
go func() { // Start the server.
server, _ := NewVM()
defer server.Close()
registerFuncs(server, rx, tx)
server.Eval("send(receive()+' reply');", EvalGlobal)
}()
fmt.Println(client.Eval("send('ping'); receive();", EvalGlobal)) // Ping the server.
}
func registerFuncs(m *VM, tx, rx chan string) {
m.RegisterFunc("send", func(s string) { tx <- s }, false)
m.RegisterFunc("receive", func() string { return <-rx }, false)
}
Output: ping reply <nil>
Index ¶
- Constants
- Variables
- func Version() string
- type Args
- func (a Args) Bool(i int) (bool, bool)
- func (a Args) Latin1(i int) (b []byte, ok bool)
- func (a Args) Len() int
- func (a Args) Number(i int) (float64, bool)
- func (a Args) String(i int) (s string, ok bool)
- func (a Args) This() Value
- func (a Args) UTF16(i int) (u []uint16, ok bool)
- func (a Args) VM() *VM
- func (a Args) Value(i int) Value
- func (a Args) WTF8(i int) (s string, ok bool)
- type Atom
- type Builtin
- type Error
- type HostFunc
- type ModuleLoaderFunc
- type ModuleNormalizeFunc
- type Object
- type PromiseCapability
- type Strip
- type Undefined
- type Unsupported
- type VM
- func (m *VM) Call(function string, args ...any) (r any, err error)
- func (m *VM) CallValue(function string, args ...any) (r Value, err error)
- func (m *VM) Close() error
- func (m *VM) Compile(javascript string, flags int) ([]byte, error)
- func (m *VM) Eval(javascript string, flags int) (r any, err error)
- func (m *VM) EvalBytecode(bytecode []byte) (r any, err error)
- func (m *VM) EvalBytecodeValue(bytecode []byte) (r Value, err error)
- func (m *VM) EvalThis(obj Value, javascript string, flags int) (r any, err error)
- func (m *VM) EvalThisValue(obj Value, javascript string, flags int) (r Value, err error)
- func (m *VM) EvalValue(javascript string, flags int) (r Value, err error)
- func (m *VM) ExecutePendingJobs() (n int, err error)
- func (m *VM) GCThreshold() uintptr
- func (m *VM) GetProperty(this Value, prop Atom) (r any, err error)
- func (m *VM) GetPropertyValue(this Value, prop Atom) (r Value, err error)
- func (m *VM) GlobalObject() (r Value)
- func (m *VM) Interrupt()
- func (m *VM) MemorySize() uintptr
- func (m *VM) NewArray(vals ...Value) (Value, error)
- func (m *VM) NewAtom(s string) (r Atom, err error)
- func (m *VM) NewBuiltinFunction(b *Builtin) (Value, error)
- func (m *VM) NewFloat64(n float64) Value
- func (m *VM) NewInt(n int) Value
- func (m *VM) NewObjectValue() (r Value, err error)
- func (m *VM) NewPromiseCapability() (*PromiseCapability, error)
- func (m *VM) NewString(s string) (r Value, err error)
- func (m *VM) NewStringLatin1(b []byte) (Value, error)
- func (m *VM) NewStringUTF16(u []uint16) (Value, error)
- func (m *VM) OnClose(f func())
- func (m *VM) RegisterFunc(name string, f any, wantThis bool) error
- func (m *VM) RegisterHostFunc(name string, fn HostFunc) error
- func (m *VM) RunGC()
- func (m *VM) SetCanBlock(value bool)
- func (m *VM) SetDefaultModuleLoader()
- func (m *VM) SetEvalTimeout(d time.Duration) error
- func (m *VM) SetGCThreshold(threshold uintptr)
- func (m *VM) SetMaxStackSize(threshold uintptr)
- func (m *VM) SetMemoryLimit(limit uintptr)
- func (m *VM) SetModuleLoader(loader ModuleLoaderFunc, normalize ModuleNormalizeFunc)
- func (m *VM) SetProperty(this Value, prop Atom, val any) (err error)
- func (m *VM) SetPropertyValue(this Value, prop Atom, val Value) (err error)
- func (m *VM) SetRegExpCache(n, bytes int) error
- func (m *VM) SetShapeCache(n int) error
- func (m *VM) SetStrip(s Strip)
- func (m *VM) StdAddHelpers() error
- type Value
- func (v Value) Any() (r any, err error)
- func (v Value) Call(this Value, args ...any) (r any, err error)
- func (v Value) CallValue(this Value, args ...any) (r Value, err error)
- func (v Value) Dup() Value
- func (v *Value) Free()
- func (v Value) GetProperty(this Value, prop Atom) (r any, err error)deprecated
- func (v Value) GetPropertyValue(prop Atom) (r Value, err error)
- func (v Value) IsUndefined() bool
- func (v Value) MarshalJSON() (r []byte, err error)
- func (v Value) Property(prop Atom) (r any, err error)
- func (v Value) SetProperty(prop Atom, val any) (err error)
- func (v Value) SetPropertyValue(prop Atom, val Value) (err error)
- func (v Value) Then(onFulfilled, onRejected func(Value)) (_ Value, err error)
- func (v *Value) VM() *VM
Examples ¶
- Package (Ping)
- Object.Into
- Object.MarshalJSON
- Object.String
- VM.Call (Function)
- VM.Call (Method)
- VM.Eval (Exception)
- VM.Eval (Expression)
- VM.Eval (Object)
- VM.Interrupt
- VM.RegisterFunc (Error)
- VM.RegisterFunc (MultipleReturn)
- VM.RegisterFunc (SingleReturn)
- VM.RegisterFunc (ThisNonNull)
- VM.RegisterFunc (ThisNonNull2)
- VM.RegisterFunc (ThisNull)
- VM.RegisterFunc (ThisNull2)
- VM.RegisterFunc (Void)
- VM.SetDefaultModuleLoader
- VM.SetEvalTimeout
Constants ¶
const ( DefaultRegExpCache = lib.RegExpCacheEntries DefaultRegExpCacheBytes = lib.RegExpCacheBytes )
DefaultRegExpCache and DefaultRegExpCacheBytes are how many compiled regexps a new VM keeps at most, and in how many bytes (see VM.SetRegExpCache).
const ( EvalGlobal = lib.MJS_EVAL_TYPE_GLOBAL // global code EvalModule = lib.MJS_EVAL_TYPE_MODULE // module code )
Eval flags.
const DefaultShapeCache = 2048
DefaultShapeCache is the number of shapes a new VM keeps (see VM.SetShapeCache).
Variables ¶
var ( // UndefinedValue is a Value representing Javascript value 'undefined'. It is // not associated with any particular VM. UndefinedValue = Value{/* contains filtered or unexported fields */} )
Functions ¶
Types ¶
type Args ¶
type Args struct {
// contains filtered or unexported fields
}
Args are the arguments of a call of a Builtin, and the VM that called it. What they return is borrowed: a Value is valid for the duration of the call (see Value.Dup to keep one longer).
func (Args) Latin1 ¶
Latin1 returns the characters of argument i, one byte each, when it is a string the engine holds that way: all its characters are below U+0100 and it was not left in pieces by concatenation (a rope). Nothing is copied: the bytes are the engine's, valid until the Builtin returns, and must not be changed. ok is false for any other argument, which Args.UTF16 or Args.String reads. A Builtin that looks at the characters of short strings, and often returns its argument as it is, reads them this way.
func (Args) Number ¶
Number returns argument i when it is a number. It converts nothing: a string or a Number object is not a number.
func (Args) String ¶
String returns argument i when it is a string, as UTF-8 with U+FFFD for each lone surrogate. It converts nothing else. ok is false too when there is no memory for the conversion, and the call then fails with the out of memory error whatever the Builtin returns.
func (Args) UTF16 ¶
UTF16 returns the 16-bit units of argument i when it is a string the engine holds that way, lone surrogates as they are: a string with a character from U+0100 on, not left in pieces by concatenation (a rope). Nothing is copied: the units are the engine's, valid until the Builtin returns, and must not be changed. ok is false for any other argument, which Args.Latin1 or Args.String reads.
func (Args) VM ¶
VM returns the VM that called the Builtin. The Builtin may evaluate more javascript on it, which runs inside the time left to the call that got there (see VM.SetEvalTimeout).
func (Args) WTF8 ¶
WTF8 is String, but with each lone surrogate as the three bytes of its code point (0xED, then 0xA0 to 0xBF, then a continuation byte), the form the engine writes it in, which is not UTF-8. A surrogate pair is its one character in UTF-8, as in String. A Builtin that has to tell lone surrogates apart, as a collator orders them, reads its string this way.
type Atom ¶
Atom is an unique identifier of, for example, a string value. Atom values are VM-specific.
type Builtin ¶
type Builtin struct {
// contains filtered or unexported fields
}
A Builtin is a Go function that javascript calls as a built-in function: VM.NewBuiltinFunction makes it a function object shaped like the engine's own built-ins, such as Math.max. It has a name and a length and no other property of its own, no prototype property, it cannot be called with new, and its toString shows [native code] rather than source.
Unlike VM.RegisterFunc and VM.RegisterHostFunc, nothing is converted on the way in and no reflection is involved: the Go function reads the arguments it wants from Args, which give a number only for a number and a string only for a string, and returns a Value. That makes a call about as cheap as a call of a javascript function, which suits functions called once per row of a table, as the formatters of package intl are.
A Builtin belongs to no VM. It is made once, typically into a package level variable, and every VM makes its own function objects of it: Args says which VM called. So a process can have at most 32768 Builtins, and they are never released. VMs on several goroutines call the same Builtin at once, so its function has to be safe for concurrent use, and state it keeps for each VM is found by Args.VM.
func NewBuiltin ¶
NewBuiltin returns a Builtin calling fn, for function objects named name whose length property is length.
fn owns the Value it returns, which goes to javascript: a Value fn did not make itself, such as an argument, is returned as its Dup. UndefinedValue and the zero Value return undefined. A Value of another VM is neither returned nor freed: the call throws a TypeError.
A non-nil error is thrown instead, and a Value of the VM returned with it is freed. An *Error, found with errors.As, is thrown as a new error of the constructor its Name says when that is one of Error, TypeError, RangeError, SyntaxError, ReferenceError and InternalError, and as an Error for any other name, with its Message. Any other error is thrown as a TypeError with the error's text, as RegisterHostFunc throws it. The engine cuts the message of a TypeError, RangeError, SyntaxError, ReferenceError or InternalError to 255 bytes. The stack of each starts at the Builtin, as that of an error a built-in of the engine throws does.
A panic in fn goes on in the Go code that called javascript, as one in a function of RegisterHostFunc does.
NewBuiltin panics when name has a NUL byte, when length is not in 0 to 255, when fn is nil, and when the process already has 32768 Builtins: all mistakes of the code making them, which runs once.
type Error ¶
type Error struct {
Name string // e.g. "ReferenceError", "TypeError"
Message string // the error message
Stack string // stack trace, one " at ...\n" frame per line
LineNumber int // line where the error occurred (parse errors only)
ColumnNumber int // column where the error occurred (parse errors only)
FileName string // file name where the error occurred (parse errors only)
// Uncatchable reports that the call ended with an exception no catch
// or finally block of the script ran for: the VM ran out of memory
// (OutOfMemory), Interrupt or the eval timeout stopped it
// (Interrupted), or a Go function that javascript called panicked
// (neither of the two). Whatever a script throws itself is never
// uncatchable, whatever its name and message.
Uncatchable bool
OutOfMemory bool // the VM ran out of memory (Uncatchable is true)
Interrupted bool // Interrupt or the eval timeout stopped the script (Uncatchable is true)
// contains filtered or unexported fields
}
Error holds structured information from a JavaScript exception. The error returned by VM.Eval, VM.Call and the other eval-family methods is an *Error; recover the fields with errors.As:
var e *quickjs.Error
if errors.As(err, &e) {
fmt.Println(e.Stack)
}
Its Error method reports the same message string the engine has always returned, so existing code comparing the error text keeps working.
Only parse/syntax errors carry the FileName, LineNumber and ColumnNumber properties. For runtime errors those fields are zero and the source location is available only from Stack.
Uncatchable, OutOfMemory and Interrupted tell an error the engine ended the call with from one the script threw, without comparing names or messages, which a script can copy:
if errors.As(err, &e) && e.OutOfMemory {
// the script needs a higher SetMemoryLimit
}
func ErrorFromValue ¶
ErrorFromValue extracts structured error information from JavaScript error value 'v', typically an Error instance caught from a JS exception.
'v' is borrowed: ErrorFromValue does not free it and the caller remains responsible for its lifetime. Like all VM operations it must be called from the VM's own goroutine. See Error for which fields are populated.
A field that cannot be read is left empty: the string form of 'v' (the result of Error) when its toString throws, a property whose getter throws, and any string field when there is no memory for its UTF-8 copy. The exception that reading throws is dropped, so ErrorFromValue leaves no exception pending.
func (*Error) Error ¶
Error implements the error interface. It returns the same string the engine produces for the exception, unchanged from earlier releases. For an Error made in Go, say to throw from a Builtin, it returns what javascript's Error.prototype.toString does: Name, or "Error" when Name is empty, then ": " and Message when Message is not empty.
type HostFunc ¶
HostFunc is a Go function exposed to JavaScript by RegisterHostFunc. It receives the call arguments already converted to Go values and returns a single value to convert back to JS, or a non-nil error which is thrown as a JavaScript exception.
type ModuleLoaderFunc ¶
ModuleLoaderFunc defines the signature for a custom module loader. It must return the module's source code (Javascript).
type ModuleNormalizeFunc ¶
ModuleNormalizeFunc defines the signature for a custom module normalizer. It receives the base name (the module making the import) and the requested name, and should return the normalized, absolute module name.
type Object ¶
type Object struct {
// contains filtered or unexported fields
}
Object represents the value of a Javascript object, but not the javascript object instance itself. Do not compare instances of Object.
func (*Object) Into ¶
Into helps you quickly deserialize an Object into a native Go type. This uses encoding/json.Unmarshal internally, so the target type must be compatible with that package.
Example ¶
JSON unmarshalling into native Go struct.
m, _ := NewVM()
defer m.Close()
obj, _ := m.Eval("obj = {a: 42+314, b: 'foo'}; obj;", EvalGlobal)
var dst struct {
A int `json:"a"`
B string `json:"b"`
}
obj.(*Object).Into(&dst)
fmt.Printf("%#v\n", dst)
Output: struct { A int "json:\"a\""; B string "json:\"b\"" }{A:356, B:"foo"}
func (*Object) MarshalJSON ¶
MarshalJSON implements encoding/json.Marshaler.
Example ¶
JSON marshalling.
m, _ := NewVM()
defer m.Close()
obj, _ := m.Eval("obj = {a: 42+314, b: 'foo'}; obj;", EvalGlobal)
s, _ := (obj.(*Object).MarshalJSON())
fmt.Printf("%s\n", s)
Output: {"a":356,"b":"foo"}
type PromiseCapability ¶
PromiseCapability holds a Promise along with its resolve and reject functions, obtained without evaluating JS source.
func (*PromiseCapability) Dup ¶
func (pc *PromiseCapability) Dup() *PromiseCapability
Dup duplicates the capability — its promise and both resolving functions — returning a new PromiseCapability that must itself be released via Free.
func (*PromiseCapability) Free ¶
func (pc *PromiseCapability) Free()
Free releases all values held by the capability.
type Strip ¶
type Strip int
Strip says what a VM leaves out of the functions it compiles (see VM.SetStrip).
const ( // StripSource leaves out the source text: the toString of a function // shows [native code] instead, as it does for the engine's built-ins. StripSource Strip = Strip(lib.MJS_STRIP_SOURCE) // StripDebug leaves out the file name, line and column numbers, so a // stack frame of the function shows only its name, and the source too. StripDebug Strip = Strip(lib.MJS_STRIP_DEBUG) )
type Unsupported ¶
type Unsupported struct{}
Unsupported represents an unsupported Javascript value.
type VM ¶
type VM struct {
// contains filtered or unexported fields
}
VM represents a Javascript context (or Realm). Each VM has its own global objects and system objects.
Note: VM is not safe for concurrent use by multiple goroutines, except for VM.Interrupt.
func (*VM) Call ¶
Call evaluates 'function(args...)' and returns the resulting (value, error).
Argument types must be one of:
Go argument type Javascript argument type ---------------------------------------------------------------- nil null Undefined undefined string string int*/uint* (value in int32 range) int int*/uint* (value out of int32 range) float bool bool float64 float64 *math/big.Int BigInt *Object object Value native Javascript Value any other type object from JSON produced by encoding.json/Marshall(arg)
Example (Function) ¶
Call a Javascript function.
m, _ := NewVM()
defer m.Close()
fmt.Println(m.Call("parseInt", "1234"))
Output: 1234 <nil>
Example (Method) ¶
Call a Javascript method.
m, _ := NewVM()
defer m.Close()
fmt.Println(m.Call("Math.abs", -1234))
Output: 1234 <nil>
func (*VM) CallValue ¶
CallValue is like Call but returns (Value, error) like EvalValue
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) Close ¶
Close releases the resources held by 'm'. That includes the module loader and normalizer set by VM.SetModuleLoader: Close removes them, so a closed VM keeps nothing they close over reachable.
func (*VM) Compile ¶
Compile compiles the bytecode representation of the passed script.
The returned bytecode can be later executed using EvalBytecode or EvalBytecodeValue.
Note: The bytecode format is linked to a given QuickJS version.
func (*VM) Eval ¶
Eval evaluates a script or module source in 'javascript'.
Javascript result type Go result type Go result error ------------------------------------------------------------------------------- exception nil non-nil null nil nil undefined Undefined nil string string nil int int nil bool bool nil float64 float64 nil BigInt *math/big.Int nil object *Object nil any other type Unsupported nil
Example (Exception) ¶
Getting exception.
m, _ := NewVM()
defer m.Close()
fmt.Println(m.Eval("throw new Error('failed');", EvalGlobal))
Output: <nil> Error: failed
Example (Expression) ¶
Evaluate a simple Javascript expression.
m, _ := NewVM()
defer m.Close()
fmt.Println(m.Eval("1+2", EvalGlobal))
Output: 3 <nil>
Example (Object) ¶
Object example.
m, _ := NewVM()
defer m.Close()
fmt.Println(m.Eval("obj = {a: 42+314, b: 'foo'}; obj;", EvalGlobal))
Output: {"a":356,"b":"foo"} <nil>
func (*VM) EvalBytecode ¶
EvalBytecode is like Eval but uses QuickJS bytecode.
Note: The bytecode format is linked to a given QuickJS version. Moreover, no security check is done before its execution. Hence the bytecode should not be loaded from untrusted sources.
Note: Javascript 'this' is always set to the global context.
func (*VM) EvalBytecodeValue ¶
EvalBytecodeValue is like EvalValue but operates on QuickJS bytecode.
Exceptions thrown during evaluation of the script are returned as Go errors.
If no error is returned, the caller must properly handle the returned Value using Dup/Free.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) EvalThisValue ¶
EvalThisValue is like EvalValue but sets javascript 'this' to obj.
func (*VM) EvalValue ¶
EvalValue evaluates a script or module source in 'javascript' and returns the resulting Value, or an error, if any.
Exceptions thrown during evaluation of the script are returned as Go errors.
If no error is returned, the caller must properly handle the returned Value using Dup/Free.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) ExecutePendingJobs ¶
ExecutePendingJobs runs queued Javascript jobs — Promise reactions (the .then/.catch/.finally callbacks) and async/await continuations — until the queue is empty, returning the number of jobs executed. The runtime does not run these itself: an embedding event loop calls ExecutePendingJobs at the end of each turn to drain the microtask queue (so a resolved Promise's .then runs, a pending await resumes, etc.). An exception thrown by a job is returned as an error — the first one — while the remaining jobs still run; a self-feeding job queue is bounded so it cannot hang the host.
func (*VM) GCThreshold ¶
GCThreshold returns the memory threshold at which a GC will be performed, in bytes. The engine checks it when it makes an object: when VM.MemorySize would pass it, the engine runs a GC and then sets the threshold to 1.5 times what the GC left. So a threshold other than the one VM.SetGCThreshold set last means the engine ran a GC since. VM.RunGC does not change it.
As with SetGCThreshold, no other goroutine may use m meanwhile (see VM), and a call after Close panics.
func (*VM) GetProperty ¶
GetProperty returns this.prop.
func (*VM) GetPropertyValue ¶
GetPropertyValue returns this.prop.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) GlobalObject ¶
GlobalObject returns m's global object.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) Interrupt ¶
func (m *VM) Interrupt()
Interrupt requests 'm' to interrupt Javascript evaluation. Interrupt can be called asynchronously, from any goroutine, at any time m is evaluating a script. The request stays pending until the outermost call into javascript returns, so javascript a host function evaluates on m meanwhile does not clear it. Interrupt is also safe while m closes and after Close, where it does nothing, so a watchdog need not know whether the script it guards has finished.
Example ¶
const timeout = time.Second
m, _ := NewVM()
defer m.Close()
go func() {
time.Sleep(timeout)
m.Interrupt()
}()
t0 := time.Now()
r, err := m.Eval(`
function f() {
var sink;
for (var i = 0; i < 10000; i++) {
sink += 42;
sink -= 42;
}
}
(function() {
for (var i = 0; i < 10000; i++) {
f();
}
return 42;
})();
`, EvalGlobal)
d := time.Since(t0)
step := timeout / 5
d = d / step * step
fmt.Println(r, err, d)
Output: <nil> InternalError: interrupted 1s
func (*VM) MemorySize ¶
MemorySize returns the memory m takes, in bytes, as VM.SetMemoryLimit and VM.SetGCThreshold count it. After VM.RunGC it is what the objects that javascript can still reach take, with the arenas they are in, plus the runtime's own structures and the object shapes it keeps for reuse.
As with SetGCThreshold, no other goroutine may use m meanwhile (see VM), and a call after Close panics.
func (*VM) NewArray ¶
NewArray returns a new array of vals, made as an array literal makes one: its elements are own properties, which no setter a page put on Array.prototype sees. It borrows vals, as VM.SetPropertyValue and Value.Call do: the caller still owns them. The zero Value is undefined. A Value of another VM, a number too, is an error, as it is for a Builtin to return one.
func (*VM) NewBuiltinFunction ¶
NewBuiltinFunction returns a new function object of b. The caller owns it: it passes it to javascript, for example as an argument of Value.Call or with VM.SetPropertyValue, and then frees it.
func (*VM) NewFloat64 ¶
NewFloat64 returns a new Value from 'n'.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) NewInt ¶
NewInt returns a new Value from 'n'.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) NewObjectValue ¶
NewObjectValue returns a new Value representing '{}'.
func (*VM) NewPromiseCapability ¶
func (m *VM) NewPromiseCapability() (*PromiseCapability, error)
NewPromiseCapability creates a new JavaScript Promise along with its resolve and reject functions.
The returned PromiseCapability must be freed via Free when no longer needed.
To expose a promise to JS from a Go function registered with RegisterFunc, return pc.Promise from the Go function. The resolve/reject values captured by the closure need no Dup because the C API already holds a reference for each:
m.RegisterFunc("delayed", func(delay int) Value {
pc, err := m.NewPromiseCapability()
if err != nil { panic(err) }
youreventloop.Schedule(func() {
time.Sleep(time.Duration(delay) * time.Millisecond)
pc.Resolve.Call(UndefinedValue, "done")
pc.Resolve.Free()
pc.Reject.Free()
// pc.Promise.Free() // <- only if returned pc.Promise.Dup()!
})
return pc.Promise
}, false)
func (*VM) NewString ¶
NewString returns a new Value from 's'.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*VM) NewStringLatin1 ¶
NewStringLatin1 returns a new string of the characters b, one byte each: a byte is the character of its value, U+0000 to U+00FF. Unlike VM.NewString it decodes no UTF-8, so a Builtin that read its argument with Args.Latin1 returns what it made of it this way, as one copy.
func (*VM) NewStringUTF16 ¶
NewStringUTF16 returns a new string of the 16-bit units u, lone surrogates as they are. A Builtin that read its argument with Args.UTF16 returns what it made of it this way, as one copy.
func (*VM) OnClose ¶
func (m *VM) OnClose(f func())
OnClose arranges for f to run when Close runs, after the VM is released, so f must not use it. Close runs the functions once each, in the order OnClose was given them. Nothing else runs them: a VM that is never closed never runs them, and neither does the garbage collector.
A package that keeps something per VM in a table of its own, such as a closure that may reference the VM, removes it here, so that the table does not keep the VM, or what it closes over, reachable after Close.
func (*VM) RegisterFunc ¶
RegisterFunc registers a Go function 'f' and makes it callable from Javascript.
The 'f' argument can be a regular Go function, a closure, a method expression or a method value. All of them are called 'Go function' below.
The Go function can have zero or more parameters. If 'wantThis' is true then the first parameter of the Go function will get the Javascript value of 'this'. Depending on context, 'this' can be Javascript null or undefined.
Go functions with multiple results return them as an Javascript array.
Go nil errors are converted to Javascript null.
Go non-nil errors are converted to Javascript strings using the Error() method.
Any Go <-> Javascript failing type conversion between arguments/return values throws a Javascript type error exception.
There is a limit on the total number of currently registered Go functions.
The function becomes the property 'name' of the global object: writable, configurable and not enumerable. A configurable property already there, such as one a script assigned or a built-in like Array, is replaced. A property that is not configurable, such as undefined, NaN, Infinity or one a script declared with var or function, is kept and RegisterFunc returns an error, as it does when the global object is not extensible. Registering a name a Go function of this VM already has returns an error too, even when a script has since deleted or replaced that function. The name is the one javascript sees: invalid UTF-8 is replaced as Go decodes it (see Eval), so two Go strings can be the same name, and a NUL byte, which would end the name, is an error.
Note: The 'name' argument should be a valid Javascript identifier. It is not currently enforced but this may change later.
For binding host objects (a DOM, console, fetch, …) prefer RegisterHostFunc, which gives the more convenient single-return / error-throws-exception shape.
A function javascript calls often, say once per item of a list, or one that has to look like a built-in, is better a Builtin: it converts nothing and uses no reflection, so a call costs far less.
Example (Error) ¶
Call error returning Go function from Javascript.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(a int) error {
if a < 0 {
return fmt.Errorf("negative")
}
return nil
}, false)
fmt.Println(m.Eval("gofunc(-1)", EvalGlobal))
fmt.Println(m.Eval("gofunc(1)", EvalGlobal))
Output: negative <nil> <nil> <nil>
Example (MultipleReturn) ¶
Call multiple return Go function from Javascript.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(a, b int) (int, int) { return 10 * a, 100 * b }, false)
fmt.Println(m.Eval("gofunc(2, 3)", EvalGlobal))
Output: [20,300] <nil>
Example (SingleReturn) ¶
Call single return Go function from Javascript.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(a, b, c int) int { return a + b*c }, false)
fmt.Println(m.Eval("gofunc(2, 3, 5)", EvalGlobal))
Output: 17 <nil>
Example (ThisNonNull) ¶
Passing Javascript 'this' to a Go function.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(this any) any { return this }, true)
fmt.Println(m.Eval("var obj = { foo: 314, method: gofunc }; obj.method()", EvalGlobal))
Output: {"foo":314} <nil>
Example (ThisNonNull2) ¶
Passing Javascript 'this' to a Go function.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(this any, n int) (any, int) { return this, 10 * n }, true)
fmt.Println(m.Eval("var obj = { foo: 314, method: gofunc }; obj.method(42)", EvalGlobal))
Output: [{"foo":314},420] <nil>
Example (ThisNull) ¶
Passing undefined Javascript 'this' to a Go function.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(this any) any { return this }, true)
fmt.Println(m.Eval("gofunc()", EvalGlobal))
Output: undefined <nil>
Example (ThisNull2) ¶
Passing undefined Javascript 'this' to a Go function.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(this any, n int) (any, int) { return this, 10 * n }, true)
fmt.Println(m.Eval("gofunc(42)", EvalGlobal))
Output: [null,420] <nil>
Example (Void) ¶
Call void Go function from Javascript.
m, _ := NewVM()
defer m.Close()
m.RegisterFunc("gofunc", func(a, b, c int) { fmt.Println(a + b*c) }, false)
fmt.Println(m.Eval("gofunc(2, 3, 5)", EvalGlobal))
Output: 17 undefined <nil>
func (*VM) RegisterHostFunc ¶
RegisterHostFunc exposes fn to JavaScript as a global function named name, using the calling convention an embedding host wants: every JS call argument arrives in the single []any slice (already converted to Go values), fn returns exactly one value to convert back to JS, and a non-nil error is thrown as a JavaScript exception.
This differs from RegisterFunc, whose reflection mapping turns a Go multiple-return into a JS array and converts a returned error like any other value (so a (value, error) pair becomes the array [value, error] rather than a value-or-throw). RegisterHostFunc is the better fit for binding host objects; RegisterFunc remains for direct, typed Go calls.
Each call converts every argument to a Go value through reflection. A function javascript calls often, or one that has to look like a built-in, is better a Builtin, which reads only the arguments it wants, as they are.
The name is handled as by RegisterFunc, including when the global object already has it.
func (*VM) RunGC ¶
func (m *VM) RunGC()
RunGC performs a GC now. It frees what javascript can no longer reach, objects in reference cycles included, and gives the small blocks the runtime keeps for reuse back to their arenas. Unlike the GC the engine runs when VM.MemorySize passes VM.GCThreshold, it leaves the threshold as it is. It runs no javascript: the callbacks of a FinalizationRegistry whose targets it frees are queued and run at the next VM.ExecutePendingJobs, so what they hold goes at a later GC.
As with SetGCThreshold, no other goroutine may use m meanwhile (see VM), and a call after Close panics.
func (*VM) SetCanBlock ¶
SetCanBlock configures m's blocking mode.
func (*VM) SetDefaultModuleLoader ¶
func (m *VM) SetDefaultModuleLoader()
SetDefaultModuleLoader will enable loading module using the default module loader.
Example ¶
Enabling the module loader.
m, _ := NewVM()
defer m.Close()
m.SetDefaultModuleLoader()
// testdata/power.js:
// export const name = "Power";
//
// export function square(x) {
// return x*x;
// }
//
// export function cube(x) {
// return x*x*x;
// }
m.Eval("import * as Power from './testdata/power.js'; globalThis.Power = Power;", EvalModule)
fmt.Println(m.Eval("[Power.square(2), Power.cube(2)];", EvalGlobal))
Output: [4,8] <nil>
func (*VM) SetEvalTimeout ¶
SetEvalTimeout sets the timeout for the various eval functions. Passing zero 'd' disables timeouts. The timeout starts with the outermost call into javascript: a host function that evaluates more javascript on m runs inside the time left to the call that got it there. The timeout runs on the monotonic clock, so setting the system clock does not move it. A timeout too long for that clock (about 292 years) never fires.
Example ¶
m, _ := NewVM()
defer m.Close()
for _, timeout := range []time.Duration{100 * time.Millisecond, time.Second, 3 * time.Second} {
m.SetEvalTimeout(timeout)
t0 := time.Now()
r, err := m.Eval(`
function f() {
var sink;
for (var i = 0; i < 10000; i++) {
sink += 42;
sink -= 42;
}
}
(function() {
for (var i = 0; i < 10000; i++) {
f();
}
return 42;
})();
`, EvalGlobal)
d := time.Since(t0)
min := timeout / 2
max := timeout * 3 / 2
fmt.Println(r, err, timeout, d >= min && d <= max)
}
Output: <nil> InternalError: interrupted 100ms true <nil> InternalError: interrupted 1s true <nil> InternalError: interrupted 3s true
func (*VM) SetGCThreshold ¶
SetGCThreshold sets the memory threshold at which a GC will be performed, in bytes.
func (*VM) SetMaxStackSize ¶
SetMaxStackSize limits the JS call depth, in libc.TLS stack slots (~one per JS call frame in the CGo-free port). Deep recursion then throws a catchable RangeError instead of overflowing the Go goroutine stack. 0 restores the MaxStackSlots default.
func (*VM) SetMemoryLimit ¶
SetMemoryLimit limits m's maxmimum memory usage, in bytes. Small values of 'limit' are not honored because the VM needs to allocate memory also for the exception object itself. The particular value of "small" is unspecified and subject to change without notice.
func (*VM) SetModuleLoader ¶
func (m *VM) SetModuleLoader(loader ModuleLoaderFunc, normalize ModuleNormalizeFunc)
SetModuleLoader configures custom Go functions to load and normalize Javascript modules. Passing nil for 'loader' removes the custom loader, and so does Close; until then the engine keeps 'loader' and 'normalize', and whatever they close over, reachable. If 'normalize' is nil, the engine falls back to the default QuickJS module normalizer.
func (*VM) SetProperty ¶
SetProperty sets this.prop = val.
func (*VM) SetPropertyValue ¶
SetPropertyValue sets this.prop = val.
func (*VM) SetRegExpCache ¶
SetRegExpCache sets how many compiled regexps m keeps at most, n, and in how many bytes, 0 for none, and lets go of the ones it kept. Compiling a regexp whose pattern and flags are strings (a literal, new RegExp, RegExp, RegExp.prototype.compile, and the copy split makes of its regexp) takes the bytecode m kept for the same pattern and flags instead of compiling again. Code that makes a new RegExp of the same pattern on every call, as a syntax highlighter made anew for each render does, then compiles each pattern once. When a new one does not fit, m lets go of the one used least recently. A new VM keeps DefaultRegExpCache regexps in DefaultRegExpCacheBytes bytes, and n can be at most math.MaxInt32/8.
What m keeps counts against the limit of SetMemoryLimit, the patterns and flags as well as the bytecode, and is not let go when an allocation fails. So a script that runs close to its memory limit can run out of memory with the cache on where it would not without it.
func (*VM) SetShapeCache ¶
SetShapeCache sets how many shapes of plain objects m keeps after their last object is gone, 0 for none. The shape of an object is its keys in order: an object that gets the same keys in the same order as an object before it, as the objects a function returns often do, finds the shapes it goes through kept, instead of copying a shape for each key. m keeps the last n shapes it would have freed, of objects whose prototype is Object.prototype and that have at most 32 keys, none of them a symbol that is not registered. A new VM keeps DefaultShapeCache shapes.
Kept shapes take memory that counts against the limit of SetMemoryLimit, and each holds the atoms of its keys. A kept shape of a few keys takes about 100 bytes. A shape of 32 keys of about ten characters, that no other object has, takes about 3 KiB with its atoms, so 2048 of them take about 6 MiB, and the table of atoms m grew for them keeps its size after they are let go. So a script that runs close to its memory limit can run out of memory with the cache on where it would not without it: give such a VM a smaller cache, or 0. Kept shapes are not let go when an allocation fails.
func (*VM) SetStrip ¶
SetStrip sets what m leaves out of the functions it compiles from then on: StripSource, StripDebug, both or 0, the default, for nothing. That is every function m compiles: from source by Eval and the like, into bytecode by Compile, and in the page's own code by eval and new Function. Functions compiled before keep what they have. The bytecode of Compile keeps what is left out left out in any VM that loads it, which suits a script that plays a built-in, such as a polyfill whose functions should not show their source: compile it on a VM of its own, so that the page's functions keep their source.
func (*VM) StdAddHelpers ¶
StdAddHelpers adds the 'print' and 'console' global objects to 'm'.
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value represents a native Javascript value. Values are reference counted and their lifetime is managed by an independent Javascript garbage collector. To avoid memory corruption/leaks caused by tripping the Javascript GC, a Value must not
- be copied. Use the Dup method instead.
- become unreachable without calling its Free method.
- be used after its Free() method was called.
- outlive its VM.
It is recommended to use native Go values instead of Value where possible.
When passing a Value down the call stack use Dup. For example in main
v, _ := EvalValue(someScript) defer v.Free() foo(v.Dup()) // Instead of foo(v)
In 'foo' Free must be used. For example
func foo(v Value) {
defer v.Free()
...
}
This ensures the/only topmost Free marks 'v' eligible for garbage collection.
Beware that the correct setup/handling becomes more complicated when using closures, Values are sent through a channel etc. In particular, if a goroutine 1 passes a Dup of 'v' to goroutine 2 and goroutine 1 completes and thus frees 'v' before goroutine 2 completes, the reference counting mechanism will fail. In other words, every Free must be strictly paired with the Dup that preceded obtaining the Value and the Dup/Free calls must respect the original nesting. This is correct.
Dup // in main
Dup // in foo
Free // in foo
Free // in main
This will fail, for example in the above discussed goroutines scenario.
Dup // in g1
Dup // in g2
Free // in g1
Free // in g2
The fix might be in this case to arrange goroutine 1 to wait for goroutine 2 to complete before executing Free in goroutine 1.
See TestMemgrind for an example of how to detect memory leaks caused not only by improper Value use.
func (Value) Any ¶
Any attemtps to convert 'v' to any using the same rules as there are for the return value of VM.Eval.
func (Value) Call ¶
Call evaluates 'v(args...)' with 'this' as the receiver and returns the resulting (value, error). 'v' must be a Javascript function. Pass UndefinedValue as 'this' when the function does not use it.
resolve.Call(quickjs.UndefinedValue, "done") reject.Call(quickjs.UndefinedValue, err.Error())
Argument types are converted using the same rules as in VM.Call and the result is unpacked using the same rules as there are for the return value of VM.Eval. Note that a Go error is not one of the recognized types, so it is marshaled to JSON like any other value — and because the standard error types have no exported fields that yields '{}'. Pass err.Error() instead.
Note: A Value passed to a Go function registered by VM.RegisterFunc is valid only for the duration of that call. To call it later, for example to settle a promise after the Go function has returned, retain it using Value.Dup and release it using Value.Free when done.
Note: See the Value documentation for details about manual memory management of Value objects.
func (Value) CallValue ¶
CallValue is like Value.Call but returns (Value, error) like VM.EvalValue.
Note: See the Value documentation for details about manual memory management of Value objects.
func (*Value) Free ¶
func (v *Value) Free()
Free marks 'v' as no longer used and updates its reference count. 'v' must not be used afterwards.
func (Value) GetProperty
deprecated
func (Value) GetPropertyValue ¶
GetPropertyValue returns v.prop.
func (Value) IsUndefined ¶
IsUndefined reports whether 'v' represents the Javascript value 'undefined'.
func (Value) MarshalJSON ¶
MarshalJSON implements encoding/json.Marshaler.
func (Value) Property ¶
Property returns v.prop. It is Value.GetProperty without the vestigial 'this' argument.
func (Value) SetProperty ¶
SetProperty sets v.prop = val.
func (Value) SetPropertyValue ¶
SetPropertyValue sets v.prop = val.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package fmt exposes some functionality of the Go stdlib fmt package to a quickjs.VM.
|
Package fmt exposes some functionality of the Go stdlib fmt package to a quickjs.VM. |
|
internal
|
|
|
fixlib
command
Command fixlib reapplies this fork's changes to the engine under lib/ after its files were taken from upstream libquickjs, as happens when a git subtree pull hits a conflict in a generated ccgo_*.go file and the upstream version is checked out.
|
Command fixlib reapplies this fork's changes to the engine under lib/ after its files were taken from upstream libquickjs, as happens when a git subtree pull hits a conflict in a generated ccgo_*.go file and the upstream version is checked out. |
|
gointl/internal/qjspack/gen
command
|
|
|
intlhook
Package intlhook connects the Intl and Temporal shims.
|
Package intlhook connects the Intl and Temporal shims. |
|
Package intl implements ECMA-402, the ECMAScript Internationalization API, for a quickjs.VM.
|
Package intl implements ECMA-402, the ECMAScript Internationalization API, for a quickjs.VM. |
|
Package libquickjs is a pure Go embeddable Javascript engine.
|
Package libquickjs is a pure Go embeddable Javascript engine. |
|
Package temporal implements Temporal, the ECMAScript date and time API, for a quickjs.VM.
|
Package temporal implements Temporal, the ECMAScript date and time API, for a quickjs.VM. |