Skip to content

feat(tests): html5lib tokenizer conformance suite (6,651/6,690 passing)#4

Merged
akankov merged 1 commit into
mainfrom
feature/html5lib-tokenizer-conformance
Jun 12, 2026
Merged

feat(tests): html5lib tokenizer conformance suite (6,651/6,690 passing)#4
akankov merged 1 commit into
mainfrom
feature/html5lib-tokenizer-conformance

Conversation

@akankov

@akankov akankov commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

M1.B part 2: wire the html5lib-tests tokenizer suites in as a conformance backstop, and fix what they caught.

Suite: 6,806 cases vendored (tests/fixtures/html5lib-tokenizer/, refreshable via bin/fetch-html5lib-tests.php; xmlViolation.test excluded by design). 6,690 run (Data state, no lastStartTag); 6,651 pass; 39 skip-listed with per-entry reasons — all reduce to two M1.C work items: CR/CRLF input normalization (13) and per-state NUL → U+FFFD (26). Token sequences compared; error codes are the follow-up.

Tokenizer fixes the triage forced:

  1. OOM on bare & at EOFreconsume() rewound after a non-advancing EOF consume, re-tokenizing the same & forever. Now matches spec 'reconsume EOF' semantics. (Found by case 47 of 6,690.)
  2. DOCTYPE public/system identifier states (§13.2.5.56–.66) — previously an M1.A shortcut to bogus-doctype; implemented fully, clearing ~317 cases (<!DOCTYPE html PUBLIC …> now parses identifiers, case-insensitive keywords, all quoting states, spec error codes).
  3. Comment-end-bang state (<!--x--!>).
  4. WhitespaceToken decoded data&Tab; raw vs \t decoded were conflated; token now exposes $data.
  5. Numeric-reference saturation — 65-bit refs overflowed to float; now saturate at 0x110000 → U+FFFD. Plus case-preserving &#X flush.

Round-trip fidelity (headline invariant) green throughout.

Test plan

  • 6,724 tests / 11,236 assertions green (incl. all pre-existing round-trip + entity tests)
  • PHPStan max, Phan (Docker), Rector, CS-Fixer all clean

…es it forced

Vendor the html5lib-tests tokenizer suites (6,806 cases; xmlViolation.test
excluded; bin/fetch-html5lib-tests.php re-downloads) and run every Data-state
case without lastStartTag through the tokenizer, comparing token sequences:
6,690 runnable, 6,651 passing, 39 skip-listed with reasons (CR/CRLF input
normalization and per-state NUL replacement — both M1.C).

Triage drove five tokenizer fixes:

- reconsume() rewound the buffer after an EOF (non-advancing) consume, so a
  bare '&' looped Data -> CharacterReference until OOM; it now only undoes
  an advancing consume, matching the spec's 'reconsume EOF' semantics.
- DOCTYPE public/system identifier states (spec 13.2.5.56-66) were an M1.A
  shortcut to bogus-doctype + force-quirks; implemented fully (~317 cases).
- Comment-end-bang state (13.2.5.52) was missing.
- WhitespaceToken now carries decoded $data ('&Tab;' raw vs "\t" decoded).
- Numeric char refs saturate at 0x110000 instead of overflowing to float on
  65-bit input; '&#X' without digits flushes its original case.

Round-trip fidelity (concat raw == input) holds throughout.
@akankov
akankov merged commit 7efa8cc into main Jun 12, 2026
7 checks passed
@akankov
akankov deleted the feature/html5lib-tokenizer-conformance branch June 12, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant