You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix: clean up owned streamed hydration ranges on unmount - #5314
A hydrated streamed Suspense boundary can retain its server fallback after its component unmounts. The reserved DOM range is not represented by ordinary child VNodes. A second problem appears when a persistent sibling suspends again: the insertion cursor can remain inside its marker range, causing new sibling content to disappear when that boundary resumes.
Retain the opening marker on the owning component, remove only its balanced range during unmount, and use the closing marker as the insertion cursor on re-suspension. Keep markers during successful resume so streaming/hydration continues to find them. Lifecycle callbacks and ordinary child cleanup still run before range removal. No observer, polling, selector-based cleanup or renderer copy is added.
Reproduction: stream a persistent root boundary beside a route boundary, hydrate while both promises remain unresolved, then replace the route with a destination heading. Resolve the root and original route afterward. The destination must remain, abandoned fallback/resolved content must be absent, and the root input/focus must survive. The added tests reproduce this directly in Preact without a router.
Validation:
Unchanged 11.0.1: all three added regressions fail; 40 existing tests in the file pass.
Candidate: 43/43 hydration tests pass.
Full minified suite on current main: 107 files pass, 1,402 tests pass, 11 existing skips.
Lint and JavaScript typechecking pass.
Ten separately built production SSR/router fixtures pass with the candidate's official build output, covering abandonment, settlement races, return, independent/nested boundaries, root revalidation, history and interruption. The alias used for that isolated experiment is not a consumer/package workaround.
This is a proposed upstream fix; no downstream release containing a patched renderer has been published. Broader upstream review is requested for marker ownership and unmount ordering.
We recognize that LLM's have become an integral tool for many users, however when using LLMs to help write issues or pull requests, disclose this. Transparency preserves the collaborative integrity that makes open-source communities work. It's the difference between "I used AI to help structure this bug report" (honest, helpful) and silently passing off generated content as your own analysis (deceptive, counterproductive). We as maintainers want to engage with humans rather than LLM-generated messages, put time in your issue report and that will be reflected back.
Examples of unacceptable behavior by participants include:
The use of sexualized language or imagery and unwelcome sexual attention or advances
Trolling, insulting/derogatory comments, and personal or political attacks
Public or private harassment
Publishing others' private information, such as a physical or electronic address, without explicit permission
Other conduct which could reasonably be considered inappropriate in a professional setting
Writing an issue, pull request or comments through an LLM without disclosing this
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
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.
A hydrated streamed Suspense boundary can retain its server fallback after its component unmounts. The reserved DOM range is not represented by ordinary child VNodes. A second problem appears when a persistent sibling suspends again: the insertion cursor can remain inside its marker range, causing new sibling content to disappear when that boundary resumes.
Retain the opening marker on the owning component, remove only its balanced range during unmount, and use the closing marker as the insertion cursor on re-suspension. Keep markers during successful resume so streaming/hydration continues to find them. Lifecycle callbacks and ordinary child cleanup still run before range removal. No observer, polling, selector-based cleanup or renderer copy is added.
Reproduction: stream a persistent root boundary beside a route boundary, hydrate while both promises remain unresolved, then replace the route with a destination heading. Resolve the root and original route afterward. The destination must remain, abandoned fallback/resolved content must be absent, and the root input/focus must survive. The added tests reproduce this directly in Preact without a router.
Validation:
This is a proposed upstream fix; no downstream release containing a patched renderer has been published. Broader upstream review is requested for marker ownership and unmount ordering.