[インデックス 10304] ファイルの概要
このコミットは、Go言語のHTMLパーサーライブラリ(src/pkg/html
)におけるHTMLドキュメントのパースロジックの改善に関するものです。特に、<head>
要素内で不正な</html>
タグが検出された場合の挙動と、それに続く要素の解釈をHTML5のパースアルゴリズムに準拠させることを目的としています。これにより、より堅牢で標準に準拠したHTMLパースが可能になります。
コミット
commit 820523d09186bd9c7078338803e41c8592158110
Author: Andrew Balholm <andybalholm@gmail.com>
Date: Wed Nov 9 19:18:26 2011 +1100
html: correctly parse </html> in <head> element.
Pass tests1.dat, test 92:
<head></html><meta><p>
| <html>
| <head>
| <body>
| <meta>
| <p>
Also pass tests through test 98:
<p><b><div><marquee></p></b></div>
R=nigeltao
CC=golang-dev
https://golang.org/cl/5359054
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/820523d09186bd9c7078338803e41c8592158110
元コミット内容
このコミットの目的は、HTMLパーサーが<head>
要素内で</html>
タグを正しく解釈するように修正することです。具体的には、以下のテストケースをパスするようにします。
<head></html><meta><p>
という入力に対して、以下のようなDOM構造を生成する。<html> <head> <body> <meta> <p>
- また、テストスイートの
tests1.dat
において、テスト98までのテストケースがパスするように改善されます。これは、<p><b><div><marquee></p></b></div>
のような、タグのネストが不正なケースも含まれます。
変更の背景
HTMLは非常に寛容な言語であり、多くのブラウザは不正なマークアップに対してもエラーを発生させることなく、ある程度の推測に基づいてDOMツリーを構築します。これは「エラー回復(Error Recovery)」または「タグスープ(Tag Soup)」の処理として知られています。HTML5の仕様では、このエラー回復の挙動が詳細に定義されており、ブラウザ間の互換性を高めるために、パーサーはこれらのルールに従う必要があります。
このコミット以前のGoのHTMLパーサーは、<head>
要素内で予期せぬ</html>
タグが来た場合に、HTML5の仕様に完全に準拠した挙動をしていなかった可能性があります。HTML5のパースアルゴリズムでは、特定のタグが特定のコンテキストで出現した場合、暗黙的に要素が閉じられたり、新しい要素が開始されたりするルールが存在します。例えば、<head>
要素の内部で<body>
や<html>
、あるいは</br>
のようなタグが検出された場合、それは<head>
要素が終了し、<body>
要素が開始されたと解釈されるべきです。
この修正は、GoのHTMLパーサーがより多くの「タグスープ」なHTMLドキュメントを、主要なブラウザと同じように解釈できるようにするための重要なステップです。これにより、GoでHTMLをパースするアプリケーションが、より広範なWebコンテンツに対して堅牢になります。
前提知識の解説
このコミットを理解するためには、以下の概念が重要です。
-
HTML5パースアルゴリズム: HTML5の仕様は、HTMLドキュメントをバイトストリームからDOMツリーに変換する詳細なアルゴリズムを定義しています。このアルゴリズムは、トークン化フェーズとツリー構築フェーズの2つの主要なフェーズに分かれています。
- トークン化フェーズ: 入力バイトストリームをHTMLトークン(開始タグ、終了タグ、テキスト、コメントなど)に変換します。
- ツリー構築フェーズ: トークンストリームを受け取り、DOMツリーを構築します。このフェーズは、現在の「挿入モード(Insertion Mode)」に基づいて動作します。
-
挿入モード(Insertion Mode): ツリー構築フェーズの核心となる概念です。HTMLパーサーは、ドキュメントの現在の状態に応じて異なる「挿入モード」を持ちます。各挿入モードは、特定のトークンが検出されたときにDOMツリーをどのように変更するかを定義する一連のルールを持っています。例えば、
<head>
要素の内部にいるときは「in head」モード、<body>
要素の内部にいるときは「in body」モードなどがあります。 -
エラー回復(Error Recovery): HTMLの仕様は、不正なマークアップが検出された場合にパーサーがどのように振る舞うべきかを厳密に定義しています。これは、ブラウザが異なる不正なHTMLを同じように解釈し、一貫したDOMツリーを生成することを保証するためです。例えば、閉じタグが欠落している場合や、タグのネストが不正な場合でも、パーサーはエラーを報告するのではなく、最も妥当なDOM構造を推測して構築します。
-
暗黙的な要素の終了/開始: HTML5パースアルゴリズムの重要な側面の一つは、特定のタグが検出されたときに、明示的な閉じタグがなくても現在の要素が暗黙的に閉じられ、新しい要素が開始される場合があることです。例えば、
<p>
要素の内部で別の<p>
タグが検出された場合、最初の<p>
は自動的に閉じられます。同様に、<head>
要素の内部で<body>
タグが検出された場合、<head>
は閉じられ、<body>
が開始されます。
技術的詳細
このコミットの技術的な核心は、GoのHTMLパーサーがHTML5のツリー構築アルゴリズムにおける「in head」および「after head」挿入モードでの終了タグの処理を改善した点にあります。
inHeadIM
関数 (in head 挿入モード)
inHeadIM
関数は、パーサーが<head>
要素の内部にいるときの挙動を定義します。HTML5の仕様では、<head>
要素の内部で特定の終了タグが検出された場合、それは<head>
要素の暗黙的な終了と解釈されます。
- 変更前: 終了タグが
</head>
の場合のみ、pop
(現在の要素をスタックからポップする、つまり<head>
を閉じる)処理を行っていました。他の終了タグはTODO
コメントがあり、適切に処理されていませんでした。 - 変更後:
EndTagToken
が検出された場合、そのタグのデータ(名前)に基づいて以下のように処理を分岐します。"head"
: これは<head>
の明示的な閉じタグなので、pop = true
として<head>
要素を閉じます。"body"
,"html"
,"br"
: これらの終了タグが<head>
要素の内部で検出された場合、HTML5の仕様では<head>
要素が暗黙的に閉じられ、パーサーは「in body」モードに移行すべきとされています。この変更ではimplied = true
を設定することで、この暗黙的な終了をトリガーします。- 上記以外の終了タグ: これらの終了タグは
<head>
要素の内部では無視されるべきです。return inHeadIM, true
とすることで、現在の挿入モードを維持し、トークンを無視します。
この修正により、<head></html><meta><p>
のような入力が与えられた場合、</html>
が<head>
内で検出されると、<head>
が閉じられ、<body>
が暗黙的に開始されるようになります。その結果、<meta>
と<p>
は<body>
の子として正しくパースされます。
afterHeadIM
関数 (after head 挿入モード)
afterHeadIM
関数は、パーサーが<head>
要素を処理し終えた後(通常は<body>
要素の開始前または内部)の挙動を定義します。
- 変更前:
EndTagToken
の処理はTODO
コメントとなっており、実装されていませんでした。 - 変更後:
EndTagToken
が検出された場合、そのタグのデータ(名前)に基づいて以下のように処理を分岐します。"body"
,"html"
,"br"
: これらの終了タグがこのモードで検出された場合、HTML5の仕様では、現在のコンテキスト(例えば、<body>
や<html>
)が暗黙的に閉じられるべきであり、framesetOK
フラグが設定されるべきです。implied = true
とframesetOK = true
を設定することで、この挙動を実装します。- 上記以外の終了タグ: これらの終了タグは無視されるべきです。
return afterHeadIM, true
とすることで、現在の挿入モードを維持し、トークンを無視します。
この修正は、特に<body>
要素がまだ明示的に開始されていない状態で</body>
や</html>
のような終了タグが来た場合に、パーサーが正しくエラー回復を行うために重要です。
テストケースの拡張
src/pkg/html/parse_test.go
の変更は、tests1.dat
から読み込むテストケースの数を92から99に増やしています。これは、上記のパースロジックの改善により、より多くのHTML5適合性テストがパスするようになったことを示しています。tests1.dat
は、HTML5のパースアルゴリズムのテストスイートの一部であり、様々なエッジケースや不正なマークアップの処理を検証するために使用されます。
コアとなるコードの変更箇所
src/pkg/html/parse.go
--- a/src/pkg/html/parse.go
+++ b/src/pkg/html/parse.go
@@ -470,10 +470,15 @@ func inHeadIM(p *parser) (insertionMode, bool) {
im = true
}
case EndTagToken:
- if p.tok.Data == "head" {
+ switch p.tok.Data {
+ case "head":
pop = true
+ case "body", "html", "br":
+ implied = true
+ default:
+ // Ignore the token.
+ return inHeadIM, true
}
- // TODO.
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
@@ -524,7 +529,14 @@ func afterHeadIM(p *parser) (insertionMode, bool) {
framesetOK = true
}
case EndTagToken:
- // TODO.
+ switch p.tok.Data {
+ case "body", "html", "br":
+ implied = true
+ framesetOK = true
+ default:
+ // Ignore the token.
+ return afterHeadIM, true
+ }
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
src/pkg/html/parse_test.go
--- a/src/pkg/html/parse_test.go
+++ b/src/pkg/html/parse_test.go
@@ -133,7 +133,7 @@ func TestParser(t *testing.T) {
n int
}{
// TODO(nigeltao): Process all the test cases from all the .dat files.
- {"tests1.dat", 92},
+ {"tests1.dat", 99},
{"tests2.dat", 0},
{"tests3.dat", 0},
}
コアとなるコードの解説
src/pkg/html/parse.go
このファイルは、Go言語のHTMLパーサーの主要なロジックを含んでいます。特に、HTML5のツリー構築アルゴリズムにおける様々な「挿入モード」を実装しています。
-
inHeadIM
関数:- この関数は、パーサーがHTMLドキュメントの
<head>
要素の内部にいるときに呼び出される挿入モードハンドラです。 - 変更の核心は、
EndTagToken
(終了タグ)が検出された際のswitch
文の追加です。 case "head"
: これは<head>
要素の正規の閉じタグです。pop = true
とすることで、パーサーの要素スタックから<head>
要素をポップし、その要素を閉じます。case "body", "html", "br"
: HTML5の仕様では、<head>
要素の内部でこれらの終了タグが検出された場合、それは<head>
要素が暗黙的に閉じられ、パーサーが「in body」モードに移行すべきであることを示します。implied = true
を設定することで、この暗黙的な終了とモード遷移をトリガーします。default
: 上記以外のすべての終了タグは、<head>
要素の内部では無視されるべきです。return inHeadIM, true
は、現在の挿入モードをinHeadIM
に維持し、現在のトークンを処理せずにスキップすることを示します。
- この関数は、パーサーがHTMLドキュメントの
-
afterHeadIM
関数:- この関数は、パーサーが
<head>
要素を処理し終えた後(通常は<body>
要素の開始前、またはframeset
要素のコンテキスト)に呼び出される挿入モードハンドラです。 - ここでも、
EndTagToken
が検出された際のswitch
文が追加されています。 case "body", "html", "br"
: これらの終了タグがこのモードで検出された場合、HTML5の仕様では、現在のコンテキスト(例えば、<body>
や<html>
)が暗黙的に閉じられるべきであり、framesetOK
フラグが設定されるべきです。implied = true
とframesetOK = true
を設定することで、この挙動を実装します。framesetOK
は、frameset
要素のパースに関連する内部フラグです。default
: 上記以外のすべての終了タグは、このモードでは無視されるべきです。return afterHeadIM, true
は、現在の挿入モードをafterHeadIM
に維持し、現在のトークンを処理せずにスキップすることを示します。
- この関数は、パーサーが
これらの変更により、GoのHTMLパーサーは、HTML5の複雑なエラー回復ルール、特に<head>
要素の処理と、特定の終了タグによる暗黙的な要素の終了をより正確に実装するようになりました。
src/pkg/html/parse_test.go
このファイルは、HTMLパーサーのテストスイートを含んでいます。
TestParser
関数:- このテスト関数は、外部の
.dat
ファイル(HTML5適合性テストスイートの一部)からテストケースを読み込み、パーサーの出力を検証します。 - 変更点である
{"tests1.dat", 92},
から{"tests1.dat", 99},
への変更は、tests1.dat
ファイル内のテストケースのうち、92番目までではなく99番目までのテストが、このコミットによってパスするようになったことを示しています。これは、パーサーの堅牢性とHTML5仕様への準拠が向上したことの直接的な証拠です。
- このテスト関数は、外部の
関連リンク
- Go CL 5359054: https://golang.org/cl/5359054 (このコミットに対応するGoのコードレビューシステム上の変更リスト)
参考にした情報源リンク
- HTML5 Parsing Algorithm:
- https://html.spec.whatwg.org/multipage/parsing.html (HTML Living Standard - Parsing HTML documents)
- 特に、"8.2.5 The tree construction stage" と "8.2.5.4.7 The "in head" insertion mode" および "8.2.5.4.8 The "after head" insertion mode" のセクションが関連します。
- HTML5 Conformance Test Suite:
- https://github.com/web-platform-tests/wpt/tree/master/html/dom/parsing (Web Platform Tests - HTML Parsing)
tests1.dat
のようなファイルは、これらのテストスイートの一部です。
- Go HTML Package Documentation:
- https://pkg.go.dev/golang.org/x/net/html (GoのHTMLパーサーパッケージのドキュメント)
- 注: このコミットはGoの初期の
src/pkg/html
パッケージに対するものですが、現在はgolang.org/x/net/html
に移行しています。基本的なパースロジックの概念は共通しています。
- 注: このコミットはGoの初期の
- https://pkg.go.dev/golang.org/x/net/html (GoのHTMLパーサーパッケージのドキュメント)
[インデックス 10304] ファイルの概要
このコミットは、Go言語のHTMLパーサーライブラリ(src/pkg/html
)におけるHTMLドキュメントのパースロジックの改善に関するものです。特に、<head>
要素内で不正な</html>
タグが検出された場合の挙動と、それに続く要素の解釈をHTML5のパースアルゴリズムに準拠させることを目的としています。これにより、より堅牢で標準に準拠したHTMLパースが可能になります。
コミット
commit 820523d09186bd9c7078338803e41c8592158110
Author: Andrew Balholm <andybalholm@gmail.com>
Date: Wed Nov 9 19:18:26 2011 +1100
html: correctly parse </html> in <head> element.
Pass tests1.dat, test 92:
<head></html><meta><p>
| <html>
| <head>
| <body>
| <meta>
| <p>
Also pass tests through test 98:
<p><b><div><marquee></p></b></div>
R=nigeltao
CC=golang-dev
https://golang.org/cl/5359054
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/820523d09186bd9c7078338803e41c8592158110
元コミット内容
このコミットの目的は、HTMLパーサーが<head>
要素内で</html>
タグを正しく解釈するように修正することです。具体的には、以下のテストケースをパスするようにします。
<head></html><meta><p>
という入力に対して、以下のようなDOM構造を生成する。<html> <head> <body> <meta> <p>
- また、テストスイートの
tests1.dat
において、テスト98までのテストケースがパスするように改善されます。これは、<p><b><div><marquee></p></b></div>
のような、タグのネストが不正なケースも含まれます。
変更の背景
HTMLは非常に寛容な言語であり、多くのブラウザは不正なマークアップに対してもエラーを発生させることなく、ある程度の推測に基づいてDOMツリーを構築します。これは「エラー回復(Error Recovery)」または「タグスープ(Tag Soup)」の処理として知られています。HTML5の仕様では、このエラー回復の挙動が詳細に定義されており、ブラウザ間の互換性を高めるために、パーサーはこれらのルールに従う必要があります。
このコミット以前のGoのHTMLパーサーは、<head>
要素内で予期せぬ</html>
タグが来た場合に、HTML5の仕様に完全に準拠した挙動をしていなかった可能性があります。HTML5のパースアルゴリズムでは、特定のタグが特定のコンテキストで出現した場合、暗黙的に要素が閉じられたり、新しい要素が開始されたりするルールが存在します。例えば、<head>
要素の内部で<body>
や<html>
、あるいは</br>
のようなタグが検出された場合、それは<head>
要素が終了し、<body>
要素が開始されたと解釈されるべきです。
この修正は、GoのHTMLパーサーがより多くの「タグスープ」なHTMLドキュメントを、主要なブラウザと同じように解釈できるようにするための重要なステップです。これにより、GoでHTMLをパースするアプリケーションが、より広範なWebコンテンツに対して堅牢になります。
前提知識の解説
このコミットを理解するためには、以下の概念が重要です。
-
HTML5パースアルゴリズム: HTML5の仕様は、HTMLドキュメントをバイトストリームからDOMツリーに変換する詳細なアルゴリズムを定義しています。このアルゴリズムは、トークン化フェーズとツリー構築フェーズの2つの主要なフェーズに分かれています。
- トークン化フェーズ: 入力バイトストリームをHTMLトークン(開始タグ、終了タグ、テキスト、コメントなど)に変換します。
- ツリー構築フェーズ: トークンストリームを受け取り、DOMツリーを構築します。このフェーズは、現在の「挿入モード(Insertion Mode)」に基づいて動作します。
-
挿入モード(Insertion Mode): ツリー構築フェーズの核心となる概念です。HTMLパーサーは、ドキュメントの現在の状態に応じて異なる「挿入モード」を持ちます。各挿入モードは、特定のトークンが検出されたときにDOMツリーをどのように変更するかを定義する一連のルールを持っています。例えば、
<head>
要素の内部にいるときは「in head」モード、<body>
要素の内部にいるときは「in body」モードなどがあります。 -
エラー回復(Error Recovery): HTMLの仕様は、不正なマークアップが検出された場合にパーサーがどのように振る舞うべきかを厳密に定義しています。これは、ブラウザが異なる不正なHTMLを同じように解釈し、一貫したDOMツリーを生成することを保証するためです。例えば、閉じタグが欠落している場合や、タグのネストが不正な場合でも、パーサーはエラーを報告するのではなく、最も妥当なDOM構造を推測して構築します。
-
暗黙的な要素の終了/開始: HTML5パースアルゴリズムの重要な側面の一つは、特定のタグが検出されたときに、明示的な閉じタグがなくても現在の要素が暗黙的に閉じられ、新しい要素が開始される場合があることです。例えば、
<p>
要素の内部で別の<p>
タグが検出された場合、最初の<p>
は自動的に閉じられます。同様に、<head>
要素の内部で<body>
タグが検出された場合、<head>
は閉じられ、<body>
が開始されます。
技術的詳細
このコミットの技術的な核心は、GoのHTMLパーサーがHTML5のツリー構築アルゴリズムにおける「in head」および「after head」挿入モードでの終了タグの処理を改善した点にあります。
inHeadIM
関数 (in head 挿入モード)
inHeadIM
関数は、パーサーが<head>
要素の内部にいるときの挙動を定義します。HTML5の仕様では、<head>
要素の内部で特定の終了タグが検出された場合、それは<head>
要素の暗黙的な終了と解釈されます。
- 変更前: 終了タグが
</head>
の場合のみ、pop
(現在の要素をスタックからポップする、つまり<head>
を閉じる)処理を行っていました。他の終了タグはTODO
コメントがあり、適切に処理されていませんでした。 - 変更後:
EndTagToken
が検出された場合、そのタグのデータ(名前)に基づいて以下のように処理を分岐します。"head"
: これは<head>
の明示的な閉じタグなので、pop = true
として<head>
要素を閉じます。"body"
,"html"
,"br"
: これらの終了タグが<head>
要素の内部で検出された場合、HTML5の仕様では<head>
要素が暗黙的に閉じられ、パーサーは「in body」モードに移行すべきとされています。この変更ではimplied = true
を設定することで、この暗黙的な終了をトリガーします。- 上記以外の終了タグ: これらの終了タグは
<head>
要素の内部では無視されるべきです。return inHeadIM, true
とすることで、現在の挿入モードを維持し、トークンを無視します。
この修正により、<head></html><meta><p>
のような入力が与えられた場合、</html>
が<head>
内で検出されると、<head>
が閉じられ、<body>
が暗黙的に開始されるようになります。その結果、<meta>
と<p>
は<body>
の子として正しくパースされます。
afterHeadIM
関数 (after head 挿入モード)
afterHeadIM
関数は、パーサーが<head>
要素を処理し終えた後(通常は<body>
要素の開始前または内部)の挙動を定義します。
- 変更前:
EndTagToken
の処理はTODO
コメントとなっており、実装されていませんでした。 - 変更後:
EndTagToken
が検出された場合、そのタグのデータ(名前)に基づいて以下のように処理を分岐します。"body"
,"html"
,"br"
: これらの終了タグがこのモードで検出された場合、HTML5の仕様では、現在のコンテキスト(例えば、<body>
や<html>
)が暗黙的に閉じられるべきであり、framesetOK
フラグが設定されるべきです。implied = true
とframesetOK = true
を設定することで、この挙動を実装します。- 上記以外の終了タグ: これらの終了タグは無視されるべきです。
return afterHeadIM, true
とすることで、現在の挿入モードを維持し、トークンを無視します。
この修正は、特に<body>
要素がまだ明示的に開始されていない状態で</body>
や</html>
のような終了タグが来た場合に、パーサーが正しくエラー回復を行うために重要です。
テストケースの拡張
src/pkg/html/parse_test.go
の変更は、tests1.dat
から読み込むテストケースの数を92から99に増やしています。これは、上記のパースロジックの改善により、より多くのHTML5適合性テストがパスするようになったことを示しています。tests1.dat
は、HTML5のパースアルゴリズムのテストスイートの一部であり、様々なエッジケースや不正なマークアップの処理を検証するために使用されます。
コアとなるコードの変更箇所
src/pkg/html/parse.go
--- a/src/pkg/html/parse.go
+++ b/src/pkg/html/parse.go
@@ -470,10 +470,15 @@ func inHeadIM(p *parser) (insertionMode, bool) {
im = true
}
case EndTagToken:
- if p.tok.Data == "head" {
+ switch p.tok.Data {
+ case "head":
pop = true
+ case "body", "html", "br":
+ implied = true
+ default:
+ // Ignore the token.
+ return inHeadIM, true
}
- // TODO.
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
@@ -524,7 +529,14 @@ func afterHeadIM(p *parser) (insertionMode, bool) {
framesetOK = true
}
case EndTagToken:
- // TODO.
+ switch p.tok.Data {
+ case "body", "html", "br":
+ implied = true
+ framesetOK = true
+ default:
+ // Ignore the token.
+ return afterHeadIM, true
+ }
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
src/pkg/html/parse_test.go
--- a/src/pkg/html/parse_test.go
+++ b/src/pkg/html/parse_test.go
@@ -133,7 +133,7 @@ func TestParser(t *testing.T) {
n int
}{
// TODO(nigeltao): Process all the test cases from all the .dat files.
- {"tests1.dat", 92},
+ {"tests1.dat", 99},
{"tests2.dat", 0},
{"tests3.dat", 0},
}
コアとなるコードの解説
src/pkg/html/parse.go
このファイルは、Go言語のHTMLパーサーの主要なロジックを含んでいます。特に、HTML5のツリー構築アルゴリズムにおける様々な「挿入モード」を実装しています。
-
inHeadIM
関数:- この関数は、パーサーがHTMLドキュメントの
<head>
要素の内部にいるときに呼び出される挿入モードハンドラです。 - 変更の核心は、
EndTagToken
(終了タグ)が検出された際のswitch
文の追加です。 case "head"
: これは<head>
要素の正規の閉じタグです。pop = true
とすることで、パーサーの要素スタックから<head>
要素をポップし、その要素を閉じます。case "body", "html", "br"
: HTML5の仕様では、<head>
要素の内部でこれらの終了タグが検出された場合、それは<head>
要素が暗黙的に閉じられ、パーサーが「in body」モードに移行すべきであることを示します。implied = true
を設定することで、この暗黙的な終了とモード遷移をトリガーします。default
: 上記以外のすべての終了タグは、<head>
要素の内部では無視されるべきです。return inHeadIM, true
は、現在の挿入モードをinHeadIM
に維持し、現在のトークンを処理せずにスキップすることを示します。
- この関数は、パーサーがHTMLドキュメントの
-
afterHeadIM
関数:- この関数は、パーサーが
<head>
要素を処理し終えた後(通常は<body>
要素の開始前、またはframeset
要素のコンテキスト)に呼び出される挿入モードハンドラです。 - ここでも、
EndTagToken
が検出された際のswitch
文が追加されています。 case "body", "html", "br"
: これらの終了タグがこのモードで検出された場合、HTML5の仕様では、現在のコンテキスト(例えば、<body>
や<html>
)が暗黙的に閉じられるべきであり、framesetOK
フラグが設定されるべきです。implied = true
とframesetOK = true
を設定することで、この挙動を実装します。framesetOK
は、frameset
要素のパースに関連する内部フラグです。default
: 上記以外のすべての終了タグは、このモードでは無視されるべきです。return afterHeadIM, true
とすることで、現在の挿入モードをafterHeadIM
に維持し、現在のトークンを処理せずにスキップすることを示します。
- この関数は、パーサーが
これらの変更により、GoのHTMLパーサーは、HTML5の複雑なエラー回復ルール、特に<head>
要素の処理と、特定の終了タグによる暗黙的な要素の終了をより正確に実装するようになりました。
src/pkg/html/parse_test.go
このファイルは、HTMLパーサーのテストスイートを含んでいます。
TestParser
関数:- このテスト関数は、外部の
.dat
ファイル(HTML5適合性テストスイートの一部)からテストケースを読み込み、パーサーの出力を検証します。 - 変更点である
{"tests1.dat", 92},
から{"tests1.dat", 99},
への変更は、tests1.dat
ファイル内のテストケースのうち、92番目までではなく99番目までのテストが、このコミットによってパスするようになったことを示しています。これは、パーサーの堅牢性とHTML5仕様への準拠が向上したことの直接的な証拠です。
- このテスト関数は、外部の
関連リンク
- Go CL 5359054: https://golang.org/cl/5359054 (このコミットに対応するGoのコードレビューシステム上の変更リスト)
参考にした情報源リンク
- HTML5 Parsing Algorithm:
- https://html.spec.whatwg.org/multipage/parsing.html (HTML Living Standard - Parsing HTML documents)
- 特に、"8.2.5 The tree construction stage" と "8.2.5.4.7 The "in head" insertion mode" および "8.2.5.4.8 The "after head" insertion mode" のセクションが関連します。
- HTML5 Conformance Test Suite:
- https://github.com/web-platform-tests/wpt/tree/master/html/dom/parsing (Web Platform Tests - HTML Parsing)
tests1.dat
のようなファイルは、これらのテストスイートの一部です。
- Go HTML Package Documentation:
- https://pkg.go.dev/golang.org/x/net/html (GoのHTMLパーサーパッケージのドキュメント)
- 注: このコミットはGoの初期の
src/pkg/html
パッケージに対するものですが、現在はgolang.org/x/net/html
に移行しています。基本的なパースロジックの概念は共通しています。
- 注: このコミットはGoの初期の
- https://pkg.go.dev/golang.org/x/net/html (GoのHTMLパーサーパッケージのドキュメント)