fix: prevent duplicated structural views during hydration - #7668
Merged
janechu merged 3 commits intoJul 29, 2026
Conversation
janechu
approved these changes
Jul 29, 2026
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.
Pull Request
📖 Description
Prevent duplicate structural views during hydration when server-rendered content exists but the initial client binding has no template.
The content binding now removes unmatched SSR structural ranges before later updates compose their current view. A nested declarative fixture reproduces the original duplicated progress and action controls.
👩💻 Reviewer Notes
This intentionally fixes the mismatch in
HTMLBindingDirective.updateContent()instead of restoring ancestor-before-child hydration waiting.The previous waiting mechanism depended on legacy
defer-hydrationbehavior and asynchronously delayed element connection. Restoring it would make hydration correctness depend on definition and connection order, reintroduce lifecycle coupling removed in FAST 3, and require handling ancestor registries, disconnection, and streaming cases globally.In this failure, hydration discovers an SSR structural range while the child’s initial client binding evaluates to no template. Because that range has no corresponding
$fastView, a later parent property update composes a new view beside the unclaimed SSR DOM. The fix reconciles that mismatch at the content binding that owns the range by removing the surplus SSR nodes. This mirrorsrepeat()hydration, which already removes extra server-rendered ranges.The tradeoff is that mismatched SSR nodes are discarded rather than adopted. This is intentional because the client binding currently says no view should exist; if state arrives later, the normal reactive update creates the correct view once. This preserves FAST 3’s synchronous, order-independent connection model.
📑 Test Plan
✅ Checklist
General
$ npm run changeAgents