weinreっていう、iPhoneやらAndroidやらの実機(別に実機じゃなくてもいいんだけど)で見ているWeb画面のJavaScriptをリモートdebugできるツールがあって、これは割と有名。
http://alpha.mixi.co.jp/blog/?p=3248
有名なんだけど、試してみると普通にブレークポイント貼ってブレークするとか、debugger;って書いてブレークするとか、そういういわゆるデバッガ的な操作がどうやら出来ないっぽい。(ひょっとしたら出来るのかもしれない、知ってたら誰か教えて下さい)
Web InspectorっぽいUIからHTMLをリアルタイム編集できたり、Consoleからいわゆるevalが出来るのはとってもステキなんだけど、「デバッグできます!」と謳っているのにブレークポイント貼ってブレークできないのは、なんか惜しい感じである。
で、今日か昨日にTwitterで見たNode.js製のAardwolfとかいうカッコええ名前の何かを試してみた。
http://lexandera.com/aardwolf/
サイトを見ると、どうやらweinreと同じような路線でかつブレークポイント貼れるっぽい。
で、試してみたら、確かにiPhoneエミュレータでもブレークできた!
ウェーイ
とか言ってる場合じゃなくて、AardWolfがどうやって外側からブレークポイントを実現しているのか気になったので調べた。
結論から言うとサーバサイドでクライアントに渡す前にJSのコード書き換えてる。
例えば、以下のような"/homura.js"というパスで読み込まれるJSがあったとする。
var a = 1; var b = 2; var c = 3;
Aardwolfは以下のように書き換えてからクライアントにそれを渡す(実際はこれに加えてtryとか入るのでちょっと違う)
Aardwolf.updatePosition("/homura.js", 1, false, aardwolfEvalFunc); var a = 1; Aardwolf.updatePosition("/homura.js", 2, false, aardwolfEvalFunc); var a = 2; Aardwolf.updatePosition("/homura.js", 3, false, aardwolfEvalFunc); var a = 3;
Aardwolf.updatePositionの中身は以下
this.updatePosition = function(file, line, isDebuggerStatement, evalScopeFunc) { /* Webkit's exceptions don't contain any useful file and line data, so we keep track of this manually for exception reporting purposes. */ lastFile = file; lastLine = line; while (true) { var shouldBreak = (breakpoints[file] && breakpoints[file][line]) || isDebuggerStatement || breakOnNext; if (!shouldBreak) { return; } dropCommandConnection(); var cmd = sendToServer('/breakpoint', { command: 'report-breakpoint', file: file, line: line, stack: getStack().slice(1) }); listenToServer(); if (!cmd) { return; } if (cmd.command == 'eval') { doEval(evalScopeFunc, cmd); } else { var isInternalCommand = processCommand(cmd); if (!isInternalCommand) { return; } } } };
…お分かりだろうか。ブレークの実体はwhile無限ループだったのだあ!じゃじゃん!
もうちょっとちゃんと説明すると、updatePositionはコールされて「ブレークすべし」というフラグがどれか立っていればwhileを使った「サーバからのコマンド待ちループ」に入る。サーバから来るコマンドを見て、次のブレーク条件をonにしたり(break on next)、returnでwhileループを抜けたり(continue)、といった風に動作を変える。
タネが分かると「なんだそうかあ」ってなるけど、その発想はあまりなかった。
Aardwolfは、ソース書き換えを行う都合上すべてのJSファイルをAardwolf経由でserveする必要がある。これはこれで仕方ないけどちょっと面倒か。あとデバッガ部分がオレオレWeb UIなので、やっぱり慣れてるWeb Inspector or FirebugなUIだったらいいのになー、とか。
Web Inspector UIなAardwolfがあればいいのになー、とかとか。
オチはありません。