シェルスクリプトでcurlとかjqを使って何かしている処理が色々あるので、JavaScriptに置き換える。
Node.jsでも良かったのだけど、もともとサーバがGoで実装されていて実行時に依存するものを増やしたくなかったので先日のGojaでやる。
Fetch API と Node.js に似た fs, child_process あたりのモジュールを実装しておく: https://github.com/binzume/goja_utils
AWSのLambdaとかで実行した方が楽そうだけど、家電のコントロールとかもしてるので、なるべくローカルネットワーク内で動かしておきたい気もする。
あとGojaはES Modules対応してなくてパース自体失敗するけど、 GrafanaがGojaからforkして開発してるSobekはES Moduleの実装が張ってるっぽい。
大涌谷

交叉する空間構造

小学生の時に来た以来なので30年ぶり?
伊香保

羊がたくさんいた。
* 日本でWindows 95が発売されてから30年
1995年はまだ小学生でSHARP X1のHu-BASICを触った頃だと思うので、プログラミング歴も30年くらいになりそう。真面目に何か作ろうと思ったのはもう少し後だけど。
あとはバーチャルボーイとFF6の飛空艇の画面見て、3Dでぐりぐり動かせるゲームを作りたいと思ったのもこの頃。
宝登山。

天気がいい。
夜、望遠鏡と双眼鏡を覗いてたのだけど、人工衛星が横切る頻度が子供の頃と比べて明らかに増えてる。
明日から一週間休み。
gojaでgoroutineで実装された非同期処理をjsから呼び出したり、逆にjs側で作ったPromiseをgoで待ったりする実装をしてたけど、基本的にgoroutine-safeでないので慣れないととても書きにくい。。。せめてPromiseに他のgoroutineからアクセスしたい。処理の奥深くからイベントループにタスクを追加しないといけないけどcontextサポートは入れない方針っぽいので、イベントループを管理するインスタンスをjsのグローバルオブジェクトにセットしておくのが簡単そう。
* goja
Goで実装されたJavaScriptエンジンのgojaがいつのまにか比較的モダンなJSを実行できるようになっていた。
https://github.com/dop251/goja
README の最初に ECMAScript 5.1(+) とか書かれているけど、実施はES2017あたりまでサポートされていそう?(モジュールは無い)
async/awaitとかも実装されている。goja自体にevent loopが無いのでそのままだと非同期処理を実行できないけど、 https://github.com/dop251/goja_nodejs にeventloopパッケージがある。
ただ、nodejs互換の環境を作る用途で実装されてるようなので、NewEventLoop()内で色々追加されてしまったり、RunしないとRuntimeオブジェクトを取れないのと、Go側で作ったPromiseとかは自分で管理しないといけないのが不便。最終的には自前で実装したほうが無難かもしれない。
package main
import (
"github.com/dop251/goja"
"github.com/dop251/goja_nodejs/eventloop"
)
const SCRIPT = `
class AsyncTest {
async run() {
for (let i = 0; i < 10; i++) {
await new Promise((r) => setTimeout(r, 200));
console.log(i);
}
}
}
(new AsyncTest()).run();
`
func main() {
loop := eventloop.NewEventLoop()
loop.Run(func(vm *goja.Runtime) {
_, err := vm.RunString(SCRIPT)
if err != nil {
panic(err)
}
})
}
今までquickjsのbindingを使うのが無難だと思ってたけど、CGOが必要になってしまうのと、パフォーマンスが微妙だった。gojaはGoの上で動作しているのでシンプルな実装のわりに実行速度が速そう。