Google Closure Compilerを使ってExtendscriptを最適化してみる

先日リリースされたCC-Extension Builder for Bracketがバカみたいに使いやすい代物でこちらでもご紹介させていただきます。
https://github.com/davidderaedt/CC-Extension-Builder-for-Brackets
ありがとう、davidderaedt氏。ついでにforkもさせていただきました。細かい所なのですが、テンプレートにAuthorとDescriptionはさみ込む為だけなんですがね…こうしておくと生成されたディレクトリをそのまんまbuilderでパッケージかけて配布という流れが可能になるものですので。
builder自体は2つの機能を包含したアプリケーションです。一つはアクションスクリプトでコーディングされたmxmlファイルをコンパイルしswfファイルを生成する機能。もう一つが生成されたデータ群をパッケージ処理してサインする機能。これらの機能は個別に働くため、今後HTML5パネルが主流になってもパッケージ処理は利用出来るのです。
まあ、本日はこの事を書きたかったのではありません。GoogleClosureCompilerを使ってみたのでレビューしておこうと言った所なのです。

スクリプターの方々向けで恐縮なのですが、ご覧下さい。

$._ext_ILST={
     applyFractal : function (dp, positive) {
          var dc =app.document;
          var pth = app.activeDocument.selection;
          var clr = new CMYKColor;
          clr.cyan = 0;
          clr.magenta = 0;
          clr.yellow = 0;
          clr.black = 100;
          var pt = new Array();
          var ln;
          for (var j=0;j<pth.length;j++){
          if (pth[j].typename!=”PathItem”) continue;
               pt = [];
               for (var i=0;i<pth[j].pathPoints.length;i++)
                    pt.push(pth[j].pathPoints[i].anchor);
               ln = app.activeDocument.pathItems.add();
               ln.stroke = true;
               ln.strokeColor = clr;
               ln.strokeWidth = 0.3;
               ln.filled =false;
               for (i=0;i<pt.length;i++){
                    if (i==pt.length-1){
                         if(pth[j].closed) $._ext_ILST.fractal(pt[i], pt[0], dp, ln, positive);
                         }else{
                              $._ext_ILST.fractal(pt[i], pt[i+1], dp, ln, positive);
                              }
                    }
               if (pth[j].closed) ln.closed = true;
               }
          return true;
          },
     fractal : function (a, b, dpth, ln, positive){
          var e;
          if (dpth==0) {
               $._ext_ILST.addPoint(b, ln);
               return;
               }
          var c = $._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(a, 2), b), 3);
          var d = $._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(b, 2), a), 3);
          var f = $._ext_ILST.dv($._ext_ILST.ad(a, b), 2);
          var v0 = $._ext_ILST.dv($._ext_ILST.sb(f, a), $._ext_ILST.len(f, a));
          var v1 = [v0[1], -v0[0]];
          if (positive)
               e = $._ext_ILST.sb(f, $._ext_ILST.mlt(v1, Math.sqrt(3) / 6 * $._ext_ILST.len(b, a)));
          else
               e = $._ext_ILST.ad(f,$. _ext_ILST.mlt(v1, Math.sqrt(3) / 6 * $._ext_ILST.len(b, a)));
          $._ext_ILST.fractal(a, c, dpth-1, ln);
          $._ext_ILST.fractal(c, e, dpth-1, ln);
          $._ext_ILST.fractal(e, d, dpth-1, ln);
          $._ext_ILST.fractal(d, b, dpth-1, ln);
          },
     mlt : function (v, n){
          return [v[0]*n, v[1]*n];
          },
     dv : function (v, n){
          return [v[0]/n, v[1]/n];
          },
     ad : function (a, b){
          return [a[0]+b[0], a[1]+b[1]];
          },
     sb : function (a, b){
          return [a[0]-b[0], a[1]-b[1]];
          },
     len: function (a, b){
          return Math.sqrt(Math.pow(a[0] – b[0], 2)
                    + Math.pow(a[1] – b[1], 2));
          },
     addPoint : function (p, ln){
          var pts = ln.pathPoints.add();
          pts.anchor = p;
          pts.leftDirection = pts.anchor;
          pts.rightDirection = pts.anchor;
          }
     };
<pth.length;j++){ if="" (pth[j].typename!="PathItem" )="" continue;="" pt="[];" for="" (var="" i="0;i<pth[j].pathPoints.length;i++)" pt.push(pth[j].pathpoints[i].anchor);="" ln="app.activeDocument.pathItems.add();" ln.stroke="true;" ln.strokecolor="clr;" ln.strokewidth="0.3;" ln.filled="false;" (i="0;i<pt.length;i++){" if(pth[j].closed)="" $._ext_ilst.fractal(pt[i],="" pt[0],="" dp,="" ln,="" positive);="" }else{="" pt[i+1],="" }="" (pth[j].closed)="" ln.closed="true;" return="" true;="" },="" fractal="" :="" function="" (a,="" b,="" dpth,="" positive){="" var="" e;="" (dpth="=0)" {="" $._ext_ilst.addpoint(b,="" ln);="" return;="" c="$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(a," 2),="" b),="" 3);="" d="$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(b," a),="" f="$._ext_ILST.dv($._ext_ILST.ad(a," 2);="" v0="$._ext_ILST.dv($._ext_ILST.sb(f," $._ext_ilst.len(f,="" a));="" v1="[v0[1]," -v0[0]];="" (positive)="" e="$._ext_ILST.sb(f," $._ext_ilst.mlt(v1,="" math.sqrt(3)="" 6="" *="" $._ext_ilst.len(b,="" a)));="" else="" _ext_ilst.mlt(v1,="" $._ext_ilst.fractal(a,="" c,="" dpth-1,="" $._ext_ilst.fractal(c,="" e,="" $._ext_ilst.fractal(e,="" d,="" $._ext_ilst.fractal(d,="" mlt="" (v,="" n){="" [v[0]*n,="" v[1]*n];="" dv="" [v[0]="" n,="" v[1]="" n];="" ad="" b){="" [a[0]+b[0],="" a[1]+b[1]];="" sb="" [a[0]-b[0],="" a[1]-b[1]];="" len:="" math.sqrt(math.pow(a[0]="" -="" b[0],="" 2)="" +="" math.pow(a[1]="" b[1],="" 2));="" addpoint="" (p,="" ln){="" pts="ln.pathPoints.add();" pts.anchor="p;" pts.leftdirection="pts.anchor;" pts.rightdirection="pts.anchor;" };

ここに挙げたのはFractalizerというAI用のスクリプトです。ExtendoscriptもECMAの端くれ、Javascriptと同様に色々なサービスにつっこむ事ができます。
今回利用するのはGoogleClosureCompiler(http://closure-compiler.appspot.com/home)というサービスです。Javascriptの最適化を行ってくれます。といってもピンと来ないかも知れません。具体的にはホワイトスペースの除去、利用されていない変数の除去、変数名称の単純化などなど色々とございますが百聞は一見にしかずということで下の帰ってきたものをご覧下さい。

こんな感じで左ペインにコードをペースとしてCompileボタンを押します。帰ってきたものを見てみましょう。

$._ext_ILST={applyFractal:function(a,b){var c=app.activeDocument.selection,f=new CMYKColor;f.cyan=0;f.magenta=0;f.yellow=0;f.black=100;for(var e=[],g,h=0;h<c.length;h++)if(“PathItem”==c[h].typename){for(var e=[],d=0;d<c[h].pathPoints.length;d++)e.push(c[h].pathPoints[d].anchor);g=app.activeDocument.pathItems.add();g.stroke=!0;g.strokeColor=f;g.strokeWidth=0.3;g.filled=!1;for(d=0;d<e.length;d++)d==e.length-1?c[h].closed&&$._ext_ILST.fractal(e[d],e[0],a,g,b):$._ext_ILST.fractal(e[d],e[d+1],a,g,b);c[h].closed&&
(g.closed=!0)}return!0},fractal:function(a,b,c,f,e){if(0==c)$._ext_ILST.addPoint(b,f);else{var g=$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(a,2),b),3),h=$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(b,2),a),3),d=$._ext_ILST.dv($._ext_ILST.ad(a,b),2),k=$._ext_ILST.dv($._ext_ILST.sb(d,a),$._ext_ILST.len(d,a)),k=[k[1],-k[0]];e=e?$._ext_ILST.sb(d,$._ext_ILST.mlt(k,Math.sqrt(3)/6*$._ext_ILST.len(b,a))):$._ext_ILST.ad(d,$._ext_ILST.mlt(k,Math.sqrt(3)/6*$._ext_ILST.len(b,a)));$._ext_ILST.fractal(a,g,
c-1,f);$._ext_ILST.fractal(g,e,c-1,f);$._ext_ILST.fractal(e,h,c-1,f);$._ext_ILST.fractal(h,b,c-1,f)}},mlt:function(a,b){return[a[0]*b,a[1]*b]},dv:function(a,b){return[a[0]/b,a[1]/b]},ad:function(a,b){return[a[0]+b[0],a[1]+b[1]]},sb:function(a,b){return[a[0]-b[0],a[1]-b[1]]},len:function(a,b){return Math.sqrt(Math.pow(a[0]-b[0],2)+Math.pow(a[1]-b[1],2))},addPoint:function(a,b){var c=b.pathPoints.add();c.anchor=a;c.leftDirection=c.anchor;c.rightDirection=c.anchor}};
<c.length;h++)if("pathitem"==c[h].typename){for(var e="[],d=0;d<c[h].pathPoints.length;d++)e.push(c[h].pathPoints[d].anchor);g=app.activeDocument.pathItems.add();g.stroke=!0;g.strokeColor=f;g.strokeWidth=0.3;g.filled=!1;for(d=0;d<e.length;d++)d==e.length-1?c[h].closed&&$._ext_ILST.fractal(e[d],e[0],a,g,b):$._ext_ILST.fractal(e[d],e[d+1],a,g,b);c[h].closed&&" (g.closed="!0)}return!0},fractal:function(a,b,c,f,e){if(0==c)$._ext_ILST.addPoint(b,f);else{var" g="$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(a,2),b),3),h=$._ext_ILST.dv($._ext_ILST.ad($._ext_ILST.mlt(b,2),a),3),d=$._ext_ILST.dv($._ext_ILST.ad(a,b),2),k=$._ext_ILST.dv($._ext_ILST.sb(d,a),$._ext_ILST.len(d,a)),k=[k[1],-k[0]];e=e?$._ext_ILST.sb(d,$._ext_ILST.mlt(k,Math.sqrt(3)/6*$._ext_ILST.len(b,a))):$._ext_ILST.ad(d,$._ext_ILST.mlt(k,Math.sqrt(3)/6*$._ext_ILST.len(b,a)));$._ext_ILST.fractal(a,g," c-1,f);$._ext_ilst.fractal(g,e,c-1,f);$._ext_ilst.fractal(e,h,c-1,f);$._ext_ilst.fractal(h,b,c-1,f)}},mlt:function(a,b){return[a[0]*b,a[1]*b]},dv:function(a,b){return[a[0]="" b,a[1]="" b]},ad:function(a,b){return[a[0]+b[0],a[1]+b[1]]},sb:function(a,b){return[a[0]-b[0],a[1]-b[1]]},len:function(a,b){return="" math.sqrt(math.pow(a[0]-b[0],2)+math.pow(a[1]-b[1],2))},addpoint:function(a,b){var="" c="b.pathPoints.add();c.anchor=a;c.leftDirection=c.anchor;c.rightDirection=c.anchor}};

なかなか読みづらいコードになっちゃってます。難読化の効果もありますので、jsxbinを利用出来ないシチュエーションでの利用も良いかも知れません。
ちなみに最適化の効果ですが、

Original Size: 745 bytes gzipped (1.91KB uncompressed)
Compiled Size: 601 bytes gzipped (1.45KB uncompressed)
Saved 19.33% off the gzipped size (24.25% without gzip)
The code may also be accessed at default.js.

この様に短いスクリプトなのですが、20%程容量を落とせています。

ten_a

Graphic Designer, Scripter and Coder. Adobe Community Professional.

シェアする