| 243 | * while maintaining local state cache for synchronous operations. |
| 244 | */ |
| 245 | export class ChartGPUWorkerProxy implements ChartGPUInstance { |
| 246 | private readonly worker: Worker; |
| 247 | private readonly chartId: string; |
| 248 | private readonly messageTimeout: number; |
| 249 | |
| 250 | // State cache (synchronized with worker) |
| 251 | private cachedOptions: ChartGPUOptions; |
| 252 | private isDisposed = false; |
| 253 | private isInitialized = false; |
| 254 | private cachedInteractionX: number | null = null; |
| 255 | private cachedZoomRange: Readonly<{ start: number; end: number }> | null = null; |
| 256 | /** |
| 257 | * Best-effort local series point counts used to keep dataset-aware zoom constraints |
| 258 | * in sync with worker zoom behavior (especially for streaming appendData()). |
| 259 | */ |
| 260 | private cachedSeriesPointCountsForZoom: number[] = []; |
| 261 | |
| 262 | // Performance metrics cache |
| 263 | private cachedPerformanceMetrics: Readonly<PerformanceMetrics> | null = null; |
| 264 | private cachedPerformanceCapabilities: Readonly<PerformanceCapabilities> | null = null; |
| 265 | private performanceUpdateCallbacks = new Set<(metrics: Readonly<PerformanceMetrics>) => void>(); |
| 266 | |
| 267 | // Message correlation system |
| 268 | private readonly pendingRequests = new Map<string, PendingRequest>(); |
| 269 | |
| 270 | // Event system |
| 271 | private readonly listeners = new Map<ChartGPUEventName, Set<AnyChartGPUEventCallback>>(); |
| 272 | |
| 273 | // Worker message handler (bound once) |
| 274 | private readonly boundMessageHandler: (event: MessageEvent) => void; |
| 275 | |
| 276 | // DOM overlays |
| 277 | private tooltip: Tooltip | null = null; |
| 278 | private legend: Legend | null = null; |
| 279 | private textOverlay: TextOverlay | null = null; |
| 280 | private annotationTextOverlay: TextOverlay | null = null; |
| 281 | private dataZoomSlider: DataZoomSlider | null = null; |
| 282 | private dataZoomSliderHost: HTMLDivElement | null = null; |
| 283 | private zoomState: ZoomState | null = null; |
| 284 | |
| 285 | // RAF batching for overlay updates |
| 286 | private pendingOverlayUpdates: PendingOverlayUpdates = {}; |
| 287 | private overlayUpdateRafId: number | null = null; |
| 288 | |
| 289 | // Zoom echo suppression flag |
| 290 | // Set to true when processing zoom changes FROM the worker to prevent sending them back |
| 291 | private isProcessingWorkerZoomUpdate = false; |
| 292 | |
| 293 | // Event forwarding to worker |
| 294 | private readonly boundEventHandlers: { |
| 295 | pointerdown: ((e: PointerEvent) => void) | null; |
| 296 | pointermove: ((e: PointerEvent) => void) | null; |
| 297 | pointerup: ((e: PointerEvent) => void) | null; |
| 298 | pointerleave: ((e: PointerEvent) => void) | null; |
| 299 | wheel: ((e: WheelEvent) => void) | null; |
| 300 | } = { |
| 301 | pointerdown: null, |
| 302 | pointermove: null, |
nothing calls this directly
no outgoing calls
no test coverage detected