-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
main.go
120 lines (94 loc) · 2.67 KB
/
main.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Simple example script which will work as a WASM binary.
package main
import (
"fmt"
"strings"
"syscall/js"
"github.com/skx/evalfilter/v2"
"github.com/skx/evalfilter/v2/object"
)
// Replace the value of the given field with the specified text.
func out(i js.Value, val string) {
js.Global().Get("document").Call("getElementById", i.String()).Set("value", val)
}
// Append text to the current output of the given field.
func append(i js.Value, val string) {
cur := js.Global().Get("document").Call("getElementById", i.String()).Get("value").String()
cur += val
js.Global().Get("document").Call("getElementById", i.String()).Set("value", cur)
}
// fnSprintf is the implementation of our `sprintf` function.
func fnSprintf(args []object.Object) object.Object {
// We expect 1+ arguments
if len(args) < 1 {
return &object.Null{}
}
// Type-check
if args[0].Type() != object.STRING {
return &object.Null{}
}
// Get the format-string.
fs := args[0].(*object.String).Value
// Convert the arguments to something go's sprintf
// code will understand.
argLen := len(args)
fmtArgs := make([]interface{}, argLen-1)
// Here we convert and assign.
for i, v := range args[1:] {
fmtArgs[i] = v.ToInterface()
}
// Call the helper
out := fmt.Sprintf(fs, fmtArgs...)
// And now return the value.
return &object.String{Value: out}
}
// run takes the script in 0 and outputs the result to 1
func run(this js.Value, i []js.Value) interface{} {
// empty the output
out(i[1], "")
// Get the input
in := js.Global().Get("document").Call("getElementById", i[0].String()).Get("value").String()
// create the environment.
eval := evalfilter.New(string(in))
// prepare the script
err := eval.Prepare()
if err != nil {
out(i[1], "Error compiling:"+err.Error())
return nil
}
// ensure that print works
eval.AddFunction("print",
func(args []object.Object) object.Object {
for _, e := range args {
append(i[1], fmt.Sprintf("%s", e.Inspect()))
}
return &object.Void{}
})
eval.AddFunction("printf",
func(args []object.Object) object.Object {
out := fnSprintf(args)
append(i[1], fmt.Sprintf("%s", out.Inspect()))
return &object.Void{}
})
// call the script
ret, err := eval.Execute(nil)
if err != nil {
out(i[1], "Error running:"+err.Error())
return nil
}
// Show the text
txt := fmt.Sprintf("Script result was '%s' (type %s) which is '%t'.\n",
ret.Inspect(), strings.ToLower(fmt.Sprintf("%s", ret.Type())), ret.True())
append(i[1], txt)
return nil
}
func registerCallbacks() {
js.Global().Set("run", js.FuncOf(run))
}
func main() {
c := make(chan struct{}, 0)
println("WASM Go Initialized")
// register functions
registerCallbacks()
<-c
}