/** * Drain the `window.$RE_q` event buffer that the inline runtime populated * before the main bundle was parsed. For each buffered event, re-dispatch a * synthesized event at the original target so handlers attached during * hydration see it. * * Lossy by design: only the event type and target are preserved. Modifier * keys, pointer positions, etc. are zeroed. This is acceptable because the * replay window is a fraction of a second between shell render and full * hydration of a streaming page; users who need pixel-accurate replay won't * lose much beyond that. */ export function drainReplayQueue(): void { const g = globalThis as any const q = g.$RE_q as Array<[string, EventTarget, number]> | undefined if (!q) return // Stop capturing before replaying so we don't re-capture what we dispatch. try { g.$RE_stop?.() } catch {} for (const [type, target] of q.splice(0)) { try { target.dispatchEvent(createEvent(type)) } catch {} } } function createEvent(type: string): Event { const options = { bubbles: true, cancelable: true } return type === 'click' ? new MouseEvent(type, options) : type === 'keydown' ? new KeyboardEvent(type, options) : type === 'input' ? new InputEvent(type, options) : new Event(type, options) }