JSXでコンパイルしたJavascriptをmongo shellで動かしてみるテスト

確実にメリットは全くないんですが何を血迷ったか、JSX でコンパイルした javascript を mongo shell に食わせて実行してみようかとふと思いついたのでやってみました。mongo shell は SpiderMonkey を使っているので、javascript が普通に動きますとのことなので、まずは試してみました。

$ mongo
> console.log("hello")
Tue Feb 12 02:20:25 ReferenceError: console is not defined (shell):1

動きませんでした。。。print()関数しかないそうなので、とりあえずこういう逃げ。

> var console = { log : function (args) { print(args); } };
> console.log("hello")
hello

さて、JSX 側でコンパイルした際にも、これをグローバルに定義してあげないとconsole.log()がエラーになります。あと、--executableで実行形式で出力したときにコマンドライン引数を処理してくれるんですが、どうも mongo shell はコマンドライン引数を普通に受け取る手段がなさそうなので、ここもこけます。というわけで、fork して branch 作りました。あとついでに shebang も変えてみた。

mongo shell の中で使えるオブジェクト(用語合ってない気がします)とかを JSX から扱うには一工夫必要らしいです。ちょっとここで時間切れになったので、とりあえずrsというレプリカセットを扱うオブジェクトに触ってみました。

import "js.jsx";

native final __fake__ class ReplicaSet {
    function status() : Message;
}

class Message {
    var errmsg : string;
}

class _Main {
    static function main (args : string[]) : void {
        var rs = js.global["rs"] as __noconvert__ ReplicaSet;
        log rs.status().errmsg;
    }
}

ソースはこちら。これをコンパイルして実行。

$ ./bin/jsx --executable mongo --output mongo.js example/mongo.jsx
$ chmod +x ./mongo.js
$ ./mongo.js
MongoDB shell version: 2.2.2
connecting to: test
not running with --replSet

とりあえず触れた様です。ちなみに普通に mongo shell で触るとこんな感じ。なのでちゃんとerrmsgが取れてるみたいです。

> rs.status()
{ "errmsg" : "not running with --replSet", "ok" : 0 }

まとめ

json 形式で帰ってきたり、メソッドミッシング的な感じで collection に触れたりする、mongo shell のいいところが 全て 潰されているので実用性はゼロですが、まぁお勉強ということで。

ちなみに JSX 触ったのは今回が初めて(というか javascript すらほとんどやってない><)でしたが、先の対応のために JSX コンパイラ自体をちょっと読むことになりました。実は先日 JSX はセルフホスティングになったのでこれがなんと JSX で書かれてるんですね!なのでコンパイラを読むだけで勉強できて素晴らしかったです。

最近 Java を触り始めたので、割とすんなり JSX に入っていけました。javascript はカオスすぎて僕には手に追えません!

Enjoy!