Skip to content

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

License

Notifications You must be signed in to change notification settings

lithdew/quickjs

Repository files navigation

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

Example

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

package main

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

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	rt := quickjs.NewRuntime()
	ctx := rt.NewContext()

	globals := ctx.Globals()

	// Test evaluating template strings.

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

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

	// Test evaluating numeric expressions.

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

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

	// Test evaluating big integer expressions.

	result, err = ctx.Eval(`128n ** 16n`)
	check(err)

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

	// Test evaluating big decimal expressions.

	result, err = ctx.Eval(`128l ** 12l`)
	check(err)

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

	// Test evaluating boolean expressions.

	result, err = ctx.Eval(`false && true`)
	check(err)

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

	// Test setting and calling functions.

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

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

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

	fmt.Println()

	// Test setting global variables.

	_, err = ctx.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)
		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 = ctx.Eval(strings.Join(flag.Args(), " "))
	check(err)

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

		fmt.Println("Object:")
		for _, name := range names {
			val := result.GetByAtom(name.Atom)
			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:
'A': function () {
    [native code]
}
'B': function () {
    [native code]
}
'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.

About

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

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages