Shiki’s Weblog

ESウェブブラウザ通信 - CSS 2.1 Test Suite #1

2011/09/28 #ESウェブブラウザ通信

前回はESウェブブラウザがAcid1テストをパスするようになったところまで進めました。その後は、CSS オフィシャル W3C テスト スイートを使って、ESウェブブラウザでこれまで実装してきた部分のテストを進めています。今回は、テストスイートのChapter 1, Chapter 2と、Chapter 8の8.3.1 Collapsing marginsの手前までで、ESブラウザで実装が入っている部分のテストについてまとめていきます。
CSSの実装にあたっては、CSSの仕様書を読みながら進めてきたわけですが、仕様書の文章だけからではどうしても解釈違い、文章の見落としなどが重なって、実装が仕様通りになっていない、という問題が発生しがちです。(こういった問題はCSSに限らずTCP/IPプロトコルなどでも緊急ポインタの位置の解釈などで問題を起こしていましたよね。)
CSS オフィシャル W3C テスト スイートは、こういった問題がなるべく起きないように、仕様書の編集者やブラウザの開発者などが作成したテストページをまとめたものです。特にCSS 2.1に関してはマイクロソフト社から提供されたページが7,000ページ以上になるとのことで、ESブラウザの開発にあたっても有用なテストスイートになっているように思います。

The only way to know if a browser has correctly implemented a specification is to develop a comprehensive set of tests for the specification.

Jason Upton, Test Manager, Internet Explorer

shand-border-000

テストスイートの一番最初のテストです。shand-border-000は、border-colorの計算値(computed value)は、border-colorが未指定の場合は要素のcolorプロパティの計算値を使用する、という規則になっているのを実装できているかどうかテストしています。
正しくブラウザが実装されてれば、テキストのまわりのボーダーは緑色で表示されるはずなのですが、r1963では以下のとおり黒色で表示してしまっていました。(このセクションの見出しの部分を最近のCSS 2.1に準拠しているブラウザで表示すれば正しい結果が見られるはずです。)

r1963

r1963では、border-colorは文法的には通常のcolorと同じなので、実装でもcolor用CSSColorValueImpクラスを使っていたために上記のような結果になっていました。
r1964では、新たにCSSBorderColorValueImpクラスを導入して、この問題を修正しました。

r1964


c45-bg-canvas-000

このテストはHTMLのhtml要素とbody要素に別々に'background'の指定をした場合の動作をテストしています。

r1965r1965

このr1965の状態でもテストが本来テストしている部分に関してはokなのですが、テキストの上下に紺色の部分があるのは正常ではないので、ついでに修正していきます。
r1966では、 CSSの"White space content that would subsequently be collapsed away according to the 'white-space' property does not generate any anonymous inline boxes."という規則の実装が入っていなかったのを追加しました。

r1966r1966

テキストの下側の紺色の部分がなくなっています。HTMLソースファイル中の以下の部分、

page. Around it on all sides should be purple.</p> </body>

は、DOMツリーに展開されると、改行だけ含んだテキストノードがbodyの最後の子ノードとして追加されます。本来は、このDOMツリーがCSSのレンダーツリーに変換されるときに、'white-space'の設定に従って改行文字は消されるので、これを含んだ匿名ボックスも生成されないという具合になります。
ESウェブブラウザの実装では、匿名、非匿名に関わらずブロックレベルボックスだけを先にすべて展開してしまって、後から個々のブロックレベルボックス内のラインボックスなどをレイアウトしていく、という具合になっています。そのため、r1965ではこの不要な匿名ボックスの分だけ下側に紺色の部分が表示されていたのでした。そこで、1966では先に生成してしまった不要な匿名ボックスを後から削除するという処理を行っています。
r1968では、マージンのつぶし処理を修正して、なるべく外側(ツリーのルート側)のボックスにマージンを残すようにしました。ボックスの座標配置自体はそれまででもよかったのですが、マージンを内側のボックスにまとめてしまっていたので、本来透明の筈の背景部分を違う色で塗ってしまっていたのでした。

r1968r1968

これでこのテストは大丈夫そうです。
margin-backgrounds-001
続いて、3章から飛ばして、8章'Box model'の方に進みました。CSSのボックスモデルは一番基本的なところなので、この部分の実装でおかしい箇所はなるべく早めにとっておきたい、というのが理由です。

このテストは単純にマージンが背景色で塗られることなく表示されるかどうかテストするだけなのですが、r1968では、テキストの下側のマージンがなくなってしまっています。(ちなみにこのテストも最初に書いたマイクロソフト社から提供されたテストのようです。各テストとも、ソースには"author"の記載があるのでわかります。)

r1968r1968

r1966では、不要な匿名ボックスを削除する様にしたわけですが、この不要な匿名ボックスと直前のテキストを含んだブロックボックスとの間でマージンのつぶし処理が先に行われていて、匿名ボックスを削除した時に一緒にマージンまでなくなっていたのでした。

r1970では、匿名ボックスを削除する際につぶしたマージンを元に戻すように修正しました。

r1970r1970

margin-001

このテストでは赤い線と緑の線がぴったり重ならないといけないのですが、r1970では右辺がずれています。

r1970r1970

これは仕様の読み違いでした。左右のマージンと幅がすべて'auto'以外に設定されていると、"If all of the above have a computed value other than 'auto', the values are said to be "over-constrained" and one of the used values will have to be different from its computed value."という条件に当てはまると想定して、右のマージンの設定を無視するようになっていたのでした。

実際には、 "over-constrained"でも、包含ボックスの幅が足りないときは右マージンの値はそのままでよくて、はみ出る部分の表示は'visibility'の設定に任せればよいわけですね。こういった仕様書の読み違いもテストが用意されていればちゃんとチェックできる、という良い例だと思います。

r1972でこの問題を修正しています(r1978でもさらにこの問題の修正が追加されています)。

r1972r1972

margin-bottom-103

このテストはマージンに負の値を指定した場合の動作をテストするものです。r1972ではまだ負のマージンに対応していなかったので下記の通り表示が崩れていました。

r1972r1972

r1973では負のマージンが指定された場合のシンプルなケースについて対応するコードを追加しました。より複雑なケースはテストスイートの§8.3.1でテストするのでここではとりあえずの修正になっています。

r1973r1973

マージンのテストとしてはこれで良いのですが、r1973では赤い線の幅が広くなりすぎています。これはグーグルのページを表示するためにとりあえず入れておいた(正しくない)修正の所為でしたので、再度r1974で修正しています。

r1974r1974

margin-left-112

このテストはwidthがauto以外で包含ボックスの幅が足りないときに、"any 'auto' values for 'margin-left' or 'margin-right' are, for the following rules, treated as zero."というルールのテストになっています。r1976ではその実装が入っていなかったので、以下のような具合でした。

r1976r1976

r1977,r1978で対応して下記の様に正常になりました。

r1977r1977

margin-inline-001

このテストはインラインボックスのマージンのテストです。r1979ではかなり崩れていました。

r1979r1979

これは仕様書のどこと対応付いているのか微妙な感じもするのですが、10.6.1の"The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height' ."でしょうか。当たり前のことを書いてあるだけのような気もしますが、ESウェブブラウザの実装であれば、ボックスを並べるときに普通は原点はマージンエッジの左上角にあるものが、インラインのボックスだとコンテンツエッジの上端とマージンエッジの左端の交点に移る感じで考えると良さそうです(Firefoxのfirebugで要素を調査したときの表示が分かりやすいと思います)。

ふつうのボックスの原点ふつうのボックスの原点

インラインボックスの原点インラインボックスの原点

r1980,r1982でこの修正を入れています。

r1980r1980

このテストで調査している範囲としてはこれでも良いのですが、見た感じ気持ち悪いので、行末の空白を'white-space'の設定に応じて削除する処理をr1984で実装しています。

r1984r1984

margin-percentage-inherit-001

このテストは親要素でmarginをパーセントで指定しているときに、それをinheritで継承した場合の処理をチェックしています。r1984では以下の様に崩れていました。

r1984r1984

これも仕様書の読み違いで、inheritで継承する値を計算値ではなくて、決定値(resolved value)を継承する様になっていたのでした。r1985では、この問題を修正しました。

r1985r1985

この辺でESウェブブラウザで実装が入っている部分に関して、Microsoft社から提供された8.3.1 Collapsing marginsの手前までのマージン関連のテストについてはほぼ通るようになってきました。

c411-vt-mrgn-000

CSSのテストスイートの方にはまだ難しめのテストが残っています。このテストは、HTMLのスペック エディタとしても有名なHixieが作成したテストのひとつです。

r1985r1985

左右で同じパターンが表示されればOKなのですが、下から3ブロック目の水色の矩形の位置がずれているのと、幅が半分の白い矩形(p.ten)が表示されていないのがエラーのある部分です。(一番下側の矩形の色が左右で違うのはHTMLのtableのセルの高さの処理が完全でないためのものでマージンの処理とは無関係です。)
このテストでは白い矩形(p.ten)がfloat要素でこれを含んだブロックボックスの高さは0になります。高さ0のブロックボックスの上端と下端のマージンはつぶし合うことができるのですが、その処理が未実装でしたので、r1986でその実装をしています。

r1986r1986

ただこういったマージンのつぶしのテストは 8.3.1 Collapsing margins のテストスイートに個別のものがあるような感じなので、こういった複合的なテストは後回しにしても良さそうな感じですね。

今回はここまでです。かなり基本的な部分でも仕様書を読み違えていたりして、改めてこういったテストスイートの重要性を感じます。次回も基本的なテストを中心にいま既に実装がある部分のバグ修正を中心に進めていきます。