/
worker.go
86 lines (68 loc) · 2.29 KB
/
worker.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
package jscoreWorker
/*
#cgo LDFLAGS: -framework JavaScriptCore
#include <stdlib.h>
#include <JavaScriptCore/JSBase.h>
#include <JavaScriptCore/JSContextRef.h>
//#include <JavaScriptCore/JSContextRefPrivate.h>
#include "bridge.h"
typedef void (*closure)();
*/
import "C"
import "strconv"
type ReceiveMessageCallback func(msg []byte) []byte
func SetFlags(args []string) []string {
return args
}
func Version() string {
return "JavaScriptCore"
}
type Worker struct {
// contains filtered or unexported fields
cb ReceiveMessageCallback
ctx *JSContext
id int
}
func New(cb ReceiveMessageCallback) *Worker {
worker := new(Worker)
worker.id = uniqueInt()
worker.cb = cb
worker.ctx = NewJSContext()
global := worker.ctx.GetGlobal()
rawSendFn := C.JSObjectMakeFunctionWithCallback(worker.ctx.ref, NewJSString("send").ref, C.closure(C.jsSend))
rawRecvFn := C.JSObjectMakeFunctionWithCallback(worker.ctx.ref, NewJSString("recv").ref, C.closure(C.jsRecv))
rawPrintFn := C.JSObjectMakeFunctionWithCallback(worker.ctx.ref, NewJSString("print").ref, C.closure(C.jsPrint))
rawWorker := NewJSObject(worker.ctx.Convert())
rawWorker.SetProperty("send", NewJSValueFromRef(worker.ctx.Convert(), C.JSValueRef(rawSendFn)))
rawWorker.SetProperty("recv", NewJSValueFromRef(worker.ctx.Convert(), C.JSValueRef(rawRecvFn)))
rawWorker.SetProperty("print", NewJSValueFromRef(worker.ctx.Convert(), C.JSValueRef(rawPrintFn)))
global.SetProperty("rawWorker", rawWorker.Value())
script := `
const JSCoreWorker = {
send (buf) {
const ret = rawWorker.send(` + strconv.Itoa(worker.id) + `, buf)
return ret ? ret.buffer : ret
},
recv (cb) { return rawWorker.recv(` + strconv.Itoa(worker.id) + `, cb) },
print (...any) { return rawWorker.print(` + strconv.Itoa(worker.id) + `, ...any) }
}
`
worker.ctx.EvaluateScript(script, "__jscoreWorker.js")
GoRecv(worker.ctx.Convert(), func(buf []byte) []byte {
return worker.cb(buf)
}, worker.id)
return worker
}
func (w *Worker) Dispose() {
}
func (w *Worker) Load(scriptName string, code string) error {
_, err := w.ctx.EvaluateScript(code, scriptName)
return err
}
func (w *Worker) SendBytes(msg []byte) error {
return GoSend(w.ctx.Convert(), msg, w.id)
}
func (w *Worker) TerminateExecution() {
// Cannot work
// C.JSContextGroupSetExecutionTimeLimit(w.ctx.group, 0, nil, nil)
}