Hatena::Diary

IT-Walker on hatena このページをアンテナに追加 RSSフィード

2008-09-04 Google Chromeについてあれこれ。

Google Chrome JavaScriptデバッガ完全マニュアル。

Google Chromeはシンプルに見えてオフラインやWebアプリショートカット作成などいろんな機能が搭載されています。

そんな中、JavaScriptデバッガがあるのも発見!

どんなもんかと思ってみてみたら、なんとコマンドラインベースのデバッガです。Firebugみたいな物を想定していたのですが、まさかgdbGNUC/C++デバッガ)みたいなのがブラウザに載ってるなんて・・・しかも全然情報ないし。


でも開発者にとっては、JavaScriptランタイムデバッグできると言うのは非常に嬉しい事ですね。そこで、Chromeデバッガの使用法についてちょっと調べてみました。


デバッガは、開発者向けメニューの中から選択する事が出来ます。立ち上げてみると、コマンドの表示結果が表示されるエリアと、コマンドを入力するテキストフィールドが並んでいるだけ、と言うシンプルなUIが表示されます。

f:id:Syunpei:20080904125502p:image

最下部のテキストフィールドにコマンドを入力して、デバッグを行う訳ですね。

例えば、「関数x()にブレークポイントを仕掛けたい」と言う場合は「break x」などと入力します。その後、1行ずつステップ実行したい場合は「next」、現在行の関数にステップインしたい場合は「step」、変数や式の値を表示させたい場合は「print」などと入力します。


こうしたデバッグコマンドを全部一覧にしたのが下のリストです。helpコマンドでは出てこないものもあるので、現時点では結構貴重なリソースかも知れません(Chromeのソースを参照しました)。

  • args・・・現在の関数における全引数の情報を表示
  • break [location] <condition>・・・ブレークポイントを設定する。locationは「関数の名前」「スクリプト:関数名」「スクリプト:行番号」「スクリプト:行番号:行中の位置」のいずれか。conditionには条件式を指定し、真の場合のみブレークする。
  • break_info [ブレークポイント番号]・・・現在のブレークポイントを一覧表示する。もしくは、一つのブレークポイントに関する情報を表示
  • backtrace [from frame #] [to frame #]・・・関数呼び出しのバックトレースを表示
  • clear <breakpoint #>・・・ブレークポイントを解除する
  • continue・・・処理を続行する
  • frame <frame #>・・・関数呼び出しのフレームを表示。(現在の関数が0、呼び出しもとが1...)
  • help [command]・・・ヘルプを表示する
  • locals・・・ローカル変数の情報を表示する
  • next・・・次の行に移動する
  • print <expression>・・・式の値を表示する
  • scripts・・・読み込まれたスクリプト(外部ファイルも含む)の情報を表示する
  • source [from line] | [<from line> <num lines>]・・・ソースを表示する。lineを省略すると、現在デバッグ中の関数を表示
  • step・・・現在行の関数にステップイン
  • stepout・・・現在の関数から戻る

上のコマンドをきっちり入力していくのは、結構骨の折れるタイピング作業になります。そこで、gdbと同じくコマンドの短縮型を用いる事も出来ます。例えば、さっきの「関数x()にブレークポイントを仕掛けたい」と言う場合は「b x」と入力する事も出来る訳です。

エイリアスコマンド
bbreak
bibreak_info
brbreak
btbacktrace
ccontinue
fframe
hhelp
?help
ssource
nnext
pprint
sstep
sostepout

では、これらのコマンドを用いて実際のデバッグを行ってみましょう。練習用に、「ボタンを押されたら、入力された文字列を逆にして表示する」と言うサンプルを用意しました。

f:id:Syunpei:20080904125503p:image

このサンプルのソースです。

<html>
<body>
<script type="text/javascript">
function reverseDisplay() {
	var input = document.getElementById("input").value;
	var out = "";
	for (var i = input.length - 1; i >= 0; i--) {
		out += input.charAt(i);
	}
	output(out);
}
function output(out) {
	document.getElementById("output").textContent = out;
}
</script>
<textarea id="input"></textarea><br/>
<button onclick="reverseDisplay();">押してね</button><br/>
<pre id="output"></pre>
</body>
</html>

では、ボタンが押されたときに関数「reverseDisplay()」で停止し、デバッグして行く様子を見て行きましょう。最初に止めていろいろ情報を見たあと、10行目にもブレークポイントを仕掛けてプログラムを再開し、その行にあるoutput()の呼び出しの中にステップインしています。

JavaScript Debugger
attached to a.html
$ b reverseDisplay      <----------reverseDisplay関数ブレークポイントを設定
set breakpoint #2
$ bt                    <----------バックトレース表示(onclick→reverseDisplayという呼出し履歴がわかる)
Frames #0 to #1 of 2:
#00 reverseDisplay() file:///C:/Documents and Settings/Administrator/デスクトップ/a.html line 5 column 2 (position 31)
#01 #<an HTMLButtonElement>.onclick(evt=#) file:///C:/Documents and Settings/Administrator/デスクトップ/a.html line 17 column 9 (position 143)
$ bi 2                  <----------ブレークポイント2の情報を表示
id=2, hit_count=0, type=function, target=reverseDisplay
paused at breakpoint 2: reverseDisplay(), file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
5:  var input = document.getElementById("input").value;
$ ls                    <----------ソースの表示
 3: 
 4: function reverseDisplay() {
>>>>    var input = document.getElementById("input").value;
 6:     var out = "";
 7:     for (var i = input.length - 1; i >= 0; i--) {
 8:         out += input.charAt(i);
 9:     }
10:     output(out);
11: }
$ n                     <----------1行進む
7:  for (var i = input.length - 1; i >= 0; i--) {
$ p input               <----------変数inputの値を表示
あいうえお
$ b :10                 <----------10行目にもブレークポイント(#3)を設定。
set breakpoint #3
$ bi                    <----------全ブレークポイントの情報を表示
Num breakpoints: 2
id=2, hit_count=1, type=function, target=reverseDisplay
id=3, hit_count=0, type=script, target=file:///C:/Documents and Settings/Administrator/デスクトップ/a.html, line=9
$ c                     <----------処理を続行。10行目まで進む
paused at breakpoint 3: reverseDisplay(), file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
10:     output(out);
$ s                     <----------output関数にステップイン
output(out=おえういあ), file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
13:     document.getElementById("output").textContent = out;
$ args                  <----------関数の引数を表示
out = "おえういあ"
$ frame                 <----------現在のフレームを表示(output関数)
#0 output, file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
13:     document.getElementById("output").textContent = out;
$ frame 1               <----------1つ上のフレームを表示(reverseDisplay関数)
#1 reverseDisplay, file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
10:     output(out);
$ frame 2               <----------2つ上のフレームを表示(onclick関数)
#2 onclick, file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
17:         reverseDisplay();
$ bt 1 2                <----------1〜2上のフレームをバックトレース
Frames #1 to #2 of 3:
#01 reverseDisplay() file:///C:/Documents and Settings/Administrator/デスクトップ/a.html line 10 column 2 (position 175)
#02 #<an HTMLButtonElement>.onclick(evt=#) file:///C:/Documents and Settings/Administrator/デスクトップ/a.html line 17 column 9 (position 143)
$ so                    <----------output関数からステップアウト
reverseDisplay(), file:///C:/Documents and Settings/Administrator/デスクトップ/a.html
11: }
$ locals                <----------ローカル変数を表示
input = "あいうえお"
out = "おえういあ"
i = -1
$ c                     <----------処理続行、終了

Chromeのデバッガもこれで完璧ですね!