-
Notifications
You must be signed in to change notification settings - Fork 1
/
function.go
89 lines (68 loc) · 2.15 KB
/
function.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Cr. https://github.com/nlepage/golang-wasm/tree/master/js/bind
// Cr. https://github.com/nlepage/golang-wasm/tree/master/js/bind
package citizenfx
import (
"reflect"
"strings"
"syscall/js"
)
const functionSuffix = "()"
var mapReturns = map[reflect.Kind]func(js.Value) []reflect.Value{
reflect.Float64: returnFloat,
reflect.Int: returnInt,
reflect.Bool: returnBool,
reflect.String: returnString,
reflect.Struct: returnStruct,
}
type function struct {
fn func() func(...interface{}) js.Value
mapReturn func(js.Value) []reflect.Value
}
func isFunction(t string) bool {
return strings.HasSuffix(t, functionSuffix)
}
func bindFunction(tag string, t reflect.Type, parent func() js.Value) reflect.Value {
return reflect.MakeFunc(t, newFunction(tag, t, parent).call)
}
func newFunction(tag string, t reflect.Type, parent func() js.Value) function {
name := strings.TrimSuffix(tag, functionSuffix)
fn := func() func(...interface{}) js.Value { return parent().Get(name).Invoke }
//FIXME check func return type
var mapReturn func(js.Value) []reflect.Value
if t.NumOut() == 0 {
mapReturn = returnVoid
} else {
var ok bool
mapReturn, ok = mapReturns[t.Out(0).Kind()]
if !ok {
println("FIXME no func mapping", t.String(), t.Out(0).Kind())
}
}
return function{fn, mapReturn}
}
func (f function) call(argValues []reflect.Value) []reflect.Value {
args := make([]interface{}, len(argValues))
for i, argValue := range argValues {
//TODO if argument is of kind struct, map it to a new JS object...
args[i] = argValue.Interface()
}
return f.mapReturn(f.fn()(args...))
}
func returnVoid(_ js.Value) []reflect.Value {
return []reflect.Value{}
}
func returnFloat(v js.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(v.Float())}
}
func returnInt(v js.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(v.Int())}
}
func returnBool(v js.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(v.Bool())}
}
func returnString(v js.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(v.String())}
}
func returnStruct(v js.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(v)}
}