Shibuya.es、じゃなかった、
Shibuya.es #3 行ってきました。
デブサミでの Shibuya.* はやっぱり場所柄からか少々おしとやかやってんなあ……
どの話もおもしろかったんですが、nazoking さんの "WiiでSAGOOL" が個人的にプチツボだったので、ちょっぴり検証してみました。
一般化すると「元のソースをできるだけ汚染しないで、関数にエラー処理を追加する」ということですから、いわゆるアスペクト指向うんぬんが得意としている領域ですよね。
確か nazoking さんの方法は(以下、記憶で書いているので間違ってたらすいません)、エラー処理を行うラッパーを用意し、関数呼び出しをそのラッパー経由で行うよう、呼び出し側を自動的に書き換えるというもの。
これにより外部参照しているスクリプトについては書き換えることなくエラー処理が追加される。一方 html 内に記述されているスクリプト、特に onClick などのイベントに直書きされているものについては手動で書き換える必要あり。
この「直書きされていると書き換える必要あり」をなんとかしたいかも。
定義されている関数全てに自動的にエラー処理を追加する方法はちと思いつかなかったんですが、関数名を指定して狙い打ちならなんとかなりそう。
<html><head>
<script type='text/javascript'><!--
function push_button(message) {
alert(message);
aaa();
}
function Test(){}
Test.prototype.push_button2 = function(message){
alert(message);
bbb();
}
var test = new Test();
--></script>
</head><body>
<input type='button' value='おして' onClick='javascript:push_button("クリックしました");' />
<input type='button' value='おして2' onClick='javascript:test.push_button2("クリックしました2");' />
</body></html>
こんな html を書いて「おして」や「おして2」をクリックしても単純にエラーになりますが、</head> の前に下記を追加すると、エラーがダイアログで表示されるようになりました。ばんざい。
<script type='text/javascript'><!--
// 指定された関数にエラー処理を追加する。
// オブジェクトに定義されている関数の場合は、2つめの引数にオブジェクトを指定
insertLogger = function(funcname) {
if (arguments.length>1) {
// オブジェクトの指定がある場合
obj=arguments[1];
obj["__"+funcname] = obj[funcname];
obj[funcname] = function(){ try{ obj["__"+funcname].apply(obj, arguments); }catch(ex){alert(ex);} };
} else {
// オブジェクトの指定がない場合
eval( "__"+funcname+"="+funcname+";" );
eval( funcname +"=function(){ try{ __"+funcname+".apply(window, arguments); }catch(ex){alert(ex);} };" );
}
}
// エラー処理を追加する関数を指定
insertLogger("push_button");
insertLogger("push_button2", test);
--></script>
alert(ex); のところを、エラー内容をサーバに GET で送り込みつつ、throw するようにすれば、nazoking さんの発表内容に近づくかな。
プレフィックスが "__" でいいのかとか、なんか勝手に bind されちゃうんですけどもーとか、ツッコミどころは……
まあ、"javascript aop" とか "javascript アスペクト" あたりでぐぐってみれば、より一般的にあれこれ挑戦してみた方の情報が出てくるから、そっちでいいかなあ、などと(苦笑)。