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

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

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

2014年6月10日

Bug-org 1015028 Should compute scancode from virtual keycode at computing KeyboardEvent.code value if the key message doesn't have proper scancode 初回投稿日時: 2014年06月10日03時17分42秒
カテゴリ: Events Mozilla Core Mozilla32 Windows バグ修正
固定リンク: id=2014061000
SNS: (list)

KeyboardEvent.codeは、Windowsでは、スキャンコードから求めていますが、::SendInput() APIから参照できる、KEYBDINPUT構造体のドキュメントを見る限り、各種ツール類が生成する疑似キーイベントには、適切なスキャンコードが設定されていない可能性が高いです。

幸い、Windowsでは、仮想キーコードから、現在選択されているキーボードレイアウトからスキャンコードを算出するAPIとして、::MapVirtualKeyEx()が存在していますので、スキャンコードがゼロの場合に限り、仮想キーコードから、スキャンコードを推測するようにしています。

ただし、この手法にも若干問題があり、0x00から0xFFで表現できない拡張キーと、拡張キーではないキーの両方で、その仮想キーコードが生成できる場合、上記のAPIは、拡張キーではない方のスキャンコードを返して来ます。ただ、これがやや期待とは異なる動作を行います。

拡張キーとは何か、ということがまずは重要ですが、一般的なキーボードで、Windowsが拡張キーとしているのは、矢印キー(ArrowDownArrowLeftArrowRightArrowUp)や、カーソル移動、編集に用いられるコントロールパッドにある、InsertDeleteHomeEndPageDownPageUp等があります。これらのキーは、テンキーのNumLockを解除している時に、同じ働きをしますが、テンキーの方は、非拡張キーにあたります。

このため、例えば、VK_DOWNの場合、算出されるスキャンコードは、テンキーのになり、その結果、.code値は、Numpad2になってしまいます。おそらく、多くのWeb開発者はArrowDownを期待すると思います。私もパッチをテストしている時に、そう期待しました。

現在のところ、この問題は、キーイベントを擬似的に生成するアプリのバグに起因する問題ですので、素直にAPIの算出結果に従うようにしています。

今後、DOMイベントがより、原始的な情報を提供できるようになればなるほど、Webアプリ開発時に、様々なブラウザ外の環境のバグも開発中のアプリに影響がでるようになっていく、ということに注意を払わなくてはいけなくなっていくことでしょう。

Bug-org 1008772 Web sites can steal ctrl+page up/down 初回投稿日時: 2014年06月10日03時26分32秒
最終更新日時: 2014年06月10日03時44分38秒
カテゴリ: Events Firefox Mozilla Core Mozilla32 バグ修正
固定リンク: id=2014061001
SNS: (list)

Webアプリが、Ctrl+PageDown等、キーボードによるタブナビゲーションのキーをkeydownイベントで、preventDefault()を呼び出していると、続くkeypressイベントが発生しなくなっているため、一部のサイトではキーボードでタブを操作できなくなっているというバグです。

よくよく調査してみると、そもそも、keypressイベントの.stopPropagation()を呼び出していると、やはり、操作不能になることが分かりましたので、<tabbox>要素や、<tabbrowser>要素のキーイベントのハンドリングがまずいことにすぐに気付きました。

このバグでは、keypressイベントを待たなくてはいけない場合を除き、keydownイベントでハンドリングするように変更することで、Webアプリがタブのナビゲーションは阻害できないように改善しています。また、.stopPropagation()対策として、システムイベントグループにリスナを登録するように変更したので、Webアプリが、通常イベントグループでstopPropagation()を呼び出しても、影響を受けなくなっています。

なお、この修正により、以下のキーイベントは、Firefoxではkeypressイベントが常に発生しなくなりました。これは、keydownイベントのpreventDefault()を呼び出す必要がある、その副作用です。ただし、Gecko以外のブラウザエンジンでは、keypressイベントが、これらの非文字入力キーで発生することがそもそも無いので、Firefoxに特化したWebアプリを作ったりしていない限りは、問題は無いと思います。

  • Ctrl+Tab
  • Ctrl+Shift+Tab
  • Ctrl+PageDown
  • Ctrl+PageUp
  • Ctrl+Shift+PageDown
  • Ctrl+Shift+PageUp
  • Ctrl+ArrowUp (Mac以外)
  • Ctrl+ArrowDown (Mac以外)
  • Ctrl+ArrowLeft (Mac以外)
  • Ctrl+ArrowRight (Mac以外)
  • Ctrl+Home (Mac以外)
  • Ctrl+End (Mac以外)
  • Command+ArrowUp (Mac)
  • Command+ArrowDown (Mac)
  • Command+ArrowLeft (Mac)
  • Command+ArrowRight (Mac)
  • Command+Home (Mac)
  • Command+End (Mac)
  • Command+Option+ArrowLeft (Mac)
  • Command+Option+ArrowRight (Mac)

加えて、Mac以外では、Ctrl+F4keypressが原則、発生しなくなりますが、ピン止めされたタブで開かれている場合には、発生します。どちらにしろ、このショートカットキーをWebアプリはハンドリングすべきではありませんが。

Bug-org 976673 While mouseup event is being dispatched, event handlers cannot steal focus from inaccessible element if preceding mousedown event's preventDefault() is called 初回投稿日時: 2014年06月10日03時57分26秒
最終更新日時: 2014年06月18日19時22分01秒
カテゴリ: Events Mozilla Core Mozilla33 バグ修正
固定リンク: id=2014061003
SNS: (list)

Geckoでは、Element.focus()を呼び出しても、そのJavascriptのコンテキストがアクセスできないノードがフォーカスを持っている場合、例えば、ブラウザのUIや、フレームに読み込まれた別ドメインのサイト等がフォーカスを持っている場合には、フォーカスを奪えないようになっています。

ただし、mousedownイベントでクリックされたドキュメントからアクセス可能な要素にフォーカスを移そうとしている場合は、例外的にこれを認めるようにしています。例えば、<label>要素のような、フォーカスのリダイレクトを実現したいという要求を実現するためです。

ちなみに、mousedownイベントがpreventDefault()で消費されない限り、mousedownイベントのデフォルトアクションとして、マウスのボタンが押された時のウインドウがフォーカスを持つようになっています。

今回見つかった問題は、有名サイトである、JSFIDDLEでは、親ドキュメントが、mousedownイベントのpreventDefault()を常に呼び出し、mouseupイベントでフォーカスをリダイレクトしようとしていたものの、サンプルを表示している<iframe>は、別ドメインなので、うまく機能していなかった、というバグです。

リスクの大きさを考えると、mousedowndefaultPrevented属性値を無視して、マウスボタンの押されたウインドウに常にフォーカスを移動させるような修正はできませんので、mousedownイベントと同様、mouseupイベントの発火中も、そのドキュメントからアクセスできるノードには、どこからでもフォーカスを奪えるように、例外措置を拡大して対応しています。

Bug-org 479942 shift+space doesn't scroll up with some keyboard layouts 初回投稿日時: 2014年06月10日04時03分16秒
カテゴリ: Events Mozilla Core Mozilla32 バグ修正
固定リンク: id=2014061004
SNS: (list)

非常に昔から存在しているバグですが、Spaceキーか、Shift+Spaceキーで、ASCIIの半角スペース以外を入力する場合、スクロールのショートカットキーとして機能しない、というバグです。

過去に、色々とハッキーなパッチを作っていましたが、レビュアのkarltがよりシンプルなものを望んでいたため、修正ができずにいました。しかし、物理キーを表現する、KeyboardEvent.codeのサポートで、これが大きく前進することができるようになりました。

今回の修正では、.code値が、Spaceの場合かつ、.charCodeが、半角スペースを意味する32ではない場合、ショートカットキーや、アクセスキーの候補リストを作成する際に、最後に、ASCIIの半角スペースを追加するようにしました。これにより、安全・確実・シンプルな修正が実現しました。

2014年6月11日

Bug-org 939006 Sort out DOM key name definition by groups in D3E draft 初回投稿日時: 2014年06月11日02時17分50秒
カテゴリ: Events Mozilla Core Mozilla32 バグ修正
固定リンク: id=2014061100
SNS: (list)

当初、D3Eの仕様書では、KeyboardEvent.keyの値をひとつのテーブルで定義していましたが、項目が増えるに従い、キーの種類ごとにテーブルを分割し、さらに、仕様書自体も、D3E本体から分離され、DOM Level 3 KeyboardEvent key Valuesに分離されています。

このバグでは、dom/events/KeyNameList.hと、widget/shared/NativeKeyToDOMKeyName.hでの、.key値の定義順を仕様書にあわせて、管理しやすくしました。

この修正に伴い、どのプラットフォームでも定義されていないkey値はコメントアウトしたので、インデックスから文字列値を取得するための配列のサイズが小さくなっているため、若干ですが、フットプリントを改善しています。

Bug-org 1020142 Should comment out KeyboardEvent.code values which any widgets don't support 初回投稿日時: 2014年06月11日02時20分48秒
カテゴリ: Events Mozilla Core Mozilla32 バグ修正
固定リンク: id=2014061101
SNS: (list)

KeyboardEvent.codeの初期実装時に、どのプラットフォームでも利用されないcode値も定義し、インデックスから文字列に変換可能にしていました。

しかし、若干とはいえ、フットプリントに無駄が生じているのももったいないので、コメントアウトして改善しています。

Bug-org 1020832 Intermittent test_imestate.html | Test timed out. 初回投稿日時: 2014年06月11日02時27分53秒
カテゴリ: Firefox Mozilla Core Mozilla33 バグ修正
固定リンク: id=2014061102
SNS: (list)

何故か、Mac OS X 10.8の最適化ビルドで、このテストを走らせた時にだけ、ランダムにタイムアウトが発生するようになったというバグです。

タイムアウトは、テスト終了時のwindow.close()が動作せず、unloadイベントも発生しないことが、ログをとってみて、すぐに分かりました。

その原因が当初は全く理解できなかったんですが、以下のログを見つけたので、原因が分かりました。

> 00:14:32     INFO -  5076 INFO TEST-START | chrome://mochitests/content/chrome/widget/tests/test_imestate.html
> 00:14:35     INFO -  JavaScript error: chrome://browser/content/tabbrowser.xml, line 3036: Cc is not defined
> 00:14:35     INFO -  JavaScript error: chrome://browser/content/tabbrowser.xml, line 357: this.browsers[i] is undefined
> 00:14:35     INFO -  JavaScript error: chrome://browser/content/tabbrowser.xml, line 357: this.browsers[i] is undefined
> 00:14:35     INFO -  JavaScript error: chrome://browser/content/browser.js, line 13823: browser is undefined

Bug-org 1008772の修正で、<tabbrowser>要素のコンストラクタを修正した際に、Ccを利用していたのですが、それがランダムに初期化されていないことがあるということのようでした。

とりあえず、コンストラクタとデストラクタという、リスキーなところでは、CcCiを利用しないようにし、正攻法でアクセスするように修正しています。

2014年6月24日

Bug-org 1019427 Log scancode -> virtual keycode table for KeyboardEvent.code debug on Windows 初回投稿日時: 2014年06月24日11時29分27秒
カテゴリ: Events Mozilla Core Mozilla33 Windows
固定リンク: id=2014062400
SNS: (list)

Bug-org 1015028の修正で、Windowsでは、スキャンコードがきちんと設定されていないキーイベントであっても、仮想キーコードからスキャンコードを算出して、KeyboardEvent.codeを求めるようになりましたが、どのような環境で、これが問題になるか分かりません。

そこで、リリースビルドでもマッピングのログがとれるようにするコードを仕込ました。

環境変数で、NSPR_LOG_MODULESを、KeyboardLayoutWidgets:5とし、NSPR_LOG_FILEを指定しておけば、起動時と、キーボードレイアウト変更時にログをとることができます。

Win8.1上のいくつかのキーボードレイアウトでログをとって、表にしてみると以下のようになりました。

これを見ると、VK_PRINT等、現在ではどのキーボードレイアウトでもマッピングされていない仮想キーコードがあるのが分かります。

Bug-org 1025982 Pressing "Digit1" key results in "Digit0" KeyboardEvent.code value (and so on) 初回投稿日時: 2014年06月24日11時42分54秒
カテゴリ: Events Mozilla Core Mozilla32 Mozilla33 Windows バグ修正
固定リンク: id=2014062401
SNS: (list)

Windowsでは、0キーから、9キーのKeyboardEvent.code値が、Digit1から、Digit0になっている、つまり、ひとつずつ数字がズレているというバグです。

単に、マッピングのテーブルがイージーミスで間違っていただけでした。Auroraでも修正しています。

Bug-org 1026397 Should not truncate input string between a surrogate pair at handling maxlength 初回投稿日時: 2014年06月24日11時52分40秒
カテゴリ: HTML Mozilla Core Mozilla33 バグ修正
固定リンク: id=2014062402
SNS: (list)

<input>要素のmaxlength属性によって、入力中のサロゲートペアの後半だけが削除されて入力されることがある、というバグです。

Bug-org 670837の報告によると、少なくとも、maxlengthはUTF-16ではなく、Unicodeのコードポイント単位で数えられるべきっぽいんですが、ひとまず、コンセンサスがとれている、サロゲートペアの分断だけは避けよう、というのがこのバグの目的です。

この修正により、サロゲートペアの片側を捨てる際には、もう一方も捨てるように修正しています。

Bug-org 1026986 Cannot build Qt-build due to nsEmbedFunctions.cpp:796:26: error:‘InstallX11ErrorHandler’was not declared in this scope 初回投稿日時: 2014年06月24日12時00分02秒
カテゴリ: Firefox GTK Mozilla Core Mozilla33 Qt バグ修正
固定リンク: id=2014062403
SNS: (list)

Qtビルドをテストのためにビルドしようとすると、Bug-org 968196のregressionでコンパイルエラーが発生するようになっていたというバグです。

Bug-org 968196では、GTK3ビルドでは、InstallX11ErrorHandler()を利用しないように修正されていたのですが、その際に、#if (MOZ_WIDGET_GTK == 2)で囲ってたのが、Qtビルドでエラーになる原因でした。

結果的には、#if (MOZ_WIDGET_GTK != 3)に変更することで修正しています。GTK固有のコードを#ifdefで有効化する際には気をつけてください。

2014年6月25日

Bug-org 1028485 Assertion failure: setCaret, "Failed to collapse normal selection" 初回投稿日時: 2014年06月25日09時05分01秒
カテゴリ: HTML Mozilla Core Mozilla33 バグ修正
固定リンク: id=2014062500
SNS: (list)

maxlength属性が指定されている時に、それを超える長さの文字列を確定した場合に、キャレット位置をmaxlength値より大きい場所にセットしようとして、assertionに引っかかる、というバグです。

IMETextTxnから、キャレット位置を設定する際に、実際にエディタ上で確定された文字列(必要に応じて削られた文字列)を確認せず、IMEが確定した文字列長だけを見ていたのが原因です。

実際に確定された文字列長を確認することで、解決しています。