Bug-org 813445の修正で、VC++では-O2で最適化ビルドを作ろうとするとコンパイラがクラッシュするというregressionが出ました。もちろんVC++自体のバグなのですが、そうも言ってられません。
パフォーマンスを意識して、メンバを一括でmemcpy()を使ってOR演算や、初期化できるようにしていましたが、コンストラクタや、代入演算子を定義していたため、C++03では、非PODクラスということになるらしく、memcpy()が危険だという助言を、例によってえむけいさんから頂きました。ところが、PODクラスにしてもVC++のクラッシュは修正できませんでした。
そこで、クラッシュした行に着目してみると、以下のようなコードになっていました。
inline EventFlags operator|(const EventFlags& aOther) const
{
EventFlags flags;
flags.SetRawFlags(GetRawFlags() | aOther.GetRawFlags());
return flags;
}
クラッシュしたのは、SetRawFlagsの行です。ここで、それぞれのメソッドの実装は次のようになっています。
inline void SetRawFlags(RawFlags aRawFlags)
{
MOZ_STATIC_ASSERT(sizeof(EventFlags) <= sizeof(RawFlags),
"mozilla::widget::EventFlags must not be bigger than the RawFlags");
memcpy(this, &aRawFlags, sizeof(EventFlags));
}
inline RawFlags GetRawFlags() const
{
RawFlags result = 0;
memcpy(&result, this, sizeof(EventFlags));
return result;
}
試しに、これらのinline指定を削除してみると、コンパイラがクラッシュしなくなりました。ということで、バグはここの最適化にあるようです。
結果的には、operatorをUnion()というメソッドに変更し、一度、変数にGetRawFlags()から得た演算結果を保存してから、SetRawFlags()を呼び出すことで、コンパイラのバグを回避しています。
また、非PODクラスのままでは不安が残るので、EventFlagsをBaseEventFlagsと名前を変更し、コンストラクタを削除、上述の通り、|=演算子をUnion()というメソッドに置き換えました。
そして、コンストラクタが無いのは不便なので、新たにEventFlagsというコンストラクタだけを追加した派生クラスを用意し、Union()メソッドを使うような局面では、こちらをローカル変数として利用することで、Clear()メソッドをいちいち呼ばなくとも、自動で初期化されるように修正しています。
Bug-org 786956の修正の後、VNC経由でMacでデバッグビルド上でモディファイアキーを押すと、MOZ_ASSERT()にひっかかってクラッシュするというバグです。
調べてみると、MacのVNCサーバはOSSではなく、Apple謹製の様ですが、そのVNCサーバの生成するFlagsChangedイベントが変なために、新しいコードではうまく処理できなくなっていました。
まず、それなりにリスキーな変更が必要なため、19からはBug-org 786956の修正の修正はバックアウトしています。
続いて、キーコードが適切に設定されていないFlagsChangedイベントであっても、keydownイベントも処理されるように修正しました。
ただし、VNCの送信するイベントの仕様上、右 shiftキー、右 controlキー、右 optionキー、右 commandキーを押しても、KeyboardEvent.locationは常に、KeyboardEvent.DOM_KEY_LOCATION_LEFTが返されます。このバグが気に入らない方はAppleに報告をお願いします。
MicrosoftのWireless Keyboard 3000 v2.0のような、マルチメディアキーがついたキーボードで、新規作成キーや、閉じるキーを押した時に、他のブラウザではタブが作成されたり、タブが閉じられたりするのですが、FirefoxではWM_APPCOMMANDのこれらのコマンドに対応していないため、キーボードユーティリティが、Ctrl+N等のよく知られたショートカットキーのイベントを生成するため、タブの代わりにウインドウが開いたり、閉じたりするというバグです。
WindowsのnsWindow側では、以下の様に、DOMCommandEventを生成するようにしました。
新たに対応したDOMCommandEventのcommand属性値と、APPCOMMAND_*値、Firefoxの機能との対応表
command属性値 | APPCOMMAND_* | 対応するFirefoxの機能 |
Close | APPCOMMAND_CLOSE | タブを閉じる |
Find | APPCOMMAND_FIND | 検索 |
Help | APPCOMMAND_HELP | ヘルプ |
New | APPCOMMAND_NEW | 新しいタブ |
Open | APPCOMMAND_OPEN | ファイルを開く... |
Print | APPCOMMAND_PRINT | 印刷... |
Save | APPCOMMAND_SAVE | 名前を付けてページを保存... |
ForwardMail | APPCOMMAND_FORWARD_MAIL | 対応機能無し |
ReplyToMail | APPCOMMAND_REPLY_TO_MAIL | 対応機能無し |
SendMail | APPCOMMAND_SEND_MAIL | ページの URL をメールで送信... |
Thunderbirdや、SeaMonkeyでもハンドラだけ書けばこれらに対応できます。SeaMonkeyのバグは既に登録されています。パッチ書く人募集中です。