Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13146] ファイルの概要

このコミットは、Go言語の実験的なHTMLパーサーライブラリ exp/html におけるテストデータの更新に関するものです。具体的には、WebKitのSubversionリポジトリ(SVNリビジョン118111)から最新のテストデータを取り込み、既存のテストがHTML5の仕様に準拠していなかったために発生していた失敗を修正しています。

コミット

commit e947eba2914d707514ca54bebef3c9cd1e23c86a
Author: Andrew Balholm <andybalholm@gmail.com>
Date:   Thu May 24 10:35:31 2012 +1000

    exp/html: update test data
    
    Import updated test data from the WebKit Subversion repository (SVN revision 118111).
    
    Some of the old tests were failing because we were HTML5 compliant, but the tests weren't.
    
    R=nigeltao
    CC=golang-dev
    https://golang.org/cl/6228049

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e947eba2914d707514ca54bebef3c9cd1e23c86a

元コミット内容

exp/html: update test data

WebKit Subversionリポジトリ(SVNリビジョン118111)から更新されたテストデータをインポートしました。

古いテストの一部は、我々(exp/htmlライブラリ)がHTML5に準拠しているにもかかわらず、テスト自体が準拠していなかったために失敗していました。

変更の背景

このコミットの背景には、Web標準の進化と、それに追従するHTMLパーサーの実装、そしてそのテストの重要性があります。

Go言語の exp/html パッケージは、HTML5仕様に準拠したHTMLパーサーを提供することを目指していました。HTML5は、それまでのHTML4やXHTMLとは異なり、より厳密な構文規則と、ブラウザの既存の挙動を反映したエラー処理規則を定義しています。Webブラウザは、たとえHTMLが不正な形式であっても、可能な限りレンダリングを試みるため、その「エラー回復」の挙動もHTML5仕様の一部として定義されています。

WebKitは、SafariやGoogle Chromeなどの主要なブラウザエンジンで採用されているオープンソースのレンダリングエンジンです。WebKitプロジェクトは、HTML、CSS、JavaScriptなどのWeb標準の解釈とレンダリングに関する広範なテストスイートを維持しています。これらのテストは、ブラウザの実装がWeb標準にどれだけ忠実であるかを検証するために非常に重要です。

exp/html パッケージは、WebKitのテストデータを利用することで、そのパーサーが実際のブラウザの挙動、特にエラー処理やDOMツリー構築の挙動を正確に模倣していることを確認しようとしていました。しかし、WebKitのテストデータもHTML5仕様の進化に合わせて更新されていきます。

このコミットが行われた2012年5月時点では、HTML5仕様はまだW3C勧告にはなっていませんでしたが、活発に開発が進められていました。exp/html パッケージがHTML5の最新のドラフト仕様に準拠するように実装を進める中で、古いWebKitのテストデータが、もはや現在のHTML5仕様に合致しないケースが出てきました。具体的には、exp/html がHTML5に「準拠」しているがゆえに、古いテストデータが期待する結果と異なる結果を返す、という状況が発生していました。これは、テストデータ自体が古いHTML仕様や、HTML5の古いドラフトに基づいて作成されていたためです。

この不一致を解消し、exp/html パッケージが最新のHTML5仕様に準拠していることを正確に検証するために、WebKitのテストデータを最新のリビジョン(SVNリビジョン118111)に更新する必要がありました。これにより、exp/html のパーサーがHTML5の最新の挙動を正しく解釈していることを確認し、テストの信頼性を向上させることが目的です。

前提知識の解説

HTML5とパーシング

HTML5は、Webコンテンツの構造と意味を定義する最新のHTML標準です。HTML5のパーシング(構文解析)は、単に正しいHTMLを解析するだけでなく、不正なHTML(タグの閉じ忘れ、不正なネストなど)に対しても、ブラウザがどのようにエラー回復を行うかを厳密に定義しています。これは「エラー回復アルゴリズム」と呼ばれ、ブラウザ間の互換性を保証するために非常に重要です。

HTMLパーサーは、HTMLドキュメントを読み込み、それをDOM(Document Object Model)ツリーと呼ばれる構造に変換します。DOMツリーは、HTMLドキュメントの論理的な構造を表現し、JavaScriptなどからアクセスして操作することができます。

WebKitとテストデータ

WebKitは、Appleが開発を主導し、Google Chrome(Blinkエンジンにフォークする前)やSafariなどで使用されているオープンソースのWebブラウザエンジンです。WebKitは、HTML、CSS、JavaScriptのレンダリングと実行を担当します。

WebKitプロジェクトは、Web標準への準拠を保証するために、非常に広範なテストスイートを維持しています。これらのテストは、特定のHTMLスニペットがどのように解析され、どのようなDOMツリーが構築されるか、どのようなエラーが報告されるかなどを検証します。WebKitのテストデータは、通常、以下のような形式で記述されています。

  • #data: テスト対象のHTMLスニペット。
  • #errors: そのHTMLスニペットを解析した際に期待されるエラーメッセージと行番号。
  • #document: そのHTMLスニペットから構築される期待されるDOMツリーの構造。

これらのテストデータは、ブラウザエンジンのHTMLパーサーがWeb標準にどれだけ正確に準拠しているかを検証するためのリファレンスとして機能します。

Subversion (SVN)

Subversionは、Gitが登場する以前に広く使われていた集中型バージョン管理システムです。リポジトリは単一のサーバー上に存在し、開発者はそこからファイルをチェックアウトし、変更をコミットします。WebKitプロジェクトは、このコミットが行われた時点ではSubversionを使用していました。SVNリビジョンは、リポジトリへのコミットごとに増加する一意の番号です。

Go言語の exp/html パッケージ

exp/html は、Go言語の標準ライブラリの一部として最終的に組み込まれることを目指して開発されていた実験的なHTMLパーサーパッケージです。このパッケージは、HTML5の仕様に厳密に準拠したパーシング機能を提供することを目的としていました。

技術的詳細

このコミットの技術的詳細は、HTML5のパーシング仕様の厳密さと、それをテストするためのWebKitのテストデータの構造に集約されます。

HTML5のパーシングアルゴリズムは、非常に複雑で、多くの状態遷移とエラー回復ルールを含んでいます。例えば、<table> 要素の内部に不正な要素が挿入された場合、ブラウザはそれをどのように処理し、DOMツリーを構築するか、といった具体的な挙動が定義されています。また、<!DOCTYPE html> の有無や、特定の要素の閉じタグの省略可能性なども、パーシング結果に影響を与えます。

WebKitのテストデータファイル(例: pending-spec-changes.dat, tables01.dat など)は、複数のテストケースをまとめて含んでいます。各テストケースは、#data#errors#document のセクションで構成されます。

  • #data: 入力となるHTML文字列。
  • #errors: HTMLパーサーがこの入力に対して報告すべきエラーのリスト。エラーメッセージ、行番号、列番号が含まれることがあります。
  • #document: 入力HTMLが解析された結果として構築されるDOMツリーのテキスト表現。これは、要素のネスト、属性、テキストノードなどがインデントされた形式で示されます。

このコミットでは、exp/html パッケージがHTML5の最新の仕様に準拠するように実装された結果、古いWebKitテストデータが期待するDOMツリーやエラーリストと、exp/html が実際に生成する結果との間に不一致が生じました。これは、exp/html が「正しく」HTML5に準拠しているにもかかわらず、テストが「古い」仕様に基づいていたために発生した「テストの失敗」です。

例えば、pending-spec-changes.dat の変更を見ると、<table><tr><td><svg><desc><td></desc><circle> というHTMLスニペットに対して、新しいテストデータではより多くのエラーが期待され、DOMツリーの構造もよりHTML5の厳密な解釈に沿ったものになっています。特に、SVG要素やMathML要素のような「外部名前空間 (foreign namespace)」の要素がHTMLコンテンツ内に埋め込まれた場合のパーシング挙動は、HTML5で詳細に定義されており、このあたりのテストケースが更新されたと考えられます。

また、plain-text-unsafe.dat のようなバイナリファイルの更新は、おそらく特定の文字エンコーディングや、NULLバイトなどの特殊文字がHTMLコンテンツに含まれる場合のパーシング挙動に関するテストデータが更新されたことを示唆しています。

このコミットは、exp/html パッケージがWeb標準の進化に追従し、その正確性を維持するための継続的な努力の一環として行われました。テストデータの更新は、パーサーの品質を保証し、将来的な互換性の問題を回避するために不可欠な作業です。

コアとなるコードの変更箇所

このコミットでは、Go言語のソースコード自体(.goファイル)の変更は含まれていません。変更のほとんどは、src/pkg/exp/html/testdata/webkit/ ディレクトリ内のテストデータファイル(.datファイル)と、それに対応するテストログファイル(.dat.logファイル)です。

具体的に変更されたファイルは以下の通りです。

  • src/pkg/exp/html/testdata/webkit/pending-spec-changes.dat
  • src/pkg/exp/html/testdata/webkit/plain-text-unsafe.dat (バイナリファイルの変更)
  • src/pkg/exp/html/testdata/webkit/tables01.dat
  • src/pkg/exp/html/testdata/webkit/tests16.dat
  • src/pkg/exp/html/testdata/webkit/tests19.dat
  • src/pkg/exp/html/testdata/webkit/tests26.dat
  • src/pkg/exp/html/testdata/webkit/tests_innerHTML_1.dat
  • src/pkg/exp/html/testdata/webkit/webkit01.dat
  • src/pkg/exp/html/testdata/webkit/webkit02.dat

そして、これらのテストデータに対応するログファイルも更新されています。

  • src/pkg/exp/html/testlogs/pending-spec-changes.dat.log
  • src/pkg/exp/html/testlogs/plain-text-unsafe.dat.log
  • src/pkg/exp/html/testlogs/tables01.dat.log
  • src/pkg/exp/html/testlogs/tests16.dat.log
  • src/pkg/exp/html/testlogs/tests19.dat.log
  • src/pkg/exp/html/testlogs/tests26.dat.log
  • src/pkg/exp/html/testlogs/tests_innerHTML_1.dat.log
  • src/pkg/exp/html/testlogs/webkit01.dat.log
  • src/pkg/exp/html/testlogs/webkit02.dat.log

これらの .dat ファイルは、入力HTML、期待されるエラー、期待されるDOMツリー構造を定義するプレーンテキストファイルです。.dat.log ファイルは、テスト実行結果のログであり、どのテストケースが PASS(成功)または FAIL(失敗)したかを示します。

コアとなるコードの解説

このコミットにおける「コアとなるコード」は、Go言語の exp/html パッケージの内部実装ではなく、更新されたWebKitのテストデータそのものです。これらの .dat ファイルは、exp/html パーサーの挙動を検証するための入力と期待される出力の仕様を定義しています。

いくつかの例を挙げます。

pending-spec-changes.dat の変更点

--- a/src/pkg/exp/html/testdata/webkit/pending-spec-changes.dat
+++ b/src/pkg/exp/html/testdata/webkit/pending-spec-changes.dat
@@ -26,3 +26,27 @@
 |         <svg svg>
 |           "foo"
 |     "bar"
++
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+7: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+30: A table cell was implicitly closed, but there were open elements.
+26: Unclosed element “desc”.
+20: Unclosed element “svg”.
+37: Stray end tag “desc”.
+45: End of file seen and there were open elements.
+45: Unclosed element “circle”.
+7: Unclosed element “table”.
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             <svg svg>
+|               <svg desc>
+|           <td>
+|             <circle>

この変更は、新しいテストケースを追加しています。 入力HTMLは <table><tr><td><svg><desc><td></desc><circle> です。 このHTMLは、テーブル要素の内部にSVG要素が不正にネストされており、さらにその中に desccircle といったSVG要素が不適切に配置されています。 新しい #errors セクションは、この不正なHTMLに対するHTML5パーサーが報告すべきエラーを詳細に定義しています。例えば、「Start tag seen without seeing a doctype first.」や「A table cell was implicitly closed, but there were open elements.」といったエラーは、HTML5の厳密なエラー回復ルールに基づいています。 #document セクションは、この不正なHTMLがどのようにDOMツリーに変換されるべきかを示しています。特に、<td> の内部に svg があり、その中にさらに svg desc がネストされ、その後に別の <td> が現れるという、ブラウザのエラー回復挙動が反映されています。

tests19.dat の変更点

--- a/src/pkg/exp/html/testdata/webkit/tests19.dat
+++ b/src/pkg/exp/html/testdata/webkit/tests19.dat
@@ -173,7 +173,7 @@
 |     <ruby>
 |       <div>
 |         <span>
-|       <rp>
+|           <rp>
 
 #data
 <!doctype html><ruby><div><p><rp>
@@ -186,7 +186,7 @@
 |     <ruby>
 |       <div>
 |         <p>
-|       <rp>
+|         <rp>
 
 #data
 <!doctype html><ruby><p><rt>
@@ -211,7 +211,7 @@
 |     <ruby>
 |       <div>
 |         <span>
-|       <rt>
+|           <rt>
 
 #data
 <!doctype html><ruby><div><p><rt>
@@ -224,7 +224,7 @@
 |     <ruby>
 |       <div>
 |         <p>
-|       <rt>
+|         <rt>
 
 #data
 <!doctype html><math/><foo>
@@ -1218,3 +1218,20 @@
 |     <plaintext>
 |       <a>
 |         "b"
++
+#data
+<!DOCTYPE html><div>a<a></div>b<p>c</p>d
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+|   <head>
+|   <body>
+|     <div>
+|       "a"
+|       <a>
+|     <a>
+|       "b"
+|       <p>
+|         "c"
+|       "d"

この変更では、ruby 要素内の rprt 要素のネストに関するDOMツリーの期待値が修正されています。インデントの変更は、DOMツリーの構造がより正確に表現されるようになったことを示唆しています。 また、<!DOCTYPE html><div>a<a></div>b<p>c</p>d という新しいテストケースが追加されています。これは、不正な閉じタグ </div> がどのように処理され、その後のテキストや要素がどのようにDOMツリーに組み込まれるかをテストしています。期待されるDOMツリーは、div の後に a が続き、その後にテキストノード "b"、そして p 要素が続くという、ブラウザのエラー回復挙動を反映したものです。

これらの変更は、exp/html パーサーがHTML5の最新の仕様、特にエラー回復とDOMツリー構築のルールに、より厳密に準拠していることを検証するために不可欠です。

関連リンク

参考にした情報源リンク

  • コミットメッセージ内の https://golang.org/cl/6228049 (Go Code Review)
  • WebKitのSubversionリポジトリ (コミット時点での情報であり、現在はGitに移行している可能性が高い)
  • HTML5パーシングアルゴリズムに関するドキュメント
  • Go言語の html パッケージのドキュメント (現在の golang.org/x/net/html)