Documentation
¶
Overview ¶
Package quickjs is an idiomatic Go wrapper for modernc.org/libquickjs, an embeddable, CGo-free Javascript engine.
See also the original C quickjs library.
Supported platforms and architectures ¶
These combinations of GOOS and GOARCH are currently supported
OS Arch ------------- linux 386 linux amd64 linux arm64 linux loong64
Builders ¶
Builder results are available at:
https://modern-c.appspot.com/-/builder/?importpath=modernc.org%2fquickjs
Performance ¶
This package @ v0.12.26
vs https://pkg.go.dev/github.com/dop251/goja@v0.0.0-20250309171923-bcd7cc6bf64c
jnml@3900x:~/src/modernc.org/quickjs/compare$ date ; make benchmark Wed Apr 23 12:15:18 CEST 2025 go test -vet=off -timeout 24h -run @ -bench . 2>&1 | tee log-benchmark goos: linux goarch: amd64 pkg: modernc.org/quickjs/compare cpu: AMD Ryzen 9 3900X 12-Core Processor BenchmarkArewefastyet/ccgo-24 1 122005890899 ns/op 169424 B/op 69 allocs/op BenchmarkArewefastyet/goja-24 1 178848393816 ns/op 25972563848 B/op 1495943715 allocs/op PASS ok modernc.org/quickjs/compare 300.876s jnml@3900x:~/src/modernc.org/quickjs/compare$
Notes ¶
Parts of the documentation were copied from the quickjs documentation, see LICENSE-QUICKJS for details.
Example (Ping) ¶
Multiple concurrent Javascript virtual machines communicating via Go channels.
package main // import "modernc.org/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
- type Atom
- type Object
- type Undefined
- type Unsupported
- type VM
- func (m *VM) AddIntrinsicBigDecimal()
- func (m *VM) AddIntrinsicBigFloat()
- func (m *VM) AddStdHelpers() error
- 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) Eval(javascript string, flags int) (r any, err error)
- func (m *VM) EvalValue(javascript string, flags int) (r Value, err error)
- 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) InitModuleStd() error
- func (m *VM) NewAtom(s string) (r Atom, err error)
- func (m *VM) NewFloat64(n float64) Value
- func (m *VM) NewInt(n int) Value
- func (m *VM) NewString(s string) (r Value, err error)
- func (m *VM) RegisterFunc(name string, f any, wantThis bool) (err error)
- func (m *VM) SetDefaultModuleLoader()
- func (m *VM) SetProperty(this Value, prop Atom, val any) (err error)
- func (m *VM) SetPropertyValue(this Value, prop Atom, val Value) (err error)
- type Value
- func (v Value) Any() (r any, err error)
- func (v Value) Dup() Value
- func (v *Value) Free()
- func (v Value) GetProperty(this Value, prop Atom) (r any, err error)
- 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) SetProperty(prop Atom, val any) (err error)
- func (v Value) SetPropertyValue(prop Atom, val Value) (err error)
- func (v *Value) VM() *VM
Examples ¶
- Package (Ping)
- Object.MarshalJSON
- Object.String
- VM.AddIntrinsicBigDecimal
- VM.AddIntrinsicBigFloat
- VM.AddStdHelpers
- VM.Call (Function)
- VM.Call (Method)
- VM.Eval (Exception)
- VM.Eval (Expression)
- VM.Eval (Object)
- VM.InitModuleStd
- 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
Constants ¶
const ( EvalGlobal = lib.MJS_EVAL_TYPE_GLOBAL // global code EvalModule = lib.MJS_EVAL_TYPE_MODULE // module code )
Eval flags.
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 ¶
This section is empty.
Types ¶
type Atom ¶ added in v0.10.1
Atom is an unique identifier of, for example, a string value. Atom values are VM-specific.
type Object ¶ added in v0.4.0
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) MarshalJSON ¶ added in v0.4.0
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 Undefined ¶ added in v0.1.0
type Undefined struct{}
Undefined represents the Javascript value "undefined".
type Unsupported ¶ added in v0.1.0
type Unsupported struct{}
Unsupported represents an unsupported Javascript value.
func (Unsupported) String ¶ added in v0.8.0
func (u Unsupported) String() string
String implements fmt.Stringer.
type VM ¶ added in v0.5.0
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.
func (*VM) AddIntrinsicBigDecimal ¶ added in v0.6.0
func (m *VM) AddIntrinsicBigDecimal()
AddIntrinsicBigDecimal adds the BigDecimal object to 'm'.
Example ¶
Enable BigDecimal.
m, _ := NewVM() defer m.Close() fmt.Println(m.Eval("BigDecimal('1234567890.123456789');", EvalGlobal)) m.AddIntrinsicBigDecimal() fmt.Println(m.Eval("BigDecimal('1234567890.123456789');", EvalGlobal))
Output: <nil> ReferenceError: 'BigDecimal' is not defined 1234567890.123456789 <nil>
func (*VM) AddIntrinsicBigFloat ¶ added in v0.6.0
func (m *VM) AddIntrinsicBigFloat()
AddIntrinsicBigFloat adds the BigFloat object to 'm'.
Example ¶
Enable BigFloat.
m, _ := NewVM() defer m.Close() fmt.Println(m.Eval("BigFloat('1234567890.123456789e+5');", EvalGlobal)) m.AddIntrinsicBigFloat() fmt.Println(m.Eval("BigFloat('1234567890.123456789e+5');", EvalGlobal))
Output: <nil> ReferenceError: 'BigFloat' is not defined 1.234567890123456789e+14 <nil>
func (*VM) AddStdHelpers ¶ added in v0.6.0
AddStdHelpers adds the 'print' and 'console' global objects to 'm'.
Example ¶
Add std helpers.
m, _ := NewVM() defer m.Close() fmt.Println(m.Eval("console.toString();", EvalGlobal)) m.AddStdHelpers() fmt.Println(m.Eval("console.toString();", EvalGlobal)) fmt.Println(m.Eval("console.log.toString();", EvalGlobal))
Output: <nil> ReferenceError: 'console' is not defined [object Object] <nil> function log() { [native code] } <nil>
func (*VM) Call ¶ added in v0.6.0
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 *math/big.Float BigFloat github.com/shopspring/decimal.Decimal BigDecimal *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 ¶ added in v0.10.0
CallValue is like Call but returns (Value, error) like EvalValue
If no error is returned, the caller must properly handle the returned Value using Dup/Free.
func (*VM) Eval ¶ added in v0.6.0
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 BigFloat *math/big.Float nil BigDecimal github.com/shopspring/decimal.Decimal 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) EvalValue ¶ added in v0.10.0
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.
func (*VM) GetProperty ¶ added in v0.10.1
GetProperty returns this.prop.
func (*VM) GetPropertyValue ¶ added in v0.10.1
GetPropertyValue returns this.prop.
func (*VM) InitModuleStd ¶ added in v0.6.0
InitModuleStd adds the "std" module to 'm'.
Example ¶
Use the std module.
m, _ := NewVM() defer m.Close() m.InitModuleStd() m.Eval(` import * as std from 'std'; globalThis.std = std; `, EvalModule) fmt.Println(m.Call("std.sprintf", "%s %i", "hello", 42))
Output: hello 42 <nil>
func (*VM) NewAtom ¶ added in v0.10.1
NewAtom returns an unique indentifier of 's' or an error, if any.
func (*VM) NewFloat64 ¶ added in v0.10.1
NewFloat64 returns a new Value from 'n'.
func (*VM) RegisterFunc ¶ added in v0.6.0
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.
Note: The 'name' argument should be a valid Javascript identifier. It is not currently enforced but this may change later.
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) SetDefaultModuleLoader ¶ added in v0.9.0
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) SetProperty ¶ added in v0.10.1
SetProperty sets this.prop = val.
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.
func (Value) Any ¶ added in v0.11.0
Any attemtps to convert 'v' to any using the same rules as there are for the return value of VM.Eval.
func (*Value) Free ¶ added in v0.10.0
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 ¶ added in v0.11.0
GetProperty returns v.prop.
func (Value) GetPropertyValue ¶ added in v0.11.0
GetPropertyValue returns v.prop.
func (Value) IsUndefined ¶ added in v0.11.0
IsUndefined reports whether 'v' represents the Javascript value 'undefined'.
func (Value) MarshalJSON ¶ added in v0.10.1
MarshalJSON implements encoding/json.Marshaler.
func (Value) SetProperty ¶ added in v0.11.0
SetProperty sets v.prop = val.
func (Value) SetPropertyValue ¶ added in v0.11.0
SetPropertyValue sets v.prop = val.