Dec 26, 2012

RestartlessのE4Xレス化

再起動の要らないアドオンをAdd-on SDK無しで開発するときの簡易的なテンプレートのような物として作っているRestartlessは、ツールバーボタンの定義や設定ダイアログの定義にE4Xを使う前提で設計してた。静的なXULファイルを別に用意しなくても、JavaScriptで書かれたロジックの中にリテラルとしてXULの定義を埋め込める、ということで重宝してたんだけど、E4Xのデフォルト無効化で完全にハシゴを外された形になってしまった。

E4Xを多用してた方々各方面悲喜こもごもあるようで、自力でスクリプトをパースしてCDATAマーク区間だけでも認識できるようにするとか色々なアプローチが試みられているようなのだけれども、僕はというと、面倒なのでE4Xはスッパリ諦める事にした。元はといえば、従来のやり方に近いやり方で再起動の要らないアドオンをラクに開発したいというのがRestartless開発の動機だったのだから、何か代わりの手段があるのであれば、E4Xにこだわる理由はなかったし。

まずE4Xで定義されたXULのコード片を受け取る部分についてだけど、これらは内部的にはXMLのソースコードの文字列に変換した後、RangeのcreateContextualFragmentでDOMDocumentFragmentにしてたので、インプットはただの文字列でも構わなかった。なのでToolbarItem.jsconfig.jsは以下の点だけ修正して終わりとした。

  • E4X無効の環境でもシンタックスエラーにならないように、E4X固有の書き方をなくした(具体的には、識別子としていきなり「*」が出てこないようにした)。
  • インプットが文字列の時は、それをそのままDOMDocumentFragmentにした後、ホワイトスペースだけのテキストノードをその都度削除するようにした(XBLの定義が手抜きなせいで、こういう場合に初期化エラーになるので)。

ツールバーボタンの定義は、手間だけど文字列リテラルに書き直すことにした(簡単なスクリプトでインデントも含めてそれっぽく置換した)。ちょよんごさんのnode-hereを移植することも考えたんだけど、単に改行込みのコード片を文字列として取得できるだけだと、E4Xの時みたいな「属性値やテキストノードの値にJSの変数の値を入れる」ということが簡単にはできなくて、そこの面倒さの方が気になったので、今回は見送ることにした。

ただ、設定ダイアログくらいの規模となると、一々文字列リテラルにしてたら埒があかないのでそこだけはなんとかしたかった。これについては、Firefox 8くらいから後のバージョンではchrome.manifestでcontentやlocaleのChrome URLを動的に登録・解除できるようになってるので、昔ながらのやり方に戻って静的なXULファイルで書くようにした

ロケールもこの要領でpropertiesファイルからDTDに書き直せばいいんだけど、Fox Splitterみたいにロケールの数が多いとそんなのやってらんないし、Fox Splitterの場合は設定ダイアログとブラウザ上のUIとで同じラベルを使い回したりしていて、どれをpropertiesファイルに残してどれをDTDにするのかとかを考えるのももう無理っぽかったので、逆転の発想で、属性値やテキストノードの値に{{ JavaScriptの文 }}という書き方を許容するようにして、XULドキュメントが開かれたときに自動的に解決するユーティリティを加えて、propertiesファイルをDTD代わりに使うことにしてみた。DOMContentLoadedのタイミングだと遅すぎるようだったので、今の所は待ち無しで実行してるけど、XBLの初期化タイミングが狂うリスクがあるので、将来的には問題が起こるかもしれない。(……と、ここまで書いて気付いたけど、node-hereを移植した上でこれと同じ記法を許容するようにすればよかったかなぁ。もう後の祭りだけど。)

Restartlessベースで作ってた各アドオン(親のタブに戻るFox Splitter、あと開発中で放置してた「Suspend Tab」)も更新済みで、masterベースのXPIはこの間から提供してる自動ビルドが既に利用できる状態になってる。Nightlyで使ってた人がもしいたら、これで動くようになってると思う。

……node-here.jsの移植はやらないでおくって書いたけど、結局やっぱり必要になってしまったので移植した。スタックトレースから列番号を取れないというGecko(SpiderMonkey?)の制限のため、1行の中に2個以上のhere()は書けない。

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能