-
Notifications
You must be signed in to change notification settings - Fork 27
/
main_js.go
129 lines (103 loc) · 3.35 KB
/
main_js.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
121
122
123
124
125
126
127
128
129
//go:build js
// +build js
package main
import (
"syscall/js"
"github.com/lmorg/murex/app"
_ "github.com/lmorg/murex/builtins"
"github.com/lmorg/murex/builtins/pipes/term"
"github.com/lmorg/murex/config/defaults"
"github.com/lmorg/murex/lang"
"github.com/lmorg/murex/shell"
signalhandler "github.com/lmorg/murex/shell/signal_handler"
"github.com/lmorg/murex/utils/ansi"
"github.com/lmorg/murex/utils/readline"
)
const interactive = true
func main() {
startMurex()
js.Global().Set("wasmShellExec", wasmShellExec())
js.Global().Set("wasmShellStart", wasmShellStart())
js.Global().Set("wasmKeyPress", wasmKeyPress())
wait := make(chan bool)
<-wait
}
func startMurex() {
lang.InitEnv()
// default config
defaults.Config(lang.ShellProcess.Config, interactive)
// compiled profile
defaultProfile()
}
// wasmShellExec returns a Promise
func wasmShellExec() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
block := args[0].String()
// Handler for the Promise: this is a JS function
// It receives two arguments, which are JS functions themselves: resolve and reject
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
resolve := args[0]
reject := args[1]
// Now that we have a way to return the response to JS, spawn a goroutine
// This way, we don't block the event loop and avoid a deadlock
go func() {
fork := lang.ShellProcess.Fork(lang.F_PARENT_VARTABLE | lang.F_NEW_MODULE | lang.F_NO_STDIN)
fork.FileRef.Source.Module = app.ShellModule
fork.Stderr = term.NewErr(ansi.IsAllowed())
var err error
lang.ShellExitNum, err = fork.Execute([]rune(block))
if err != nil {
errorConstructor := js.Global().Get("Error")
errorObject := errorConstructor.New(err.Error())
reject.Invoke(errorObject)
}
resolve.Invoke("wasmShellExec(): " + block)
}()
// The handler of a Promise doesn't return any value
return nil
})
// Create and return the Promise object
promiseConstructor := js.Global().Get("Promise")
return promiseConstructor.New(handler)
})
}
// wasmShellStart starts the interactive shell as a Promise
func wasmShellStart() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
resolve := args[0]
//reject := args[1]
go func() {
resolve.Invoke("Starting interactive shell....")
shell.Start()
}()
// The handler of a Promise doesn't return any value
return nil
})
// Create and return the Promise object
promiseConstructor := js.Global().Get("Promise")
return promiseConstructor.New(handler)
})
}
// wasmKeyPress starts the interactive shell as a Promise
func wasmKeyPress() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
stdin := args[0].String()
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
//resolve := args[0]
//reject := args[1]
go func() {
readline.Stdin <- stdin
}()
// The handler of a Promise doesn't return any value
return nil
})
// Create and return the Promise object
promiseConstructor := js.Global().Get("Promise")
return promiseConstructor.New(handler)
})
}
func registerSignalHandlers(interactiveMode bool) {
signalhandler.Handlers = &signalhandler.SignalFunctionsT{}
signalhandler.EventLoop(interactiveMode)
}