Bug-org 968056 keypress event shouldn't be fired for non-printable keys
初回投稿日時: 2018年12月11日23時35分00秒
最終更新日時: 2018年12月12日00時00分39秒
カテゴリ: Events IME KeyboardEvent Mozilla Core Mozilla65 バグ修正
SNS:
Tweet (list)
長年、Geckoでは、モディファイアキーを除くキーの入力時に、keypress
イベントを発火していました。しかし、UI Events (旧DOM Level 3 Events)ではkeypress
は文字の入力時にのみ発火するという定義が(後から)行われました(例えば、aの入力では発火するが、Ctrl+aでは発火しない、また、ArrowDownのように、端から文字を入力しないキーの場合にも発火しない)。このバグ修正は、Geckoの動作をUI Evnetsの仕様通りの動作にあわせたものです。
Geckoではほぼ全てのショートカットキーがkeypress
イベントを処理することで実装されています。そこで、まず考えられるのは、全ての内部のkeypress
ハンドラをkeydown
イベントハンドラで書き換えることでした。しかし、ひとつ問題があります。keypress
イベントは、keydown
のpreventDefault()
が呼び出されない限りは発火しなくてはいけません。ですので、先行するkeydown
イベントでのショートカットキーの実装は無理であると分かりました。
仕方ないので、keypress
イベントのリスナを、Gecko内部システムグループに全て書き換えることにしました。Geckoはイベントの発火を毎回2回ずつ行っており、最初の発火でデフォルトグループと呼ばれるリスナ(通常のWebアプリのリスナはすべてこちら)向けに発火し、その後、システムグループのリスナ向けに再発火しています。そう、本来は全てのGeckoもしくはFirefoxのデフォルトアクションは、システムグループのリスナで実装されていなければ、Webアプリのリスナとどちらが先に処理するかというレースが発生してしまうので、これは潜在的だったバグを全て修正していく作業になりました。そしてもちろん、この大きな修正は、大量の自動テストの修正が余儀なくされたり、多くのregressionを出しつつ、潰しつつ、という作業に終始しました。
そして最終的に、上述のデフォルトグループでの発火のみを停止し、Webアプリからはkeypress
イベントが、文字の入力がある場合にのみ発火するかのように見えるようになっています。
ちなみに、Enterキーの扱いのみが特殊です。そもそもEnterが押された場合、改行が行われますが、文字が入る訳ではありません。しかし、どのブラウザでもEnterキーが押された場合にはkeypress
イベントが発火するので、Geckoもそれにあわせています。しかし、モディファイアキーと組み合わせた場合にkeypress
イベントが発火するかどうかはブラウザ依存だったので、GeckoではShift+Enter、Ctrl+Enterはkeypress
イベントを発火するようにしています。特にCtrl+EnterはGeckoでは何も起きないのですが。
ちなみに、この修正はGoogleの検索チームから、これを修正しないとFirefox for AndroidのサポートをTier1から外したままにするよっていう宣告が来たのでかなりがんばって修正したんですが、この修正によって一番広範囲に壊れたのはGoogle Closure Libraryと、これをベースにしてるGoogle Docs等、Googleの他のチームのプロダクトだったというのがオチですかね……(Closureのチームと、Google Docsのチームは本当に大変な修正に尽力してくださったことに、あらためてお礼を言っておきます。ありがとうございました。)