ScalaJSからpure javascriptなライブラリを呼び出す(あるいはmsgpackのjs実装のバグを見つけたかもしれない話)

少し前にこんなのを書きましたが

ScalaJSを使ってブラウザ上のみでJSONからMessagePackに変換するやつを作った


「msgpackって当然pureなjavascript実装もあるよね?」

scala-jsから当然javascript呼べるよね?」(逆にjsからscala-js呼ぶでもいいけど)

「つまりscala-js版のscodec-msgpackでシリアライズして他のjsのライブラリでデシリアライズ、またはその逆、などができるはずだよね?そして両方の実装が正しいなら、それをやっても必ず元に戻るはずだよね?」



と、思いつきやってみたという記録です。

なお、執筆時点のscala-js 0.6.5時点の記録なので、そのうち古くなるかもしれません。



まずmsgpackというよりscalajsやsbtの話


scala-jsから外部のjavascriptファイル呼び出しするためのsbtの設定

に関しては、公式に書いてあるので、それを読もう

http://www.scala-js.org/doc/project/dependencies.html

webjarなどで管理されてるものなら、1行jsDependenciesというkeyに追加でいけるらしい。
今回はそうではなく、とりあえず単一のjsファイルを半手動ダウンロードして追加したかったので、別の方法。

sbt上でのリソースのディレクトリに追加後、以下のように書くらしい。

jsDependencies += ProvidedJS / "myJSLibrary.js"

sbt上でのリソースディレクトリは、src/main/resourcesでもresourceManagedのKeyによる自動生成用ディレクトリでもどちらでもいいらしいので、手動で置く方ではなく、自動生成用を使った。

あと、これが一番ハマったのだが、なぜか

commonJSName "msgpack"

みたいに書かないといけなかった(詳細は面倒になって理解してない)。詳細知りたい人は、以下のstack overflowの回答と、そこからのscala-jsの該当issueやpull req見ましょう

http://stackoverflow.com/a/31954152

scala-js側からの呼び出し

基本的な情報は公式サイトまとまってるし、今回は大体これで十分だった

http://www.scala-js.org/doc/interoperability/types.html

ちゃんとjs.Objectというものを継承したやつを作るなど、いくつか方法があるが、今回はべつにそこは丁寧に頑張りたくないため*1、雑にキャストしたりした

結論としては、以下のjsのpackという関数を呼び出すためのscala-jsのコードがこんな感じ

https://github.com/msgpack/msgpack-javascript/blob/2cfda99e28b5b7599427300a88a11cfb71ec9eba/msgpack.codec.js#L9

js.Dynamic.global.msgpack.msgpack.pack(i.asInstanceOf[js.Any]).asInstanceOf[js.Array[Int]]

さて、ここからがmsgpackな話



まずは公式のmsgpack organizationにある
https://github.com/msgpack/msgpack-javascript *2
について試したのですが、失敗します。*3
https://github.com/xuwei-k/scodec-msgpack/commit/2d6c93bf806a52fad6cc8351c
大雑把には

  • msgpack-javascriptがバグってる?
  • scodec-msgpackがバグってる?
  • どちらもバグってないけど、テストの書き方が悪い?

のどれかだと思うのですが、詳細把握できてません。ただ、
「msgpack-javascriptシリアライズして、msgpack-javascriptでデシリアライズ」をしても元に戻らないケースがある?ので、msgpack-javascript自体のバグの可能性が高いのでは?という気がしています。
バグってませんでした


さて、msgpack-liteという、べつのjs実装も試しました

最初、jvmというかそれを受け継いたscala-jsのByteのセマンティクスの違い*4に悩まされた(結局0xffとの論理積をとってunsignedとして扱うコード入れないといけない?)
けど、その0xffとの論理積さえ入れればうまくいったので、いよいよmsgpack-javascriptがダメな可能性が高まった気がします・・・。 バグってませんでした



ここまでやって、若干飽きたので、誰かこの続き調査してください(ぇ


あと色々補足情報としては

といったところでしょうか


追記:

続編書いたのでこちらを参照

*1:ライブラリ作るわけではないので

*2: id:uupaa さん作かな http://d.hatena.ne.jp/uupaa/20101206

*3:具体例としてはscala.Int.MinValueの場合?

*4:という言い方で正しいのかすら謎ですが