-
Notifications
You must be signed in to change notification settings - Fork 0
/
func.go
72 lines (65 loc) · 2.04 KB
/
func.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
// +build js,wasm
package ui
import (
"context"
"sync"
"syscall/js"
)
// InitDomFuncs registers the logging and otp javascript functions.
func InitDomFuncs(ctx context.Context, wg *sync.WaitGroup) {
logFuncs := map[string]js.Func{
"clear": NewJsFunc(clearLog),
}
otpFuncs := map[string]js.Func{
"encrypt": NewJsEventFunc(encryptMessage),
"decrypt": NewJsEventFunc(decryptCipher),
"generateKey": NewJsEventFunc(generateKey),
}
RegisterFuncs(ctx, wg, "log", logFuncs)
RegisterFuncs(ctx, wg, "otp", otpFuncs)
initOtp(ctx, wg)
}
// NewJsFunc creates a new javascript function from the provided function.
func NewJsFunc(fn func()) js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
defer AlertOnPanic()
fn()
return nil
})
}
// NewJsEventFunc creates a new javascript function from the provided function that processes an event and returns nothing.
// PreventDefault is called on the event before applying the function.
func NewJsEventFunc(fn func(event js.Value)) js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
event := args[0]
event.Call("preventDefault")
defer AlertOnPanic()
fn(event)
return nil
})
}
// RegisterFuncs sets the function as fields on the parent.
// The parent object is created if it does not exist.
func RegisterFuncs(ctx context.Context, wg *sync.WaitGroup, parentName string, jsFuncs map[string]js.Func) {
global := js.Global()
parent := global.Get(parentName)
if parent.IsUndefined() {
parent = js.ValueOf(make(map[string]interface{}))
global.Set(parentName, parent)
}
for fnName, fn := range jsFuncs {
parent.Set(fnName, fn)
}
wg.Add(1)
go ReleaseJsFuncsOnDone(ctx, wg, jsFuncs)
}
// ReleaseJsFuncsOnDone releases the jsFuncs and decrements the waitgroup when the context is done.
// This function should be called on a separate goroutine.
func ReleaseJsFuncsOnDone(ctx context.Context, wg *sync.WaitGroup, jsFuncs map[string]js.Func) {
defer AlertOnPanic()
<-ctx.Done() // BLOCKING
for _, f := range jsFuncs {
f.Release()
}
wg.Done()
}