import type { Chunk } from './html' export type NodeMap = WeakMap export type HydrationHook = (map: NodeMap, visited: WeakSet) => void export interface HydrationCapture { hooks: WeakMap } type HydrationCaptureProvider = () => HydrationCapture | null let hydrationCaptureProvider: HydrationCaptureProvider | null = null export function installHydrationCaptureProvider( provider: HydrationCaptureProvider | null ) { hydrationCaptureProvider = provider } export function createHydrationCapture(): HydrationCapture { return { hooks: new WeakMap(), } } export function getHydrationCapture(): HydrationCapture | null { return hydrationCaptureProvider?.() ?? null } export function registerHydrationHook(chunk: Chunk, hook: HydrationHook) { const capture = getHydrationCapture() if (!capture) return const hooks = capture.hooks.get(chunk) if (hooks) { hooks.push(hook) } else { capture.hooks.set(chunk, [hook]) } } export function adoptCapturedChunk( capture: HydrationCapture, chunk: Chunk, map: NodeMap, visited = new WeakSet() ) { if (visited.has(chunk)) return visited.add(chunk) const ref = chunk.ref if (ref.f) ref.f = (map.get(ref.f) as ChildNode | undefined) ?? ref.f if (ref.l) ref.l = (map.get(ref.l) as ChildNode | undefined) ?? ref.l capture.hooks.get(chunk)?.forEach((hook) => hook(map, visited)) }