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

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

もずはっく日記(2014年8月)

2014年8月26日

Bug-org 1053048 Accessing selectionStart or selectionEnd from nsISelectionListener::NotifySelectionChanged() may cause cancelling the edit action
初回投稿日時: 2014年08月26日11時45分49秒
最終更新日時: 2014年08月26日11時48分36秒
カテゴリ: Firefox OS Mozilla Core Mozilla34 TSF バグ修正
SNS: (list)

<input>要素や、<textarea>要素に対して、アドオン等がnsISelectionListener利用して、キャレット位置の変化を監視し、NotifySelectionChanged()が呼び出された時に、selectionStartや、selectionEndの値を取得しようとしている場合、これらの要素のkeydownイベントで、要素のレイアウトを変更すると、編集した内容がキャンセルされる、というバグです。

日本で必要としている、Firefox OSのキーボードAPIの修正が投入されないので、該当のバグを読んでみると、このバグが原因で、一部のテストがオレンジになっていることが分かりました。そこで、急遽、調査して修正することにしました。ちなみに、TSFには、キャンセル前のテキストの変更通知が行われた後、キャンセルされていたので、TIPを混乱させる原因になっていそうです。実害は未確認ですが。

nsEditorは、編集作業を行っている間、表示がばたついてパフォーマンスが落ちないように、選択範囲・キャレット位置の変更通知や、画面の再描画を抑制し、編集が終わってから一気に行う様になっています。それが終わると、締めに、nsIEditorObserver::EditAction()または、nsIEditorObserver::CancelEditAction()を呼び出しています。

一方、<input>要素や、<textarea>要素は初めてフォーカスを持った時にnsPlaintextEditorを生成し、編集を管理させ、レイアウトの変更で、フレームが再構築される場合には一旦、エディタを破棄し、フレームが再生成された後にエディタを再度作成し、そのvalue値を編集対象としています。

この、value値の保存タイミングと、値に変化があったかどうかを保持しているフラグの更新タイミングが問題でした。前者は、エディタを破棄する直前にvalue値を内部で保持している変数にエディタの最新情報を設定していたのですが、後者のフラグは、nsIEditorObserver::EditAction()が呼び出された時に、初めて更新されていました。このため、エディタを破棄する際には、新しいvalue値をすでに取得しているものの、変更されたことはまだ記録していないので、デフォルトのvalue値を取得しにいき、編集前のvalue値でエディタが再生成され、編集がキャンセルされてしまっていました。

今回の修正で、要素を管理している側では、エディタを破棄する前に、まだ、nsIEditorObserver::EditAction()が呼び出されていなかった場合には、先に呼び出すように変更し、何があっても、期待通りの順序で処理が行われるように修正しています。

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

bug-org 1053048を含むエントリ