fix: preserve siblings around raw HTML updates - #466
Merged
Mohamed Mansour (mohamedmansour) merged 4 commits intoAug 23, 2026
Merged
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0807f5af-f9d9-45ad-b7d2-907084c53ea0
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0807f5af-f9d9-45ad-b7d2-907084c53ea0
Mohamed Mansour (mohamedmansour)
requested review from
Bang Lee (Qusic),
Akrosh Gandhi (akroshg),
Jane Chu (janechu) and
mcritzjam
and
a lite review from Copilot
August 22, 2026 18:14
Copilot started reviewing on behalf of
Mohamed Mansour (mohamedmansour)
August 22, 2026 18:15
View session
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the WebUI end-to-end raw HTML contract (parser → protocol → handler → client runtime) so reactive triple-brace updates replace only the intended sibling range instead of replacing a whole parent node, preserving static/conditional siblings and aligning client-created DOM structure with SSR.
Changes:
- Introduce indexed comment-bounded ownership ranges (
<!--wN-->/<!--/wN-->) for raw HTML bindings and update the framework hydration/update logic to patch within the bounded range. - Extend protocol/spec to carry
raw_text_contextfor signals in HTML text-only/raw-text contexts, and propagate the binding “owns range” boolean to handler plugins. - Add/expand Playwright and unit coverage for sibling preservation, table-context parsing, adjacent raw ranges, keyed identity/movement/removal, reconnects, and raw-text-context behavior.
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/webui-framework/tests/fixtures/raw-html-light/webui.config.json | Adds Light DOM fixture configuration. |
| packages/webui-framework/tests/fixtures/raw-html-light/state.json | Adds initial state for Light DOM raw HTML fixture. |
| packages/webui-framework/tests/fixtures/raw-html-light/src/test-raw-html-light/test-raw-html-light.html | Fixture template covering sibling preservation + table row context. |
| packages/webui-framework/tests/fixtures/raw-html-light/src/index.html | Fixture page entry for the Light DOM raw HTML fixture. |
| packages/webui-framework/tests/fixtures/raw-html-light/raw-html-light.spec.ts | Playwright coverage for Light DOM sibling preservation + <tbody> contextual parsing. |
| packages/webui-framework/tests/fixtures/raw-html-light/element.ts | Fixture element with observables used by Light DOM tests. |
| packages/webui-framework/tests/fixtures/raw-html-conditional/state.json | Expands fixture state for additional raw scenarios (adjacent, inline, table, keyed). |
| packages/webui-framework/tests/fixtures/raw-html-conditional/src/test-raw-html/test-raw-html.html | Extends fixture template to exercise multiple raw/text adjacency and table context. |
| packages/webui-framework/tests/fixtures/raw-html-conditional/src/test-raw-html-keyed-repeat/test-raw-html-keyed-repeat.html | Adds keyed repeat fixture for raw range identity/movement/removal. |
| packages/webui-framework/tests/fixtures/raw-html-conditional/src/index.html | Registers additional fixture component on the test page. |
| packages/webui-framework/tests/fixtures/raw-html-conditional/raw-html-conditional.spec.ts | Major Playwright expansion covering raw range ordering, reconnect, adjacency, raw CSS, client-created instances, keyed behavior. |
| packages/webui-framework/tests/fixtures/raw-html-conditional/element.ts | Adds new fixture component and methods for keyed repeat manipulation. |
| packages/webui-framework/src/template-element.ts | Core runtime changes: raw ownership anchors, SSR hydration raw range collection, bounded Range-based patching, instance node ownership updates. |
| packages/webui-framework/src/hydration-mismatch.test.ts | Updates mismatch logic tests to reflect raw ranges being non-text-owned data. |
| packages/webui-framework/src/element/types.ts | Updates TextBinding to support comment anchors + cached raw value + ownership metadata. |
| packages/webui-framework/src/element/markers.ts | Adds raw marker helpers and SSR index support for raw ranges; skip logic updated accordingly. |
| packages/webui-framework/src/element/markers.test.ts | Adds tests for raw range collection and legacy-looking comments within raw ranges. |
| packages/webui-framework/README.md | Documents raw HTML update costs/constraints and SSR resolution behavior changes. |
| docs/guide/concepts/plugins/index.md | Updates HandlerPlugin docs to include the new raw: bool parameter. |
| DESIGN.md | Updates spec for raw_text_context, tx encoding, SSR marker set, and hydration/update semantics. |
| crates/webui-test-utils/src/lib.rs | Extends fragment matchers and formatting for raw-text-context signals. |
| crates/webui-protocol/src/lib.rs | Adds raw_text_signal(...) constructor and tests; sets defaults. |
| crates/webui-protocol/src/gen_webui.rs | Regenerates protobuf struct with raw_text_context field. |
| crates/webui-protocol/proto/webui.proto | Adds raw_text_context field to WebUIFragmentSignal schema. |
| crates/webui-parser/src/plugin/webui.rs | Updates compilation of text runs for raw binding separation/adjacency and CSS signal comment handling. |
| crates/webui-parser/src/lib.rs | Emits raw_text_signal for appropriate contexts and CSS comment signals; adds raw-text-context tests. |
| crates/webui-handler/src/plugin/webui.rs | Emits <!--wN--> / <!--/wN--> markers for raw bindings using the new hook signature. |
| crates/webui-handler/src/plugin/mod.rs | Updates HandlerPlugin trait signature and related tests/docs. |
| crates/webui-handler/src/plugin/fast.rs | Updates plugin test to match new hook signature. |
| crates/webui-handler/src/plugin/fast_v3.rs | Updates plugin implementation/tests to accept the new raw argument. |
| crates/webui-handler/src/plugin/fast_v2.rs | Updates plugin implementation/tests to accept the new raw argument. |
| crates/webui-handler/src/lib.rs | Threads owns_html_range into plugin hooks and uses raw_text_context to suppress range ownership for raw-text contexts. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Replace the deny-list check with an explicit match over the known raw-text/RCDATA scope strings returned by boundary_parent_scope, so a future scope value must be deliberately classified instead of silently defaulting to text-only. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0807f5af-f9d9-45ad-b7d2-907084c53ea0
Document that raw_text_context only governs HTML sibling-marker
ownership and never changes escaping. signal.raw keeps its usual
meaning (HTML-encode vs. verbatim) uniformly across contexts,
including inside HTML raw-text elements (<script>, <style>, <xmp>)
which never decode character references, unlike RCDATA elements
(<title>, <textarea>) which do. Callers binding values that may
contain HTML-significant characters inside raw-text elements must
use the raw ({{{value}}}) form.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0807f5af-f9d9-45ad-b7d2-907084c53ea0
Jane Chu (janechu)
approved these changes
Aug 23, 2026
Mohamed Mansour (mohamedmansour)
merged commit Aug 23, 2026
53d8c24
into
microsoft:main
24 checks passed
Mohamed Mansour (mohamedmansour)
deleted the
mohamedmansour-harden-raw-html
branch
August 23, 2026 15:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Raw HTML updates currently replace their entire parent, which can erase static siblings and structural anchors. Client-created bindings also use a wrapper that diverges from SSR structure.
This change gives each raw binding an indexed comment-bounded sibling range. Updates parse in the live parent context with an ephemeral DOM Range, preserve adjacent content, and keep instance node ownership synchronized for keyed movement, removal, reconnects, shadow DOM, light DOM, and table rows.
The parser and protocol carry raw-text context separately from brace escaping so
<style>and other HTML text-only contexts remain marker-free.HandlerPlugin::on_binding_startandon_binding_endnow receive the owned-range boolean directly; the coordinated build/render contract makes this intentional API change safe, and all built-in plugins were updated together.Coverage includes multi-node/empty transitions, adjacent raw ranges, escaped text alignment, marker-like comments, contextual
<tbody>parsing, client-created instances, reconnects, keyed identity/removal, light DOM, and raw CSS hydration.Performance impact:
Validation:
cargo xtask check: passed