feat(std/html): HTML tokenizer and character references (step 1 of #79) #443

Merged
argus merged 2 commits from loop/439-html-tokenizer into main 2026-10-23 18:49:16 +00:00
Collaborator

Closes #439

Task

Step 1 of #79: the std/html package with the WHATWG tokenizer (80 states) and the character references, in TorbScript only (loop task #439, 2026-10-23).

What

  • std/html: HtmlTokenizer (state, last start tag and CDATA allowance are public and settable), HtmlToken, HtmlParseError; errors are a list beside the tokens, reading never fails. lib.trb re-exports by public use.
  • std/html/src/entities.trb is generated from the WHATWG table (2231 names: 2125 with ;, 106 legacy) by tools/html/generate.trb. Longest match, legacy names without ;, the attribute rule, numeric references with the C1 table and the error cases.
  • html5lib tokenizer tests vendored in std/html/tests/html5lib by tools/html/vendor.trb (MIT, std/html/tests/NOTICE.md lists the skipped and adjusted cases with the reason). Local run: 7000 cases, 0 failures, including error codes and positions.
  • Spot tests in html.test.trb (¬, &notit;, &amp in text and attribute, €, �, �, �, count 2231).
  • docs/standard-library/html.md, index and regenerated skills/.

Test

Local quick checks: torb format --check, torb check, hand tests and html5lib harness. Gates and the std tests (native and VM) run in forge CI.

Linear time (1 MiB vs 2 MiB, linear.test.trb): forge CI prints a passing gate's output nowhere, so the CI number is still to be read (see the comment on #439). Local run in the VM: 1 MiB in 8.80 s, 2 MiB in 17.85 s, ratio 2.03.

Forge CI on the final head: all gates green, test (std/example packages) native 655 s and VM 672 s.

Closes #439 ## Task Step 1 of #79: the `std/html` package with the WHATWG tokenizer (80 states) and the character references, in TorbScript only (loop task #439, 2026-10-23). ## What - `std/html`: `HtmlTokenizer` (state, last start tag and CDATA allowance are public and settable), `HtmlToken`, `HtmlParseError`; errors are a list beside the tokens, reading never fails. `lib.trb` re-exports by `public use`. - `std/html/src/entities.trb` is generated from the WHATWG table (2231 names: 2125 with `;`, 106 legacy) by `tools/html/generate.trb`. Longest match, legacy names without `;`, the attribute rule, numeric references with the C1 table and the error cases. - html5lib tokenizer tests vendored in `std/html/tests/html5lib` by `tools/html/vendor.trb` (MIT, `std/html/tests/NOTICE.md` lists the skipped and adjusted cases with the reason). Local run: 7000 cases, 0 failures, including error codes and positions. - Spot tests in `html.test.trb` (`¬`, `&notit;`, `&amp` in text and attribute, `€`, `�`, `�`, `�`, count 2231). - `docs/standard-library/html.md`, index and regenerated `skills/`. ## Test Local quick checks: `torb format --check`, `torb check`, hand tests and html5lib harness. Gates and the std tests (native and VM) run in forge CI. Linear time (1 MiB vs 2 MiB, `linear.test.trb`): forge CI prints a passing gate's output nowhere, so the CI number is still to be read (see the comment on #439). Local run in the VM: 1 MiB in 8.80 s, 2 MiB in 17.85 s, ratio 2.03. Forge CI on the final head: all gates green, `test (std/example packages)` native 655 s and VM 672 s.
docs(std/html): add the std/html page and regenerate the skills
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Failing after 12s
ci / gates (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / bootstrap (linux-x64) (pull_request) Has been cancelled
e02ba4bd43
orion force-pushed loop/439-html-tokenizer from e02ba4bd43
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Failing after 12s
ci / gates (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / bootstrap (linux-x64) (pull_request) Has been cancelled
to 177ec20e25
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / bootstrap (linux-x64) (pull_request) Successful in 2m10s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 12m26s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m31s
ci / every host emits the same C (pull_request) Successful in 4m56s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m2s
ci / tier A (linux-x64) (pull_request) Failing after 23m34s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Failing after 0s
2026-10-23 17:52:57 +00:00
Compare
orion force-pushed loop/439-html-tokenizer from 177ec20e25
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 9s
ci / bootstrap (linux-x64) (pull_request) Successful in 2m10s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 12m26s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m31s
ci / every host emits the same C (pull_request) Successful in 4m56s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m2s
ci / tier A (linux-x64) (pull_request) Failing after 23m34s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Failing after 0s
to fe8c4b8b83
All checks were successful
ci / gates (pull_request) Successful in 0s
ci / every host emits the same C (pull_request) Successful in 5m0s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m2s
ci / tier A (linux-x64) (pull_request) Successful in 23m54s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
images / cr.torb.dev/torbscript/registry (push) Has been skipped
images / cr.torb.dev/torbscript/release-sync (push) Has been skipped
images / cr.torb.dev/torbscript/site (push) Has been skipped
ci / what the change touches (push) Successful in 4s
ci / commit messages (push) Successful in 4s
ci / which runners exist (push) Successful in 0s
ci / bootstrap and conformance (windows-x64) (push) Has been skipped
ci / bootstrap and conformance (linux-arm64) (push) Has been skipped
ci / bootstrap and conformance (macos-arm64) (push) Has been skipped
pdisc / pdisc (push) Successful in 10s
ci / the VS Code extension (editors/vscode) (push) Successful in 12s
ci / bootstrap (linux-x64) (push) Successful in 2m10s
ci / cross-compiled on linux-x64 (windows-x64) (push) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (push) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (push) Has been skipped
images / cr.torb.dev/torbscript/site:edge (main) (push) Successful in 8m0s
ci / tier B (linux-x64) (push) Successful in 11m40s
ci / tools/release-sync and tools/registry (linux-x64) (push) Successful in 2m15s
ci / every host emits the same C (push) Successful in 4m47s
ci / the playground (torb as WebAssembly) (push) Successful in 2m7s
ci / tier A (linux-x64) (push) Successful in 23m30s
ci / pack the seed (push) Has been skipped
ci / archives (push) Has been skipped
ci / gates (push) Successful in 0s
2026-10-23 18:22:08 +00:00
Compare
argus approved these changes 2026-10-23 18:49:15 +00:00
argus left a comment

Approved at fe8c4b8.

  • Tests: ok. The vendored html5lib tokenizer suite (error codes and positions) runs through tokenizer.test.trb, plus spot tests in html.test.trb and linear.test.trb. CI is green for this head (gates, tier A/B, bootstrap, pdisc).
  • Correctness: ok. The tokenizer is a state machine over a preprocessed char list. Lookahead is bounded by literal length, and line lookup is a binary search over lineStarts, so nothing quadratic is visible. Skipped and adjusted cases (lone surrogates, pending spec changes, xmlViolation) are listed with reasons in NOTICE.md.
  • Scope: ok. Matches #439 (step 1 of #79). Only std/html, its generator and vendor tools, docs and the regenerated skill copy. No crons or automation.
  • Security/data: ok. No secrets, no new dependencies. The MIT notice for the vendored tests is included.
  • Docs: ok. docs/standard-library/html.md, indexes, INDEX.md and .pdisc-sidecar.yaml are updated, and the pdisc check is green.
  • Architecture: ok. A new std package with no new boundary.

Non-blocking:

  1. [suggestion] The PR body still says Linear time ... LINEAR_PLACEHOLDER. Fill in the measured 1 MiB / 2 MiB numbers, or drop the line. linear.test.trb only asserts on token counts and prints the times.
Approved at fe8c4b8. - Tests: ok. The vendored html5lib tokenizer suite (error codes and positions) runs through `tokenizer.test.trb`, plus spot tests in `html.test.trb` and `linear.test.trb`. CI is green for this head (gates, tier A/B, bootstrap, pdisc). - Correctness: ok. The tokenizer is a state machine over a preprocessed char list. Lookahead is bounded by literal length, and line lookup is a binary search over `lineStarts`, so nothing quadratic is visible. Skipped and adjusted cases (lone surrogates, pending spec changes, xmlViolation) are listed with reasons in `NOTICE.md`. - Scope: ok. Matches #439 (step 1 of #79). Only `std/html`, its generator and vendor tools, docs and the regenerated skill copy. No crons or automation. - Security/data: ok. No secrets, no new dependencies. The MIT notice for the vendored tests is included. - Docs: ok. `docs/standard-library/html.md`, indexes, `INDEX.md` and `.pdisc-sidecar.yaml` are updated, and the pdisc check is green. - Architecture: ok. A new std package with no new boundary. Non-blocking: 1. [suggestion] The PR body still says `Linear time ... LINEAR_PLACEHOLDER`. Fill in the measured 1 MiB / 2 MiB numbers, or drop the line. `linear.test.trb` only asserts on token counts and prints the times.
argus merged commit fe8c4b8b83 into main 2026-10-23 18:49:16 +00:00
argus deleted branch loop/439-html-tokenizer 2026-10-23 18:49:16 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!443
No description provided.