Jul 09, 2010
XUL/Migemo 0.13.xで中身の方をだいぶ変えて(環境によっては)高速化しました
半分眠ったまんまで作業してたのでしょーもないregressionを仕込む→修正して公開→またregressionということを繰り返した結果、既に0.13.3になってしまったわけですが、バージョン0.13.0で結構大きくいじりました。機能的には全然変わってないですが。
- 開発メモにちょっと書いてるけど、このバージョンからFirefox 2とThunderbird 2をサポートしなくなりました。
- Gecko 1.8どころかGecko 1.9.0も切り捨てたという事で、Firefox 3.5より後で入った便利機能を心置きなく使えるようになったり、Firefox 2→Firefox 3の間で大きく変わったAPIの両方に対応するためのめんどくさい場合分けをゴソッと削除できたりしたので、だいぶスッキリした気がします。
- ウィンドウごとに分ける必要がないコードでXPCOMコンポーネント化してなかった物は積極的にJavaScriptコードモジュール化しました。
- Thunderbird専用のコードは、XPCOMコンポーネントにしてはあったものの、そんなに汎用性が無かったので、これも全部JavaScriptコードモジュール化しました。
- 検索でヒットした箇所が多い時に、Safari風の強調表示等の機能を有効にしているとフリーズしてしまう問題について、ヒット箇所の強調表示を段階的に非同期で行うようにしてみました(0.13.4)。
- Gecko 1.9.2以降ではnsIDOMWindowUtilsの
nodesFromRect()
を使うようにしたので、見えているスクロール位置から検索を始める処理が相当速くなりました。 - Minefieldに最近入った機能のおかげで、DOM Rangeから検索用のテキストを取得する部分が爆速になりました。
nodesFromRect()
の効果と合わせて、Minefield 4.0b2preではページ内検索のストレスがほとんど無くなったと思います。
Minefieldで検索が速くなったのは、Bug 39098 – Elements with visibility:hidden, visibility:collapse, or display:none get copied to the clipboardがfixされたおかげです。
- これまでXUL/Migemoのページ内検索が非常に重かったのは、Rangeを一旦文字列にして正規表現でマッチングして、その結果を使ってもう一度ページ内検索するという仕組みに理由があります。
- この時、Rangeをそのまま
toString()
で文字列にすると、CSSで非表示になっている要素のテキストまで一緒に取得されてしまうのですが、その後rangefindで検索する時は非表示のテキストは検索対象にならないため、場合によってはヒット箇所が飛ばされてしまったり検索が止まってしまったりという問題が起こります。 - そこで現在のXUL/Migemoでは、
というやり方で個々のテキストノードの可視・不可視の状態を判別して不可視のテキストを除外した結果を取得して、正規表現のマッチングに使うようにしていました。DOMWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsISelectionDisplay) .QueryInterface(Ci.nsISelectionController) .checkVisibility(textNode, 0, textNode.nodeValue.length)
- しかしこの方法は、テキストノードの数が増えると判断の回数も同じだけ増えてしまうため、MXRのページのように内容が小さなテキストノードに分断されているページだととんでもなく処理に時間がかかってしまいます。
- 5月末にBug 39098で入った変更によって、テキストリンクの高速化の時にも使ったnsIDocumentEncoderに、「非表示状態のテキストを結果の文字列に出力しない」というオプションが加わりました。なのでMinefield上では、この機能を使ってRangeの中の可視状態のテキストだけを一気に取得するようにしました。
Minefield 4.0b2preにXUL/Migemo 0.13.xを入れてMXRのページでページ内検索してみると、効果の程がよく分かると思います。僕は、今すぐにでもFirefox 3.6を窓から投げ捨ててしまいたくなりました。
あとはJägerMonkeyが入ってくれれば……
ところで、他のアドオンからXUL/MigemoのAPIを呼び出す時はちょっと注意が必要になってます。
- ずっと前に「ユーザ辞書の内容がWebページのスクリプトから取れてしまうのはセキュリティ的に宜しくない」という指摘を受けたんですが、どうやってこの問題を回避すればいいものか悩んで、結局、グローバルなJavaScriptのプロパティの
migemo
オブジェクトから機能を呼び出す時には常にシステム辞書の内容だけを返すように仕様を変えました。 - ユーザ辞書に追加された単語も含めた正規表現を取得したい場合、
Components.utils.import('resource://xulmigemo-modules/service.jsm')
でユーティリティを読み込んでXMigemoCore
の各メソッドを呼ぶか、Cc['@piro.sakura.ne.jp/xmigemo/factory;1'].getService(Ci.xmIXMigemoFactory).getService('ja')
てな感じでXPCOMコンポーネントを直接呼び出すかする必要があります。 XMigemoCore
でもxmIXMigemoCoreでもどっちにしても、これらが持つ機能で正規表現を生成する時は戻り値は常に文字列(正規表現のソース文字列)になるので、その都度new RegExp()
してやる必要があります。- 辞書が絡まない機能は
migemo
のメソッドを使って問題ありません。XUL/MigemoのUI周りでもそうしてます。
wikieditish message: Ready to edit this entry.