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

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

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

2012年12月18日

Bug-org 813445 Sort out around flags of nsGUIEvent.h
初回投稿日時: 2012年12月18日23時56分01秒
カテゴリ: Mozilla Core Mozilla20 バグ修正
SNS: (list)

nsEvent::flagsは、uint32_tとして定義され、ビットマスクでその意味が定義されていました。しかし、その種類は多く、また大半はその意味がどこにも書かれておらず、さらに酷いことに、一部のフラグは他でも使い回されているという有様でした。そこで、これを整理しようというのがこのバグです。

当初考えていたのは、各フラグの意味をコメントで明確にし、ビット演算することなく、ヘルパーメソッドを大量にnsEventに定義して、イージーミスを回避することだけをひとつめの目標としていました。しかし、えむけいさんの提案で、C++のビットフィールドを用いた本格的なリファクタリングになってしまいました。

まず、mozilla::widget::EventFlagsという構造体を定義し、この中に1ビットのboolメンバを持たせ、各メンバにコメントでその意味を明確に説明するように修正しました。

フラグの参照側はbool変数をテストするだけですので、ビット演算によるイージーミスは無くなります(現に、修正中にイージーミスをひとつ発見しました)。

次に、nsEventDispatcherが、nsEventListenerManagerに登録されているイベントリスナを呼び出すコード部分では、イベントの処理状況を示すフラグとして、NS_EVENT_FLAG_BUBBLENS_EVENT_FLAG_CAPTURENS_EVENT_FLAG_SYSTEM_EVENTをメソッドのパラメータにセットし、フェイズやイベントグループをnsEventListenerManager側で判断できるようにしていました。しかし、これらの状態をそもそもnsEvent::mFlagsに持っていますので、nsEventListenerManagerがこれを参照するようにすることで、nsEventDispatcherまわりの単純化に成功しています。

さらに、nsEventListenerManagerにイベントリスナを登録する際にリスナの情報を指定する際に、そしてnsEventListenerManagerがこれを保存するのに、NS_EVENT_FLAG_BUBBLENS_EVENT_FLAG_CAPTURENS_EVENT_FLAG_SYSTEM_EVENTNS_PRIV_EVENT_UNTRUSTED_PERMITTEDNS_PRIV_EVENT_FLAG_SCRIPTが利用されていましたが、mozilla::dom::EventListenerFlagsという、ビットフィールドを利用した構造体を利用することで、nsGUIEvent.hからも、nsEventからも独立した情報として処理するように修正しました。

ただ、GCCではビットマスクによる実装よりも、ビットフィールドによる実装の方が若干遅い様で、極端なベンチマークを行うと、パッチ適用後はパフォーマンスが落ちていました。VCでは逆に若干の高速化が見られたのですが。ただ、どちらにしろ、Tpテストでは検出できない程度の話ですので、そのまま投入されています。

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

bug-org 813445を含むエントリ