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

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

このコミットは、Go言語の実験的なHTMLパーサーライブラリ exp/html 内の atom パッケージに、いくつかの新しいHTMLアトム(要素名や属性名)を追加するものです。具体的には、src/pkg/exp/html/atom/gen.gosrc/pkg/exp/html/atom/table.gosrc/pkg/exp/html/atom/table_test.go の3つのファイルが変更されています。

コミット

commit 834edc4257b45176d8bbacc4d612a43372f9556b
Author: Nigel Tao <nigeltao@golang.org>
Date:   Fri Jun 15 15:39:25 2012 +1000

    exp/html/atom: add some more atoms.
    
    R=r, dsymonds
    CC=golang-dev
    https://golang.org/cl/6298085

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

https://github.com/golang/go/commit/834edc4257b45176d8bbacc4d612a43372f9556b

元コミット内容

このコミットの目的は、exp/html/atom パッケージにさらにいくつかのHTMLアトムを追加することです。これにより、HTMLパーサーがより多くのHTML要素や属性を認識し、効率的に処理できるようになります。

変更の背景

Go言語の exp/html パッケージは、HTML5の仕様に準拠した堅牢なHTMLパーサーを提供することを目指していました。このパーサーは、HTMLドキュメントを解析し、DOMツリーを構築するために使用されます。HTMLの要素名や属性名は非常に多岐にわたるため、これらを効率的に扱うためのメカニズムが必要です。

exp/html/atom パッケージは、HTMLの要素名や属性名を数値ID(アトム)にマッピングすることで、文字列比較のオーバーヘッドを削減し、パーサーのパフォーマンスを向上させる役割を担っています。新しいHTML要素や属性が標準化されたり、広く使われるようになったりするにつれて、それらを atom パッケージに追加していく必要がありました。

このコミットは、当時まだ実験的であった exp/html パッケージが、より多くのHTML構造を正確に解析できるようにするための継続的な改善の一環として行われました。特に、blinkpromptpublicspacersystem といった、HTMLの歴史の中で登場した、あるいは特定の文脈で使われる可能性のある要素や属性が追加されています。

前提知識の解説

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

exp/html は、Go言語の標準ライブラリ html パッケージの前身、または実験的なバージョンとして開発されていたパッケージです。HTML5の仕様に基づいて、HTMLドキュメントを解析し、DOM(Document Object Model)ツリーを生成する機能を提供します。このパッケージは、ウェブスクレイピング、HTMLテンプレートの処理、HTMLコンテンツの検証など、様々な用途で利用されます。

HTMLアトム (Atom)

HTMLパーサーにおいて、「アトム」とは、HTMLの要素名(例: div, p, a)や属性名(例: href, class, id)を、内部的に一意の数値IDにマッピングしたものです。これにより、文字列としてこれらの名前を扱う代わりに、数値IDとして扱うことができます。

アトム化の主な利点は以下の通りです。

  1. パフォーマンスの向上: 文字列の比較は計算コストが高い操作ですが、数値の比較は非常に高速です。HTMLドキュメントの解析では、要素名や属性名の比較が頻繁に行われるため、アトム化によってパーサーの処理速度が大幅に向上します。
  2. メモリ使用量の削減: 同じ要素名や属性名がドキュメント内で何度も出現する場合でも、メモリ上にはその文字列が一度だけ格納され、それ以降は数値IDが参照されるため、メモリ使用量を削減できます。
  3. コードの簡潔化: 特定の要素や属性を識別する際に、文字列リテラルではなく、定義済みのアトム定数を使用することで、コードの可読性が向上し、タイプミスによるバグを防ぐことができます。

exp/html/atom パッケージは、これらのアトムを管理し、文字列と数値ID間の変換機能を提供します。

gen.gotable.go の役割

  • gen.go: このファイルは、HTMLアトムのリストを定義するために使用されます。通常、このファイルは手動で編集されるのではなく、アトムのリストを元に table.go のような他のファイルを自動生成するためのスクリプトやツールによって利用されます。extra 変数には、標準的なHTML5の要素や属性以外に、パーサーが認識すべき追加のアトムが文字列スライスとして定義されています。
  • table.go: このファイルは、gen.go の情報に基づいて自動生成されることが想定されています。HTMLアトムの文字列と数値IDのマッピング、およびその逆のマッピング(数値IDから文字列への変換)を効率的に行うためのデータ構造(ハッシュテーブルや配列など)が定義されています。このファイルには、各アトムに対応する Atom 型の定数と、アトムのルックアップテーブルが含まれています。

table_test.go の役割

  • table_test.go: このファイルは、table.go で定義されたアトムのルックアップテーブルが正しく機能するかどうかを検証するための単体テストが含まれています。アトムの文字列から数値IDへの変換、および数値IDから文字列への変換が期待通りに行われることを確認します。新しいアトムが追加された場合、それらが正しく認識されることを保証するために、テストケースも更新される必要があります。

技術的詳細

このコミットでは、主に以下の技術的変更が行われています。

  1. gen.goextra スライスへの追加: extra スライスは、HTMLパーサーが認識すべき追加の要素名や属性名を文字列として保持しています。このコミットでは、"blink""prompt""public""spacer""system" の5つの文字列がこのスライスに追加されました。これらの要素は、HTMLの歴史の中で存在したり、特定のブラウザでサポートされたり、あるいはXML/SVGなどの関連技術で使われたりする可能性のあるものです。

    • blink: Netscape Navigatorでサポートされていた非標準の要素で、テキストを点滅させる効果がありました。
    • prompt: HTML4以前のフォーム要素で、ユーザー入力のプロンプトを表示するために使われました。HTML5では非推奨です。
    • public: XMLやSGMLのDTD(Document Type Definition)で使われるPUBLIC識別子に関連する可能性があります。
    • spacer: Netscape Navigatorでサポートされていた非標準の要素で、空白スペースを挿入するために使われました。
    • system: SVGやXMLの文脈で、システム関連の識別子として使われる可能性があります。
  2. table.goAtom 定数とルックアップテーブルの更新: gen.goextra スライスに新しいアトムが追加されたことに伴い、table.go が再生成(または手動で更新)され、これらの新しいアトムに対応する Atom 型の定数が追加されました。また、アトムの文字列と数値IDのマッピングを管理する内部ルックアップテーブル(table 配列と atomText 文字列)も更新されています。 Atom 定数の値は、通常、アトムの文字列が atomText 内で始まるオフセットと、その文字列の長さの組み合わせでエンコードされます。例えば、Atom = 0xNNNLL の形式で、NNN がオフセット、LL が長さを示すといった内部的な規則があります。このコミットでは、既存のアトムのオフセットも多数変更されており、これは新しいアトムの挿入によって atomText 文字列のレイアウトが再構築されたためと考えられます。

  3. table_test.gotestAtomList スライスへの追加: 新しいアトムが正しく認識され、アトム化されることを検証するために、testAtomList スライスにも "blink""prompt""public""spacer""system" が追加されました。これにより、テストスイートがこれらの新しいアトムの正確な処理を保証します。

これらの変更は、exp/html パーサーがより広範なHTMLコンテンツを正確に解析できるようにするための、データ層の拡張に相当します。

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

src/pkg/exp/html/atom/gen.go

--- a/src/pkg/exp/html/atom/gen.go
+++ b/src/pkg/exp/html/atom/gen.go
@@ -599,6 +599,7 @@ var extra = []string{\n 	\"basefont\",\n 	\"bgsound\",\n 	\"big\",\n+\t\"blink\",\n 	\"center\",\n 	\"color\",\n 	\"desc\",\n@@ -624,8 +625,12 @@ var extra = []string{\n 	\"noembed\",\n 	\"noframes\",\n 	\"plaintext\",\n+\t\"prompt\",\n+\t\"public\",\n+\t\"spacer\",\n 	\"strike\",\n 	\"svg\",\n+\t\"system\",\n 	\"tt\",\n 	\"xmp\",\n }\n```

### `src/pkg/exp/html/atom/table.go`

このファイルは非常に多くの変更がありますが、主要な変更は新しい `Atom` 定数の追加と、既存の定数の値(オフセットと長さのエンコード)の再計算です。

例:
- `Blink Atom = 0x14705` (新規追加)
- `Prompt Atom = 0x5bf06` (新規追加)
- `Public Atom = 0x42706` (新規追加)
- `Spacer Atom = 0x30006` (新規追加)
- `System Atom = 0x5ed06` (新規追加)

また、`atomText` 文字列も新しいアトムを含むように再構築されています。

### `src/pkg/exp/html/atom/table_test.go`

```diff
--- a/src/pkg/exp/html/atom/table_test.go
+++ b/src/pkg/exp/html/atom/table_test.go
@@ -30,6 +30,7 @@ var testAtomList = []string{\n 	\"bdo\",\n 	\"bgsound\",\n 	\"big\",\n+\t\"blink\",\n 	\"blockquote\",\n 	\"body\",\n 	\"border\",
@@ -263,6 +264,8 @@ var testAtomList = []string{\n 	\"pre\",\n 	\"preload\",\n 	\"progress\",\n+\t\"prompt\",\n+\t\"public\",\n 	\"q\",\n 	\"radiogroup\",\n 	\"readonly\",
@@ -289,6 +292,7 @@ var testAtomList = []string{\n 	\"sizes\",\n 	\"small\",\n 	\"source\",\n+\t\"spacer\",\n 	\"span\",\n 	\"span\",\n 	\"spellcheck\",
@@ -305,6 +309,7 @@ var testAtomList = []string{\n 	\"summary\",\n 	\"sup\",\n 	\"svg\",\n+\t\"system\",\n 	\"tabindex\",\n 	\"table\",\n 	\"target\",

コアとなるコードの解説

このコミットの核心は、HTMLパーサーが認識できる「語彙」を拡張することにあります。

  1. gen.go の変更: extra スライスに新しい文字列を追加することは、Goの exp/html パッケージが将来的にサポートすべき、あるいは認識すべきHTML要素/属性の候補を明示的に指定する行為です。これは、パーサーの「知識ベース」を更新する第一歩となります。
  2. table.go の変更: このファイルは、exp/html パッケージのパフォーマンスの鍵となる部分です。新しいアトムが追加されると、table.go 内のデータ構造が再構築されます。具体的には、Atom 定数の数値IDが更新され、atomText という巨大な文字列(すべてのアトム文字列を連結したもの)と、table というハッシュテーブル(またはルックアップ配列)が再生成されます。この再生成は、新しいアトムが既存のアトムの間に挿入されることで、既存のアトムのオフセットがずれるため、広範囲にわたる変更となります。これにより、文字列比較ではなく数値比較で高速にアトムを識別できるようになります。
  3. table_test.go の変更: testAtomList に新しいアトムを追加することは、これらのアトムがパーサーによって正しくアトム化され、その逆の変換も正しく行われることを保証するためのテストカバレッジを確保します。これは、変更がライブラリの安定性と正確性を損なわないことを確認するために不可欠です。

全体として、このコミットは、GoのHTMLパーサーがより多くのHTML構造を効率的かつ正確に処理できるようにするための、基盤となるデータ構造の更新とテストの追加を行っています。

関連リンク

参考にした情報源リンク