• Stars
    star
    147
  • Rank 251,347 (Top 5 %)
  • Language
    C
  • License
    MIT License
  • Created over 4 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

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.

More Repositories

1

flatend

Quickly build microservices using p2p networking in NodeJS/Go.
TypeScript
650
star
2

rheia

A blockchain written in Zig.
Zig
246
star
3

reliable

A reliability layer for UDP connections in Go.
Go
138
star
4

pike

Async I/O for Zig
Zig
118
star
5

monte

The bare minimum for high performance, fully-encrypted bidirectional RPC over TCP in Go with zero memory allocations.
Go
117
star
6

alon

Remix for Solana.
JavaScript
100
star
7

casso

A Go implementation of the Cassowary constraint solving algorithm.
Go
75
star
8

youtube

A library for executing search queries, retrieving metadata, and obtaining direct links to video-only/audio-only/muxed versions of videos on YouTube in Go.
Go
68
star
9

lmdb-zig

Lightweight, fully-featured, idiomatic cross-platform Zig bindings to Lightning Memory-Mapped Database (LMDB).
Zig
65
star
10

hyperia

Zig
45
star
11

snow

A small, fast, cross-platform, async Zig networking framework built on top of lithdew/pike.
Zig
36
star
12

hello

Multi-threaded cross-platform HTTP/1.1 web server example in Zig.
Zig
33
star
13

solana-zig

Write Solana programs in Zig.
Zig
24
star
14

cuckoo

A fast, vectorized Cuckoo filter implementation in Go. Zero allocations in hot paths with zero-copy binary representation.
Go
15
star
15

borsh-zig

A Zig implementation of the Borsh binary format specification.
Zig
15
star
16

kademlia-go

S/Kademlia in Go. Heavy WIP.
Go
11
star
17

nicehttp

Helper utilities for downloading files/making requests with valyala/fasthttp.
Go
9
star
18

flatlang

An embeddable human-friendly configuration language with zero keywords in Go. Heavily inspired by Google Starlark and CUE.
Go
8
star
19

usockets-zig

A fork of uSockets packaged for Zig.
Zig
8
star
20

seq

A fast implementation of sequence buffers in Go with 100% unit test coverage.
Go
7
star
21

oauth2-go

What does it take to write a minimal security-first OAuth 2.0 Server w/ OpenID Connect support in Go?
Go
6
star
22

bincode-zig

A Zig implementation of the Bincode binary format specification.
Zig
6
star
23

bytesutil

Utilities for reducing memory allocations in Go w/ 100% unit test coverage.
Go
5
star
24

boringssl-zig

A fork of boringssl packaged for Zig.
Assembly
4
star
25

recaptcha

Quickly verify reCAPTCHA v2/v3 submissions in Go.
Go
4
star
26

libuv-zig

A fork of libuv packaged for Zig.
Zig
3
star
27

rhh-ts

Robin-hood hashing vs. B+Trees in TypeScript.
TypeScript
3
star
28

uwebsockets-zig

A fork of uWebSockets packaged for Zig.
Zig
2
star
29

asciigraph

Go package to make lightweight ASCII line graph β•­β”ˆβ•― in command line apps. Mindful fork of guptarohit/asciigraph.
Go
1
star
30

ed25519-donna-zig

Minimal Zig bindings to ed25519-donna.
Zig
1
star
31

alon-sysroot

Sysroot for Alon.
C
1
star
32

sqlutil

Utilities for working with SQL in Go.
Go
1
star
33

slept

Research on reliable, high-peformance transport protocols for p2p networking.
Go
1
star