Skip to content

fix: preserve hydration and suspended error recovery contracts - #43

Open
tannerlinsley wants to merge 1 commit into
mainfrom
taren/fix-hydration-and-suspense-recovery
Open

tannerlinsley wants to merge 1 commit into
mainfrom
taren/fix-hydration-and-suspense-recovery

Conversation

@tannerlinsley

@tannerlinsley tannerlinsley commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Hydration and suspended error recovery can alter already-correct DOM, trigger resource loads, suppress application scrolling, or render retained subscribers against stale props. This ports the fixes with standalone regressions using public React APIs.

  • Preserve case-sensitive SVG attributes through SSR, hydration, and updates.
  • Normalize hydration attributes in an inert document so validation does not fetch lazy images or construct custom elements.
  • Preserve matching opaque head content, while retaining mismatch recovery and suppression policies.
  • Remove the global hydration scrollTo wrapper so the application owns scroll restoration.
  • Queue document-root deletion before placement, while keeping mutations transactional.
  • Propagate errors thrown by a fallback to an ancestor, abandon stale captured errors after resets, and reconnect catch lifecycles in the right order after Suspense.
  • Retry already-queued retained subscribers through their Suspense boundary.

Validation

The full local CI gate passes: unit tests, types, build/export verification, and source/dist size budgets. All 14 Chromium regressions pass and now run in PR CI. The same regression suite reproduces failures against pristine main. Shared-contract cases are also checked against React; the measurement report explicitly identifies Redact-specific policies excluded from that control.

The complete before/after size table and reproduction commands are in benchmarks/HYDRATION_SUSPENSE_RECOVERY.md. Built combined client: 28,060 to 28,634 gzip bytes (+574). Default Vite client: 23,232 to 23,814 (+582). Only exceeded budgets increase, to measured values without extra margin. This is a correctness cost, not a performance improvement claim.

Includes a patch changeset. No generated bundles or source maps are committed.

Summary by CodeRabbit

  • Bug Fixes
    • Improved hydration recovery for SVG attributes, document roots, and mismatched markup while preserving existing page content and matching styles.
    • Prevented unnecessary custom-element construction and offscreen lazy-image fetching during hydration.
    • Improved recovery when Suspense, error fallbacks, or external-store updates occur during rendering.
    • Preserved application scroll behavior during hydration.
  • Testing
    • Added browser-based regression coverage for hydration and recovery scenarios.

@changeset-bot

changeset-bot Bot commented Oct 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fceb482

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@tanstack/redact Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e35fc102-7b66-4a89-aa80-2d2e888c19ff
📥 Commits

Reviewing files that changed from the base of the PR and between becad73 and fceb482.

📒 Files selected for processing (17)
  • .changeset/calm-hydration-recovery.md
  • .github/workflows/pr.yml
  • benchmarks/HYDRATION_SUSPENSE_RECOVERY.md
  • package.json
  • packages/redact/src/core/attributes.ts
  • packages/redact/src/dom/features/class/full.ts
  • packages/redact/src/dom/features/hydration/full.ts
  • packages/redact/src/dom/features/hydration/stub.ts
  • packages/redact/src/dom/features/suspense/full.ts
  • packages/redact/src/dom/reconcile.ts
  • scripts/hydration-recovery-browser.config.mjs
  • scripts/hydration-recovery.config.mjs
  • scripts/size-check.mjs
  • tests/error-fallback-recovery.test.tsx
  • tests/hydration-runtime-regressions.test.tsx
  • tests/hydration-scroll-ownership.test.tsx
  • tests/retained-store-departure.test.tsx
💤 Files with no reviewable changes (1)
  • packages/redact/src/dom/features/hydration/stub.ts

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

📝 Walkthrough

The PR changes SVG attribute handling, hydration validation and DOM adoption, and Suspense and error-boundary recovery. It adds regression tests for those paths, configures browser-based test execution, updates bundle-size budgets, and records a patch changeset.

Changes: Hydration and recovery

Layer / File(s) Summary
Hydration validation and DOM adoption
packages/redact/src/core/attributes.ts, packages/redact/src/dom/features/hydration/*, tests/hydration-*.test.tsx
Hydration preserves listed SVG attribute casing and uses inert documents for validation probes. DOM adoption uses the validation result when recovering mismatched opaque HTML. The temporary scroll guard is removed. Tests cover SVG, custom elements, head styles, lazy images, opaque markup, and scroll ownership.
Suspense and error-boundary retries
packages/redact/src/dom/reconcile.ts, packages/redact/src/dom/features/class/full.ts, packages/redact/src/dom/features/suspense/full.ts, tests/error-fallback-recovery.test.tsx, tests/retained-store-departure.test.tsx
Reconciliation updates retained Suspense retries and child ordering. Error-boundary fallback rendering, capture reset handling, and deferred lifecycle callbacks are updated. Tests cover suspended fallbacks, reset props, document-root recovery, and queued store notifications.
Regression execution and release records
package.json, scripts/hydration-recovery*.config.mjs, .github/workflows/pr.yml, benchmarks/HYDRATION_SUSPENSE_RECOVERY.md, scripts/size-check.mjs, .changeset/calm-hydration-recovery.md
A browser recovery test script and CI steps are added. The benchmark records size measurements and regression commands; size budgets and the patch changeset are updated.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to fceb4

The identified cleanup and recovery concerns do not block merging. The change is ready for normal checks.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 6.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 31 functions across 12 files. (4 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely summarizes the main changes: preserving hydration behavior and suspended error recovery contracts.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 6.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 31 functions across 12 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant