JavaScript
関数コールの追跡
@kobayan_tokyo
自己紹介
@kobayan_tokyo (またはkobake)
http://blog.clock-up.jp/
・元ゲーム屋(10年)
・現フリーランスWeb屋(1年)
・C++, C#, Java, PHP, Ruby, JavaScript, CoffeeScript
・Ruby on Rails, CakePHP, .NET Framework
・Web, Windows, Android
・Visual Studio, IntelliJ IDEA, Brackets
JavaScriptの関数コールを追跡したい
人様の作ったサイトをハック解析したい
↓
とりあえず関数コールの流れをザックリ見たい
手がかり1:ブレークポイント
・あたりをつけて「適当な場所にブレークポイントを付ける」
・目的の関数が呼ばれたタイミングは分かる
・いちいち「これが呼ばれるだろう」というあたりを付けなければならない
・ブレークポイントに達する度にいちいち処理が止まって鬱陶しい
(我々は何か特定の問題を解決したいのではなく、構造の解析を行いたいのだ)
手がかり2:関数のラップ
・あたりをつけて「適当な関数をラップする」
・目的の関数が呼ばれたタイミングは分かる
・いちいち「これが呼ばれるだろう」というあたりを付けなければならない
・ブレークポイントに達する度にいちいち処理が止まって鬱陶しい
・いまだに「あたりを付ける」必要はある
-------------------------------------------------
org_hoge = hoge;
hoge = function(){
console.log("---- hoge called ----");
org_hoge();
}
-------------------------------------------------
手がかり3:Function.prototype.call
http://stackoverflow.com/questions/4921966/live-javascript-debugging-by-recording-function-calls-and-
parameters
--------------------------------------------------------------------------------------------------------------------------
Can you override Function.prototype.call and retrieve arguments and arguments.callee?
--------------------------------------------------------------------------------------------------------------------------
な・・る・・ほ・・ど・・??
- Function.prototype.call … すべての関数の呼び出し
- arguments.callee … 関数内で参照できる関数そのもの
それはつまり、
関数すべてのコールを書き換えるという暴力的な働きかけ
Function.prototype.call書き換え
http://stackoverflow.com/questions/5226550/can-i-override-the-javascript-function-object-to-log-all-
function-calls
---------------------------------------------------------------------
var origCall = Function.prototype.call;
Function.prototype.call = function (thisArg) {
console.log("calling a function");
var args = Array.prototype.slice.call(arguments, 1);
origCall.apply(thisArg, args);
};
---------------------------------------------------------------------
想像には及びませんがこれは console.log 諸々自体の呼び出しにより 無限ループに。
書き換える範囲を絞る
http://stackoverflow.com/questions/5033836/adding-console-log-to-every-function-automatically
-------------------------------------------------------------------------------
function augment(withFn) {
var name, fn;
for (name in window) {
fn = window[name];
if (typeof fn === 'function') {
window[name] = (function(name, fn) {
var args = arguments;
return function() {
withFn.apply(this, args);
return fn.apply(this, arguments);
}
})(name, fn);
}
}
}
augment(function(name, fn) {
console.log("-------- calling " + name + " --------");
});
-------------------------------------------------------------------------------
window配下の関数(?)のみラップする
やってみよう
ログ多すぎ!
もう少し絞る
if (typeof fn === 'function') {
if(name == 'setTimeout') continue;
if(name == 'clearTimeout') continue;
window[name] = (function(name, fn) {
var args = arguments;
return function() {
withFn.apply(this, args);
return fn.apply(this, arguments);
}
})(name, fn);
}
絞った結果
少しログ量が減った(それでも多いけど)
さらなる一歩
・グローバル関数(?)以外の関数も監視したい
・コールスタックなんかも表示したい
・行番号やファイル名なんかも出したいよね
(無名関数とかもあるし、これが無いとなんとも)
(準備時間オーバーしました)
(引き続き情報まとめ&調査していきます)
近況
・Chromeビルド環境構築中(ディスク足りなくなり
そうなので出直し中)

Java script関数コールの追跡