イントロダクション
JavaScriptで記載したソースコードの圧縮・最適化のために、Google Closure Compilerを使用しています。今回は、Google Closure Compiler でコンパイルする前のソースコードでは正常に動作していたものが、コンパイル後のソースコードでは、実行途中でエラーが出てしまった事例を紹介します。
コード
コンパイルに使用したコードを一部抜粋します。function generateReferenceLink() {
/* --- 省略 --- */
if (currentMode == "single") {
/* --- 省略 --- */
} else {
/* --- 省略 --- */
genFromUri(uri_list[list_count], genNext);
function genNext() {
// 全ての生成が終わるまで繰り返し実行
list_count++;
if (uri_list.length > list_count) {
genFromUri(uri_list[list_count], genNext);
} else {
finish();
}
}
}
/* --- 省略 --- */
}
コンパイル方法
コンパイルは以下のコマンドにて、コンパイルしました。java -jar C:\tool\compiler-latest\compiler.jar --charset utf8 --js main.js --js_output_file main_compiled.js
実行結果
以下のように、TypeError が発生してしまいました。
順序を変えたコード
コンパイル後のソースコードの場合、圧縮・最適化によって難読化されているため、原因箇所を突き止めるのは容易なことではありません。
しかしながら、今回はいろいろな動作を外部から与えることで、原因となっているであろう箇所を上記の抜粋したソースコードの箇所であることを突き止めることが出来ました。
上記エラーを踏まえて、Closure Compiler の最適化に起因するだろうという推測の元、ソースコードの順番を入れ替えて、再度コンパイルしてみることにしました。
以下の赤いテキスト背景色の部分のコードと、青いテキスト背景色の部分のコードの順番を入れ替えました。
/* --- 省略 --- */
if (currentMode == "single") {
/* --- 省略 --- */
} else {
/* --- 省略 --- */
function genNext() {
// 全ての生成が終わるまで繰り返し実行
list_count++;
if (uri_list.length > list_count) {
genFromUri(uri_list[list_count], genNext);
} else {
finish();
}
}
genFromUri(uri_list[list_count], genNext);
}
/* --- 省略 --- */
}
その結果、今度は実行途中にエラーが出ることなく実行できました。
何が違うのか?
Google Closure Compiler でコンパイルした結果の diff をとり、異なる部分を抜き出しました。エラーあり:h=0;a(k[h],l);var l=function(){h++;k.length>h?a(k[h],l):f()}}}
エラーなし:h=0,l=function(){h++;k.length>h?a(k[h],l):f()};a(k[h],l)}}
コメントを投稿
コメント投稿機能について