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

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

もずはっく日記(2013年10月)

2013年10月31日

Bug-org 920377 Get rid of legacy event class names (ns*Event) 初回投稿日時: 2013年10月31日14時41分06秒
カテゴリ: Mozilla Core Mozilla27 バグ修正
固定リンク: id=2013103100
SNS: (list)

Bug-org 912956の修正で、イベントのクラス名が全てリネームされましたが、typedefで古いクラス名をそのまま使えるようにしていました。このバグの修正で、古いns*Eventは全て新しい名前に置換され、typedef宣言も削除されました。

Bug-org 920425 WidgetEvent should have As*Event() methods for capsuling event struct check and static cast 初回投稿日時: 2013年10月31日14時59分44秒
最終更新日時: 2013年10月31日15時01分10秒
カテゴリ: Mozilla Core Mozilla27 バグ修正
固定リンク: id=2013103101
SNS: (list)

WidgetEvent::As*Event()を実装して、コードを簡略化・安全性を高めようというバグです。

現在、多くの箇所で、

if (aEvent->eventStructType == NS_KEY_EVENT) {
  foo = static_cast<WidgetKeyboardEvent*>(aEvent)->mBar;
}

といった形でイベントのサブクラスのメンバにアクセスしています。このケースでは、まだ問題が少ないのですが、共通する基底クラスがある場合に処理をするような場合、大きな問題があります。例えば、

switch (aEvent->eventStructType) {
  case NS_INPUT_EVENT:
  case NS_KEY_EVENT:
  case NS_MOUSE_EVENT:
  case NS_DRAG_EVENT:
  case NS_TOUCH_EVENT:
  case NS_SIMPLE_GESTURE_EVENT:
    foo = static_cast<WidgetInputEvent*>(aEvent)->mBar;
    break;
  default:
    break;
}

このようなコードが各所にあった場合、WidgetInputEventを継承するイベントが増えた場合、全てのこのような箇所を修正しなくてはいけないため、修正漏れが簡単に発生します。また、このうちの一部のイベントが、WidgetInputEventを継承しなくなった場合、非常に危険なバグになり得る可能性もありますし、無意味な値を返すだけの分かり難いバグを産むことになります。

こういった問題を解決するのが、As*Eventです。このコードは、以下のように書き換えることができます。

WidgetInputEvent* inputEvent = aEvent->AsInputEvent();
if (inputEvent) {
  foo = inputEvent->mBar;
}

この場合、イベントクラス側での仕様変更で、ハンドリングしている側に影響が出ることはありません。また、スーパークラスの型を前提にしているコードであっても、適合しなくなった場合、nullptrが返され、クラッシュという形で簡単にバグを発見することができるようになります。

逆に言うと、このバグの修正が原因で、クラッシュバグが新たに発生している場合、このバグの修正にミスが無かった場合には、現在リリースされているGeckoのバグが発見されたことを意味している上に、そのバグは危険なものかもしれませんので、報告する際には注意してください。

このAs*Eventメソッドは、virtualメソッドとして実装されているため、デストラクタもvirtualになりました。このため、delete static_cast<WidgetInputEvent*>(mEvent)のようなコードは不要になり、かなり簡略化されています。

Bug-org 930860 Move some methods in WidgetEvent to WidgetMouseEvent 初回投稿日時: 2013年10月31日15時05分45秒
カテゴリ: Mozilla Core Mozilla27 バグ修正
固定リンク: id=2013103102
SNS: (list)

nsGUIEvent.hで、マクロとして実装されていた、イベントの種類を判別するメソッド類は、全て、WidgetEventのメソッドとして再実装していましたが、Smaugが、WidgetEventの肥大化を懸念したため、これを見直し、マウスイベント関連のメソッドは、WidgetMouseEventや、WidgetMouseEventBaseに移動しました。

Bug-org 930855 Replace WidgetEvent::Is*DerivedClass() with As*Event() 初回投稿日時: 2013年10月31日15時10分05秒
カテゴリ: Mozilla Core Mozilla28 バグ修正
固定リンク: id=2013103103
SNS: (list)

Bug-org 920425の修正により、WidgetEvent::Is*DerivedClass()の実装は、単に、return As*Event() != nullptr;となっていました。単純に、if (aEvent->Is*DerivedClass())は、if (aEvent->As*Event())で置き換えられるため、これらのメソッドを削除しました。

Bug-org 930900 KeyboardEvent.key doesn't return correct value after event dispatch finished 初回投稿日時: 2013年10月31日15時14分53秒
カテゴリ: Events Mozilla Core Mozilla28 バグ修正
固定リンク: id=2013103104
SNS: (list)

KeyboardEventをイベントハンドラで、グローバル変数等に保存しておき、イベントの伝播が終了した後に、KeyboardEvent.keyの値を取得すると、常に空文字列になっている、というバグです。

.keyの実装時に、複製されたイベント情報がある状態と、document.createEvent()生成された場合との見分けがつかない、状態を示す変数を参照して、返す値を決めていたのが原因です。まもなく、KeyboardEventのコンストラクタを実装して、.key属性値も指定できるようにする予定ですので、それにあわせた修正を一足先に入れて解決しています。