80.4 LuneScript の WebAssembly 対応
LuneScript で作成したコードを Web ブラウザ上で動作させる方法には、 次の 2 つあります。
- LuneScript から Lua にトランスコンパイルし、その Lua コードを fengari 等で動かす
- LuneScript から go にトランスコンパイルし、その go コードを WebAssemly に変換する
ここでは、 go から WebAssemly に変換する方法について説明します。
go から Web Assemly への変換
go から WebAssemly への変換は、 go の機能を利用します。
go で WebAssembly を利用する方法の基本的な流れは、 次のオフィシャルドキュメントを参照してください。
<https://github.com/golang/go/wiki/WebAssembly>
ここでは、 LuneScript 特有の話をします。
Lua のランタイムは gopherlua を利用する
LuneScript のコードを go のアプリに変換するには、 Lua のランタイムが必要になります。
LuneScript は、Lua のランタイムとして次の 2 つをサポートしています。
- オフィシャルな Lua ランタイム
- gopherlua
ここで、「オフィシャルな Lua ランタイム」は WebAssembly では利用できないため、 gopherlua を利用することになります。
よって、 go から WebAssembly に変換する場合のコマンドは以下のように
-tags gopherlua
を指定することになります。
$ GOOS=js GOARCH=wasm go build -tags gopherlua -o main.wasm
JavaScript と LuneScript 間の連携動作
JavaScript と LuneScript 間の連携動作は、main() が実行されている間可能です。
逆に言えば、 JavaScript から非同期に LuneScript と連携動作させるには、 LuneScript の処理を終わらさずに待たせる必要があります。
この待ち処理を実現するには、次の 2 つの方法があります。
- go 外部モジュールで処理する
- __AsyncItem を利用する
以下で説明します。
go 外部モジュールで処理する
- go の channel を生成して、その channel からデータの読み出しを行なう。
- この処理を go の外部モジュールとして定義し、 LuneScript の module 宣言等で、 そのモジュールを実行する。
__AsyncItem を利用する
- LuneScript の __AsyncItem インタフェースを利用し、 pipe を作成し、その pipe からデータ読み出しを行なう。
- __AsyncItem のインタフェースを extend した独自のクラスを定義し、 そのクラスから pipe を作成する。
- この pipe の put, get メソッドを利用する。
- 次のサンプルの loop() が待ち処理で、 notify() が pipe へのデータ書き込み処理です。
- この notify() を利用することで、JavaScript から非同期のメッセージを受信できます。
// @lnsFront: ok
pub class AsyncItem extend (__AsyncItem,Mapping) {
let val:str {pub};
}
let queue = __lns.Sync._createPipe( AsyncItem, 0 );
fn loop() {
when! queue {
while true {
let! item = queue.get() {
break;
};
print( item.$val );
}
}
}
pub fn notify( val:str ) {
when! queue {
queue.put( new AsyncItem( val ) );
}
}
LuneScript 内の非同期処理
現状の WebAssembly では、 LuneScript 内の非同期処理は次が指定された時と同じ動きになります。
GOMAXPROCS=1
つまり、いずれかの処理が動作している間は、他の処理は動きません。
__asyncLock や pipe の待ちなどのタイミングで処理が切り替わります。
__asyncLock や pipe 以外で、いずれかの処理がブロックすると、 そのブロックを抜けるまでは全体の処理が止まります。
tinygo
go から WebAssembly に変換する方法には、 オフィシャルな go を使う方法と、tinygo を使う方法があります。
tinygo を利用した方が、 WebAssembly のサイズや JavaScript との連携が簡単になるようです。
しかし、現時点で最新の tinygo v0.22.0 では LuneScript で利用するパッケージの対応がされていないため、 tinygo を利用できません。
以上。