Shiki’s Weblog

ESウェブブラウザ通信 - CSSの実装のバグを見つけてから直すまでの手順

2013/06/01 #ESウェブブラウザ通信

前回はescort 0.3.1の話とW3Cでのテストスイートの開発の話をまとめました。ESウェブブラウザは次のバージョン0.3.2では、escortがタブ ブラウザになる予定です。現状でも、GitHubのリポジトリから最新のソースを直接ビルトしてescortを実行すると既にタブが使えるようになっています。

タブブラウザ化したescort 0.3.2 (開発中のもの)タブブラウザ化したescort 0.3.2 (開発中のもの)

今回は久しぶりにCSSモジュールの開発・改善についての話題をまとめたいと思います。

CSSモジュールの実装の改善手順

ESウェブブラウザは、W3CのCSS 2.1テストスイートに関しては約92%のテストにパスするようになっていて、単純に数字の上ではメジャーなブラウザ並みの準拠率になっています。しかし、実際にインターネット上のサイトを表示させてみると、表示が崩れていたり、ブラウザごとクラッシュする場面がまだまだ多いのが現状です。その理由として、ひとつには、CSS 2.1テストスイートでは個々のCSSのプロパティーについてそれが想定通りに動いているかどうか、という最低限のテストにとどまっているものがほとんどだということが挙げられると思います。また仕様書通りの実装になっているかどうかという点のテストにウェイトが置かれているので、実際のウェブサイトではまったく使われないようなレイアウトを施したドキュメントのテストが結構ある一方で、実際のウェブサイトでよく使われるレイアウトを重点的にテストすることによってブラウザの実用性を向上させよう、というような種類のテストはあまりない、ということもあるように思います。たとえば、GitHubの6800297の段階で、人力検索はてなのページを表示しようとすると、下のような画面のところまで進んだ段階で StackingContext::addFloat の中の assert で必ず落ちてしまっていました。

人力検索はてなのページの処理中にクラッシュしたところ ( 6800297 )人力検索はてなのページの処理中にクラッシュしたところ ( 6800297 )

assertで停止してくれるバグは、バグの中ではまだ対処しやすい方なのですが(コーディング中に想定していたことと違うことが何かの原因で発生しているので、それを突き止めれば良い)、それでも700行以上のhtmlファイルを相手にソースコードとにらめっこというのは簡単ではありません。ですので、こういったバグが見つかったら、続いてバグを再現させることができる、できるだけ小さなhtmlドキュメントを作って、それでテストする、ということになります。補足 : ESウェブブラウザに限らず、一般的にソフトウェアのバグを報告するときは、できればここまで(バグを再現する最小手順を見つけるところまで)はバグの発見者側で行なって、バグを報告してあげるようにすると、開発サイドの人たちにはとても喜ばれることになります :-) で、今回見つかったバグを再現するために用意したhtmlファイルが、26行のcss-004.htmlになります。その中身は、 ・ フロート ・ 相対位置指定された、overflow: hiddenのインライン ブロック ・ インラインブロック ・ フロート という構造になっています。イレギュラーな処理が入るフロートやインライン ブロック、スタッキング コンテキストを作る相対位置指定、特にWebKitの製作者から仕様上の問題点を指摘されていたoverflow: hidden (できればこれもスタッキングコンテキストを作りたかった)、とこれだけ集まれば、未テストであればいかにも問題が起きそうな感じがします。(逆に言うと問題の起きたページから、問題の発生した要素からルートに向かって、通常の処理だけで済む要素を取り除いていくと、上記のような4要素だけが残るわけです。) assertで落ちた原因は内側のフロートを2回描画しようとしている、というものでしたので、css-003.htmlというもうひとつ小さなドキュメントを用意して、その問題を修正したのがb860795になります。このバグの原因は、ESウェブブラウザ内部では、インラインブロックは、インラインボックスとブロックボックスを2つ組み合わせて表現しているのですが、これが位置指定されていると、スタッキングコンテキストで処理するボックスとして2つとも登録されてしまっていて、子孫のフロートも2重に処理しようとしてしまっていた、というものでした。これは以前、インラインブロックはブロックボックス1つだけで表現するように修正するかもしれない、と書いていたようにもともとESウェブブラウザの設計上に問題があった部分ということになりそうです。で、この段階でcss-004.htmlはどうなったかというと、assertで落ちることはなくなったのですが、PASSというテキストが表示されないままでした。これはoverflowの処理にバグが残っていたもので(子孫の中で作られたフロートを処理できていなかった)、2fae4b2で修正しました。ここまで来ると人力検索はてなのページもだいぶ表示できるようになってきて、下の画面のような表示をして、そのままイベントループに入れるようになりました。

人力検索はてなのページを表示したところ ( 2fae4b2 )人力検索はてなのページを表示したところ ( 2fae4b2 )

まだ崩れているところが残っていますが、修正前の状況からはかなり改善することができました。

まとめ

CSSモジュールの実装では、ちょっとしたバグでも最終的に表示される画面に対する影響はとても大きかったりすることがわかります。今回のようにイレギュラーなレイアウト要素が複合的に絡んだ場合のテストについ ては、W3CのCSS 2.1テストスイートだけでは不十分なので、どう対処していくか、というのはESウェブブラウザに残っている課題のひとつです。最近のメジャーなサイトはHTML5などのAPIの実装も進んでいないと対応できない場合もあるので、単純にCSSの実装を進めていくだけではテストできなかったりするのも大変なところだったりします。建前としては、CSSとHTML/DOMは別モジュールなので(Selectors APIとか、もはやどっちなのかよくわからないのもありますが)、こつこつどちらも優先度をその都度設定しながら進めていく、という感じで今のところ進めています。というわけで今回はここまでです。次回は0.3.2のリリースに合わせて報告するような予定でいます。