{"version":3,"file":"hydration-scheduler.mjs","sources":["../../../src/lib/hydration/hydration-scheduler.ts"],"sourcesContent":["/**\n * @file Hydration Scheduler\n * @description Core scheduler for the Auto-Prioritized Hydration System.\n *\n * The scheduler orchestrates hydration of React components using:\n * - Priority queue for ordering tasks by urgency\n * - IntersectionObserver for visibility-based hydration\n * - requestIdleCallback for background hydration\n * - Frame budgeting to prevent main thread blocking\n * - Interaction replay for seamless user experience\n *\n * Key Performance Optimizations:\n * - Never blocks main thread for more than 50ms per frame\n * - Yields to user input during hydration batches\n * - Uses passive observers where possible\n * - Pools common resources to reduce allocations\n *\n * @module hydration/hydration-scheduler\n */\n\nimport { HydrationPriorityQueue, type PriorityQueueStats } from './priority-queue';\nimport { getInteractionReplayManager, type InteractionReplayManager, } from './interaction-replay';\nimport type {\n  HydrationBoundaryId,\n  HydrationEvent,\n  HydrationEventListener,\n  HydrationEventType,\n  HydrationMetric,\n  HydrationMetricsSnapshot,\n  HydrationPriority,\n  HydrationSchedulerConfig,\n  HydrationStatus,\n  HydrationTask,\n} from './types';\nimport { createInitialHydrationStatus, DEFAULT_SCHEDULER_CONFIG, PRIORITY_WEIGHTS, } from './types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Internal representation of a registered boundary.\n */\ninterface RegisteredBoundary {\n  task: HydrationTask;\n  status: HydrationStatus;\n  visibilityUnsubscribe?: () => void;\n  timeoutId?: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Scheduler state for external observation.\n */\nexport interface SchedulerState {\n  readonly isRunning: boolean;\n  readonly isPaused: boolean;\n  readonly isProcessing: boolean;\n  readonly queueSize: number;\n  readonly hydratedCount: number;\n  readonly pendingCount: number;\n  readonly failedCount: number;\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Checks if requestIdleCallback is available.\n */\nfunction hasIdleCallback(): boolean {\n  return typeof window !== 'undefined' && 'requestIdleCallback' in window;\n}\n\n/**\n * Safe requestIdleCallback with fallback.\n */\nfunction requestIdle(\n  callback: (deadline: IdleDeadline) => void,\n  options?: IdleRequestOptions\n): number {\n  if (hasIdleCallback()) {\n    return window.requestIdleCallback(callback, options);\n  }\n\n  // Fallback using setTimeout with simulated deadline\n\n  return window.setTimeout(() => {\n    callback({\n      didTimeout: false,\n      timeRemaining: () => 50,\n    });\n  }, options?.timeout ?? 100);\n}\n\n/**\n * Safe cancelIdleCallback with fallback.\n */\nfunction cancelIdle(handle: number): void {\n  if (hasIdleCallback()) {\n    window.cancelIdleCallback(handle);\n  } else {\n    window.clearTimeout(handle);\n  }\n}\n\n/**\n * Type for the experimental Scheduler API on window\n */\ninterface WindowWithScheduler extends Window {\n  scheduler: {\n    yield: () => Promise<void>;\n  };\n}\n\n/**\n * Type guard for checking if window has the scheduler.yield API\n */\nfunction hasSchedulerYieldAPI(win: Window): win is WindowWithScheduler {\n  return (\n    'scheduler' in win &&\n    typeof (win as WindowWithScheduler).scheduler === 'object' &&\n    (win as WindowWithScheduler).scheduler !== null &&\n    'yield' in (win as WindowWithScheduler).scheduler\n  );\n}\n\n/**\n * Yields to the main thread.\n */\nasync function yieldToMain(): Promise<void> {\n  return new Promise((resolve) => {\n    if (hasSchedulerYieldAPI(window)) {\n      // Use scheduler.yield if available (modern browsers)\n      void window.scheduler.yield().then(resolve);\n    } else {\n      // Fallback to setTimeout\n      setTimeout(resolve, 0);\n    }\n  });\n}\n\n/**\n * Calculates percentile from sorted array.\n */\nfunction percentile(sortedValues: number[], p: number): number {\n  if (sortedValues.length === 0) return 0;\n  const index = Math.ceil((p / 100) * sortedValues.length) - 1;\n  const clampedIndex = Math.max(0, Math.min(index, sortedValues.length - 1));\n  return sortedValues[clampedIndex] ?? 0;\n}\n\n// ============================================================================\n// Hydration Scheduler Class\n// ============================================================================\n\n/**\n * Core scheduler for auto-prioritized hydration.\n *\n * @example\n * ```typescript\n * const scheduler = new HydrationScheduler({ debug: true });\n *\n * scheduler.register({\n *   id: 'hero-section',\n *   priority: 'critical',\n *   trigger: 'immediate',\n *   hydrate: async () => { ... },\n * });\n *\n * scheduler.start();\n * ```\n */\nexport class HydrationScheduler {\n  /** Configuration */\n  private readonly config: HydrationSchedulerConfig;\n\n  /** Priority queue for pending tasks */\n  private readonly queue: HydrationPriorityQueue;\n\n  /** Registered boundaries */\n  private readonly boundaries = new Map<HydrationBoundaryId, RegisteredBoundary>();\n\n  /** Visibility observer */\n  private visibilityObserver: IntersectionObserver | null = null;\n\n  /** Media query listeners */\n  private readonly mediaListeners = new Map<string, MediaQueryList>();\n\n  /** Interaction replay manager */\n  private readonly replayManager: InteractionReplayManager;\n\n  /** Event listeners */\n  private readonly eventListeners = new Map<HydrationEventType, Set<HydrationEventListener>>();\n\n  /** Metrics storage */\n  private readonly metrics: HydrationMetric[] = [];\n\n  /** State */\n  private isRunning = false;\n  private isPaused = false;\n  private isProcessing = false;\n  private idleCallbackHandle: number | null = null;\n  private animationFrameHandle: number | null = null;\n  private startTime: number | null = null;\n  private aboveFoldHydrationTime: number | null = null;\n  private fullHydrationTime: number | null = null;\n\n  /**\n   * Creates a new HydrationScheduler.\n   *\n   * @param config - Scheduler configuration\n   */\n  constructor(config: Partial<HydrationSchedulerConfig> = {}) {\n    this.config = {\n      ...DEFAULT_SCHEDULER_CONFIG,\n      ...config,\n      budget: {\n        ...DEFAULT_SCHEDULER_CONFIG.budget,\n        ...config.budget,\n      },\n      visibility: {\n        ...DEFAULT_SCHEDULER_CONFIG.visibility,\n        ...config.visibility,\n      },\n    };\n\n    this.queue = new HydrationPriorityQueue({\n      maxSize: this.config.maxQueueSize,\n      onOverflow: (task) => {\n        this.emitEvent('queue:overflow', task.id, { task });\n        this.log(`Queue overflow, dropped task: ${task.id}`, 'warn');\n      },\n    });\n\n    this.replayManager = getInteractionReplayManager(\n      undefined,\n      this.config.debug\n    );\n\n    this.initializeVisibilityObserver();\n  }\n\n  // ==========================================================================\n  // Lifecycle API\n  // ==========================================================================\n\n  /**\n   * Starts the hydration scheduler.\n   * Begins processing queued tasks according to their priority and triggers.\n   */\n  start(): void {\n    if (this.isRunning) {\n      this.log('Scheduler already running');\n      return;\n    }\n\n    this.isRunning = true;\n    this.startTime = performance.now();\n\n    this.log('Scheduler started');\n    this.scheduleProcessing();\n  }\n\n  /**\n   * Stops the hydration scheduler.\n   * Pending tasks remain in queue but processing stops.\n   */\n  stop(): void {\n    if (!this.isRunning) {\n      return;\n    }\n\n    this.isRunning = false;\n    this.cancelScheduledProcessing();\n\n    this.log('Scheduler stopped');\n  }\n\n  /**\n   * Pauses the scheduler without clearing the queue.\n   */\n  pause(): void {\n    if (this.isPaused) {\n      return;\n    }\n\n    this.isPaused = true;\n    this.cancelScheduledProcessing();\n    this.emitEvent('scheduler:paused');\n\n    this.log('Scheduler paused');\n  }\n\n  /**\n   * Resumes a paused scheduler.\n   */\n  resume(): void {\n    if (!this.isPaused) {\n      return;\n    }\n\n    this.isPaused = false;\n    this.emitEvent('scheduler:resumed');\n\n    if (this.isRunning) {\n      this.scheduleProcessing();\n    }\n\n    this.log('Scheduler resumed');\n  }\n\n  /**\n   * Disposes of all resources.\n   * Call when unmounting the hydration system.\n   */\n  dispose(): void {\n    this.stop();\n\n    // Clean up boundaries\n    for (const [id, boundary] of this.boundaries) {\n      boundary.visibilityUnsubscribe?.();\n      if (boundary.timeoutId) {\n        clearTimeout(boundary.timeoutId);\n      }\n      this.replayManager.clearCaptured(id);\n    }\n    this.boundaries.clear();\n\n    // Clean up observer\n    this.visibilityObserver?.disconnect();\n    this.visibilityObserver = null;\n\n    // Clean up media listeners\n    // Clear the map - the MediaQueryList will be garbage collected\n    this.mediaListeners.clear();\n\n    // Clear event listeners\n    this.eventListeners.clear();\n\n    // Clear queue\n    this.queue.clear();\n\n    this.log('Scheduler disposed');\n  }\n\n  // ==========================================================================\n  // Registration API\n  // ==========================================================================\n\n  /**\n   * Registers a hydration task.\n   *\n   * @param task - The hydration task to register\n   */\n  register(task: HydrationTask): void {\n    // Check if already registered\n    if (this.boundaries.has(task.id)) {\n      this.log(`Boundary ${task.id} already registered, updating`);\n      this.unregister(task.id);\n    }\n\n    // Create registered boundary\n    const boundary: RegisteredBoundary = {\n      task,\n      status: createInitialHydrationStatus(),\n    };\n\n    this.boundaries.set(task.id, boundary);\n    this.emitEvent('boundary:registered', task.id, { task });\n\n    // Setup trigger-specific behavior\n    this.setupTrigger(boundary);\n\n    this.log(`Registered boundary: ${task.id} (${task.priority}/${task.trigger})`);\n  }\n\n  /**\n   * Unregisters a hydration task.\n   *\n   * @param id - ID of the task to unregister\n   */\n  unregister(id: HydrationBoundaryId): void {\n    const boundary = this.boundaries.get(id);\n\n    if (!boundary) {\n      return;\n    }\n\n    // Clean up trigger\n    boundary.visibilityUnsubscribe?.();\n    if (boundary.timeoutId) {\n      clearTimeout(boundary.timeoutId);\n    }\n\n    // Remove from queue if pending\n    this.queue.remove(id);\n\n    // Clean up replay buffer\n    this.replayManager.clearCaptured(id);\n\n    this.boundaries.delete(id);\n    this.emitEvent('boundary:unregistered', id);\n\n    this.log(`Unregistered boundary: ${id}`);\n  }\n\n  // ==========================================================================\n  // Control API\n  // ==========================================================================\n\n  /**\n   * Updates the priority of a registered boundary.\n   *\n   * @param id - ID of the boundary\n   * @param priority - New priority level\n   */\n  updatePriority(id: HydrationBoundaryId, priority: HydrationPriority): void {\n    const boundary = this.boundaries.get(id);\n\n    if (!boundary) {\n      this.log(`Cannot update priority: boundary ${id} not found`, 'warn');\n      return;\n    }\n\n    // Update task\n    const updatedTask: HydrationTask = {\n      ...boundary.task,\n      priority,\n    };\n    boundary.task = updatedTask;\n\n    // Update queue position if queued\n    if (this.queue.has(id)) {\n      this.queue.updatePriority(id, priority);\n    }\n\n    this.log(`Updated priority for ${id}: ${priority}`);\n  }\n\n  /**\n   * Forces immediate hydration of a specific boundary.\n   *\n   * @param id - ID of the boundary to hydrate\n   */\n  async forceHydrate(id: HydrationBoundaryId): Promise<void> {\n    const boundary = this.boundaries.get(id);\n\n    if (!boundary) {\n      throw new Error(`Boundary ${id} not found`);\n    }\n\n    if (boundary.status.state === 'hydrated') {\n      return;\n    }\n\n    // Remove from queue to avoid double hydration\n    this.queue.remove(id);\n\n    await this.hydrateTask(boundary);\n  }\n\n  /**\n   * Forces hydration of all registered boundaries.\n   */\n  async forceHydrateAll(): Promise<void> {\n    const pending = Array.from(this.boundaries.values()).filter(\n      (b) => b.status.state === 'pending'\n    );\n\n    // Sort by priority for predictable order\n    pending.sort((a, b) =>\n      PRIORITY_WEIGHTS[a.task.priority] - PRIORITY_WEIGHTS[b.task.priority]\n    );\n\n    for (const boundary of pending) {\n      await this.forceHydrate(boundary.task.id);\n    }\n  }\n\n  // ==========================================================================\n  // Query API\n  // ==========================================================================\n\n  /**\n   * Gets the status of a specific boundary.\n   *\n   * @param id - ID of the boundary\n   * @returns The hydration status, or undefined if not found\n   */\n  getStatus(id: HydrationBoundaryId): HydrationStatus | undefined {\n    return this.boundaries.get(id)?.status;\n  }\n\n  /**\n   * Gets the current scheduler state.\n   */\n  getState(): SchedulerState {\n    let hydratedCount = 0;\n    let pendingCount = 0;\n    let failedCount = 0;\n\n    for (const boundary of this.boundaries.values()) {\n      switch (boundary.status.state) {\n        case 'hydrated':\n          hydratedCount++;\n          break;\n        case 'pending':\n        case 'hydrating':\n          pendingCount++;\n          break;\n        case 'error':\n          failedCount++;\n          break;\n      }\n    }\n\n    return {\n      isRunning: this.isRunning,\n      isPaused: this.isPaused,\n      isProcessing: this.isProcessing,\n      queueSize: this.queue.size,\n      hydratedCount,\n      pendingCount,\n      failedCount,\n    };\n  }\n\n  /**\n   * Gets queue statistics.\n   */\n  getQueueStats(): PriorityQueueStats {\n    return this.queue.getStats();\n  }\n\n  /**\n   * Gets aggregated metrics snapshot.\n   */\n  getMetrics(): HydrationMetricsSnapshot {\n    const state = this.getState();\n    const durations = this.metrics\n      .filter((m) => m.success)\n      .map((m) => m.hydrationDuration)\n      .sort((a, b) => a - b);\n\n    const totalReplayed = this.metrics.reduce(\n      (sum, m) => sum + m.replayedInteractions,\n      0\n    );\n\n    return {\n      totalBoundaries: this.boundaries.size,\n      hydratedCount: state.hydratedCount,\n      pendingCount: state.pendingCount,\n      failedCount: state.failedCount,\n      averageHydrationDuration:\n        durations.length > 0\n          ? durations.reduce((a, b) => a + b, 0) / durations.length\n          : 0,\n      p95HydrationDuration: percentile(durations, 95),\n      totalReplayedInteractions: totalReplayed,\n      timeToFullHydration: this.fullHydrationTime,\n      timeToAboveFoldHydration: this.aboveFoldHydrationTime,\n      queueSize: this.queue.size,\n      timestamp: Date.now(),\n    };\n  }\n\n  /**\n   * Gets the scheduler configuration.\n   */\n  getConfig(): HydrationSchedulerConfig {\n    return this.config;\n  }\n\n  // ==========================================================================\n  // Event API\n  // ==========================================================================\n\n  /**\n   * Adds an event listener.\n   *\n   * @param type - Event type to listen for\n   * @param listener - Callback function\n   * @returns Unsubscribe function\n   */\n  on(type: HydrationEventType, listener: HydrationEventListener): () => void {\n    if (!this.eventListeners.has(type)) {\n      this.eventListeners.set(type, new Set());\n    }\n    const listeners = this.eventListeners.get(type);\n    if (listeners) {\n      listeners.add(listener);\n    }\n\n    return () => {\n      this.eventListeners.get(type)?.delete(listener);\n    };\n  }\n\n  /**\n   * Removes an event listener.\n   */\n  off(type: HydrationEventType, listener: HydrationEventListener): void {\n    this.eventListeners.get(type)?.delete(listener);\n  }\n\n  // ==========================================================================\n  // Private: Trigger Setup\n  // ==========================================================================\n\n  /**\n   * Sets up trigger-specific behavior for a boundary.\n   */\n  private setupTrigger(boundary: RegisteredBoundary): void {\n    const { task } = boundary;\n\n    switch (task.trigger) {\n      case 'immediate':\n        // Queue immediately with high priority\n        this.enqueue(boundary);\n        break;\n\n      case 'visible':\n        // Setup visibility observation\n        this.observeVisibility(boundary);\n        break;\n\n      case 'interaction':\n        // Start interaction capture and observe\n        this.setupInteractionTrigger(boundary);\n        break;\n\n      case 'idle':\n        // Queue with idle priority\n        this.enqueue(boundary);\n        break;\n\n      case 'media':\n        // Setup media query listener\n        this.setupMediaTrigger(boundary);\n        break;\n\n      case 'manual':\n        // Don't auto-queue, wait for explicit hydrate call\n        break;\n    }\n\n    // Setup timeout if specified\n    if (task.timeout != null && task.timeout !== 0 && task.trigger !== 'immediate') {\n      boundary.timeoutId = setTimeout(() => {\n        if (boundary.status.state === 'pending') {\n          this.log(`Timeout reached for ${task.id}, queueing`);\n          this.enqueue(boundary);\n        }\n      }, task.timeout);\n    }\n  }\n\n  /**\n   * Observes visibility for a boundary.\n   */\n  private observeVisibility(boundary: RegisteredBoundary): void {\n    const { task } = boundary;\n\n    if (!task.element || !this.visibilityObserver) {\n      // No element reference, queue immediately\n      this.enqueue(boundary);\n      return;\n    }\n\n    // Store unsubscribe function\n    boundary.visibilityUnsubscribe = () => {\n      if (task.element && this.visibilityObserver) {\n        this.visibilityObserver.unobserve(task.element);\n      }\n    };\n\n    // Start observing\n    this.visibilityObserver.observe(task.element);\n  }\n\n  /**\n   * Sets up interaction trigger for a boundary.\n   */\n  private setupInteractionTrigger(boundary: RegisteredBoundary): void {\n    const { task } = boundary;\n\n    if (!task.element) {\n      // No element, fall back to visibility\n      this.observeVisibility(boundary);\n      return;\n    }\n\n    // Start capturing interactions\n    this.replayManager.startCapture(task.id, task.element);\n\n    // Also observe visibility as a fallback\n    this.observeVisibility(boundary);\n\n    // Setup interaction listeners for immediate hydration\n    const interactionHandler = (): void => {\n      if (boundary.status.state === 'pending') {\n        this.log(`Interaction triggered hydration for ${task.id}`);\n        // Boost priority and queue\n        boundary.task = { ...boundary.task, priority: 'critical' };\n        this.enqueue(boundary);\n      }\n    };\n\n    const events = ['click', 'focus', 'touchstart'];\n    for (const event of events) {\n      task.element.addEventListener(event, interactionHandler, {\n        once: true,\n        capture: true,\n        passive: true,\n      });\n    }\n\n    // Update unsubscribe to include interaction cleanup\n    const originalUnsubscribe = boundary.visibilityUnsubscribe;\n    boundary.visibilityUnsubscribe = () => {\n      originalUnsubscribe?.();\n      for (const event of events) {\n        task.element?.removeEventListener(event, interactionHandler, { capture: true });\n      }\n    };\n  }\n\n  /**\n   * Sets up media query trigger for a boundary.\n   */\n  private setupMediaTrigger(boundary: RegisteredBoundary): void {\n    const { task } = boundary;\n    const mediaQuery = task.metadata?.routePath; // Using routePath as media query for now\n\n    if (mediaQuery == null || mediaQuery === '' || typeof window === 'undefined') {\n      this.enqueue(boundary);\n      return;\n    }\n\n    let mql = this.mediaListeners.get(mediaQuery);\n\n    if (mql == null) {\n      mql = window.matchMedia(mediaQuery);\n      this.mediaListeners.set(mediaQuery, mql);\n    }\n\n    const handler = (event: MediaQueryListEvent | MediaQueryList): void => {\n      if (event.matches && boundary.status.state === 'pending') {\n        this.enqueue(boundary);\n      }\n    };\n\n    // Check initial state\n    if (mql.matches) {\n      this.enqueue(boundary);\n    } else {\n      mql.addEventListener('change', handler as (e: MediaQueryListEvent) => void);\n\n      boundary.visibilityUnsubscribe = () => {\n        mql?.removeEventListener('change', handler as (e: MediaQueryListEvent) => void);\n      };\n    }\n  }\n\n  // ==========================================================================\n  // Private: Processing\n  // ==========================================================================\n\n  /**\n   * Enqueues a boundary for hydration.\n   */\n  private enqueue(boundary: RegisteredBoundary): void {\n    if (boundary.status.state !== 'pending') {\n      return;\n    }\n\n    // Cancel timeout if any\n    if (boundary.timeoutId) {\n      clearTimeout(boundary.timeoutId);\n      boundary.timeoutId = undefined;\n    }\n\n    // Stop visibility observation\n    boundary.visibilityUnsubscribe?.();\n    boundary.visibilityUnsubscribe = undefined;\n\n    // Add to queue\n    this.queue.insert(boundary.task);\n\n    // Ensure processing is scheduled\n    if (this.isRunning && !this.isPaused) {\n      this.scheduleProcessing();\n    }\n  }\n\n  /**\n   * Schedules processing using appropriate callback.\n   */\n  private scheduleProcessing(): void {\n    if (this.isProcessing || this.isPaused || !this.isRunning) {\n      return;\n    }\n\n    // Cancel any existing scheduled processing\n    this.cancelScheduledProcessing();\n\n    // Check if we have critical tasks\n    const nextTask = this.queue.peek();\n\n    if (nextTask?.priority === 'critical') {\n      // Process critical tasks immediately in next frame\n      this.animationFrameHandle = requestAnimationFrame(() => {\n        void this.processQueue();\n      });\n    } else if (nextTask?.priority === 'idle' && this.config.useIdleCallback) {\n      // Process idle tasks in idle time\n      this.idleCallbackHandle = requestIdle(\n        (deadline) => {\n          void this.processQueueWithDeadline(deadline);\n        },\n        { timeout: 5000 }\n      );\n    } else if (nextTask != null) {\n      // Process normal tasks in next frame\n      this.animationFrameHandle = requestAnimationFrame(() => {\n        void this.processQueue();\n      });\n    }\n  }\n\n  /**\n   * Cancels any scheduled processing.\n   */\n  private cancelScheduledProcessing(): void {\n    if (this.idleCallbackHandle !== null) {\n      cancelIdle(this.idleCallbackHandle);\n      this.idleCallbackHandle = null;\n    }\n    if (this.animationFrameHandle !== null) {\n      cancelAnimationFrame(this.animationFrameHandle);\n      this.animationFrameHandle = null;\n    }\n  }\n\n  /**\n   * Processes the queue with a deadline (for idle callback).\n   */\n  private async processQueueWithDeadline(deadline: IdleDeadline): Promise<void> {\n    if (!this.isRunning || this.isPaused || this.isProcessing) {\n      return;\n    }\n\n    this.isProcessing = true;\n\n    try {\n      while (\n        !this.queue.isEmpty() &&\n        (deadline.timeRemaining() > 0 || deadline.didTimeout)\n      ) {\n        const task = this.queue.extractMin();\n        if (task) {\n          const boundary = this.boundaries.get(task.id);\n          if (boundary?.status.state === 'pending') {\n            await this.hydrateTask(boundary);\n          }\n        }\n\n        // Check if we should yield\n        if (\n          deadline.timeRemaining() <= 0 &&\n          !deadline.didTimeout &&\n          !this.queue.isEmpty()\n        ) {\n          break;\n        }\n      }\n    } finally {\n      this.isProcessing = false;\n\n      // Schedule more processing if needed\n      if (!this.queue.isEmpty()) {\n        this.scheduleProcessing();\n      } else {\n        this.checkFullHydration();\n      }\n    }\n  }\n\n  /**\n   * Processes the queue with frame budget.\n   */\n  private async processQueue(): Promise<void> {\n    if (!this.isRunning || this.isPaused || this.isProcessing) {\n      return;\n    }\n\n    this.isProcessing = true;\n    const frameStart = performance.now();\n    let tasksProcessed = 0;\n\n    try {\n      while (\n        !this.queue.isEmpty() &&\n        tasksProcessed < this.config.budget.maxTasksPerFrame\n      ) {\n        // Check frame budget\n        const elapsed = performance.now() - frameStart;\n        if (elapsed >= this.config.budget.frameTimeLimit) {\n          break;\n        }\n\n        const task = this.queue.extractMin();\n        if (task) {\n          const boundary = this.boundaries.get(task.id);\n          if (boundary?.status.state === 'pending') {\n            await this.hydrateTask(boundary);\n            tasksProcessed++;\n          }\n        }\n\n        // Yield to main thread if configured\n        if (this.config.budget.yieldToMain && tasksProcessed % 3 === 0) {\n          await yieldToMain();\n        }\n      }\n    } finally {\n      this.isProcessing = false;\n\n      // Schedule more processing if needed\n      if (!this.queue.isEmpty()) {\n        this.scheduleProcessing();\n      } else {\n        this.checkFullHydration();\n      }\n    }\n  }\n\n  /**\n   * Hydrates a single task.\n   */\n  private async hydrateTask(boundary: RegisteredBoundary): Promise<void> {\n    const { task } = boundary;\n    const startTime = performance.now();\n\n    // Update status to hydrating\n    boundary.status = {\n      ...boundary.status,\n      state: 'hydrating',\n      startedAt: startTime,\n      attempts: boundary.status.attempts + 1,\n    };\n\n    this.emitEvent('hydration:start', task.id);\n    this.log(`Hydrating: ${task.id}`);\n\n    try {\n      // Execute hydration\n      await task.hydrate();\n\n      const endTime = performance.now();\n      const duration = endTime - startTime;\n\n      // Update status to hydrated\n      boundary.status = {\n        ...boundary.status,\n        state: 'hydrated',\n        completedAt: endTime,\n        duration,\n      };\n\n      // Replay any captured interactions\n      let replayedCount = 0;\n      if (this.config.interactionStrategy === 'replay') {\n        replayedCount = await this.replayManager.replayInteractions(task.id);\n        if (replayedCount > 0) {\n          boundary.status = {\n            ...boundary.status,\n            triggeredByReplay: true,\n          };\n        }\n      }\n\n      // Collect metrics\n      if (this.config.collectMetrics && Math.random() <= this.config.metricsSampleRate) {\n        this.recordMetric(boundary, duration, true, replayedCount);\n      }\n\n      // Track above-the-fold hydration\n      if (\n        task.metadata?.aboveTheFold === true &&\n        this.aboveFoldHydrationTime == null &&\n        this.startTime != null &&\n        this.startTime !== 0\n      ) {\n        this.aboveFoldHydrationTime = endTime - this.startTime;\n      }\n\n      // Callbacks\n      task.onHydrated?.();\n\n      this.emitEvent('hydration:complete', task.id, { duration, replayedCount });\n      this.log(`Hydrated: ${task.id} (${duration.toFixed(2)}ms)`);\n    } catch (error) {\n      const endTime = performance.now();\n      const duration = endTime - startTime;\n      const err = error instanceof Error ? error : new Error(String(error));\n\n      // Update status to error\n      boundary.status = {\n        ...boundary.status,\n        state: 'error',\n        completedAt: endTime,\n        duration,\n        error: err,\n      };\n\n      // Stop capturing interactions\n      this.replayManager.clearCaptured(task.id);\n\n      // Collect metrics\n      if (this.config.collectMetrics) {\n        this.recordMetric(boundary, duration, false, 0, err.message);\n      }\n\n      // Callbacks\n      task.onError?.(err);\n\n      this.emitEvent('hydration:error', task.id, { error: err, duration });\n      this.log(`Hydration failed: ${task.id} - ${err.message}`, 'error');\n    }\n  }\n\n  /**\n   * Records a hydration metric.\n   */\n  private recordMetric(\n    boundary: RegisteredBoundary,\n    hydrationDuration: number,\n    success: boolean,\n    replayedInteractions: number,\n    errorMessage?: string\n  ): void {\n    const { task, status } = boundary;\n    const queueDuration = status.startedAt != null && status.startedAt !== 0\n      ? status.startedAt - task.enqueuedAt\n      : 0;\n\n    const metric: HydrationMetric = {\n      boundaryId: task.id,\n      componentName: task.metadata?.componentName,\n      priority: task.priority,\n      trigger: task.trigger,\n      queueDuration,\n      hydrationDuration,\n      totalDuration: queueDuration + hydrationDuration,\n      success,\n      errorMessage,\n      replayedInteractions,\n      timestamp: Date.now(),\n    };\n\n    this.metrics.push(metric);\n\n    // Keep metrics bounded\n    while (this.metrics.length > 1000) {\n      this.metrics.shift();\n    }\n  }\n\n  /**\n   * Checks if all boundaries are hydrated.\n   */\n  private checkFullHydration(): void {\n    if (this.fullHydrationTime !== null) {\n      return;\n    }\n\n    const allHydrated = Array.from(this.boundaries.values()).every(\n      (b) => b.status.state === 'hydrated' || b.status.state === 'error' || b.status.state === 'skipped'\n    );\n\n    if (allHydrated && this.startTime != null && this.startTime !== 0) {\n      this.fullHydrationTime = performance.now() - this.startTime;\n      this.log(`Full hydration complete: ${this.fullHydrationTime.toFixed(2)}ms`);\n    }\n  }\n\n  // ==========================================================================\n  // Private: Visibility Observer\n  // ==========================================================================\n\n  /**\n   * Initializes the IntersectionObserver for visibility-based hydration.\n   */\n  private initializeVisibilityObserver(): void {\n    if (typeof window === 'undefined' || !('IntersectionObserver' in window)) {\n      return;\n    }\n\n    const thresholdValue = this.config.visibility.threshold;\n    let threshold: number | number[];\n    if (Array.isArray(thresholdValue)) {\n      threshold = thresholdValue.slice() as number[];\n    } else if (thresholdValue != null) {\n      threshold = thresholdValue as number;\n    } else {\n      threshold = 0;\n    }\n    this.visibilityObserver = new IntersectionObserver(\n      (entries) => {\n        for (const entry of entries) {\n          if (entry.isIntersecting) {\n            this.handleVisibilityChange(entry.target as HTMLElement);\n          }\n        }\n      },\n      {\n        root: this.config.visibility.root ?? null,\n        rootMargin: this.config.visibility.rootMargin ?? '100px 0px',\n        threshold,\n      }\n    );\n  }\n\n  /**\n   * Handles visibility change for an element.\n   */\n  private handleVisibilityChange(element: HTMLElement): void {\n    // Find the boundary for this element\n    for (const [id, boundary] of this.boundaries) {\n      if (boundary.task.element === element && boundary.status.state === 'pending') {\n        this.log(`Visibility triggered hydration for ${id}`);\n        this.enqueue(boundary);\n        break;\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Private: Event Emission\n  // ==========================================================================\n\n  /**\n   * Emits an event to all listeners.\n   */\n  private emitEvent(\n    type: HydrationEventType,\n    boundaryId?: HydrationBoundaryId,\n    payload?: unknown\n  ): void {\n    const event: HydrationEvent = {\n      type,\n      timestamp: Date.now(),\n      boundaryId,\n      payload,\n    };\n\n    const listeners = this.eventListeners.get(type);\n    if (listeners) {\n      for (const listener of listeners) {\n        try {\n          listener(event);\n        } catch (error) {\n          console.error(`[HydrationScheduler] Event listener error:`, error);\n        }\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Private: Logging\n  // ==========================================================================\n\n  /**\n   * Debug logging helper.\n   */\n  private log(message: string, level: 'log' | 'warn' | 'error' = 'log'): void {\n    if (this.config.debug) {\n      let logger: typeof console.log;\n      if (level === 'error') {\n        logger = console.error;\n      } else if (level === 'warn') {\n        logger = console.warn;\n      } else {\n        logger = console.info;\n      }\n      logger(`[HydrationScheduler] ${message}`);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet schedulerInstance: HydrationScheduler | null = null;\n\n/**\n * Gets or creates the global HydrationScheduler instance.\n *\n * @param config - Scheduler configuration (only used if creating new instance)\n * @returns The global HydrationScheduler instance\n */\nexport function getHydrationScheduler(\n  config?: Partial<HydrationSchedulerConfig>\n): HydrationScheduler {\n  schedulerInstance ??= new HydrationScheduler(config);\n  return schedulerInstance;\n}\n\n/**\n * Resets the global HydrationScheduler instance.\n * Primarily useful for testing.\n */\nexport function resetHydrationScheduler(): void {\n  if (schedulerInstance) {\n    schedulerInstance.dispose();\n    schedulerInstance = null;\n  }\n}\n\n// ============================================================================\n// HMR Support\n// ============================================================================\n\n// Vite HMR disposal to prevent memory leaks during hot module replacement\nif (import.meta.hot) {\n  import.meta.hot.dispose(() => {\n    resetHydrationScheduler();\n  });\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n// SchedulerState is already exported inline above\n"],"names":["hasIdleCallback","requestIdle","callback","options","cancelIdle","handle","hasSchedulerYieldAPI","win","yieldToMain","resolve","percentile","sortedValues","p","index","clampedIndex","HydrationScheduler","config","DEFAULT_SCHEDULER_CONFIG","HydrationPriorityQueue","task","getInteractionReplayManager","id","boundary","createInitialHydrationStatus","priority","updatedTask","pending","b","a","PRIORITY_WEIGHTS","hydratedCount","pendingCount","failedCount","state","durations","m","totalReplayed","sum","type","listener","listeners","interactionHandler","events","event","originalUnsubscribe","mediaQuery","mql","handler","nextTask","deadline","frameStart","tasksProcessed","startTime","endTime","duration","replayedCount","error","err","hydrationDuration","success","replayedInteractions","errorMessage","status","queueDuration","metric","thresholdValue","threshold","entries","entry","element","boundaryId","payload","message","level","logger","schedulerInstance","getHydrationScheduler","resetHydrationScheduler"],"mappings":"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"}