Dart (frogc) でJavaScriptの機能を直接呼ぶ方法
Dart specには含まれていないようだが、処理系によってはnativeキーワードでJavaScriptを参照できるようだ*1。ただし、使いたいメソッドすべてに宣言が必要なので多少の手間がかかる。
// JavaScriptのクラスというかオブジェクトを参照する // 'Math'はJSのネイティブオブジェクト class NativeMath native "Math" { static double floor(double value) native; } // native classは任意のJS式を参照できるので // nodeの場合requireも使える class Util native "require('util')" { // デフォルト引数をdart側で処理できる! static String inspect(Object value, [ bool all = false, int depth = 3]) native; } void main() { // 宣言したメソッドを使用できる // 宣言していないものを呼ぶとランタイムエラー Map map = { "hoge" : NativeMath.floor(3.14) }; // nodeのutilモジュールのinspect関数を呼ぶ // 名前付き引数はDart処理系によって解釈される print( Util.inspect(map, depth: 4) ); }
frogcでコンパイルすると以下のようになる。肝心なところだけ抜粋。余計なラッパーなどは生成されない。
var NativeMath, Util; // ... // ********** Library NativeCall ************** // ********** Code for NativeMath ************** NativeMath = Math; // ********** Code for Util ************** Util = require('util'); // ********** Code for top level ************** function main() { var map = _map(["hoge", NativeMath.floor((3.14))]); print$(Util.inspect(map, false, (4))); } // ...
実行結果は以下のようになる。これは面白い。
{ _map: { _numberOfEntries: 1, _numberOfDeleted: 0, _loadLimit: 6, _keys: [ , , , , , , 'hoge', ], _values: [ , , , , , , { _element: { key: 'hoge', value: 3 }, _next: { _element: null, _next: [Circular], _previous: [Circular] }, _previous: { _element: null, _next: [Circular], _previous: [Circular] } }, ] }, _list: { _sentinel: { _element: null, _next: { _element: { key: 'hoge', value: 3 }, _next: [Circular], _previous: [Circular] }, _previous: { _element: { key: 'hoge', value: 3 }, _next: [Circular], _previous: [Circular] } } } }
Dartはオプショナルとはいえ静的方付けでしかも名前付き引数をサポートしているので、うまくバインディングを定義するともとのJSコードよりも使いやすいかもしれない。