pure go の javascript 処理系を使ってみた
23時に寝て2時に起きてだらだらして寝て7時に起きた。テンカイチ 日本最強武芸者決定戦 という漫画を読んでた。
pure go の javascript 処理系⌗
ユーザー定義スクリプトを実行する要件がある。システム管理者がスクリプトを書くなら javascript がいいかなと次のリファレンスを調べたりしていた。
- How to support custom Javascript scripting in Go Applications
- goja alternatives
- Choosing scripting extension - need advice
これらを読んだ結果として dop251/goja がよいだろうと判断した。README だけ読めばすぐに実装できてめっちゃ簡単で感心した。こういうライブラリを私も会社のプロダクトとして作ってみたい。万人が使うものではなくても、必要なときがたまにあって、すごく使いやすいみたいな。こんな感じで goja の機能を使ってライブラリ実装してみた。
type FunctionCaller func(funcName string, args ...interface{}) (interface{}, error)
func NewFunctionCaller(script string) (FunctionCaller, error) {
vm := goja.New()
_, err := vm.RunString(script)
if err != nil {
return nil, err
}
return func(funcName string, args ...interface{}) (interface{}, error) {
f, ok := goja.AssertFunction(vm.Get(funcName))
if !ok {
return nil, fmt.Errorf("failed to get function: %s", funcName)
}
funcArgs := make([]goja.Value, 0, len(args))
for _, arg := range args {
funcArgs = append(funcArgs, vm.ToValue(arg))
}
value, err := f(goja.Undefined(), funcArgs...)
if err != nil {
return nil, fmt.Errorf("failed to call javascript function: %w", err)
}
return value.Export(), nil
}, nil
}
Is it goroutine-safe? によると、goroutine-safe ではないので毎回 js の runtime を生成する必要がある。用途によっては、実行したいスクリプトが大きくなるとオーバーヘッドを無視できない状況もあるかもしれない。うちの要件は小さいユーザー定義スクリプトを実行するだけなのでおそらくそれほど問題にはならないだろうという想定。
Read other posts