作った → https://github.com/shokai/iphone-js-console

iPhone用のJavaScript shellのようなもの。FirebugやChromeの開発パネルみたいな感じで使う。

chrome拡張やiPhoneシミュレータでiPhone用のwebページの動作は確認できるが、加速度センサやGeo Location APIなんかは実機で動かさないとデバッグできない。
しかしデバッグをしようにも、iPhone上で大量のalertを出すと気が狂ってしまう。iPhoneで実行中のwebページ上の任意のオブジェクトの中身を、Macから覗いたり値を書き換えたり関数を実行したりするツールが必要だったので作った。

なお、Androidのブラウザにはwebsocketが無いのでこのツールは動かない。Androidではlogcatで

adb logcat | grep "^./browser" --color=auto
すればconsole.log、console.errorの出力は見れるので、それで何とか我慢している。



■セットアップ
MacとiPhoneを用意する。MacとiPhoneは同じ無線LANの下に接続して、互いに通信できるようにしておく。

github.com/shokai/iphone-js-consoleからcloneしてくる。

iphone-js-console.jsをhtmlに読み込ませる。JsConsole.startで自分のMacに接続させるようにする。
<script src='iphone-js-console.js' type='text/javascript' />
<script type='text/javascript'>
JsConsole.start('ws://192.168.1.38:8088'); // Addr of Console Server
</script>
(あらかじめconsoleを起動するMacのIPアドレスは調べておこう)


Macで、iphone-js-consoleを起動する
./iphone-js-console

iphone-js-consoleの起動時に、rubygemsが足りないという警告がでたら足りないgemをインストールする。
gem install eventmachine em-websocket
多分これで足りる。
あとreadlineを使っているけど、Macの最初から入っているreadlineは腐ってた気がするので、brewかportsで入れるといい。(わからなかったら飛ばしても多分良い)



■使う
Macのiphone-js-consoleで
alert(document.title)
と打つと、


このようにiPhoneのSafari上でJavaScriptが実行される。


また、iPhoneのSafariの変数を参照することもできる。
> window.navigator.appVersion
<1> "5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"


中身が複雑なオブジェクトは整形されて表示される。
> location
<1>
{"href"=>"http://192.168.1.38:8080/debug-sample.html",
"hash"=>"",
"port"=>"8080",
"protocol"=>"http:",
"origin"=>"http://192.168.1.38:8080",
"pathname"=>"/debug-sample.html",
"hostname"=>"192.168.1.38",
"host"=>"192.168.1.38:8080",
"search"=>""}


もちろん、エラーも出力される。
> homu
<1> "error : Can't find variable: homu"
> 1+2
<1> 3
> 1+
<1> "error : Parse error"


iPhoneのJSで、あらかじめ
console.log(foo);
とか書いておけばもちろんMacのiphone-js-consoleにfooの値が表示される。


一度入力したコマンドは、キーボード上下で履歴を呼び出したりできる。
大変便利ですね。




■技術的なこと
iPhoneとiphone-js-consoleの接続にはWebSocketを使っている。EventMachine::WebSocketが便利だった。

iphone-js-consoleからiphoneへ送信された文字列は、そのままiPhone上でevalで実行させている。
iphoneからiphone-js-consoleへのオブジェクトの送信は、iPhone上でJSON.stringifyでシリアライズして送信して、iphone-js-consoleでparseして適当に整形して表示している。

別に難しいことはしていない。