ESTKのプリプロセッサディレクティブ、#targetengine
について少し調べたのでメモ。当然すべてInDesignでの検証です。
動的にエンジンを変更できるか
以下のコードをテスト。
#targetengine hoge alert($.engineName); var a = "Hello"; #targetengine fuga alert($.engineName); a += " World!"; #targetengine main alert(a);
結果は、エンジン「main」で実行され、最後の行で問題なく?「Hello World!」と言われる。
また、#targetengine main
をコメントアウトすると、動作するエンジンが「fuga」になるため、どうやらコード内に記述されたtargetengineは最後のものが優先されるらしい。
#targetengine
をeval
してはどうか?
#targetengine hoge alert($.engineName); var a = "Hello"; eval('#targetengine fuga'); alert($.engineName); a += " World!"; eval('#targetengine main'); alert(a);
こうするとエンジン名は「hoge」となる。スクリプト実行前にコードが読み込まれた段階で、実行するエンジンは決定されるもよう。
全部eval
だと?
eval('#targetengine hoge'); alert($.engineName); var a = "Hello"; eval('#targetengine fuga'); alert($.engineName); a += " World!"; eval('#targetengine main'); alert(a);
こうするとエンジンは「main」。コード内にtargetengineの指定がないと見なされ、mainで実行される。
prototype拡張がエンジンをまたぐか?
3つのスクリプトを用意して、InDesignから順に実行する。
hoge.jsx
#targetengine hoge String.prototype.hoge = function (string){ return this + string; }
hogeAlert.jsx
#targetengine hoge alert("ふが".hoge("ほげ"));
fugaAlert.jsx
#targetengine fuga alert("ふが".hoge("ほげ"));
結果は、
- hogeAlert>成功
- fugaAlert>エラー
となるので、prototype拡張をしても、targetengineを分ければグローバルな汚染は防げる。想定した通りだったのでちょっと安心した。
まとめ
- スクリプト内に
#targetengine
が複数定義してある場合、最後に記述されたものがそのスクリプトのエンジンになる - スクリプト内に
#targetengine
が定義されていなかった場合、mainエンジンになる(当然) #targetengine
は後から動的に変更できない- prototypeチェーンは
#targetengine
ごとに保存される=エンジン間で汚染されない
動的にtargetengineが変更できればいろいろおもしろいなぁと思って実験したのですが、まぁそうですよね、という結果でしたね。
prototype拡張を行う場合はtargetengineを指定したほうが安全かなーという印象。まぁそもそも一回使っておしまいというのがDTPのスクリプトなので、そこまでシビアに考えなくてもいいのかなという気はしますが。
今回は自分用のメモ書きなので部分部分の細かい説明は割愛させてもらいました。
追記【5/28 18:15】
またまたあるふぁ(仮)さんに追検証していただき、InDesignのApplication.doScript
メソッドでは異なるtargetengineを指定できると教えていただきました。
その後自分でも検証を重ねていたのですが、なんだか妙なことになりました。
#targetengine 'hoge' alert($.engineName); //hoge app.doScript("""#targetengine 'foo' alert($.engineName); //foo """);
これは確かに動的にtargetengineを変更します。しかしdoScriptの中のtargetengineの前で改行してしまうと結果が変わります。
#targetengine 'hoge' alert($.engineName); //foo app.doScript(""" #targetengine 'foo' alert($.engineName); //foo """);
かなり怪しいです。ちなみに、似たようなことをevalメソッドでやると
#targetengine 'hoge' alert($.engineName); //hoge eval("""#targetengine eva alert($.engineName);""") //hoge
に対して
#targetengine 'hoge' alert($.engineName); //eva eval(""" #targetengine eva alert($.engineName);""") //eva
となります。
ここまでやって、僕はtargetengineは後から定義しないほうがよい、という結論に至りました。要するに、スクリプト冒頭でtargetengineを指定するオーソドックスなやり方以外は、書き方次第で結果が変わってしまう可能性があるので避けたほうが良いということです。
これは後からjsxincファイルをincludeする際にも同じことが言えて、jsxincファイルにはtargetengineなどは指定しないほうが(万が一不具合が起きた場合の検証のしやすさを鑑みて)良いだろうということです。後からtargetengineをどうこうするということを、スクリプトの設計として想定されていないのではないかな、と思いました。
したがって、僕個人は「targetengineを動的に操作する」ということを今後一切しないことにします。
首を突っ込んで調べてみるものですね。勉強になりました。