この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2012年11月)

2012年11月14日

Bug-org 806996 CreateTextStateManager not called when editor is reframed during focus
初回投稿日時: 2012年11月14日13時58分50秒
カテゴリ: Mozilla Core Mozilla19 TSF バグ修正
SNS: (list)

Bug-org 805306の修正によるregressionで、<input type="text">や、<textarea>といった要素が、フォーカスを持っている際に、nsTextStateManagerはその匿名div要素を監視して、選択位置の変更や、テキストの変化をIMEに通知していますが、一部リフローが原因でリフレームが発生した場合に、監視している匿名div要素がエディタから削除され、新たに別の匿名div要素が使われるようになっても、古い方を監視し続けていた、というバグです。

Android版で、Google Instantがうまく動かず、未確定文字列が複製され続けるという形で症状は出ていたようです(私の端末ではIMEの違いのせいか、再現しませんでしたが)。

nsEditorからnsIMEStateManagerにフォーカスが変わったと擬似的に通知していたのですが、nsTextStateManagerはまだ、古い匿名div要素で監視が成功していると判断していたのがこのバグの直接的な原因でした。ただ、nsIMEStateManagernsTextStateManagerの設計の悪さがこのバグを招いているので、この機会に再設計を行っています。

まず、エディタからは、実際に起きたことをそのまま伝えるように、nsIMEStateManager::OnChangeFocus()ではなく、nsIMEStateManager::UpdateIMEState()を利用するようにしました。

nsIMEStateManager::UpdateIMEState()はIMEの状態に変化がない場合には、何もしていなかったので、変化がない場合でも、nsTextStateManagerが監視している匿名div要素が既にドキュメント内にない場合には作り直すように修正しています。

また、このままではIMEへのフォーカス移動通知が非常に壊れやすい設計であることも問題なので、これを確実に通知できるように、nsTextStateManagerは編集可能な要素がフォーカスを持つ場合には常に存在するように修正し、nsTextStateManagerのコンストラクタで、nsIWidget::OnIMEFocusChange(true)を呼び出し、nsTextStateManager::Destroy()で、nsIWidget::OnIMEFocusChange(false)を呼び出すようにし、確実に1:1の呼び出し回数で、ミス無く処理できるように改善しています。

また、IMEのテスト中にのみ、IMEにフォーカス移動を通知する直前にその内容をカスタムDOMイベントで、そのドキュメントに通知するようにし、自動テストでカバーしています。

この修正により、nsTextStateManagerの動作が非常に分かりやすい物になったと思います。

関連するかもしれないエントリ

bug-org 806996を含むエントリ