Repository navigation
Commit 061a07a
Marcus Karlos
Interactivity API: Fix hydratedIslands race condition and bfcache recovery
Move hydratedIslands.add() from toVdom() to hydrateRegions(), replace the
bare WeakSet with a resettable wrapper, and add a pageshow listener for
bfcache recovery.
**Root cause (race condition):**
toVdom() is called by both the hydration phase and the interactivity-router.
When the router module evaluates before @wordpress/interactivity completes
hydration (reproducible on Safari/Firefox due to JS engine scheduling),
it calls toVdom() internally. The original code inside toVdom() called
hydratedIslands.add(elementNode) for each island it parsed. When
hydrateRegions() ran afterward, every node already passed has(), so the
loop silently skipped all islands — resulting in a permanently un-hydrated
DOM with dead event listeners and no reactive bindings.
**Root cause (bfcache freeze):**
hydrateRegions() is async and yields at each await splitTask() boundary.
If the browser freezes the page into bfcache during a yield, the async
continuation is permanently lost. On restore the DOM looks intact but
Preact's vdom trees are incomplete or detached.
**Changes:**
- Add hydratedIslands.add(node) in hydrateRegions(), after
initialVdom.set(node, vdom) and before hydrate(vdom, fragment).
An island is hydrated when Preact owns it — not when parsed.
- Add window.addEventListener('pageshow', ...) at module level.
On event.persisted === true: reset() the tracker and re-run
hydrateRegions(). Calling hydrate() a second time is safe —
Preact reconciles existing nodes and re-attaches all listeners.
Fixes WordPress#757781 parent 83a8f44 commit 061a07a
1 file changed
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
46 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
0 commit comments