イディオムを安全に短縮記法に変換する Javascript プリプロセッサ

Firefox のアドオン開発をしていると、Component.classes などのよく使う言い回しは、Cc といった短縮記法で表現することが多くなります。例えば、OS を検出するコード

(function () {
  return Component.classes["@mozilla.org/xre/app-info;1"].getService(Component.interfaces.nsIXULRuntime).OS;
})() #=> "Darwin"

は、短縮記法を用いると、

(function () {
  return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
}() #=> "Darwin"

という風にすっきり表現できます。ただ、これをやるためにグローバルな名前空間を汚染してしまうのは、名前空間を共有している他の拡張機能と競合するリスクがあるので、多くの開発者の方は、関数毎に泣く泣く

(function () {
  var Cc = Component.Classes;
  var Ci = Component.interfaces;
  return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
})() #=> "Darwin"

といった記述をしているのではないかと思います。今回ご説明するのは、Javascript で一度関数のソースコードを変換することによって、より安全に短縮記法を利用するための方法です。

var preprocessor = {
    build : function (func) {
        var code = func.toString();
        for (key in this.idioms) {
            code = code.replace(new RegExp("\\$"+key+"(\W*?)"),this.idioms[key]+"$1");
        }
        return eval("("+code+")");
    },

    idioms : {
        // 変換リスト
        "Cc" : "Components.classes",
        "Ci" : "Components.interfaces",
        "" : "document.getElementById"
    }
}

このソースコードをインクルードすると、次のような書き方が可能になります。

preprocessor.build(function () {
  return $Cc["@mozilla.org/xre/app-info;1"].getService($Ci.nsIXULRuntime).OS;
})() #=> "Darwin"

いかがでしょうか。ちなみに $ を先頭に付けているのは、短縮記法であることを明記し、ソースコードの可読性を向上させるためです。