Friday, December 16, 2011
■ [Internet Explorer]JavaScript エンジン Chakra を無理矢理使う。

こんにちは。JavaScript Advent Calendar 2011 オレ標準コース16日目です。
Internet Explorer 9で新たに導入されたJavaScript エンジン、Chakraを非公開な方法で使うという誰得な話です。
はじめに
WindowsにはJavaScriptのMicrosoft実装であるJScriptやVBScriptなどスクリプト言語(サードパーティー製でPerlとかRubyとかもある)をいい感じにあつかうActiveScriptという枠組みがあり、それを使ってスクリプトを実行するWSH(Windows Scripting Host)というのがあります。
Cscript.exeとかWscript.exeといったものがそれです。Windowsでなんとか.jsという名前で保存してダブルクリックすると起動するのはWscript.exeです。ActiveScriptはスクリプトエンジン、WSHはそれをホストして機能を提供するものと覚えておけばよいでしょう。
JScriptのバージョン
そんなJScriptにはバージョンがあります。大体IEとセットでバージョンアップしていくのでIE7で5.7、IE8で5.8となっています。詳しくはno titleに書いてあります。
7(.NET 1.x)と8(.NET 2.0)と10(.NET 4)は.NETのJScriptで、IE9のChakraは位置づけ的にはJScriptエンジンではなくJavaScriptエンジンとしてるようですが 9となっています。たぶんIE10は10でかぶりそうですが.NET版は忘れましょう。
WSHとChakra
IE9の話に戻りますがChakraはIE9をインストールすると勝手に入ります。それならばと思ってWSHでJavaScriptを実行すると残念なことにJScript 5.8で動作します。
試しにIE9の入っている環境で以下のプログラムを実行してみます。
WScript.Echo(ScriptEngine() + '/' + [ScriptEngineMajorVersion(), ScriptEngineMinorVersion(), ScriptEngineBuildVersion()].join('.'));
するとJScript 5.8 (つまりIE8のJavaScriptエンジンと同等)として動作します。
C:\Users\Tomoyo\Desktop>cscript //NoLogo test.js JScript/5.8.16982
なぜ5.8で動作しているのかというとChakraは今までのエンジンの実体が別になったためです。今まではJScript.dllというライブラリでしたがChakraは別にJScript9.dllという別なライブラリに分かれています。
じゃあJScript9.dllの方を呼び出せれば解決しそうです。JScript9.dllもActiveScriptエンジンとして登録されているのでWSHにそれを使うように指示すればよさそうです。
幸いWSHの実行ファイルWScript.exe/CScript.exeにはスクリプトエンジンを指定するコマンドラインオプション(//E)があるのでそれが使えます。例えば//E:JScriptとか//E:VBScriptとかという感じです。
JScript9のような名前は登録されていないのですが、若干裏技で呼び出せます。というわけで呼び出してみます。
C:\Users\Tomoyo\Desktop>cscript //NoLogo //E:{16d51579-a30b-4c8b-a276-0ff4dc41e755} test.js
JScript/9.0.16440
なかなかクールな名前ですね。それは置いておいてスクリプトエンジンのバージョンが9になりました。つまりChakraです。
しかしChakraが本当に使われているかわかりませんね。というわけで以下のようななんとなく時間のかかりそうな処理スクリプト( JavaScript でフィボナッチ数列を高速に求める - IT戦記からコピペしました)を実行してみます。
WScript.Echo(ScriptEngine() + '/' + [ScriptEngineMajorVersion(), ScriptEngineMinorVersion(), ScriptEngineBuildVersion()].join('.')); function fib(i) { if(i == 0 || i == 1) return i; return fib(i-1) + fib(i-2); } var startAt = new Date(); fib(30); WScript.Echo(new Date() - startAt + "ms");
C:\Users\Tomoyo\Desktop>cscript //NoLogo //E:JScript test.js
JScript/5.8.16982
3531ms
C:\Users\Tomoyo\Desktop>cscript //NoLogo //E:{16d51579-a30b-4c8b-a276-0ff4dc41e755} test.js
JScript/9.0.16440
1114ms
ちゃんと実行速度がはやくなりました。よかったよかった。
と思いきや一つ残念なお知らせがあります。5.8の時と同様にegtraさんが書いているように5.7互換モードで動作しています。
Chakraで動いても5.7互換モードなのでJSONやES5の素敵機能を使えません。単にWSHを高速に実行できるだけで、互換モードから5.8以降に変えることはできません。激しく残念。
Chakraをホストする
WSHではどうやっても5.7互換でしか動きませんでした。これはChakraに限らず5.8の時でも同様です。その部分はegtraさんが書かれていますが、自分でエンジンをホストする場合にはオプションを指定すれば5.8モードに変更できます。
とするともしかしてChakraもモードを指定すれば変わるのでは?と思いますよね。指定できるモードの説明 IActiveScriptProperty::SetProperty を読むと2 (SCRIPTLANGUAGEVERSION_5_8)
とか書いてあるのでもしかして3かも?と思って3を指定したら見事に動作しました。
// WSHの時と同様にChakraエンジンを呼び出す _engine = Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("16D51579-A30B-4C8B-A276-0FF4DC41E755"))) as IActiveScript; var prop = _engine as IActiveScriptProperty; Object invokeVer; invokeVer = 3; // JScript9 hr = prop.SetProperty(/*SCRIPTPROP_INVOKEVERSIONING*/0x00004000, IntPtr.Zero, ref invokeVer);
JScript 9モードで動作するとJSONやECMAScript 5thっぽい機能が使えるようになるのでホストする場合には幸せになれそうですね。
おまけ: Classic ASPでChakra
ところでWindows ServerにはASPというActiveScriptを使ったサーバーサイドのWeb技術があります。
先ほどのChakraというかJScript9.dllのGUIDにちゃんと名前をつけてあげるとClassic ASPのlanguageで指定できるようになってASPで動くようになります。
無駄に高速なClassic ASPになりますがなぜか一度しかリクエストを処理できないので何の役に立ちません。
おしまい
明日は@polygon_planetさんです。