├── .gitignore ├── LICENSE ├── README.md ├── context-raw.go ├── context.go ├── error.go ├── function.go ├── install.sh ├── main └── main.go ├── module.go ├── quickjs-bridge.c ├── quickjs-bridge.h ├── quickjs.go ├── runtime.go └── value.go /.gitignore: -------------------------------------------------------------------------------- 1 | ### Go ### 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Dependency directories (remove the comment below to include it) 16 | # vendor/ 17 | 18 | ### Go Patch ### 19 | /vendor/ 20 | /Godeps/ 21 | 22 | ### Intellij ### 23 | /.idea/ 24 | 25 | ### Project ### 26 | quickjs.h 27 | quickjs-libc.h 28 | libquickjs.a 29 | /quickjs-source/ 30 | quickjs-source.tar.xz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Plutonist Fu 4 | Copyright (c) 2017-2019 Fabrice Bellard 5 | Copyright (c) 2017-2019 Charlie Gordon 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-quickjs 2 | QuickJS engine bindings for Go. 3 | 4 | **Warning: At present, both the original project `quickjs` and this project are still in the early stage of development. Please use this project carefully in the production environment.** 5 | 6 | ## Features 7 | * Evaluate script 8 | * Evaluate bytecode in `[]byte` 9 | * Compile script into bytecode in `[]byte` 10 | * Simple exception throwing and catching 11 | * Invoke Go function from JavaScript 12 | * Operate JavaScript values and objects in Go 13 | 14 | ## Get Started 15 | Install: (MacOS tested only) 16 | ```bash 17 | wget https://raw.github.com/wspl/go-quickjs/master/install.sh && sh ./install.sh 18 | ``` 19 | Hello world: 20 | ```go 21 | package main 22 | 23 | import "github.com/wspl/go-quickjs" 24 | 25 | func main() { 26 | runtime := quickjs.NewJSRuntime() 27 | defer runtime.Free() 28 | context := runtime.NewContext() 29 | defer context.Free() 30 | 31 | ret, err := context.Eval("'Hello ' + 'World!'", "") 32 | if err != nil { 33 | println(err.Message()) 34 | } 35 | println(ret.String()) 36 | } 37 | ``` 38 | Invoke Go function in JavaScript: 39 | ```go 40 | package main 41 | 42 | import . "github.com/wspl/go-quickjs" 43 | 44 | func main() { 45 | runtime := NewJSRuntime() 46 | defer runtime.Free() 47 | context := runtime.NewContext() 48 | defer context.Free() 49 | 50 | fn := context.NewGoFunction(func(args []*JSValue, this *JSValue) (*JSValue, *JSError) { 51 | println("Invoked!") 52 | return context.NewString("Hello World"), nil 53 | }) 54 | fn.Value().Expose("hello") 55 | ret, err := context.Eval("hello()", "") 56 | if err != nil { 57 | println(err.Message()) 58 | } 59 | println(ret.String()) 60 | } 61 | 62 | ``` 63 | 64 | ## TODOs 65 | - Test cases 66 | - Module support 67 | - Fix bugs 68 | 69 | ## License 70 | [MIT](./LICENSE) -------------------------------------------------------------------------------- /context-raw.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | 10 | type JSContextRaw struct { 11 | ref *C.JSContext 12 | } 13 | 14 | func JSNewContextRaw(runtime JSRuntime) *JSContextRaw { 15 | ctx := new(JSContextRaw) 16 | ctx.ref = C.JS_NewContextRaw(runtime.ref) 17 | return ctx 18 | } 19 | 20 | func (ctx *JSContext) ToContext() JSContext { 21 | return JSContext{ 22 | ref: ctx.ref, 23 | } 24 | } 25 | 26 | func (ctx *JSContextRaw) AddIntrinsicBaseObjects() { 27 | C.JS_AddIntrinsicBaseObjects(ctx.ref) 28 | } 29 | 30 | func (ctx *JSContextRaw) AddIntrinsicDate() { 31 | C.JS_AddIntrinsicDate(ctx.ref) 32 | } 33 | 34 | func (ctx *JSContextRaw) AddIntrinsicEval() { 35 | C.JS_AddIntrinsicEval(ctx.ref) 36 | } 37 | 38 | func (ctx *JSContextRaw) AddIntrinsicStringNormalize() { 39 | C.JS_AddIntrinsicStringNormalize(ctx.ref) 40 | } 41 | 42 | func (ctx *JSContextRaw) AddIntrinsicRegExpCompiler() { 43 | C.JS_AddIntrinsicRegExpCompiler(ctx.ref) 44 | } 45 | 46 | func (ctx *JSContextRaw) AddIntrinsicRegExp() { 47 | C.JS_AddIntrinsicRegExp(ctx.ref) 48 | } 49 | 50 | func (ctx *JSContextRaw) AddIntrinsicJSON() { 51 | C.JS_AddIntrinsicJSON(ctx.ref) 52 | } 53 | 54 | func (ctx *JSContextRaw) AddIntrinsicProxy() { 55 | C.JS_AddIntrinsicProxy(ctx.ref) 56 | } 57 | 58 | func (ctx *JSContextRaw) AddIntrinsicMapSet() { 59 | C.JS_AddIntrinsicMapSet(ctx.ref) 60 | } 61 | 62 | func (ctx *JSContextRaw) AddIntrinsicTypedArrays() { 63 | C.JS_AddIntrinsicTypedArrays(ctx.ref) 64 | } 65 | 66 | func (ctx *JSContextRaw) AddIntrinsicPromise() { 67 | C.JS_AddIntrinsicPromise(ctx.ref) 68 | } 69 | -------------------------------------------------------------------------------- /context.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | var ctxMap = make(map[*C.JSContext]*JSContext) 14 | 15 | type JSContext struct { 16 | ref *C.JSContext 17 | functions []*JSGoFunction 18 | cFunction C.JSValue 19 | global *JSValue 20 | } 21 | 22 | func NewJSContext(runtime *JSRuntime) *JSContext { 23 | ctx := new(JSContext) 24 | ctx.ref = C.JS_NewContext(runtime.ref) 25 | ctx.functions = []*JSGoFunction{} 26 | ctx.cFunction = C.JS_NewCFunction(ctx.ref, (*C.JSCFunction)(unsafe.Pointer(C.InvokeGoHandler)), nil, C.int(5)) 27 | ctx.global = ctx.WrapValue(C.JS_GetGlobalObject(ctx.ref)) 28 | 29 | ctxMap[ctx.ref] = ctx 30 | 31 | return ctx 32 | } 33 | 34 | func (ctx *JSContext) FreeCValue(value C.JSValue) { 35 | C.JS_FreeValue(ctx.ref, value) 36 | } 37 | 38 | func (ctx *JSContext) FreeValue(value *JSValue) { 39 | C.JS_FreeValue(ctx.ref, value.ref) 40 | } 41 | 42 | func (ctx *JSContext) Free() { 43 | ctx.FreeCValue(ctx.cFunction) 44 | ctx.global.Free() 45 | C.JS_FreeContext(ctx.ref) 46 | } 47 | 48 | func (ctx *JSContext) Eval(script string, filename string) (*JSValue, *JSError) { 49 | scriptCstr := C.CString(script) 50 | defer C.free(unsafe.Pointer(scriptCstr)) 51 | scriptClen := C.ulong(len(script)) 52 | 53 | filenameCstr := C.CString(filename) 54 | defer C.free(unsafe.Pointer(filenameCstr)) 55 | 56 | ret := ctx.WrapValue(C.JS_Eval(ctx.ref, scriptCstr, scriptClen, filenameCstr, C.int(0))) 57 | e := ctx.Exception() 58 | if e != nil { 59 | return ret, e 60 | } 61 | return ret, nil 62 | } 63 | 64 | func (ctx *JSContext) EvalBinary(buf []byte) (*JSValue, *JSError) { 65 | ret := ctx.WrapValue(C.JS_EvalBinary(ctx.ref, (*C.uchar)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(0))) 66 | e := ctx.Exception() 67 | if e != nil { 68 | return ret, e 69 | } 70 | return ret, nil 71 | } 72 | 73 | func (ctx *JSContext) Binary(script string, filename string) []byte { 74 | scriptCstr := C.CString(script) 75 | defer C.free(unsafe.Pointer(scriptCstr)) 76 | scriptClen := C.ulong(len(script)) 77 | 78 | filenameCstr := C.CString(filename) 79 | defer C.free(unsafe.Pointer(filenameCstr)) 80 | 81 | obj := C.JS_Eval( 82 | ctx.ref, 83 | scriptCstr, 84 | scriptClen, 85 | filenameCstr, 86 | C.JS_EVAL_TYPE_MODULE|C.JS_EVAL_FLAG_COMPILE_ONLY, 87 | ) 88 | outBufLen := C.size_t(0) 89 | outBuf := C.JS_WriteObject(ctx.ref, &outBufLen, obj, C.JS_WRITE_OBJ_BYTECODE) 90 | return C.GoBytes(unsafe.Pointer(outBuf), C.int(outBufLen)) 91 | } 92 | 93 | func (ctx *JSContext) Global() *JSValue { 94 | return ctx.global 95 | } 96 | 97 | func (ctx *JSContext) NewGoFunction(fn JSGoFunctionCallback) *JSGoFunction { 98 | return NewJSGoFunction(ctx, fn) 99 | } 100 | 101 | func (ctx *JSContext) NewBool(bool bool) *JSValue { 102 | n := 0 103 | if bool { 104 | n = 1 105 | } 106 | return ctx.WrapValue(C.JS_NewBool(ctx.ref, C.int(n))) 107 | } 108 | 109 | func (ctx *JSContext) NewInt32(int int32) *JSValue { 110 | return ctx.WrapValue(C.JS_NewInt32(ctx.ref, C.int32_t(int))) 111 | } 112 | 113 | func (ctx *JSContext) NewInt64(int int64) *JSValue { 114 | return ctx.WrapValue(C.JS_NewInt64(ctx.ref, C.int64_t(int))) 115 | } 116 | 117 | func (ctx *JSContext) NewFloat64(double float64) *JSValue { 118 | return ctx.WrapValue(C.JS_NewFloat64(ctx.ref, C.double(double))) 119 | } 120 | 121 | func (ctx *JSContext) NewObject() *JSValue { 122 | return ctx.WrapValue(C.JS_NewObject(ctx.ref)) 123 | } 124 | 125 | func (ctx *JSContext) NewString(string string) *JSValue { 126 | cstr := C.CString(string) 127 | defer C.free(unsafe.Pointer(cstr)) 128 | return ctx.WrapValue(C.JS_NewString(ctx.ref, cstr)) 129 | } 130 | 131 | func (ctx *JSContext) NewNull() *JSValue { 132 | return ctx.WrapValue(C.JS_NULL) 133 | } 134 | 135 | func (ctx *JSContext) NewUndefined() *JSValue { 136 | return ctx.WrapValue(C.JS_UNDEFINED) 137 | } 138 | 139 | func (ctx *JSContext) NewException() *JSValue { 140 | return ctx.WrapValue(C.JS_EXCEPTION) 141 | } 142 | 143 | func (ctx *JSContext) NewUninitialized() *JSValue { 144 | return ctx.WrapValue(C.JS_UNINITIALIZED) 145 | } 146 | 147 | func (ctx *JSContext) WrapValue(cval C.JSValue) *JSValue { 148 | return NewJSValue(ctx, cval) 149 | } 150 | 151 | func (ctx *JSContext) WrapError(cerr C.JSValue) *JSError { 152 | return WrapJSError(ctx, cerr) 153 | } 154 | 155 | func (ctx *JSContext) Exception() *JSError { 156 | val := ctx.WrapValue(C.JS_GetException(ctx.ref)) 157 | if val.IsNull() { 158 | return nil 159 | } 160 | return val.Error() 161 | } 162 | 163 | func (ctx *JSContext) Try() { 164 | obj := ctx.NewObject() 165 | obj.SetProperty("a", ctx.NewInt64(22444)) 166 | obj.SetProperty("b", ctx.NewString("Hello")) 167 | obj.Expose("obj") 168 | buf := ctx.Binary("JSON.stringify(obj)", "") 169 | println(string(buf)) 170 | ret, _ := ctx.EvalBinary(buf) 171 | println(ret.String()) 172 | } 173 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | 10 | type JSError struct { 11 | ref C.JSValue 12 | ctx *JSContext 13 | val *JSValue 14 | } 15 | 16 | func WrapJSError(ctx *JSContext, cerr C.JSValue) *JSError { 17 | jse := new(JSError) 18 | jse.ref = cerr 19 | jse.ctx = ctx 20 | return jse 21 | } 22 | 23 | func (jse *JSError) Value() *JSValue { 24 | if jse.val == nil { 25 | jse.val = jse.ctx.WrapValue(jse.ref) 26 | } 27 | return jse.val 28 | } 29 | 30 | func (jse *JSError) Message() string { 31 | return jse.Value().Property("message").String() 32 | } 33 | 34 | func (jse *JSError) Errno() string { 35 | return jse.Value().Property("errno").String() 36 | } 37 | -------------------------------------------------------------------------------- /function.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | import "unsafe" 10 | 11 | //export GoHandler 12 | func GoHandler(cctx *C.JSContext, cthis C.JSValueConst, cargc C.int, cargv *C.JSValueConst) C.JSValue { 13 | ctx := ctxMap[cctx] 14 | cargs := (*[1 << 28]C.JSValueConst)(unsafe.Pointer(cargv))[:cargc:cargc] 15 | id := ctx.WrapValue(cargs[0]).Int() 16 | this := ctx.WrapValue(cthis) 17 | var args []*JSValue 18 | for _, carg := range cargs { 19 | args = append(args, ctx.WrapValue(carg)) 20 | } 21 | result, err := ctx.functions[id].fn(args, this) 22 | if err != nil { 23 | return err.ref 24 | } 25 | return result.ref 26 | } 27 | 28 | type JSGoFunctionCallback func(args []*JSValue, this *JSValue) (*JSValue, *JSError) 29 | 30 | type JSGoFunction struct { 31 | ref C.JSValue 32 | ctx *JSContext 33 | fn JSGoFunctionCallback 34 | } 35 | 36 | func NewJSGoFunction(ctx *JSContext, fn JSGoFunctionCallback) *JSGoFunction { 37 | jsf := new(JSGoFunction) 38 | jsf.ctx = ctx 39 | jsf.fn = fn 40 | jsf.init() 41 | return jsf 42 | } 43 | 44 | func (jsf *JSGoFunction) init() { 45 | wrapperScript := "(invokeGoFunction, id) => function () { return invokeGoFunction.call(this, id, arguments) }" 46 | wrapperFn, _ := jsf.ctx.Eval(wrapperScript, "") 47 | defer wrapperFn.Free() 48 | 49 | id := len(jsf.ctx.functions) 50 | jsf.ctx.functions = append(jsf.ctx.functions, jsf) 51 | 52 | idVal := jsf.ctx.NewInt32(int32(id)) 53 | wrapperArgs := []C.JSValue{ 54 | jsf.ctx.cFunction, 55 | idVal.ref, 56 | } 57 | 58 | jsf.ref = C.JS_Call(jsf.ctx.ref, wrapperFn.ref, jsf.ctx.NewNull().ref, 2, &wrapperArgs[0]) 59 | } 60 | 61 | func (jsf *JSGoFunction) Value() *JSValue { 62 | return jsf.ctx.WrapValue(jsf.ref) 63 | } 64 | 65 | func (jsf *JSGoFunction) Call(args []*JSValue, this *JSValue) *JSValue { 66 | return jsf.Value().Call(args, this) 67 | } 68 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | go_quickjs="github.com/wspl/go-quickjs" 3 | install_dir="$GOPATH/src/$go_quickjs" 4 | quickjs="https://bellard.org/quickjs/quickjs-2019-07-28.tar.xz" 5 | 6 | old_pwd=$(pwd) 7 | 8 | if test -f "quickjs.go"; then 9 | install_dir=$(pwd) 10 | else 11 | go get -d $go_quickjs 12 | cd $install_dir 13 | fi 14 | 15 | rm -rf ./libquickjs.a 16 | rm -rf ./quickjs-source 17 | 18 | wget -O quickjs-source.tar.xz $quickjs 19 | mkdir quickjs-source 20 | tar xvf quickjs-source.tar.xz -C quickjs-source 21 | 22 | cd quickjs-source/quickjs* 23 | 24 | cp quickjs.h $install_dir 25 | cp quickjs-libc.h $install_dir 26 | 27 | sed -i -e '37d' ./Makefile 28 | make 29 | cp libquickjs.a $install_dir 30 | 31 | cd $install_dir 32 | go install 33 | 34 | cd $old_pwd 35 | -------------------------------------------------------------------------------- /main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "C" 4 | import ( 5 | . "go-quickjs" 6 | ) 7 | 8 | func main() { 9 | runtime := NewJSRuntime() 10 | defer runtime.Free() 11 | context := runtime.NewContext() 12 | defer context.Free() 13 | 14 | fn := context.NewGoFunction(func(args []*JSValue, this *JSValue) (*JSValue, *JSError) { 15 | println("Invoked!") 16 | return context.NewString("Hello World"), nil 17 | }) 18 | fn.Value().Expose("hello") 19 | ret, err := context.Eval("hello()", "") 20 | if err != nil { 21 | println(err.Message()) 22 | } 23 | println(ret.String()) 24 | } 25 | -------------------------------------------------------------------------------- /module.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | 10 | //import "unsafe" 11 | 12 | //type JSModuleInitFunc func(ctx *JSContext, mod *JSGoModule) 13 | 14 | //type JSGoModule struct { 15 | // ref C.JSModuleDef 16 | //} 17 | // 18 | //func NewJSGoModule(ctx JSContext, moduleName string) { 19 | // jsm := new(JSGoModule) 20 | // 21 | // moduleNameCstr := C.CString(moduleName) 22 | // defer C.free(unsafe.Pointer(moduleNameCstr)) 23 | // jsm.ref = C.JS_NewCModule(ctx.ref, moduleNameCstr) 24 | //} 25 | -------------------------------------------------------------------------------- /quickjs-bridge.c: -------------------------------------------------------------------------------- 1 | #include "_cgo_export.h" 2 | 3 | JSValue InvokeGoHandler(JSContext *ctx, JSValueConst thisObj, int argc, JSValueConst *argv) { 4 | return GoHandler(ctx, thisObj, argc, argv); 5 | } -------------------------------------------------------------------------------- /quickjs-bridge.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern JSValue InvokeGoHandler(JSContext *ctx, JSValueConst thisObj, int argc, JSValueConst *argv); -------------------------------------------------------------------------------- /quickjs.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #cgo CFLAGS: -I. 5 | #cgo LDFLAGS: -L. -lquickjs -lm 6 | #include "quickjs-bridge.h" 7 | */ 8 | import "C" 9 | -------------------------------------------------------------------------------- /runtime.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | /* 4 | #include "quickjs-bridge.h" 5 | */ 6 | import "C" 7 | 8 | type JSRuntime struct { 9 | ref *C.JSRuntime 10 | } 11 | 12 | func NewJSRuntime() *JSRuntime { 13 | rt := new(JSRuntime) 14 | rt.ref = C.JS_NewRuntime() 15 | return rt 16 | } 17 | 18 | func (rt *JSRuntime) NewContext() *JSContext { 19 | return NewJSContext(rt) 20 | } 21 | 22 | func (rt *JSRuntime) Free() { 23 | C.JS_FreeRuntime(rt.ref) 24 | } 25 | -------------------------------------------------------------------------------- /value.go: -------------------------------------------------------------------------------- 1 | package quickjs 2 | 3 | import "unsafe" 4 | 5 | /* 6 | #cgo CFLAGS: -I. 7 | #cgo LDFLAGS: -L. -lquickjs 8 | #include "quickjs-bridge.h" 9 | */ 10 | import "C" 11 | 12 | var valueMap = make(map[*C.JSValue]JSValue) 13 | 14 | type JSValue struct { 15 | ref C.JSValue 16 | ctx *JSContext 17 | } 18 | 19 | func NewJSValue(ctx *JSContext, cval C.JSValue) *JSValue { 20 | val := new(JSValue) 21 | val.ref = cval 22 | val.ctx = ctx 23 | return val 24 | } 25 | 26 | func (val *JSValue) Free() { 27 | C.JS_FreeValue(val.ctx.ref, val.ref) 28 | } 29 | 30 | func (val *JSValue) AttachContext(ctx *JSContext) { 31 | val.ctx = ctx 32 | } 33 | 34 | func (val *JSValue) String() string { 35 | cstr := C.JS_ToCString(val.ctx.ref, val.ref) 36 | return C.GoString(cstr) 37 | } 38 | 39 | func (val *JSValue) Float64() float64 { 40 | i := C.double(0) 41 | C.JS_ToFloat64(val.ctx.ref, &i, val.ref) 42 | return float64(i) 43 | } 44 | 45 | func (val *JSValue) Int64() int64 { 46 | i := C.int64_t(0) 47 | C.JS_ToInt64(val.ctx.ref, &i, val.ref) 48 | return int64(i) 49 | } 50 | 51 | func (val *JSValue) Int() int { 52 | i := C.int64_t(0) 53 | C.JS_ToInt64(val.ctx.ref, &i, val.ref) 54 | return int(i) 55 | } 56 | 57 | func (val *JSValue) Int32() int32 { 58 | i := C.int32_t(0) 59 | C.JS_ToInt32(val.ctx.ref, &i, val.ref) 60 | return int32(i) 61 | } 62 | 63 | func (val *JSValue) Bool() bool { 64 | i := C.JS_ToBool(val.ctx.ref, val.ref) 65 | return val.valueToBool(i) 66 | } 67 | 68 | func (val *JSValue) Error() *JSError { 69 | return val.ctx.WrapError(val.ref) 70 | } 71 | 72 | func (val *JSValue) valueToBool(cval C.int) bool { 73 | if cval == 1 { 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func (val *JSValue) IsInteger() bool { 80 | return val.valueToBool(C.JS_IsInteger(val.ref)) 81 | } 82 | 83 | func (val *JSValue) IsBigFloat() bool { 84 | return val.valueToBool(C.JS_IsBigFloat(val.ref)) 85 | } 86 | 87 | func (val *JSValue) IsBool() bool { 88 | return val.valueToBool(C.JS_IsBool(val.ref)) 89 | } 90 | 91 | func (val *JSValue) IsUndefined() bool { 92 | return val.valueToBool(C.JS_IsUndefined(val.ref)) 93 | } 94 | 95 | func (val *JSValue) IsNull() bool { 96 | return val.valueToBool(C.JS_IsNull(val.ref)) 97 | } 98 | 99 | func (val *JSValue) IsException() bool { 100 | return val.valueToBool(C.JS_IsException(val.ref)) 101 | } 102 | 103 | func (val *JSValue) IsUninitialized() bool { 104 | return val.valueToBool(C.JS_IsUninitialized(val.ref)) 105 | } 106 | 107 | func (val *JSValue) IsString() bool { 108 | return val.valueToBool(C.JS_IsString(val.ref)) 109 | } 110 | 111 | func (val *JSValue) IsSymbol() bool { 112 | return val.valueToBool(C.JS_IsSymbol(val.ref)) 113 | } 114 | 115 | func (val *JSValue) IsObject() bool { 116 | return val.valueToBool(C.JS_IsObject(val.ref)) 117 | } 118 | 119 | func (val *JSValue) IsError() bool { 120 | return val.valueToBool(C.JS_IsError(val.ctx.ref, val.ref)) 121 | } 122 | 123 | func (val *JSValue) IsFunction() bool { 124 | return val.valueToBool(C.JS_IsFunction(val.ctx.ref, val.ref)) 125 | } 126 | 127 | func (val *JSValue) IsConstructor() bool { 128 | return val.valueToBool(C.JS_IsConstructor(val.ctx.ref, val.ref)) 129 | } 130 | 131 | func (val *JSValue) IsExtensible() bool { 132 | return val.valueToBool(C.JS_IsExtensible(val.ctx.ref, val.ref)) 133 | } 134 | 135 | func (val *JSValue) IsInstanceOf(ctor *JSValue) bool { 136 | return val.valueToBool(C.JS_IsInstanceOf(val.ctx.ref, val.ref, ctor.ref)) 137 | } 138 | 139 | func (val *JSValue) Call(args []*JSValue, this *JSValue) *JSValue { 140 | if this == nil { 141 | this = val.ctx.Global() 142 | } 143 | var cargs []C.JSValue 144 | for _, arg := range args { 145 | cargs = append(cargs, arg.ref) 146 | } 147 | return val.ctx.WrapValue(C.JS_Call(val.ctx.ref, val.ref, this.ref, C.int(len(args)), &cargs[0])) 148 | } 149 | 150 | func (val *JSValue) PropertyByInt(key int) *JSValue { 151 | return val.ctx.WrapValue(C.JS_GetPropertyUint32(val.ctx.ref, val.ref, C.uint32_t(key))) 152 | } 153 | 154 | func (val *JSValue) Property(key string) *JSValue { 155 | cstr := C.CString(key) 156 | defer C.free(unsafe.Pointer(cstr)) 157 | return val.ctx.WrapValue(C.JS_GetPropertyStr(val.ctx.ref, val.ref, cstr)) 158 | } 159 | 160 | func (val *JSValue) SetPropertyByInt(key int, value *JSValue) { 161 | C.JS_SetPropertyInt64(val.ctx.ref, val.ref, C.int64_t(key), value.ref) 162 | } 163 | 164 | func (val *JSValue) SetProperty(key string, value *JSValue) { 165 | cstr := C.CString(key) 166 | defer C.free(unsafe.Pointer(cstr)) 167 | C.JS_SetPropertyStr(val.ctx.ref, val.ref, cstr, value.ref) 168 | } 169 | 170 | func (val *JSValue) Expose(name string) { 171 | val.ctx.global.SetProperty(name, val) 172 | } 173 | --------------------------------------------------------------------------------