Skip to content

Fix hydration-susepsnse crashing due to sCU bail - #5134

Merged
JoviDeCroock merged 1 commit into
v10.xfrom
patch-crashing-at-suspense-bail
Jul 3, 2026
Merged

Fix hydration-susepsnse crashing due to sCU bail#5134
JoviDeCroock merged 1 commit into
v10.xfrom
patch-crashing-at-suspense-bail

Conversation

@JoviDeCroock

Copy link
Copy Markdown
Member
  1. During hydration, the Suspense child throws a promise.
  2. Suspense preserves the existing server DOM instead of showing the fallback.
  3. Because the component threw before diffChildren() ran, its vnode can be left with _children === null.
  4. That vnode becomes the oldVNode on the next update.
  5. The parent update reaches the suspended child, and shouldComponentUpdate() === false takes the bailout path.
  6. The bailout does:
  newVNode._children = oldVNode._children;
  newVNode._children.some(...)

but oldVNode._children is null, so it crashes.
7. The fix makes the recovery path establish the invariant that recovered vnodes always have iterable _children: partial children if already produced, old children if available, otherwise [].

@JoviDeCroock
JoviDeCroock force-pushed the patch-crashing-at-suspense-bail branch from 1fb6634 to d781aa5 Compare July 3, 2026 07:25
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

📊 Tachometer Benchmark Results

Summary

duration

  • create10k: unsure 🔍 -0% - +1% (-3.16ms - +3.83ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -0% - +1% (-0.07ms - +0.22ms)
    preact-local vs preact-main
  • hydrate1k: unsure 🔍 -1% - +3% (-0.42ms - +1.68ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -1% - +3% (-0.19ms - +0.41ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -1% - +3% (-0.36ms - +1.42ms)
    preact-local vs preact-main
  • text-update: unsure 🔍 -2% - +6% (-0.04ms - +0.12ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -3% - +1% (-0.73ms - +0.24ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -5% - +2% (-1.49ms - +0.73ms)
    preact-local vs preact-main

usedJSHeapSize

  • create10k: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • hydrate1k: unsure 🔍 -5% - +1% (-0.24ms - +0.04ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -0% - +0% (-0.00ms - +0.01ms)
    preact-local vs preact-main
  • text-update: slower ❌ 0% - 7% (0.00ms - 0.07ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -0% - +0% (-0.01ms - +0.00ms)
    preact-local vs preact-main

Results

create10k

duration

VersionAvg timevs preact-localvs preact-main
preact-local753.58ms - 758.77ms-unsure 🔍
-0% - +1%
-3.16ms - +3.83ms
preact-main753.50ms - 758.18msunsure 🔍
-1% - +0%
-3.83ms - +3.16ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local19.21ms - 19.21ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main19.21ms - 19.21msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
filter-list

duration

VersionAvg timevs preact-localvs preact-main
preact-local16.45ms - 16.73ms-unsure 🔍
-0% - +1%
-0.07ms - +0.22ms
preact-main16.48ms - 16.55msunsure 🔍
-1% - +0%
-0.22ms - +0.07ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.56ms - 1.56ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main1.56ms - 1.56msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
hydrate1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local59.97ms - 61.61ms-unsure 🔍
-1% - +3%
-0.42ms - +1.68ms
preact-main59.50ms - 60.82msunsure 🔍
-3% - +1%
-1.68ms - +0.42ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local5.08ms - 5.22ms-unsure 🔍
-5% - +1%
-0.24ms - +0.04ms
preact-main5.13ms - 5.37msunsure 🔍
-1% - +5%
-0.04ms - +0.24ms
-
many-updates

duration

VersionAvg timevs preact-localvs preact-main
preact-local15.99ms - 16.37ms-unsure 🔍
-1% - +3%
-0.19ms - +0.41ms
preact-main15.84ms - 16.30msunsure 🔍
-3% - +1%
-0.41ms - +0.19ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.73ms - 3.74ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main3.73ms - 3.74msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
replace1k
  • Browser: chrome-headless
  • Sample size: 100
  • Built by: CI #5619
  • Commit: c3b4f0f

duration

VersionAvg timevs preact-localvs preact-main
preact-local55.52ms - 56.89ms-unsure 🔍
-1% - +3%
-0.36ms - +1.42ms
preact-main55.11ms - 56.25msunsure 🔍
-3% - +1%
-1.42ms - +0.36ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.02ms - 3.02ms-unsure 🔍
-0% - +0%
-0.00ms - +0.01ms
preact-main3.02ms - 3.02msunsure 🔍
-0% - +0%
-0.01ms - +0.00ms
-

run-warmup-0

VersionAvg timevs preact-localvs preact-main
preact-local26.41ms - 27.16ms-unsure 🔍
-3% - +1%
-0.87ms - +0.26ms
preact-main26.67ms - 27.51msunsure 🔍
-1% - +3%
-0.26ms - +0.87ms
-

run-warmup-1

VersionAvg timevs preact-localvs preact-main
preact-local31.20ms - 32.16ms-unsure 🔍
-1% - +4%
-0.16ms - +1.19ms
preact-main30.69ms - 31.64msunsure 🔍
-4% - +0%
-1.19ms - +0.16ms
-

run-warmup-2

VersionAvg timevs preact-localvs preact-main
preact-local31.36ms - 32.43ms-unsure 🔍
-3% - +2%
-0.82ms - +0.74ms
preact-main31.37ms - 32.50msunsure 🔍
-2% - +3%
-0.74ms - +0.82ms
-

run-warmup-3

VersionAvg timevs preact-localvs preact-main
preact-local25.41ms - 26.38ms-unsure 🔍
-1% - +3%
-0.37ms - +0.75ms
preact-main25.43ms - 25.98msunsure 🔍
-3% - +1%
-0.75ms - +0.37ms
-

run-warmup-4

VersionAvg timevs preact-localvs preact-main
preact-local22.31ms - 23.36ms-unsure 🔍
-3% - +4%
-0.74ms - +0.80ms
preact-main22.23ms - 23.37msunsure 🔍
-4% - +3%
-0.80ms - +0.74ms
-

run-final

VersionAvg timevs preact-localvs preact-main
preact-local20.96ms - 21.39ms-unsure 🔍
-1% - +2%
-0.28ms - +0.36ms
preact-main20.90ms - 21.37msunsure 🔍
-2% - +1%
-0.36ms - +0.28ms
-
text-update
  • Browser: chrome-headless
  • Sample size: 220
  • Built by: CI #5619
  • Commit: c3b4f0f

duration

VersionAvg timevs preact-localvs preact-main
preact-local1.88ms - 1.98ms-unsure 🔍
-2% - +6%
-0.04ms - +0.12ms
preact-main1.83ms - 1.95msunsure 🔍
-6% - +2%
-0.12ms - +0.04ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.04ms - 1.10ms-slower ❌
0% - 7%
0.00ms - 0.07ms
preact-main1.01ms - 1.05msfaster ✔
0% - 7%
0.00ms - 0.07ms
-
todo

duration

VersionAvg timevs preact-localvs preact-main
preact-local25.60ms - 26.02ms-unsure 🔍
-3% - +1%
-0.73ms - +0.24ms
preact-main25.62ms - 26.49msunsure 🔍
-1% - +3%
-0.24ms - +0.73ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.26ms - 1.26ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main1.26ms - 1.26msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
update10th1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local30.04ms - 31.43ms-unsure 🔍
-5% - +2%
-1.49ms - +0.73ms
preact-main30.25ms - 31.98msunsure 🔍
-2% - +5%
-0.73ms - +1.49ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local2.98ms - 2.99ms-unsure 🔍
-0% - +0%
-0.01ms - +0.00ms
preact-main2.98ms - 3.00msunsure 🔍
-0% - +0%
-0.00ms - +0.01ms
-

tachometer-reporter-action v2 for CI

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Size Change: -20 B (-0.03%)

Total Size: 79.6 kB

📦 View Changed
Filename Size Change
compat/dist/compat.js 4.22 kB +8 B (+0.19%)
compat/dist/compat.mjs 4.15 kB +7 B (+0.17%)
compat/dist/compat.module.js 4.15 kB +7 B (+0.17%)
compat/dist/compat.umd.js 4.29 kB +15 B (+0.35%)
dist/preact.js 4.83 kB -6 B (-0.12%)
dist/preact.min.js 4.84 kB -10 B (-0.21%)
dist/preact.min.module.js 4.85 kB -7 B (-0.14%)
dist/preact.min.umd.js 4.86 kB -9 B (-0.18%)
dist/preact.mjs 4.85 kB -7 B (-0.14%)
dist/preact.module.js 4.85 kB -7 B (-0.14%)
dist/preact.umd.js 4.87 kB -11 B (-0.23%)
ℹ️ View Unchanged
Filename Size
debug/dist/debug.js 3.85 kB
debug/dist/debug.mjs 3.85 kB
debug/dist/debug.module.js 3.85 kB
debug/dist/debug.umd.js 3.93 kB
devtools/dist/devtools.js 260 B
devtools/dist/devtools.mjs 274 B
devtools/dist/devtools.module.js 274 B
devtools/dist/devtools.umd.js 346 B
hooks/dist/hooks.js 1.51 kB
hooks/dist/hooks.mjs 1.54 kB
hooks/dist/hooks.module.js 1.54 kB
hooks/dist/hooks.umd.js 1.58 kB
jsx-runtime/dist/jsxRuntime.js 1.01 kB
jsx-runtime/dist/jsxRuntime.mjs 985 B
jsx-runtime/dist/jsxRuntime.module.js 985 B
jsx-runtime/dist/jsxRuntime.umd.js 1.08 kB
test-utils/dist/testUtils.js 473 B
test-utils/dist/testUtils.mjs 477 B
test-utils/dist/testUtils.module.js 477 B
test-utils/dist/testUtils.umd.js 555 B

compressed-size-action

@JoviDeCroock
JoviDeCroock force-pushed the patch-crashing-at-suspense-bail branch 4 times, most recently from 5c0daec to f98dbbc Compare July 3, 2026 08:53
Assisted-By: devx/f79ddc2d-9f3b-44d1-85dc-4cb2c75c5ad5
@JoviDeCroock
JoviDeCroock force-pushed the patch-crashing-at-suspense-bail branch from f98dbbc to c3b4f0f Compare July 3, 2026 09:02
@JoviDeCroock
JoviDeCroock merged commit 893845a into v10.x Jul 3, 2026
12 checks passed
@JoviDeCroock
JoviDeCroock deleted the patch-crashing-at-suspense-bail branch July 3, 2026 09:45
@JoviDeCroock JoviDeCroock mentioned this pull request Jul 3, 2026
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.

2 participants