久しぶりにBugzilla-jpに報告されたバグの修正です。maxlength
が指定されている<input>
要素で既に限界まで文字が入力されている状態で、IMEで文字列を入力して確定すると、未確定文字列がそのまま残り、value
プロパティ値には含まれてしまっているため、制限文字数を超えて入力できてしまう、というバグです。
原因は、maxlength
に到達している段階で文字を入力しようとすると、そのまま処理を中断するように修正されていたことでした。
未確定文字列は内部では独立したテキストノードとして挿入されていて、さらにこのテキストノードを内部処理用の特殊な選択範囲で選択していることにしています。今までは文字列がまったく入力できない状態でも、この未確定文字列を掃除する処理が走っていたのですが、前述の修正でこれまでスキップされるようになっていました。
IMEによる文字列の挿入時にはショートカットしないように修正して解決しています。
ちなみに、今回のように、ブラウザのバグで制限文字数を超えた値がサーバに送信されてしまう可能性もありますが、意図的な攻撃でそうなる可能性もありますので、Webアプリの開発者の方は必ず値の妥当性は検査するのを忘れないようにしてください。
WindowsでVista以降、WM_MOUSEWHEEL
やWM_MOUSEHWHEEL
のデルタ値が基準の120よりも小さい値をマウスのユーティリティが利用できるようになりました。このため、例えば1回のホイールイベントで0.5行だけスクロールする、といったイベントが利用できるようになりました。しかし、Geckoでは最低、1行分のデルタ値がたまったときに初めてスクロールを行っていました。
今回、Logitech (日本ではLogicool)のマウス・キーボードチームのマネージャの方からの要請で、彼らのドライバの精度に十分に対応できるように修正しました。
Macでは以前から、トラックパッドのスクロールイベントはOSからピクセル単位で発生していたため、Gecko内部のホイールイベントに、ピクセルスクロール、というものがありました。本格的に小数の精度でスクロールする処理に対応すると作業量が多いので、ひとまず、これを利用したアドホックなやり方で対応しようというのが今回の修正のテーマでしたが、ここに色々と落とし穴があって、現在もregression対応に追われています。
どのように実装したのかというと、小さなデルタ値で上記メッセージを受け取ったら、ひとまずそれが、何行分のスクロールになるのかを小数込みで計算します。このとき、1行以上であれば、その行数分のホイールイベントを発行します。そして、1未満の小数部分を未送信のデルタ値として保存しておきます。
この内部イベントの生成時に、スクロールターゲットの行高等を確認し、ネイティブイベントのデルタ値で何ピクセルスクロールすべきなのかを、やはり小数を含めて計算し、ピクセルスクロールイベントを生成します。当然、余った1ピクセル未満の端数は内部で保存しておきます。
実際のスクロールは、通常はピクセルスクロールイベントで行われます。XULのツリー等、行単位でしかスクロールできない要素は、ピクセルスクロールは無視し、従来からあるホイールスクロールイベントを利用します。
そして、それ以降に来るネイティブイベントは、保存してある端数を考慮して同様に処理していきます。
これにより、高精度なホイールイベントを生成するマウスを持っている方は、スムーズスクロールを有効にしなくても、今までよりもなめらかなスクロールが行える様になりました。しかし、副作用として当然、それだけ再描画回数が増えるのでスクロール時の負荷は高くなっています。
マイクロソフトのマウスでは設定値にもよりますが、あまり修正前と動作に違いはありません。また、OS標準のドライバをそのまま利用する安価なマウスでも効果はありません。Logitech (日本ではLogicool)のSetPoint 6.20以降だとかなり精度の高い数字でイベントを生成するので効果があります。ただし、同じLogitech (日本ではLogicool)製のマウスでもゲーミングマウスは高精度なイベントを生成しませんのでご注意ください。
上記の解説の通り、Webコンテンツ作者から見た場合にほとんど動作に差異は無いと思われますが、DOMMouseScroll
イベントと、スクロールのlistener
を併用している場合、処理順序が変わることになりますのでご注意ください。