quickjs

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

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

Go to latest
Published: Jul 14, 2020 License: MIT Imports: 8 Imported by: 14

README

quickjs

MIT License go.dev reference Discord Chat

Go bindings to QuickJS: a fast, small, and embeddable ES2020 JavaScript interpreter.

These bindings are a WIP and do not match full parity with QuickJS' API, though expose just enough features to be usable. The version of QuickJS that these bindings bind to may be located here.

These bindings have been tested to cross-compile and run successfully on Linux, Windows, and Mac using gcc-7 and mingw32 without any addtional compiler or linker flags.

Usage

$ go get github.com/lithdew/quickjs

Guidelines

  1. Free quickjs.Runtime and quickjs.Context once you are done using them.
  2. Free quickjs.Value's returned by Eval() and EvalFile(). All other values do not need to be freed, as they get garbage-collected.
  3. You may access the stacktrace of an error returned by Eval() or EvalFile() by casting it to a *quickjs.Error.
  4. Make new copies of arguments should you want to return them in functions you created.
  5. Make sure to call runtime.LockOSThread() to ensure that QuickJS always operates in the exact same thread.

Example

The full example code below may be found by clicking here. Find more API examples here.

package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/lithdew/quickjs"
	"strings"
)

func check(err error) {
	if err != nil {
		var evalErr *quickjs.Error
		if errors.As(err, &evalErr) {
			fmt.Println(evalErr.Cause)
			fmt.Println(evalErr.Stack)
		}
		panic(err)
	}
}

func main() {
	runtime := quickjs.NewRuntime()
	defer runtime.Free()

	context := runtime.NewContext()
	defer context.Free()

	globals := context.Globals()

	// Test evaluating template strings.

	result, err := context.Eval("`Hello world! 2 ** 8 = ${2 ** 8}.`")
	check(err)
	defer result.Free()

	fmt.Println(result.String())
	fmt.Println()

	// Test evaluating numeric expressions.

	result, err = context.Eval(`1 + 2 * 100 - 3 + Math.sin(10)`)
	check(err)
	defer result.Free()

	fmt.Println(result.Int64())
	fmt.Println()

	// Test evaluating big integer expressions.

	result, err = context.Eval(`128n ** 16n`)
	check(err)
	defer result.Free()

	fmt.Println(result.BigInt())
	fmt.Println()

	// Test evaluating big decimal expressions.

	result, err = context.Eval(`128l ** 12l`)
	check(err)
	defer result.Free()

	fmt.Println(result.BigFloat())
	fmt.Println()

	// Test evaluating boolean expressions.

	result, err = context.Eval(`false && true`)
	check(err)
	defer result.Free()

	fmt.Println(result.Bool())
	fmt.Println()

	// Test setting and calling functions.

	A := func(ctx *quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
		fmt.Println("A got called!")
		return ctx.Null()
	}

	B := func(ctx *quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
		fmt.Println("B got called!")
		return ctx.Null()
	}

	globals.Set("A", context.Function(A))
	globals.Set("B", context.Function(B))

	_, err = context.Eval(`for (let i = 0; i < 10; i++) { if (i % 2 === 0) A(); else B(); }`)
	check(err)

	fmt.Println()

	// Test setting global variables.

	_, err = context.Eval(`HELLO = "world"; TEST = false;`)
	check(err)

	names, err := globals.PropertyNames()
	check(err)

	fmt.Println("Globals:")
	for _, name := range names {
		val := globals.GetByAtom(name.Atom)
		defer val.Free()

		fmt.Printf("'%s': %s\n", name, val)
	}
	fmt.Println()

	// Test evaluating arbitrary expressions from flag arguments.

	flag.Parse()
	if flag.NArg() == 0 {
		return
	}

	result, err = context.Eval(strings.Join(flag.Args(), " "))
	check(err)
	defer result.Free()

	if result.IsObject() {
		names, err := result.PropertyNames()
		check(err)

		fmt.Println("Object:")
		for _, name := range names {
			val := result.GetByAtom(name.Atom)
			defer val.Free()

			fmt.Printf("'%s': %s\n", name, val)
		}
	} else {
		fmt.Println(result.String())
	}
}
$ go run examples/main.go '(() => ({hello: "world", test: 2 ** 3}))()'
Hello world! 2 ** 8 = 256.

197

5192296858534827628530496329220096

1.9342813113834066795e+25

false

A got called!
B got called!
A got called!
B got called!
A got called!
B got called!
A got called!
B got called!
A got called!
B got called!

Globals:
'Object': function Object() {
    [native code]
}
'Function': function Function() {
    [native code]
}
'Error': function Error() {
    [native code]
}
'EvalError': function EvalError() {
    [native code]
}
'RangeError': function RangeError() {
    [native code]
}
'ReferenceError': function ReferenceError() {
    [native code]
}
'SyntaxError': function SyntaxError() {
    [native code]
}
'TypeError': function TypeError() {
    [native code]
}
'URIError': function URIError() {
    [native code]
}
'InternalError': function InternalError() {
    [native code]
}
'AggregateError': function AggregateError() {
    [native code]
}
'Array': function Array() {
    [native code]
}
'parseInt': function parseInt() {
    [native code]
}
'parseFloat': function parseFloat() {
    [native code]
}
'isNaN': function isNaN() {
    [native code]
}
'isFinite': function isFinite() {
    [native code]
}
'decodeURI': function decodeURI() {
    [native code]
}
'decodeURIComponent': function decodeURIComponent() {
    [native code]
}
'encodeURI': function encodeURI() {
    [native code]
}
'encodeURIComponent': function encodeURIComponent() {
    [native code]
}
'escape': function escape() {
    [native code]
}
'unescape': function unescape() {
    [native code]
}
'Infinity': Infinity
'NaN': NaN
'undefined': undefined
'__date_clock': function __date_clock() {
    [native code]
}
'Number': function Number() {
    [native code]
}
'Boolean': function Boolean() {
    [native code]
}
'String': function String() {
    [native code]
}
'Math': [object Math]
'Reflect': [object Object]
'Symbol': function Symbol() {
    [native code]
}
'eval': function eval() {
    [native code]
}
'globalThis': [object Object]
'Date': function Date() {
    [native code]
}
'RegExp': function RegExp() {
    [native code]
}
'JSON': [object JSON]
'Proxy': function Proxy() {
    [native code]
}
'Map': function Map() {
    [native code]
}
'Set': function Set() {
    [native code]
}
'WeakMap': function WeakMap() {
    [native code]
}
'WeakSet': function WeakSet() {
    [native code]
}
'ArrayBuffer': function ArrayBuffer() {
    [native code]
}
'SharedArrayBuffer': function SharedArrayBuffer() {
    [native code]
}
'Uint8ClampedArray': function Uint8ClampedArray() {
    [native code]
}
'Int8Array': function Int8Array() {
    [native code]
}
'Uint8Array': function Uint8Array() {
    [native code]
}
'Int16Array': function Int16Array() {
    [native code]
}
'Uint16Array': function Uint16Array() {
    [native code]
}
'Int32Array': function Int32Array() {
    [native code]
}
'Uint32Array': function Uint32Array() {
    [native code]
}
'BigInt64Array': function BigInt64Array() {
    [native code]
}
'BigUint64Array': function BigUint64Array() {
    [native code]
}
'Float32Array': function Float32Array() {
    [native code]
}
'Float64Array': function Float64Array() {
    [native code]
}
'DataView': function DataView() {
    [native code]
}
'Atomics': [object Atomics]
'Promise': function Promise() {
    [native code]
}
'BigInt': function BigInt() {
    [native code]
}
'BigFloat': function BigFloat() {
    [native code]
}
'BigFloatEnv': function BigFloatEnv() {
    [native code]
}
'BigDecimal': function BigDecimal() {
    [native code]
}
'Operators': function Operators() {
    [native code]
}
'A': function() { return proxy.call(this, id, ...arguments); }
'B': function() { return proxy.call(this, id, ...arguments); }
'HELLO': world
'TEST': false

Object:
'hello': world
'test': 8

License

QuickJS is released under the MIT license.

QuickJS bindings are copyright Kenta Iwasaki, with code copyright Fabrice Bellard and Charlie Gordon.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Atom

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

func (Atom) Free

func (a Atom) Free()

func (Atom) String

func (a Atom) String() string

func (Atom) Value

func (a Atom) Value() Value

type Context

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

func (*Context) Array

func (ctx *Context) Array() Value

func (*Context) Atom

func (ctx *Context) Atom(v string) Atom

func (*Context) BigUint64

func (ctx *Context) BigUint64(v uint64) Value

func (*Context) Bool

func (ctx *Context) Bool(b bool) Value

func (*Context) Error

func (ctx *Context) Error(err error) Value

func (*Context) Eval

func (ctx *Context) Eval(code string) (Value, error)

func (*Context) EvalFile

func (ctx *Context) EvalFile(code, filename string) (Value, error)

func (*Context) Exception

func (ctx *Context) Exception() error

func (*Context) Float64

func (ctx *Context) Float64(v float64) Value

func (*Context) Free

func (ctx *Context) Free()

func (*Context) Function

func (ctx *Context) Function(fn Function) Value

func (*Context) Globals

func (ctx *Context) Globals() Value

func (*Context) Int32

func (ctx *Context) Int32(v int32) Value

func (*Context) Int64

func (ctx *Context) Int64(v int64) Value

func (*Context) Null

func (ctx *Context) Null() Value

func (*Context) Object

func (ctx *Context) Object() Value

func (*Context) String

func (ctx *Context) String(v string) Value

func (*Context) Throw

func (ctx *Context) Throw(v Value) Value

func (*Context) ThrowError

func (ctx *Context) ThrowError(err error) Value

func (*Context) ThrowInternalError

func (ctx *Context) ThrowInternalError(format string, args ...interface{}) Value

func (*Context) ThrowRangeError

func (ctx *Context) ThrowRangeError(format string, args ...interface{}) Value

func (*Context) ThrowReferenceError

func (ctx *Context) ThrowReferenceError(format string, args ...interface{}) Value

func (*Context) ThrowSyntaxError

func (ctx *Context) ThrowSyntaxError(format string, args ...interface{}) Value

func (*Context) ThrowTypeError

func (ctx *Context) ThrowTypeError(format string, args ...interface{}) Value

func (*Context) Uint32

func (ctx *Context) Uint32(v uint32) Value

func (*Context) Undefined

func (ctx *Context) Undefined() Value

func (*Context) Uninitialized

func (ctx *Context) Uninitialized() Value

type Error

type Error struct {
	Cause string
	Stack string
}

func (Error) Error

func (err Error) Error() string

type Function

type Function func(ctx *Context, this Value, args []Value) Value

type PropertyEnum

type PropertyEnum struct {
	IsEnumerable bool
	Atom         Atom
}

func (PropertyEnum) String

func (p PropertyEnum) String() string

type Runtime

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

func NewRuntime

func NewRuntime() Runtime

func (Runtime) ExecutePendingJob

func (r Runtime) ExecutePendingJob() (Context, error)

func (Runtime) Free

func (r Runtime) Free()

func (Runtime) NewContext

func (r Runtime) NewContext() *Context

func (Runtime) RunGC

func (r Runtime) RunGC()

type Value

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

func (Value) BigFloat

func (v Value) BigFloat() *big.Float

func (Value) BigInt

func (v Value) BigInt() *big.Int

func (Value) Bool

func (v Value) Bool() bool

func (Value) Context

func (v Value) Context() *Context

func (Value) Error

func (v Value) Error() error

func (Value) Float64

func (v Value) Float64() float64

func (Value) Free

func (v Value) Free()

func (Value) Get

func (v Value) Get(name string) Value

func (Value) GetByAtom

func (v Value) GetByAtom(atom Atom) Value

func (Value) GetByUint32

func (v Value) GetByUint32(idx uint32) Value

func (Value) Int32

func (v Value) Int32() int32

func (Value) Int64

func (v Value) Int64() int64

func (Value) IsArray

func (v Value) IsArray() bool

func (Value) IsBigDecimal

func (v Value) IsBigDecimal() bool

func (Value) IsBigFloat

func (v Value) IsBigFloat() bool

func (Value) IsBigInt

func (v Value) IsBigInt() bool

func (Value) IsBool

func (v Value) IsBool() bool

func (Value) IsConstructor

func (v Value) IsConstructor() bool

func (Value) IsError

func (v Value) IsError() bool

func (Value) IsException

func (v Value) IsException() bool

func (Value) IsFunction

func (v Value) IsFunction() bool

func (Value) IsNull

func (v Value) IsNull() bool

func (Value) IsNumber

func (v Value) IsNumber() bool

func (Value) IsObject

func (v Value) IsObject() bool

func (Value) IsString

func (v Value) IsString() bool

func (Value) IsSymbol

func (v Value) IsSymbol() bool

func (Value) IsUndefined

func (v Value) IsUndefined() bool

func (Value) IsUninitialized

func (v Value) IsUninitialized() bool

func (Value) Len

func (v Value) Len() int64

func (Value) PropertyNames

func (v Value) PropertyNames() ([]PropertyEnum, error)

func (Value) Set

func (v Value) Set(name string, val Value)

func (Value) SetByAtom

func (v Value) SetByAtom(atom Atom, val Value)

func (Value) SetByInt64

func (v Value) SetByInt64(idx int64, val Value)

func (Value) SetByUint32

func (v Value) SetByUint32(idx uint32, val Value)

func (Value) SetFunction

func (v Value) SetFunction(name string, fn Function)

func (Value) String

func (v Value) String() string

func (Value) Uint32

func (v Value) Uint32() uint32

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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