Add set_inner_html to WP_HTML_Processor#80
Conversation
Implementation: the method validates by construction rather than by rule lists. It re-parses the current document to locate the inner span and records a signature for every stack event (operation, provenance, node, namespace, position, breadcrumbs) from the context element's close to EOF; then re-parses the spliced candidate, requiring that new content stays strictly inside the context element and that the post-close event stream is identical. Any escape — <a> popping the context A, </div> closing it, unclosed <b> re-wrapping later content, fostered table text — shows up as a stream mismatch and rejects with a clean false; the processor and document are untouched. On success it commits through the existing WP_HTML_Text_Replacement machinery, purges bookmarks into the replaced span, and stays paused on the opening tag so parsing continues into the new content. Two divergences re-parsing can't see are rejected by a lexical pre-scan: <html>/<body> openers and SELECT contexts. WP still parses selects per the old spec. Content in or introducing a SELECT is limited to OPTION/OPTGROUP/HR/text/comments for now. Verification: 55 PHPUnit tests (194 assertions) covering A-in-A, LI, </a> escape, tables, SVG, templates, bookmarks, seek interaction, and repeated calls; the full html-api group passes (1,547 tests) and PHPCS is clean. Separately, a scratchpad fuzz harness cross-checked every accepted replacement against Dom\HTMLDocument: 12,285 doc×content cases, 4,003 accepted, zero cases where the tree outside the context element changed.
|
This is interesting to consider: https://github.com/josepharhar/react/blob/main/packages/react-dom-bindings/src/client/validateDOMNesting.js |
Parse new content as an HTML fragment at the context element and splice the serialization of the parsed result, the same interpretation the DOM innerHTML setter applies: syntax which parsers ignore is dropped and unclosed elements are explicitly closed. Content is rejected only when its parsed tree cannot be represented in HTML text at the target location without modifying the structure outside the context element. Restrict SELECT-context content to tokens parsed identically before and after the customizable-select changes to HTML, pending #63736. Add a Dom\HTMLDocument oracle harness verifying that accepted replacements never modify the document outside the context element. Claude-Session: https://claude.ai/code/session_01QBsi2fhwwV2b5gUgo9Yipm
|
Status update: 2a80aa5 supersedes the contract described in the PR body. The original design spliced the caller's bytes verbatim and rejected anything that didn't verify. The problem with that contract: it conflated two distinct failure modes — noise that every HTML parser silently ignores ( ContractContent is interpreted the way the DOM
What splice-and-verify checksPrefix state needs no check (byte-identical prefix + deterministic parser). Verified: (1) during the content parse, every insertion lands inside the context subtree and nothing the content didn't open is popped; (2) the context element closes at the same suffix position, by the same cause; (3) the stack-event stream from the close to EOF matches event-for-event (operation, provenance, name, namespace, relative position, breadcrumbs). The check is deliberately extensional — it verifies consequences rather than comparing parser state at the boundary, so it cannot rot as the parser grows new state components. Load-bearing assumption: every structural mutation surfaces as a stack event with correct breadcrumbs. North starAfter ConfidenceRelative to the HTML Processor's own semantics: very high, because the invariant is enforced by verification, not by rules. Nothing reasons "this content is safe"; the implementation splices, reparses, and requires the post-close event stream to match. A violation requires a bug in the verifier itself or a breach of the event-model assumption above. Relative to real browsers: high, but empirical. The verifier runs on this parser's semantics, so the browser-facing guarantee is only as strong as the parser's fidelity where it doesn't bail. The oracle harness ( Canaries (labeled in the tests)Tests are written assuming the processor will eventually parse arbitrary HTML; rejection outcomes don't depend on bail semantics except where explicitly pinned:
Suite status: 57 tests / 189 assertions, full html-api group green (1,549 tests), PHPCS clean. Known warts: verification costs two full reparses per call, and PRE leading-newline inner fidelity matches the #64776 family. |
Implementation: the method validates by construction rather than by rule lists. It re-parses the current document to locate the inner span and records a signature for every stack event (operation, provenance, node, namespace, position, breadcrumbs) from the context element's close to EOF; then re-parses the spliced candidate, requiring that new content stays strictly inside the context element and that the post-close event stream is identical. Any escape —
<a>popping the contextA,</div>closing it, unclosed<b>re-wrapping later content, fostered table text — shows up as a stream mismatch and rejects with a clean false; the processor and document are untouched. On success it commits through the existingWP_HTML_Text_Replacementmachinery, purges bookmarks into the replaced span, and stays paused on the opening tag so parsing continues into the new content.Two divergences re-parsing can't see are rejected by a lexical pre-scan:
<html>/<body>openers and SELECT contexts. WP still parses selects per the old spec. Content in or introducing a SELECT is limited to OPTION/OPTGROUP/HR/text/comments for now.Verification: 55 PHPUnit tests (194 assertions) covering A-in-A, LI,
</a>escape, tables, SVG, templates, bookmarks, seek interaction, and repeated calls; the full html-api group passes (1,547 tests) and PHPCS is clean. Separately, a scratchpad fuzz harness cross-checked every accepted replacement against Dom\HTMLDocument: 12,285 doc×content cases, 4,003 accepted, zero cases where the tree outside the context element changed.Trac ticket:
Use of AI Tools
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.