JSXをPhantomJSで動かしてみる
遅くなりましたが、AltJS Advent Calendarの7日目です。
PhantomJSというのは、コマンドラインで使えるJavaScript実行環境です。Mac+Homebrewだと brew install phantomjs
でインストールできます。
さて、まずは以下のようなJavaScript source codeを用意してみましょう。通常のJavaScriptと違うのは、 phantom.exit()
を実行しないとスクリプトが終了しないことです。
// hello-phantom.js console.log("Hello, world!"); phantom.exit();
実行するにはphantomjs(1)にファイル名を与えて起動するだけです。
$ phantomjs hello-phatntom.js Hello, world!
これだけみると単なるJavaScript実行環境に見えますが、PhantomJSはWebKit frameworkを使ってGUIなしにHTML+JavaScriptからなるウェブアプリケーションを実行できるというものなのです。実用的な観点から見ると、HTML5ウェブアプリケーションの自動テストやスクレイピング、開発ツールの提供などに使うことができます。
さて、PhantomJSはJavaScript実行環境、ということはJSXもPhantomJSで動かすことができるはず!そこでPhantomJSのJSXバインディング、PhantomJSXを作ってみました。
PhantomJSXをcloneしたら、make hello
で簡単なデモを見ることができます。
phantomjsx$ make hello jsx --executable web --output example/hello.jsx.js example/hello.jsx JSX_RUNJS=phantomjs jsx --executable commonjs --run example/phantom-hello.jsx Hello, PhantomJSX! system.version: {"major":1,"minor":7,"patch":0} system.os: {"architecture":"32bit","name":"mac","version":"10.8 (Mountain Lion)"} console: start hello.jsx open hello.html
最初の一行は、実行しようとするWebApp用JSXコードのコンパイルで、二行目がPhantomJSX用コードのコンパイルと実行です。三行以降が出力結果です。実行されるコードは以下のようになっています。
// `make hello` to run (see Makefile for details) // // `example/hello.jsx(.js)` and `example/hello.html` is a web application, // and example/phantom-hello.jsx (this file) is a PhantomJSX driver // which controls the web application. // import "js/web.jsx"; import "../lib/phantom.jsx"; class _Main { static function main(args : string[]) : void { log "Hello, PhantomJSX!"; log "system.version: " + JSON.stringify(phantom.version); log "system.os: " + JSON.stringify(system.os); var page = webpage.create(); page.onConsoleMessage = function(msg, line, id) { log "console: ", msg; }; page.open("example/hello.html", function(status) { log "open hello.html"; phantom.exit(); }); } } // vim: set tabstop=2 shiftwidth=2 expandtab:
このコードは、hello.html
をWebPageとして実行し、そのWebPageの中でJavaScriptアプリケーションがconsole.log()で出力するものを page.onConsoleMessage
でフックする、というものです。これで phantom.exit()
が必須な理由もお分かりいただけたでしょう。WebPageはスクリプトコードを実行し終えた後も存在し続けている(イベントループが生きている)ので、どこかで無理やり終了させなければならないからですね。
なお、フックできるイベントは、コンソール出力の他にも alert()
などのモーダルダイアログやページのロード開始・終了などがあります。詳しいことはPhantomJSのAPI referenceをどうぞ。面白いことに、fsモジュールでファイルシステムにアクセスしたり、webserverモジュールでhttpdになったりすることもできます。これを利用すれば、テキストエディタに対してブラウザのデバッグコンソールと等価なREPLを提供することもできそうです。
さてPhantomJSのAPIを呼び出せるようにはなりました。今後はJSX本体のweb interface (web compilerなど) にテストがなくしばしば壊れがちなので、JSX本体に組み込んでしまおうと計画中です。