agent-react-devtools 0.4.0-canary-20260402222730 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/daemon.js CHANGED
@@ -376,6 +376,11 @@ function skipRects(operations, i) {
376
376
  if (count === -1) return i;
377
377
  return i + count * 4;
378
378
  }
379
+ function isSignificantHost(node) {
380
+ if (node.key !== null) return true;
381
+ if (node.displayName.includes("-")) return true;
382
+ return false;
383
+ }
379
384
  var ComponentTree = class {
380
385
  nodes = /* @__PURE__ */ new Map();
381
386
  roots = [];
@@ -594,37 +599,68 @@ var ComponentTree = class {
594
599
  getNode(id) {
595
600
  return this.nodes.get(id);
596
601
  }
597
- getTree(maxDepth) {
602
+ getTree(maxDepthOrOpts) {
603
+ const opts = typeof maxDepthOrOpts === "number" ? { maxDepth: maxDepthOrOpts } : maxDepthOrOpts || {};
604
+ const { maxDepth, noHost, rootId } = opts;
598
605
  const result = [];
599
606
  this.labelToId.clear();
600
607
  this.idToLabel.clear();
601
608
  let labelCounter = 1;
602
- const walk = (id, depth) => {
609
+ const effectiveChildren = noHost ? /* @__PURE__ */ new Map() : null;
610
+ const walk = (id, depth, effectiveParentId) => {
603
611
  const node = this.nodes.get(id);
604
612
  if (!node) return;
605
613
  if (maxDepth !== void 0 && depth > maxDepth) return;
606
614
  const label = `@c${labelCounter++}`;
607
615
  this.labelToId.set(label, node.id);
608
616
  this.idToLabel.set(node.id, label);
609
- const treeNode = {
610
- id: node.id,
611
- label,
612
- displayName: node.displayName,
613
- type: node.type,
614
- key: node.key,
615
- parentId: node.parentId,
616
- children: node.children,
617
- depth
618
- };
619
- if (node.errors > 0) treeNode.errors = node.errors;
620
- if (node.warnings > 0) treeNode.warnings = node.warnings;
621
- result.push(treeNode);
622
- for (const childId of node.children) {
623
- walk(childId, depth + 1);
617
+ const skipThis = noHost && node.type === "host" && !isSignificantHost(node) && !(rootId !== void 0 && id === rootId);
618
+ if (skipThis) {
619
+ for (const childId of node.children) {
620
+ walk(childId, depth, effectiveParentId);
621
+ }
622
+ } else {
623
+ if (effectiveChildren) {
624
+ let siblings = effectiveChildren.get(effectiveParentId);
625
+ if (!siblings) {
626
+ siblings = [];
627
+ effectiveChildren.set(effectiveParentId, siblings);
628
+ }
629
+ siblings.push(node.id);
630
+ }
631
+ const treeNode = {
632
+ id: node.id,
633
+ label,
634
+ displayName: node.displayName,
635
+ type: node.type,
636
+ key: node.key,
637
+ parentId: rootId !== void 0 && depth === 0 ? null : effectiveParentId,
638
+ children: node.children,
639
+ // patched below when noHost
640
+ depth
641
+ };
642
+ if (node.errors > 0) treeNode.errors = node.errors;
643
+ if (node.warnings > 0) treeNode.warnings = node.warnings;
644
+ result.push(treeNode);
645
+ for (const childId of node.children) {
646
+ walk(childId, depth + 1, node.id);
647
+ }
624
648
  }
625
649
  };
626
- for (const rootId of this.roots) {
627
- walk(rootId, 0);
650
+ if (rootId !== void 0) {
651
+ const rootNode = this.nodes.get(rootId);
652
+ if (rootNode) {
653
+ walk(rootId, 0, null);
654
+ }
655
+ } else {
656
+ for (const rid of this.roots) {
657
+ walk(rid, 0, null);
658
+ }
659
+ }
660
+ if (effectiveChildren) {
661
+ for (const node of result) {
662
+ node.children = effectiveChildren.get(node.id) ?? [];
663
+ }
628
664
  }
629
665
  return result;
630
666
  }
@@ -707,12 +743,13 @@ var ComponentTree = class {
707
743
  * the labeled tree range.
708
744
  */
709
745
  resolveId(id) {
710
- if (typeof id === "number") return id;
746
+ if (typeof id === "number") return this.nodes.has(id) ? id : void 0;
711
747
  const match = id.match(/^@c\?\(id:(\d+)\)$/);
712
748
  if (match) return parseInt(match[1], 10);
713
749
  if (id.startsWith("@c")) return this.labelToId.get(id);
714
750
  const num = parseInt(id, 10);
715
- return isNaN(num) ? void 0 : num;
751
+ if (isNaN(num)) return void 0;
752
+ return this.nodes.has(num) ? num : void 0;
716
753
  }
717
754
  toTreeNode(node) {
718
755
  let depth = 0;
@@ -1261,8 +1298,26 @@ var Daemon = class {
1261
1298
  }
1262
1299
  };
1263
1300
  case "get-tree": {
1264
- const treeData = this.tree.getTree(cmd.depth);
1265
- const response = { ok: true, data: treeData };
1301
+ let resolvedRoot;
1302
+ if (cmd.root !== void 0) {
1303
+ resolvedRoot = this.tree.resolveId(cmd.root);
1304
+ if (resolvedRoot === void 0) {
1305
+ return { ok: false, error: `Component ${cmd.root} not found` };
1306
+ }
1307
+ }
1308
+ const totalCount = this.tree.getComponentCount();
1309
+ const treeData = this.tree.getTree({
1310
+ maxDepth: cmd.depth,
1311
+ noHost: cmd.noHost,
1312
+ rootId: resolvedRoot
1313
+ });
1314
+ if (resolvedRoot !== void 0 && treeData.length === 0) {
1315
+ return { ok: false, error: `Component ${cmd.root} not found` };
1316
+ }
1317
+ const response = {
1318
+ ok: true,
1319
+ data: { nodes: treeData, totalCount }
1320
+ };
1266
1321
  if (treeData.length === 0) {
1267
1322
  const health = this.bridge.getConnectionHealth();
1268
1323
  if (health.hasEverConnected && health.connectedApps === 0 && health.lastDisconnectAt !== null) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/daemon.ts","../src/devtools-bridge.ts","../src/component-tree.ts","../src/profile-export.ts","../src/profiler.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DevToolsBridge } from './devtools-bridge.js';\nimport { ComponentTree } from './component-tree.js';\nimport { Profiler } from './profiler.js';\nimport type { IpcCommand, IpcResponse, DaemonInfo, StatusInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet STATE_DIR = DEFAULT_STATE_DIR;\n\nfunction getSocketPath(): string {\n return path.join(STATE_DIR, 'daemon.sock');\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(STATE_DIR, 'daemon.json');\n}\n\n/**\n * Enrich profiling result items with label + type from the component tree.\n */\nfunction enrichWithLabels(\n items: Array<{ id: number; label?: string; type?: string }>,\n tree: ComponentTree,\n): void {\n for (const item of items) {\n if (!item.label) item.label = tree.getLabel(item.id);\n if (!item.type) {\n const node = tree.getNode(item.id);\n if (node) item.type = node.type;\n }\n }\n}\n\nclass Daemon {\n private ipcServer: net.Server | null = null;\n private bridge: DevToolsBridge;\n private tree: ComponentTree;\n private profiler: Profiler;\n private port: number;\n private startedAt = Date.now();\n\n constructor(port: number) {\n this.port = port;\n this.tree = new ComponentTree();\n this.profiler = new Profiler();\n this.bridge = new DevToolsBridge(port, this.tree, this.profiler);\n }\n\n async start(): Promise<void> {\n // Ensure state directory exists\n fs.mkdirSync(STATE_DIR, { recursive: true });\n\n // Clean up stale socket\n const socketPath = getSocketPath();\n if (fs.existsSync(socketPath)) {\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // ignore\n }\n }\n\n // Start WebSocket bridge\n await this.bridge.start();\n\n // Start IPC server\n await this.startIpc(socketPath);\n\n // Write daemon info\n let buildMtime: number | undefined;\n try {\n buildMtime = fs.statSync(new URL(import.meta.url).pathname).mtimeMs;\n } catch {\n // ignore\n }\n const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\n buildMtime,\n };\n fs.writeFileSync(getDaemonInfoPath(), JSON.stringify(info, null, 2));\n\n console.log(`Daemon started (pid=${process.pid}, port=${this.port})`);\n\n // Handle shutdown\n const shutdown = () => {\n this.stop();\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n }\n\n private startIpc(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.ipcServer = net.createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n\n // Process complete messages (newline-delimited JSON)\n let newlineIdx: number;\n while ((newlineIdx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + 1);\n\n try {\n const cmd: IpcCommand = JSON.parse(line);\n this.handleCommand(cmd, conn).then((response) => {\n if (!conn.destroyed) {\n conn.write(JSON.stringify(response) + '\\n');\n }\n });\n } catch {\n const response: IpcResponse = {\n ok: false,\n error: 'Invalid JSON',\n };\n conn.write(JSON.stringify(response) + '\\n');\n }\n }\n });\n });\n\n this.ipcServer.on('error', reject);\n\n this.ipcServer.listen(socketPath, () => {\n resolve();\n });\n });\n }\n\n private async handleCommand(cmd: IpcCommand, conn: net.Socket): Promise<IpcResponse> {\n try {\n switch (cmd.type) {\n case 'ping':\n return { ok: true, data: 'pong' };\n\n case 'status':\n return {\n ok: true,\n data: {\n daemonRunning: true,\n port: this.port,\n connectedApps: this.bridge.getConnectedAppCount(),\n componentCount: this.tree.getComponentCount(),\n profilingActive: this.profiler.isActive(),\n uptime: Date.now() - this.startedAt,\n connection: this.bridge.getConnectionHealth(),\n } satisfies StatusInfo,\n };\n\n case 'get-tree': {\n const treeData = this.tree.getTree(cmd.depth);\n const response: IpcResponse = { ok: true, data: treeData };\n if (treeData.length === 0) {\n const health = this.bridge.getConnectionHealth();\n if (health.hasEverConnected && health.connectedApps === 0 && health.lastDisconnectAt !== null) {\n const ago = Math.round((Date.now() - health.lastDisconnectAt) / 1000);\n response.hint = `app disconnected ${ago}s ago, waiting for reconnect...`;\n }\n }\n return response;\n }\n\n case 'get-component': {\n const resolvedId = this.tree.resolveId(cmd.id);\n if (resolvedId === undefined) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n const element = await this.bridge.inspectElement(resolvedId);\n if (!element) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n // Include error/warning counts when non-zero\n const treeNode = this.tree.getNode(resolvedId);\n const enriched: Record<string, unknown> = { ...element };\n if (treeNode && treeNode.errors > 0) enriched.errors = treeNode.errors;\n if (treeNode && treeNode.warnings > 0) enriched.warnings = treeNode.warnings;\n // Include the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: enriched, label };\n }\n\n case 'find':\n return {\n ok: true,\n data: this.tree.findByName(cmd.name, cmd.exact),\n };\n\n case 'count':\n return {\n ok: true,\n data: this.tree.getCountByType(),\n };\n\n case 'errors':\n this.tree.getTree();\n return {\n ok: true,\n data: this.tree.getComponentsWithErrorsOrWarnings(),\n };\n\n case 'profile-start':\n this.profiler.start(cmd.name);\n // Snapshot existing component names so they survive unmounts\n for (const id of this.tree.getAllNodeIds()) {\n const node = this.tree.getNode(id);\n if (node) this.profiler.trackComponent(id, node.displayName);\n }\n this.bridge.startProfiling();\n return { ok: true, data: 'Profiling started' };\n\n case 'profile-stop': {\n await this.bridge.stopProfilingAndCollect();\n const session = this.profiler.stop(this.tree);\n if (!session) {\n return { ok: false, error: 'No active profiling session' };\n }\n enrichWithLabels(session.componentRenderCounts, this.tree);\n return { ok: true, data: session };\n }\n\n case 'profile-report': {\n const resolvedCompId = this.tree.resolveId(cmd.componentId);\n if (resolvedCompId === undefined) {\n return { ok: false, error: `Component ${cmd.componentId} not found` };\n }\n const report = this.profiler.getReport(resolvedCompId, this.tree);\n if (!report) {\n return {\n ok: false,\n error: `No profiling data for component ${cmd.componentId}`,\n };\n }\n enrichWithLabels([report], this.tree);\n const compLabel = typeof cmd.componentId === 'string' ? cmd.componentId : undefined;\n return { ok: true, data: report, label: compLabel };\n }\n\n case 'profile-slow': {\n const slowest = this.profiler.getSlowest(this.tree, cmd.limit);\n enrichWithLabels(slowest, this.tree);\n return { ok: true, data: slowest };\n }\n\n case 'profile-rerenders': {\n const rerenders = this.profiler.getMostRerenders(this.tree, cmd.limit);\n enrichWithLabels(rerenders, this.tree);\n return { ok: true, data: rerenders };\n }\n\n case 'profile-timeline':\n return {\n ok: true,\n data: this.profiler.getTimeline(cmd.limit, cmd.offset, cmd.sort),\n };\n\n case 'profile-commit': {\n const detail = this.profiler.getCommitDetails(cmd.index, this.tree, cmd.limit);\n if (!detail) {\n return { ok: false, error: `Commit #${cmd.index} not found` };\n }\n enrichWithLabels(detail.components, this.tree);\n return { ok: true, data: detail };\n }\n\n case 'profile-export': {\n const exportData = this.profiler.getExportData(this.tree);\n if (!exportData) {\n return { ok: false, error: 'No profiling data to export (run profile start/stop first)' };\n }\n return { ok: true, data: exportData };\n }\n\n case 'wait':\n return this.handleWait(cmd, conn);\n\n default:\n return { ok: false, error: `Unknown command: ${(cmd as any).type}` };\n }\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private handleWait(\n cmd: Extract<IpcCommand, { type: 'wait' }>,\n conn: net.Socket,\n ): Promise<IpcResponse> {\n const timeout = cmd.timeout ?? 30_000;\n\n // Check if condition is already met\n if (this.isWaitConditionMet(cmd)) {\n return Promise.resolve({ ok: true, data: { met: true, condition: cmd.condition } });\n }\n\n return new Promise((resolve) => {\n let settled = false;\n const settle = (response: IpcResponse) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n unsubscribe();\n conn.removeListener('close', onClose);\n resolve(response);\n };\n\n const unsubscribe = this.bridge.onStateChange(() => {\n if (this.isWaitConditionMet(cmd)) {\n settle({ ok: true, data: { met: true, condition: cmd.condition } });\n }\n });\n\n const timer = setTimeout(() => {\n settle({ ok: true, data: { met: false, condition: cmd.condition, timeout: true } });\n }, timeout);\n\n const onClose = () => {\n settle({ ok: false, error: 'Client disconnected' });\n };\n conn.on('close', onClose);\n });\n }\n\n private isWaitConditionMet(cmd: Extract<IpcCommand, { type: 'wait' }>): boolean {\n switch (cmd.condition) {\n case 'connected':\n return this.bridge.getConnectedAppCount() > 0;\n case 'component':\n return this.tree.findByName(cmd.name, true).length > 0;\n default:\n return false;\n }\n }\n\n stop(): void {\n this.bridge.stop();\n if (this.ipcServer) {\n this.ipcServer.close();\n this.ipcServer = null;\n }\n // Clean up files\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n console.log('Daemon stopped');\n }\n}\n\n// ── Main ──\n\nconst portArg = process.argv.find((a) => a.startsWith('--port='));\nconst port = portArg ? parseInt(portArg.split('=')[1], 10) : 8097;\n\nconst stateDirArg = process.argv.find((a) => a.startsWith('--state-dir='));\nif (stateDirArg) {\n STATE_DIR = stateDirArg.split('=')[1];\n}\n\nconst daemon = new Daemon(port);\ndaemon.start().catch((err) => {\n console.error('Failed to start daemon:', err);\n process.exit(1);\n});\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { ComponentTree } from './component-tree.js';\nimport type { Profiler } from './profiler.js';\nimport type { InspectedElement, ConnectionHealth, ConnectionEvent } from './types.js';\n\n/**\n * React DevTools protocol bridge.\n *\n * Implements the \"Wall\" messaging pattern that React DevTools uses:\n * - The backend (inside React app) sends operations, profiling data, etc.\n * - The frontend (us) can request element inspection, start/stop profiling, etc.\n *\n * Message format over WebSocket:\n * { event: string, payload: any }\n */\n\ninterface DevToolsMessage {\n event: string;\n payload: unknown;\n}\n\ninterface PendingInspection {\n resolve: (value: InspectedElement | null) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\ninterface PendingProfilingCollect {\n resolve: () => void;\n timer: ReturnType<typeof setTimeout>;\n remaining: number;\n}\n\nexport class DevToolsBridge {\n private wss: WebSocketServer | null = null;\n private connections = new Set<WebSocket>();\n private port: number;\n private tree: ComponentTree;\n private profiler: Profiler;\n private pendingInspections = new Map<number, PendingInspection>();\n private pendingProfilingCollect: PendingProfilingCollect | null = null;\n private rendererIds = new Set<number>();\n /** Track which root fiber IDs belong to each WebSocket connection */\n private connectionRoots = new Map<WebSocket, Set<number>>();\n private hasEverConnected = false;\n private lastDisconnectAt: number | null = null;\n private recentEvents: ConnectionEvent[] = [];\n private reconnectWindowMs = 5000;\n private stateChangeListeners = new Set<() => void>();\n\n constructor(port: number, tree: ComponentTree, profiler: Profiler) {\n this.port = port;\n this.tree = tree;\n this.profiler = profiler;\n }\n\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({ port: this.port }, () => {\n resolve();\n });\n\n this.wss.on('error', (err) => {\n reject(err);\n });\n\n this.wss.on('connection', (ws) => {\n this.connections.add(ws);\n\n // Reconnect = going from 0 to 1 connected app shortly after a disconnect\n const wasDisconnected = this.connections.size === 1 &&\n this.lastDisconnectAt !== null &&\n (Date.now() - this.lastDisconnectAt) < this.reconnectWindowMs;\n const eventType = wasDisconnected ? 'reconnected' as const : 'connected' as const;\n this.hasEverConnected = true;\n this.lastDisconnectAt = null;\n this.pushEvent({ type: eventType, timestamp: Date.now() });\n this.notifyStateChange();\n\n ws.on('message', (data) => {\n try {\n const msg: DevToolsMessage = JSON.parse(data.toString());\n this.handleMessage(ws, msg);\n } catch {\n // ignore parse errors\n }\n });\n\n ws.on('close', () => {\n this.cleanupConnection(ws);\n });\n\n ws.on('error', () => {\n this.cleanupConnection(ws);\n });\n });\n });\n }\n\n stop(): void {\n for (const conn of this.connections) {\n conn.close();\n }\n this.connections.clear();\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n getConnectedAppCount(): number {\n return this.connections.size;\n }\n\n /**\n * Request detailed inspection of a specific element.\n * Sends a request to the React app and waits for the response.\n */\n inspectElement(id: number): Promise<InspectedElement | null> {\n const node = this.tree.getNode(id);\n if (!node) return Promise.resolve(null);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.pendingInspections.delete(id);\n resolve(null);\n }, 5000);\n\n this.pendingInspections.set(id, { resolve, timer });\n\n this.sendToAll({\n event: 'inspectElement',\n payload: {\n id,\n rendererID: node.rendererId,\n forceFullData: true,\n requestID: id,\n path: null,\n },\n });\n });\n }\n\n startProfiling(): void {\n this.sendToAll({\n event: 'startProfiling',\n payload: { recordChangeDescriptions: true },\n });\n }\n\n /**\n * Stop profiling and request data from each renderer.\n * Returns a promise that resolves when profilingData arrives (or 5s timeout).\n */\n stopProfilingAndCollect(): Promise<void> {\n this.sendToAll({\n event: 'stopProfiling',\n payload: undefined,\n });\n\n // If no renderers known, resolve immediately\n if (this.rendererIds.size === 0) {\n return Promise.resolve();\n }\n\n // Request profiling data from each renderer\n for (const rendererID of this.rendererIds) {\n this.sendToAll({\n event: 'getProfilingData',\n payload: { rendererID },\n });\n }\n\n const expected = this.rendererIds.size;\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingProfilingCollect = null;\n resolve();\n }, 5000);\n\n this.pendingProfilingCollect = { resolve, timer, remaining: expected };\n });\n }\n\n private handleMessage(ws: WebSocket, msg: DevToolsMessage): void {\n switch (msg.event) {\n case 'backendInitialized':\n // Send the full frontend handshake sequence\n this.sendTo(ws, { event: 'getBridgeProtocol', payload: undefined });\n this.sendTo(ws, { event: 'getBackendVersion', payload: undefined });\n this.sendTo(ws, { event: 'getIfHasUnsupportedRendererVersion', payload: undefined });\n this.sendTo(ws, { event: 'getHookSettings', payload: undefined });\n this.sendTo(ws, { event: 'getProfilingStatus', payload: undefined });\n break;\n\n case 'bridgeProtocol':\n case 'backendVersion':\n case 'profilingStatus':\n case 'overrideComponentFilters':\n break;\n\n case 'operations':\n this.handleOperations(ws, msg.payload as number[]);\n break;\n\n case 'inspectedElement':\n this.handleInspectedElement(msg.payload);\n break;\n\n case 'profilingData':\n this.handleProfilingData(msg.payload);\n break;\n\n case 'renderer': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'rendererAttached': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'shutdown':\n ws.close();\n break;\n\n // Silently ignore known but unhandled events\n case 'hookSettings':\n case 'isBackendStorageAPISupported':\n case 'isReactNativeEnvironment':\n case 'isReloadAndProfileSupportedByBackend':\n case 'isSynchronousXHRSupported':\n case 'syncSelectionFromNativeElementsPanel':\n case 'unsupportedRendererVersion':\n break;\n\n default:\n break;\n }\n }\n\n private handleOperations(ws: WebSocket, operations: number[]): void {\n if (operations.length >= 2) {\n // Track renderer ID (first element of every operations array)\n this.rendererIds.add(operations[0]);\n\n // Track which root fiber IDs belong to this connection\n const rootFiberId = operations[1];\n let roots = this.connectionRoots.get(ws);\n if (!roots) {\n roots = new Set();\n this.connectionRoots.set(ws, roots);\n }\n roots.add(rootFiberId);\n }\n const added = this.tree.applyOperations(operations);\n\n // Cache display names during profiling so unmounted components are still identifiable\n if (this.profiler.isActive()) {\n for (const node of added) {\n this.profiler.trackComponent(node.id, node.displayName);\n }\n }\n\n this.notifyStateChange();\n }\n\n private cleanupConnection(ws: WebSocket): void {\n this.connections.delete(ws);\n // Remove all root trees that belonged to this connection\n const roots = this.connectionRoots.get(ws);\n if (roots) {\n for (const rootId of roots) {\n this.tree.removeRoot(rootId);\n }\n this.connectionRoots.delete(ws);\n }\n this.lastDisconnectAt = Date.now();\n this.pushEvent({ type: 'disconnected', timestamp: Date.now() });\n this.notifyStateChange();\n }\n\n private handleInspectedElement(payload: unknown): void {\n const data = payload as {\n type: string;\n id: number;\n value?: {\n id: number;\n displayName: string;\n type: number;\n key: string | null;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n hooks: unknown[] | { data: unknown[]; cleaned: unknown[]; unserializable: unknown[] } | null;\n };\n };\n\n if (data.type !== 'full-data' && data.type !== 'hydrated-path') {\n // No data available\n const pending = this.pendingInspections.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n pending.resolve(null);\n }\n return;\n }\n\n const pending = this.pendingInspections.get(data.id);\n if (!pending || !data.value) return;\n\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n\n const node = this.tree.getNode(data.id);\n const inspected: InspectedElement = {\n id: data.id,\n displayName: data.value.displayName || node?.displayName || 'Unknown',\n type: node?.type || 'other',\n key: data.value.key,\n props: cleanDehydrated(data.value.props) as Record<string, unknown>,\n state: data.value.state\n ? (cleanDehydrated(data.value.state) as Record<string, unknown>)\n : null,\n hooks: data.value.hooks\n ? parseHooks(extractHooksArray(data.value.hooks))\n : null,\n renderedAt: null,\n };\n\n pending.resolve(inspected);\n }\n\n private handleProfilingData(payload: unknown): void {\n // React DevTools sends profiling data as a complex nested structure.\n // We forward it to the profiler for processing.\n this.profiler.processProfilingData(payload);\n\n // Resolve once all expected renderer responses have arrived\n if (this.pendingProfilingCollect) {\n this.pendingProfilingCollect.remaining--;\n if (this.pendingProfilingCollect.remaining <= 0) {\n clearTimeout(this.pendingProfilingCollect.timer);\n const pending = this.pendingProfilingCollect;\n this.pendingProfilingCollect = null;\n pending.resolve();\n }\n }\n }\n\n getConnectionHealth(): ConnectionHealth {\n return {\n connectedApps: this.connections.size,\n hasEverConnected: this.hasEverConnected,\n lastDisconnectAt: this.lastDisconnectAt,\n recentEvents: [...this.recentEvents],\n };\n }\n\n onStateChange(listener: () => void): () => void {\n this.stateChangeListeners.add(listener);\n return () => { this.stateChangeListeners.delete(listener); };\n }\n\n private pushEvent(event: ConnectionEvent): void {\n this.recentEvents.push(event);\n if (this.recentEvents.length > 20) {\n this.recentEvents = this.recentEvents.slice(-20);\n }\n }\n\n private notifyStateChange(): void {\n for (const listener of this.stateChangeListeners) {\n listener();\n }\n }\n\n private sendTo(ws: WebSocket, msg: DevToolsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n }\n\n private sendToAll(msg: DevToolsMessage): void {\n const raw = JSON.stringify(msg);\n for (const conn of this.connections) {\n if (conn.readyState === WebSocket.OPEN) {\n conn.send(raw);\n }\n }\n }\n}\n\n/**\n * React DevTools uses \"dehydrated\" values for complex objects.\n * These appear as objects with `type: 'string'` and other metadata.\n * We simplify them for display.\n */\nfunction cleanDehydrated(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(cleanDehydrated);\n\n const record = obj as Record<string, unknown>;\n\n // Dehydrated value markers from React DevTools\n if ('type' in record && 'preview_short' in record) {\n return record['preview_short'];\n }\n\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record)) {\n cleaned[key] = cleanDehydrated(value);\n }\n return cleaned;\n}\n\n/**\n * React DevTools may send hooks as a plain array or as a dehydrated object\n * with { data: unknown[], cleaned: unknown[], unserializable: unknown[] }.\n * Extract the array in either case.\n */\nfunction extractHooksArray(hooks: unknown): unknown[] {\n if (Array.isArray(hooks)) return hooks;\n if (hooks && typeof hooks === 'object' && 'data' in hooks && Array.isArray((hooks as Record<string, unknown>).data)) {\n return (hooks as Record<string, unknown>).data as unknown[];\n }\n return [];\n}\n\nfunction parseHooks(hooks: unknown[]): { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] }[] {\n return hooks.map((hook) => {\n const h = hook as {\n id: number | null;\n isStateEditable: boolean;\n name: string;\n value: unknown;\n subHooks?: unknown[];\n };\n const result: { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] } = {\n name: h.name,\n value: cleanDehydrated(h.value),\n };\n if (h.subHooks && h.subHooks.length > 0) {\n result.subHooks = parseHooks(h.subHooks) as { name: string; value: unknown }[];\n }\n return result;\n });\n}\n","import type { ComponentNode, ComponentType } from './types.js';\n\n/**\n * React DevTools operations encoding (protocol v2):\n * Operations is a flat array of numbers representing tree mutations.\n *\n * Format: [rendererID, rootFiberID, stringTableSize, ...stringTable, ...ops]\n *\n * The string table encodes display names and keys. Each entry is:\n * [length, ...charCodes]\n * String ID 0 = null. String ID 1 = first entry, etc.\n *\n * Operation types (from React DevTools source):\n */\nconst TREE_OPERATION_ADD = 1;\nconst TREE_OPERATION_REMOVE = 2;\nconst TREE_OPERATION_REORDER_CHILDREN = 3;\nconst TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nconst TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\nconst TREE_OPERATION_REMOVE_ROOT = 6;\nconst TREE_OPERATION_SET_SUBTREE_MODE = 7;\n\n/**\n * Suspense tree operations (newer React DevTools backends, e.g. browser extension):\n */\nconst SUSPENSE_TREE_OPERATION_ADD = 8;\nconst SUSPENSE_TREE_OPERATION_REMOVE = 9;\nconst SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;\nconst SUSPENSE_TREE_OPERATION_RESIZE = 11;\nconst SUSPENSE_TREE_OPERATION_SUSPENDERS = 12;\nconst TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE = 13;\n\n/**\n * Element types from React DevTools (react-devtools-shared/src/frontend/types.js)\n */\nconst ELEMENT_TYPE_CLASS = 1;\n// const ELEMENT_TYPE_CONTEXT = 2;\nconst ELEMENT_TYPE_FUNCTION = 5;\nconst ELEMENT_TYPE_FORWARD_REF = 6;\nconst ELEMENT_TYPE_HOST = 7;\nconst ELEMENT_TYPE_MEMO = 8;\n// const ELEMENT_TYPE_OTHER = 9;\nconst ELEMENT_TYPE_PROFILER = 10;\nconst ELEMENT_TYPE_ROOT = 11;\nconst ELEMENT_TYPE_SUSPENSE = 12;\n\nfunction toComponentType(elementType: number): ComponentType {\n switch (elementType) {\n case ELEMENT_TYPE_CLASS:\n return 'class';\n case ELEMENT_TYPE_FUNCTION:\n return 'function';\n case ELEMENT_TYPE_FORWARD_REF:\n return 'forwardRef';\n case ELEMENT_TYPE_HOST:\n return 'host';\n case ELEMENT_TYPE_MEMO:\n return 'memo';\n case ELEMENT_TYPE_PROFILER:\n return 'profiler';\n case ELEMENT_TYPE_SUSPENSE:\n return 'suspense';\n case ELEMENT_TYPE_ROOT:\n return 'other'; // roots are internal, map to 'other'\n default:\n return 'other';\n }\n}\n\n/**\n * Skip a variable-length rect encoding in the operations array.\n * Rects are encoded as: count, then count * 4 values (x, y, w, h each × 1000).\n * A count of -1 means null (no rects).\n * Returns the new index after skipping.\n */\nfunction skipRects(operations: number[], i: number): number {\n const count = operations[i++];\n if (count === -1) return i;\n return i + count * 4;\n}\n\nexport interface TreeNode {\n id: number;\n label: string;\n displayName: string;\n type: ComponentType;\n key: string | null;\n parentId: number | null;\n children: number[];\n depth: number;\n /** Non-zero error count (omitted when 0) */\n errors?: number;\n /** Non-zero warning count (omitted when 0) */\n warnings?: number;\n}\n\nexport class ComponentTree {\n private nodes = new Map<number, ComponentNode>();\n private roots: number[] = [];\n /** Index: lowercase display name → set of node ids */\n private nameIndex = new Map<string, Set<number>>();\n /** Label → real node ID (e.g., \"@c1\" → 10) */\n private labelToId = new Map<string, number>();\n /** Real node ID → label */\n private idToLabel = new Map<number, string>();\n /**\n * Whether the backend uses the extended ADD format (8 fields with namePropStringID).\n * Auto-detected from the presence of SUSPENSE_TREE_OPERATION opcodes.\n */\n private extendedAddFormat = false;\n\n applyOperations(operations: number[]): Array<{ id: number; displayName: string }> {\n if (operations.length < 2) return [];\n\n const added: Array<{ id: number; displayName: string }> = [];\n const rendererId = operations[0];\n // operations[1] is the root fiber ID\n let i = 2;\n\n // Parse the string table (protocol v2)\n const stringTable: Array<string | null> = [null]; // ID 0 = null\n const stringTableSize = operations[i++];\n const stringTableEnd = i + stringTableSize;\n while (i < stringTableEnd) {\n const strLen = operations[i++];\n let str = '';\n for (let j = 0; j < strLen; j++) {\n str += String.fromCodePoint(operations[i++]);\n }\n stringTable.push(str);\n }\n\n // Parse operations\n while (i < operations.length) {\n const op = operations[i];\n\n switch (op) {\n case TREE_OPERATION_ADD: {\n const id = operations[i + 1];\n const elementType = operations[i + 2];\n i += 3;\n\n if (elementType === ELEMENT_TYPE_ROOT) {\n // Root node: isStrictModeCompliant, supportsProfiling,\n // supportsStrictMode, hasOwnerMetadata\n i += 4;\n\n const node: ComponentNode = {\n id,\n displayName: 'Root',\n type: 'other',\n key: null,\n parentId: null,\n children: [],\n rendererId,\n errors: 0,\n warnings: 0,\n };\n this.nodes.set(id, node);\n added.push({ id, displayName: node.displayName });\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parentId = operations[i++];\n i++; // ownerID\n const displayNameStringId = operations[i++];\n const keyStringId = operations[i++];\n if (this.extendedAddFormat) {\n i++; // namePropStringID (added in newer backends)\n }\n\n const displayName =\n (displayNameStringId > 0 ? stringTable[displayNameStringId] : null) ||\n (elementType === ELEMENT_TYPE_HOST ? 'HostComponent' : 'Anonymous');\n const key = keyStringId > 0 ? stringTable[keyStringId] || null : null;\n\n const node: ComponentNode = {\n id,\n displayName,\n type: toComponentType(elementType),\n key,\n parentId: parentId === 0 ? null : parentId,\n children: [],\n rendererId,\n errors: 0,\n warnings: 0,\n };\n\n this.nodes.set(id, node);\n added.push({ id, displayName });\n\n // Add to parent's children\n if (parentId === 0) {\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parent = this.nodes.get(parentId);\n if (parent) {\n parent.children.push(id);\n }\n }\n\n // Update name index\n if (displayName) {\n const lower = displayName.toLowerCase();\n let set = this.nameIndex.get(lower);\n if (!set) {\n set = new Set();\n this.nameIndex.set(lower, set);\n }\n set.add(id);\n }\n }\n break;\n }\n\n case TREE_OPERATION_REMOVE: {\n const numRemoved = operations[i + 1];\n for (let j = 0; j < numRemoved; j++) {\n const id = operations[i + 2 + j];\n this.removeNode(id);\n }\n i += 2 + numRemoved;\n break;\n }\n\n case TREE_OPERATION_REORDER_CHILDREN: {\n const id = operations[i + 1];\n const numChildren = operations[i + 2];\n const newChildren: number[] = [];\n for (let j = 0; j < numChildren; j++) {\n newChildren.push(operations[i + 3 + j]);\n }\n const node = this.nodes.get(id);\n if (node) {\n node.children = newChildren;\n }\n i += 3 + numChildren;\n break;\n }\n\n case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n // id, baseDuration — skip\n i += 3;\n break;\n }\n\n case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n const id = operations[i + 1];\n const numErrors = operations[i + 2];\n const numWarnings = operations[i + 3];\n const node = this.nodes.get(id);\n if (node) {\n node.errors = numErrors;\n node.warnings = numWarnings;\n }\n i += 4;\n break;\n }\n\n case TREE_OPERATION_REMOVE_ROOT: {\n const rootId = operations[i + 1];\n this.removeNode(rootId);\n i += 2;\n break;\n }\n\n case TREE_OPERATION_SET_SUBTREE_MODE: {\n // id, mode\n i += 3;\n break;\n }\n\n // ── Suspense tree operations (newer backends) ──\n\n case SUSPENSE_TREE_OPERATION_ADD: {\n // Presence of suspense ops means the backend also uses 8-field ADD\n this.extendedAddFormat = true;\n // fiberID, parentID, nameStringID, isSuspended, rects\n i += 5; // opcode + 4 fields\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REMOVE: {\n this.extendedAddFormat = true;\n // numIDs, then that many IDs\n const numIds = operations[i + 1];\n i += 2 + numIds;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n this.extendedAddFormat = true;\n // parentID, numChildren, then that many child IDs\n const numSuspenseChildren = operations[i + 2];\n i += 3 + numSuspenseChildren;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_RESIZE: {\n this.extendedAddFormat = true;\n // fiberID, rects\n i += 2; // opcode + fiberID\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n this.extendedAddFormat = true;\n // numChanges, then numChanges * 4 values\n const numChanges = operations[i + 1];\n i += 2 + numChanges * 4;\n break;\n }\n\n case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n this.extendedAddFormat = true;\n // id\n i += 2;\n break;\n }\n\n default:\n // Unknown operation — skip one value and try to continue.\n // Future protocol additions may cause brief misalignment but\n // subsequent operations batches will self-correct.\n i++;\n break;\n }\n }\n\n return added;\n }\n\n private removeNode(id: number): void {\n const node = this.nodes.get(id);\n if (!node) return;\n\n // Remove from parent's children\n if (node.parentId !== null) {\n const parent = this.nodes.get(node.parentId);\n if (parent) {\n parent.children = parent.children.filter((c) => c !== id);\n }\n }\n\n // Remove from roots\n this.roots = this.roots.filter((r) => r !== id);\n\n // Remove from name index\n if (node.displayName) {\n const lower = node.displayName.toLowerCase();\n const set = this.nameIndex.get(lower);\n if (set) {\n set.delete(id);\n if (set.size === 0) this.nameIndex.delete(lower);\n }\n }\n\n // Recursively remove children\n for (const childId of node.children) {\n this.removeNode(childId);\n }\n\n this.nodes.delete(id);\n }\n\n getNode(id: number): ComponentNode | undefined {\n return this.nodes.get(id);\n }\n\n getTree(maxDepth?: number): TreeNode[] {\n const result: TreeNode[] = [];\n\n // Rebuild label maps on every getTree() call\n this.labelToId.clear();\n this.idToLabel.clear();\n let labelCounter = 1;\n\n const walk = (id: number, depth: number) => {\n const node = this.nodes.get(id);\n if (!node) return;\n if (maxDepth !== undefined && depth > maxDepth) return;\n\n const label = `@c${labelCounter++}`;\n this.labelToId.set(label, node.id);\n this.idToLabel.set(node.id, label);\n\n const treeNode: TreeNode = {\n id: node.id,\n label,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n };\n if (node.errors > 0) treeNode.errors = node.errors;\n if (node.warnings > 0) treeNode.warnings = node.warnings;\n result.push(treeNode);\n\n for (const childId of node.children) {\n walk(childId, depth + 1);\n }\n };\n\n for (const rootId of this.roots) {\n walk(rootId, 0);\n }\n return result;\n }\n\n findByName(name: string, exact?: boolean): TreeNode[] {\n const results: TreeNode[] = [];\n\n if (exact) {\n const lower = name.toLowerCase();\n const ids = this.nameIndex.get(lower);\n if (ids) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node && node.displayName.toLowerCase() === lower) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n } else {\n const lower = name.toLowerCase();\n for (const [indexName, ids] of this.nameIndex) {\n if (indexName.includes(lower)) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n }\n }\n\n return results;\n }\n\n getComponentCount(): number {\n return this.nodes.size;\n }\n\n getCountByType(): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const node of this.nodes.values()) {\n counts[node.type] = (counts[node.type] || 0) + 1;\n }\n return counts;\n }\n\n getAllNodeIds(): number[] {\n return Array.from(this.nodes.keys());\n }\n\n /**\n * Return all nodes that have non-zero error or warning counts.\n */\n getComponentsWithErrorsOrWarnings(): TreeNode[] {\n const results: TreeNode[] = [];\n for (const node of this.nodes.values()) {\n if (node.errors > 0 || node.warnings > 0) {\n results.push(this.toTreeNode(node));\n }\n }\n return results;\n }\n\n getRootIds(): number[] {\n return [...this.roots];\n }\n\n removeRoot(rootId: number): void {\n this.removeNode(rootId);\n }\n\n /**\n * Look up the @cN label for a given component ID.\n * Returns undefined if the ID has no label assigned.\n */\n getLabel(id: number): string | undefined {\n return this.idToLabel.get(id);\n }\n\n /**\n * Resolve a label like \"@c3\" to a real node ID.\n * Returns undefined if label not found.\n */\n resolveLabel(label: string): number | undefined {\n return this.labelToId.get(label);\n }\n\n /**\n * Resolve either a label string (\"@c3\") or a numeric ID to a real node ID.\n * Also handles the \"@c?(id:N)\" format emitted by find for components outside\n * the labeled tree range.\n */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return id;\n // Handle @c?(id:N) format for unresolved labels\n const match = id.match(/^@c\\?\\(id:(\\d+)\\)$/);\n if (match) return parseInt(match[1], 10);\n if (id.startsWith('@c')) return this.labelToId.get(id);\n // Try parsing as number\n const num = parseInt(id, 10);\n return isNaN(num) ? undefined : num;\n }\n\n private toTreeNode(node: ComponentNode): TreeNode {\n // Calculate depth by walking up the tree\n let depth = 0;\n let current = node;\n while (current.parentId !== null) {\n depth++;\n const parent = this.nodes.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n\n const treeNode: TreeNode = {\n id: node.id,\n label: this.idToLabel.get(node.id) || `@c?`,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n };\n if (node.errors > 0) treeNode.errors = node.errors;\n if (node.warnings > 0) treeNode.warnings = node.warnings;\n return treeNode;\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ComponentType,\n ProfilingDataExport,\n ProfilingDataForRootExport,\n CommitDataExport,\n SnapshotNodeExport,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\n\n/**\n * Build a React DevTools Profiler export (version 5) from a profiling session.\n *\n * When raw data from React DevTools is available (collected via\n * processProfilingData), it is passed through to ensure full fidelity —\n * including initialTreeBaseDurations that DevTools needs for correct\n * flame graph rendering. Snapshots are always built from the ComponentTree\n * since the protocol sends them empty.\n */\nexport function buildExportData(\n session: ProfilingSession,\n tree: ComponentTree,\n): ProfilingDataExport | null {\n if (session.commits.length === 0) return null;\n\n if (session.rawRoots.length > 0) {\n return {\n version: 5,\n dataForRoots: session.rawRoots.map((raw) => {\n const subtreeIds = collectSubtreeIds(raw.rootID, tree);\n const snapshots = buildSnapshots(raw.rootID, subtreeIds, tree);\n const operations = raw.operations.length > 0\n ? raw.operations\n : session.commits.map(() => []);\n\n return {\n commitData: raw.commitData as CommitDataExport[],\n displayName: raw.displayName,\n initialTreeBaseDurations: raw.initialTreeBaseDurations,\n operations,\n rootID: raw.rootID,\n snapshots,\n };\n }),\n };\n }\n\n // Fallback: reconstruct from parsed commits (e.g. if data came via flat format)\n return buildFromParsedCommits(session, tree);\n}\n\nfunction buildFromParsedCommits(\n session: ProfilingSession,\n tree: ComponentTree,\n): ProfilingDataExport {\n let rootIds = tree.getRootIds();\n if (rootIds.length === 0) {\n rootIds = [1];\n }\n\n const dataForRoots: ProfilingDataForRootExport[] = [];\n\n for (const rootId of rootIds) {\n const rootNode = tree.getNode(rootId);\n const subtreeIds = collectSubtreeIds(rootId, tree);\n const snapshots = buildSnapshots(rootId, subtreeIds, tree);\n\n const baseDurationMap = new Map<number, number>();\n for (const nodeId of subtreeIds) {\n baseDurationMap.set(nodeId, 0);\n }\n for (const commit of session.commits) {\n for (const [id, duration] of commit.fiberSelfDurations) {\n if (baseDurationMap.has(id)) {\n baseDurationMap.set(id, duration);\n }\n }\n }\n\n const commitData: CommitDataExport[] = session.commits.map(\n (commit) => convertCommit(commit),\n );\n\n dataForRoots.push({\n commitData,\n displayName: rootNode?.displayName || 'Root',\n initialTreeBaseDurations: Array.from(baseDurationMap.entries()),\n operations: session.commits.map(() => []),\n rootID: rootId,\n snapshots,\n });\n }\n\n return {\n version: 5,\n dataForRoots,\n };\n}\n\nfunction convertCommit(commit: ProfilingCommit): CommitDataExport {\n const changeDescriptions: Array<[number, {\n context: null;\n didHooksChange: boolean;\n isFirstMount: boolean;\n props: string[] | null;\n state: string[] | null;\n hooks: number[] | null;\n }]> = [];\n\n for (const [id, desc] of commit.changeDescriptions) {\n changeDescriptions.push([id, {\n context: null,\n didHooksChange: desc.didHooksChange,\n isFirstMount: desc.isFirstMount,\n props: desc.props,\n state: desc.state,\n hooks: desc.hooks,\n }]);\n }\n\n return {\n changeDescriptions: changeDescriptions.length > 0 ? changeDescriptions : null,\n duration: commit.duration,\n effectDuration: commit.effectDuration ?? 0,\n fiberActualDurations: Array.from(commit.fiberActualDurations.entries()),\n fiberSelfDurations: Array.from(commit.fiberSelfDurations.entries()),\n passiveEffectDuration: commit.passiveEffectDuration ?? 0,\n priorityLevel: commit.priorityLevel ?? null,\n timestamp: commit.timestamp,\n updaters: commit.updaters as CommitDataExport['updaters'],\n };\n}\n\nfunction buildSnapshots(\n rootId: number,\n subtreeIds: number[],\n tree: ComponentTree,\n): Array<[number, SnapshotNodeExport]> {\n const snapshots: Array<[number, SnapshotNodeExport]> = [];\n for (const nodeId of subtreeIds) {\n const node = tree.getNode(nodeId);\n if (!node) continue;\n const elementType =\n nodeId === rootId && node.type === 'other'\n ? 11\n : componentTypeToElementType(node.type);\n snapshots.push([nodeId, {\n id: nodeId,\n children: node.children,\n displayName: node.displayName || null,\n hocDisplayNames: null,\n key: node.key,\n type: elementType,\n compiledWithForget: false,\n }]);\n }\n return snapshots;\n}\n\nfunction collectSubtreeIds(rootId: number, tree: ComponentTree): number[] {\n const ids: number[] = [];\n const visit = (id: number) => {\n const node = tree.getNode(id);\n if (!node) return;\n ids.push(id);\n for (const childId of node.children) {\n visit(childId);\n }\n };\n visit(rootId);\n return ids;\n}\n\nfunction componentTypeToElementType(type: ComponentType): number {\n switch (type) {\n case 'class': return 1;\n case 'context': return 2;\n case 'function': return 5;\n case 'forwardRef': return 6;\n case 'host': return 7;\n case 'memo': return 8;\n case 'profiler': return 10;\n case 'suspense': return 12;\n case 'other': return 9;\n default: return 9;\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n ChangedKeys,\n ProfilingDataExport,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\nimport { buildExportData } from './profile-export.js';\n\nexport interface ProfileSummary {\n name: string;\n duration: number;\n commitCount: number;\n componentRenderCounts: { id: number; displayName: string; label?: string; type?: string; count: number }[];\n}\n\nexport interface TimelineEntry {\n index: number;\n timestamp: number;\n duration: number;\n componentCount: number;\n}\n\nexport interface TimelineResult {\n entries: TimelineEntry[];\n total: number;\n offset: number;\n}\n\nexport interface CommitDetail {\n index: number;\n timestamp: number;\n duration: number;\n components: Array<{\n id: number;\n displayName: string;\n label?: string;\n type?: string;\n actualDuration: number;\n selfDuration: number;\n causes: RenderCause[];\n changedKeys?: ChangedKeys;\n }>;\n totalComponents: number;\n}\n\nexport class Profiler {\n private session: ProfilingSession | null = null;\n /** Display names captured during profiling (survives unmounts) */\n private displayNames = new Map<number, string>();\n\n isActive(): boolean {\n return this.session !== null && this.session.stoppedAt === null;\n }\n\n start(name?: string): void {\n this.displayNames.clear();\n this.session = {\n name: name || `session-${Date.now()}`,\n startedAt: Date.now(),\n stoppedAt: null,\n commits: [],\n rawRoots: [],\n };\n }\n\n /** Cache a component's display name (call during profiling to survive unmounts) */\n trackComponent(id: number, displayName: string): void {\n this.displayNames.set(id, displayName);\n }\n\n stop(tree?: ComponentTree): ProfileSummary | null {\n if (!this.session) return null;\n this.session.stoppedAt = Date.now();\n\n const duration = this.session.stoppedAt - this.session.startedAt;\n\n // Count renders per component\n const renderCounts = new Map<number, number>();\n for (const commit of this.session.commits) {\n for (const [id] of commit.fiberActualDurations) {\n renderCounts.set(id, (renderCounts.get(id) || 0) + 1);\n }\n }\n\n const componentRenderCounts = Array.from(renderCounts.entries())\n .map(([id, count]) => ({\n id,\n displayName: tree?.getNode(id)?.displayName || this.displayNames.get(id) || '',\n count,\n }))\n .sort((a, b) => b.count - a.count);\n\n return {\n name: this.session.name,\n duration,\n commitCount: this.session.commits.length,\n componentRenderCounts,\n };\n }\n\n /**\n * Process profiling data sent from React DevTools.\n *\n * The data format varies between React versions. We handle the common\n * format where each commit contains:\n * - commitTime\n * - duration\n * - fiberActualDurations: [id, duration, ...]\n * - fiberSelfDurations: [id, duration, ...]\n * - changeDescriptions: Map<id, description>\n */\n processProfilingData(payload: unknown): void {\n if (!this.session) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n rootID?: number;\n commitData?: unknown[];\n operations?: Array<number[]>;\n initialTreeBaseDurations?: Array<[number, number]>;\n snapshots?: Array<[number, unknown]>;\n displayName?: string;\n }>;\n // Alternative flat format\n commitData?: unknown[];\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n // Store raw root data for export passthrough\n this.session.rawRoots.push({\n rootID: root.rootID ?? 1,\n commitData: root.commitData ?? [],\n initialTreeBaseDurations: root.initialTreeBaseDurations ?? [],\n operations: root.operations ?? [],\n snapshots: root.snapshots ?? [],\n displayName: root.displayName ?? 'Root',\n });\n\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData as Record<string, unknown>);\n }\n }\n }\n return;\n }\n\n // Handle flat format\n if (data?.commitData) {\n for (const commitData of data.commitData) {\n this.processCommitData(commitData as Record<string, unknown>);\n }\n }\n }\n\n private processCommitData(commitData: Record<string, unknown>): void {\n const commit: ProfilingCommit = {\n timestamp: (commitData.timestamp as number) || Date.now(),\n duration: (commitData.duration as number) || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n effectDuration: (commitData.effectDuration as number) ?? null,\n passiveEffectDuration: (commitData.passiveEffectDuration as number) ?? null,\n priorityLevel: (commitData.priorityLevel as string) ?? null,\n updaters: (commitData.updaters as unknown[]) ?? null,\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations as Array<[number, number]> | number[], commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations as Array<[number, number]> | number[], commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n const rawDescs = commitData.changeDescriptions as Array<[number, unknown]> | Map<number, unknown> | undefined;\n if (rawDescs) {\n const entries =\n rawDescs instanceof Map\n ? rawDescs.entries()\n : rawDescs[Symbol.iterator]();\n for (const [id, desc] of entries) {\n const d = desc as {\n didHooksChange?: boolean;\n isFirstMount?: boolean;\n props?: string[] | null;\n state?: string[] | null;\n hooks?: number[] | null;\n };\n commit.changeDescriptions.set(id as number, {\n didHooksChange: d.didHooksChange || false,\n isFirstMount: d.isFirstMount || false,\n props: d.props || null,\n state: d.state || null,\n hooks: d.hooks || null,\n });\n }\n }\n\n this.session!.commits.push(commit);\n }\n\n getReport(\n componentId: number,\n tree: ComponentTree,\n ): ComponentRenderReport | null {\n if (!this.session) return null;\n\n const node = tree.getNode(componentId);\n let renderCount = 0;\n let totalDuration = 0;\n let maxDuration = 0;\n const causeSet = new Set<RenderCause>();\n const propsSet = new Set<string>();\n const stateSet = new Set<string>();\n const hooksSet = new Set<number>();\n\n for (const commit of this.session.commits) {\n const duration = commit.fiberActualDurations.get(componentId);\n if (duration !== undefined) {\n renderCount++;\n totalDuration += duration;\n if (duration > maxDuration) maxDuration = duration;\n\n const desc = commit.changeDescriptions.get(componentId);\n if (desc) {\n for (const cause of describeCauses(desc)) {\n causeSet.add(cause);\n }\n const keys = extractChangedKeys(desc);\n for (const p of keys.props) propsSet.add(p);\n for (const s of keys.state) stateSet.add(s);\n for (const h of keys.hooks) hooksSet.add(h);\n }\n }\n }\n\n if (renderCount === 0) return null;\n\n return {\n id: componentId,\n displayName: node?.displayName || this.displayNames.get(componentId) || `Component#${componentId}`,\n renderCount,\n totalDuration,\n avgDuration: totalDuration / renderCount,\n maxDuration,\n causes: Array.from(causeSet),\n changedKeys: {\n props: Array.from(propsSet),\n state: Array.from(stateSet),\n hooks: Array.from(hooksSet),\n },\n };\n }\n\n getSlowest(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, limit);\n }\n\n getMostRerenders(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.renderCount - a.renderCount)\n .slice(0, limit);\n }\n\n getCommitDetails(index: number, tree: ComponentTree, limit = 10): CommitDetail | null {\n if (!this.session) return null;\n if (index < 0 || index >= this.session.commits.length) return null;\n\n const commit = this.session.commits[index];\n const components: CommitDetail['components'] = [];\n\n for (const [id, actualDuration] of commit.fiberActualDurations) {\n const selfDuration = commit.fiberSelfDurations.get(id) || 0;\n const desc = commit.changeDescriptions.get(id);\n components.push({\n id,\n displayName: tree.getNode(id)?.displayName || this.displayNames.get(id) || `Component#${id}`,\n actualDuration,\n selfDuration,\n causes: desc ? describeCauses(desc) : [],\n changedKeys: desc ? extractChangedKeys(desc) : { props: [], state: [], hooks: [] },\n });\n }\n\n components.sort((a, b) => b.selfDuration - a.selfDuration);\n\n const totalCount = components.length;\n\n return {\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n components: limit > 0 ? components.slice(0, limit) : components,\n totalComponents: totalCount,\n };\n }\n\n getTimeline(limit: number = 20, offset?: number, sort?: 'duration' | 'timeline'): TimelineResult {\n if (!this.session) return { entries: [], total: 0, offset: offset ?? 0 };\n\n const all = this.session.commits.map((commit, index) => ({\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n componentCount: commit.fiberActualDurations.size,\n }));\n\n if (sort === 'duration') all.sort((a, b) => b.duration - a.duration);\n const start = Math.max(0, offset ?? 0);\n return {\n entries: all.slice(start, start + limit),\n total: all.length,\n offset: start,\n };\n }\n\n getExportData(tree: ComponentTree): ProfilingDataExport | null {\n if (!this.session) return null;\n return buildExportData(this.session, tree);\n }\n\n private getAllReports(tree: ComponentTree): ComponentRenderReport[] {\n if (!this.session) return [];\n\n // Collect all component IDs that appear in profiling data\n const componentIds = new Set<number>();\n for (const commit of this.session.commits) {\n for (const id of commit.fiberActualDurations.keys()) {\n componentIds.add(id);\n }\n }\n\n const reports: ComponentRenderReport[] = [];\n for (const id of componentIds) {\n const report = this.getReport(id, tree);\n if (report) reports.push(report);\n }\n return reports;\n }\n}\n\nfunction parseDurations(\n raw: Array<[number, number]> | number[],\n target: Map<number, number>,\n): void {\n if (raw.length === 0) return;\n\n // Check if it's array of tuples or flat array\n if (Array.isArray(raw[0])) {\n // [[id, duration], ...]\n for (const [id, duration] of raw as Array<[number, number]>) {\n target.set(id, duration);\n }\n } else {\n // [id, duration, id, duration, ...]\n const flat = raw as number[];\n for (let i = 0; i < flat.length; i += 2) {\n target.set(flat[i], flat[i + 1]);\n }\n }\n}\n\nfunction describeCauses(desc: ChangeDescription): RenderCause[] {\n const causes: RenderCause[] = [];\n if (desc.isFirstMount) {\n causes.push('first-mount');\n return causes;\n }\n if (desc.props && desc.props.length > 0) causes.push('props-changed');\n if (desc.state && desc.state.length > 0) causes.push('state-changed');\n if (desc.didHooksChange) causes.push('hooks-changed');\n // If no specific cause found, it was likely parent-triggered\n if (causes.length === 0) causes.push('parent-rendered');\n return causes;\n}\n\nfunction extractChangedKeys(desc: ChangeDescription): ChangedKeys {\n return {\n props: desc.props ?? [],\n state: desc.state ?? [],\n hooks: desc.hooks ?? [],\n };\n}\n"],"mappings":"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","names":["port","pending","port"]}
1
+ {"version":3,"sources":["../src/daemon.ts","../src/devtools-bridge.ts","../src/component-tree.ts","../src/profile-export.ts","../src/profiler.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DevToolsBridge } from './devtools-bridge.js';\nimport { ComponentTree } from './component-tree.js';\nimport { Profiler } from './profiler.js';\nimport type { IpcCommand, IpcResponse, DaemonInfo, StatusInfo } from './types.js';\n\nconst DEFAULT_STATE_DIR = path.join(\n process.env.HOME || process.env.USERPROFILE || '/tmp',\n '.agent-react-devtools',\n);\n\nlet STATE_DIR = DEFAULT_STATE_DIR;\n\nfunction getSocketPath(): string {\n return path.join(STATE_DIR, 'daemon.sock');\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(STATE_DIR, 'daemon.json');\n}\n\n/**\n * Enrich profiling result items with label + type from the component tree.\n */\nfunction enrichWithLabels(\n items: Array<{ id: number; label?: string; type?: string }>,\n tree: ComponentTree,\n): void {\n for (const item of items) {\n if (!item.label) item.label = tree.getLabel(item.id);\n if (!item.type) {\n const node = tree.getNode(item.id);\n if (node) item.type = node.type;\n }\n }\n}\n\nclass Daemon {\n private ipcServer: net.Server | null = null;\n private bridge: DevToolsBridge;\n private tree: ComponentTree;\n private profiler: Profiler;\n private port: number;\n private startedAt = Date.now();\n\n constructor(port: number) {\n this.port = port;\n this.tree = new ComponentTree();\n this.profiler = new Profiler();\n this.bridge = new DevToolsBridge(port, this.tree, this.profiler);\n }\n\n async start(): Promise<void> {\n // Ensure state directory exists\n fs.mkdirSync(STATE_DIR, { recursive: true });\n\n // Clean up stale socket\n const socketPath = getSocketPath();\n if (fs.existsSync(socketPath)) {\n try {\n fs.unlinkSync(socketPath);\n } catch {\n // ignore\n }\n }\n\n // Start WebSocket bridge\n await this.bridge.start();\n\n // Start IPC server\n await this.startIpc(socketPath);\n\n // Write daemon info\n let buildMtime: number | undefined;\n try {\n buildMtime = fs.statSync(new URL(import.meta.url).pathname).mtimeMs;\n } catch {\n // ignore\n }\n const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\n buildMtime,\n };\n fs.writeFileSync(getDaemonInfoPath(), JSON.stringify(info, null, 2));\n\n console.log(`Daemon started (pid=${process.pid}, port=${this.port})`);\n\n // Handle shutdown\n const shutdown = () => {\n this.stop();\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n }\n\n private startIpc(socketPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.ipcServer = net.createServer((conn) => {\n let buffer = '';\n\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n\n // Process complete messages (newline-delimited JSON)\n let newlineIdx: number;\n while ((newlineIdx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, newlineIdx);\n buffer = buffer.slice(newlineIdx + 1);\n\n try {\n const cmd: IpcCommand = JSON.parse(line);\n this.handleCommand(cmd, conn).then((response) => {\n if (!conn.destroyed) {\n conn.write(JSON.stringify(response) + '\\n');\n }\n });\n } catch {\n const response: IpcResponse = {\n ok: false,\n error: 'Invalid JSON',\n };\n conn.write(JSON.stringify(response) + '\\n');\n }\n }\n });\n });\n\n this.ipcServer.on('error', reject);\n\n this.ipcServer.listen(socketPath, () => {\n resolve();\n });\n });\n }\n\n private async handleCommand(cmd: IpcCommand, conn: net.Socket): Promise<IpcResponse> {\n try {\n switch (cmd.type) {\n case 'ping':\n return { ok: true, data: 'pong' };\n\n case 'status':\n return {\n ok: true,\n data: {\n daemonRunning: true,\n port: this.port,\n connectedApps: this.bridge.getConnectedAppCount(),\n componentCount: this.tree.getComponentCount(),\n profilingActive: this.profiler.isActive(),\n uptime: Date.now() - this.startedAt,\n connection: this.bridge.getConnectionHealth(),\n } satisfies StatusInfo,\n };\n\n case 'get-tree': {\n let resolvedRoot: number | undefined;\n if (cmd.root !== undefined) {\n resolvedRoot = this.tree.resolveId(cmd.root);\n if (resolvedRoot === undefined) {\n return { ok: false, error: `Component ${cmd.root} not found` };\n }\n }\n const totalCount = this.tree.getComponentCount();\n const treeData = this.tree.getTree({\n maxDepth: cmd.depth,\n noHost: cmd.noHost,\n rootId: resolvedRoot,\n });\n // If a specific root was requested but returned empty, the node\n // was removed between resolveId and getTree (stale label)\n if (resolvedRoot !== undefined && treeData.length === 0) {\n return { ok: false, error: `Component ${cmd.root} not found` };\n }\n const response: IpcResponse = {\n ok: true,\n data: { nodes: treeData, totalCount },\n };\n if (treeData.length === 0) {\n const health = this.bridge.getConnectionHealth();\n if (health.hasEverConnected && health.connectedApps === 0 && health.lastDisconnectAt !== null) {\n const ago = Math.round((Date.now() - health.lastDisconnectAt) / 1000);\n response.hint = `app disconnected ${ago}s ago, waiting for reconnect...`;\n }\n }\n return response;\n }\n\n case 'get-component': {\n const resolvedId = this.tree.resolveId(cmd.id);\n if (resolvedId === undefined) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n const element = await this.bridge.inspectElement(resolvedId);\n if (!element) {\n return { ok: false, error: `Component ${cmd.id} not found` };\n }\n // Include error/warning counts when non-zero\n const treeNode = this.tree.getNode(resolvedId);\n const enriched: Record<string, unknown> = { ...element };\n if (treeNode && treeNode.errors > 0) enriched.errors = treeNode.errors;\n if (treeNode && treeNode.warnings > 0) enriched.warnings = treeNode.warnings;\n // Include the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: enriched, label };\n }\n\n case 'find':\n return {\n ok: true,\n data: this.tree.findByName(cmd.name, cmd.exact),\n };\n\n case 'count':\n return {\n ok: true,\n data: this.tree.getCountByType(),\n };\n\n case 'errors':\n this.tree.getTree();\n return {\n ok: true,\n data: this.tree.getComponentsWithErrorsOrWarnings(),\n };\n\n case 'profile-start':\n this.profiler.start(cmd.name);\n // Snapshot existing component names so they survive unmounts\n for (const id of this.tree.getAllNodeIds()) {\n const node = this.tree.getNode(id);\n if (node) this.profiler.trackComponent(id, node.displayName);\n }\n this.bridge.startProfiling();\n return { ok: true, data: 'Profiling started' };\n\n case 'profile-stop': {\n await this.bridge.stopProfilingAndCollect();\n const session = this.profiler.stop(this.tree);\n if (!session) {\n return { ok: false, error: 'No active profiling session' };\n }\n enrichWithLabels(session.componentRenderCounts, this.tree);\n return { ok: true, data: session };\n }\n\n case 'profile-report': {\n const resolvedCompId = this.tree.resolveId(cmd.componentId);\n if (resolvedCompId === undefined) {\n return { ok: false, error: `Component ${cmd.componentId} not found` };\n }\n const report = this.profiler.getReport(resolvedCompId, this.tree);\n if (!report) {\n return {\n ok: false,\n error: `No profiling data for component ${cmd.componentId}`,\n };\n }\n enrichWithLabels([report], this.tree);\n const compLabel = typeof cmd.componentId === 'string' ? cmd.componentId : undefined;\n return { ok: true, data: report, label: compLabel };\n }\n\n case 'profile-slow': {\n const slowest = this.profiler.getSlowest(this.tree, cmd.limit);\n enrichWithLabels(slowest, this.tree);\n return { ok: true, data: slowest };\n }\n\n case 'profile-rerenders': {\n const rerenders = this.profiler.getMostRerenders(this.tree, cmd.limit);\n enrichWithLabels(rerenders, this.tree);\n return { ok: true, data: rerenders };\n }\n\n case 'profile-timeline':\n return {\n ok: true,\n data: this.profiler.getTimeline(cmd.limit, cmd.offset, cmd.sort),\n };\n\n case 'profile-commit': {\n const detail = this.profiler.getCommitDetails(cmd.index, this.tree, cmd.limit);\n if (!detail) {\n return { ok: false, error: `Commit #${cmd.index} not found` };\n }\n enrichWithLabels(detail.components, this.tree);\n return { ok: true, data: detail };\n }\n\n case 'profile-export': {\n const exportData = this.profiler.getExportData(this.tree);\n if (!exportData) {\n return { ok: false, error: 'No profiling data to export (run profile start/stop first)' };\n }\n return { ok: true, data: exportData };\n }\n\n case 'wait':\n return this.handleWait(cmd, conn);\n\n default:\n return { ok: false, error: `Unknown command: ${(cmd as any).type}` };\n }\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private handleWait(\n cmd: Extract<IpcCommand, { type: 'wait' }>,\n conn: net.Socket,\n ): Promise<IpcResponse> {\n const timeout = cmd.timeout ?? 30_000;\n\n // Check if condition is already met\n if (this.isWaitConditionMet(cmd)) {\n return Promise.resolve({ ok: true, data: { met: true, condition: cmd.condition } });\n }\n\n return new Promise((resolve) => {\n let settled = false;\n const settle = (response: IpcResponse) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n unsubscribe();\n conn.removeListener('close', onClose);\n resolve(response);\n };\n\n const unsubscribe = this.bridge.onStateChange(() => {\n if (this.isWaitConditionMet(cmd)) {\n settle({ ok: true, data: { met: true, condition: cmd.condition } });\n }\n });\n\n const timer = setTimeout(() => {\n settle({ ok: true, data: { met: false, condition: cmd.condition, timeout: true } });\n }, timeout);\n\n const onClose = () => {\n settle({ ok: false, error: 'Client disconnected' });\n };\n conn.on('close', onClose);\n });\n }\n\n private isWaitConditionMet(cmd: Extract<IpcCommand, { type: 'wait' }>): boolean {\n switch (cmd.condition) {\n case 'connected':\n return this.bridge.getConnectedAppCount() > 0;\n case 'component':\n return this.tree.findByName(cmd.name, true).length > 0;\n default:\n return false;\n }\n }\n\n stop(): void {\n this.bridge.stop();\n if (this.ipcServer) {\n this.ipcServer.close();\n this.ipcServer = null;\n }\n // Clean up files\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n console.log('Daemon stopped');\n }\n}\n\n// ── Main ──\n\nconst portArg = process.argv.find((a) => a.startsWith('--port='));\nconst port = portArg ? parseInt(portArg.split('=')[1], 10) : 8097;\n\nconst stateDirArg = process.argv.find((a) => a.startsWith('--state-dir='));\nif (stateDirArg) {\n STATE_DIR = stateDirArg.split('=')[1];\n}\n\nconst daemon = new Daemon(port);\ndaemon.start().catch((err) => {\n console.error('Failed to start daemon:', err);\n process.exit(1);\n});\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { ComponentTree } from './component-tree.js';\nimport type { Profiler } from './profiler.js';\nimport type { InspectedElement, ConnectionHealth, ConnectionEvent } from './types.js';\n\n/**\n * React DevTools protocol bridge.\n *\n * Implements the \"Wall\" messaging pattern that React DevTools uses:\n * - The backend (inside React app) sends operations, profiling data, etc.\n * - The frontend (us) can request element inspection, start/stop profiling, etc.\n *\n * Message format over WebSocket:\n * { event: string, payload: any }\n */\n\ninterface DevToolsMessage {\n event: string;\n payload: unknown;\n}\n\ninterface PendingInspection {\n resolve: (value: InspectedElement | null) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\ninterface PendingProfilingCollect {\n resolve: () => void;\n timer: ReturnType<typeof setTimeout>;\n remaining: number;\n}\n\nexport class DevToolsBridge {\n private wss: WebSocketServer | null = null;\n private connections = new Set<WebSocket>();\n private port: number;\n private tree: ComponentTree;\n private profiler: Profiler;\n private pendingInspections = new Map<number, PendingInspection>();\n private pendingProfilingCollect: PendingProfilingCollect | null = null;\n private rendererIds = new Set<number>();\n /** Track which root fiber IDs belong to each WebSocket connection */\n private connectionRoots = new Map<WebSocket, Set<number>>();\n private hasEverConnected = false;\n private lastDisconnectAt: number | null = null;\n private recentEvents: ConnectionEvent[] = [];\n private reconnectWindowMs = 5000;\n private stateChangeListeners = new Set<() => void>();\n\n constructor(port: number, tree: ComponentTree, profiler: Profiler) {\n this.port = port;\n this.tree = tree;\n this.profiler = profiler;\n }\n\n async start(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.wss = new WebSocketServer({ port: this.port }, () => {\n resolve();\n });\n\n this.wss.on('error', (err) => {\n reject(err);\n });\n\n this.wss.on('connection', (ws) => {\n this.connections.add(ws);\n\n // Reconnect = going from 0 to 1 connected app shortly after a disconnect\n const wasDisconnected = this.connections.size === 1 &&\n this.lastDisconnectAt !== null &&\n (Date.now() - this.lastDisconnectAt) < this.reconnectWindowMs;\n const eventType = wasDisconnected ? 'reconnected' as const : 'connected' as const;\n this.hasEverConnected = true;\n this.lastDisconnectAt = null;\n this.pushEvent({ type: eventType, timestamp: Date.now() });\n this.notifyStateChange();\n\n ws.on('message', (data) => {\n try {\n const msg: DevToolsMessage = JSON.parse(data.toString());\n this.handleMessage(ws, msg);\n } catch {\n // ignore parse errors\n }\n });\n\n ws.on('close', () => {\n this.cleanupConnection(ws);\n });\n\n ws.on('error', () => {\n this.cleanupConnection(ws);\n });\n });\n });\n }\n\n stop(): void {\n for (const conn of this.connections) {\n conn.close();\n }\n this.connections.clear();\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n }\n\n getConnectedAppCount(): number {\n return this.connections.size;\n }\n\n /**\n * Request detailed inspection of a specific element.\n * Sends a request to the React app and waits for the response.\n */\n inspectElement(id: number): Promise<InspectedElement | null> {\n const node = this.tree.getNode(id);\n if (!node) return Promise.resolve(null);\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n this.pendingInspections.delete(id);\n resolve(null);\n }, 5000);\n\n this.pendingInspections.set(id, { resolve, timer });\n\n this.sendToAll({\n event: 'inspectElement',\n payload: {\n id,\n rendererID: node.rendererId,\n forceFullData: true,\n requestID: id,\n path: null,\n },\n });\n });\n }\n\n startProfiling(): void {\n this.sendToAll({\n event: 'startProfiling',\n payload: { recordChangeDescriptions: true },\n });\n }\n\n /**\n * Stop profiling and request data from each renderer.\n * Returns a promise that resolves when profilingData arrives (or 5s timeout).\n */\n stopProfilingAndCollect(): Promise<void> {\n this.sendToAll({\n event: 'stopProfiling',\n payload: undefined,\n });\n\n // If no renderers known, resolve immediately\n if (this.rendererIds.size === 0) {\n return Promise.resolve();\n }\n\n // Request profiling data from each renderer\n for (const rendererID of this.rendererIds) {\n this.sendToAll({\n event: 'getProfilingData',\n payload: { rendererID },\n });\n }\n\n const expected = this.rendererIds.size;\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingProfilingCollect = null;\n resolve();\n }, 5000);\n\n this.pendingProfilingCollect = { resolve, timer, remaining: expected };\n });\n }\n\n private handleMessage(ws: WebSocket, msg: DevToolsMessage): void {\n switch (msg.event) {\n case 'backendInitialized':\n // Send the full frontend handshake sequence\n this.sendTo(ws, { event: 'getBridgeProtocol', payload: undefined });\n this.sendTo(ws, { event: 'getBackendVersion', payload: undefined });\n this.sendTo(ws, { event: 'getIfHasUnsupportedRendererVersion', payload: undefined });\n this.sendTo(ws, { event: 'getHookSettings', payload: undefined });\n this.sendTo(ws, { event: 'getProfilingStatus', payload: undefined });\n break;\n\n case 'bridgeProtocol':\n case 'backendVersion':\n case 'profilingStatus':\n case 'overrideComponentFilters':\n break;\n\n case 'operations':\n this.handleOperations(ws, msg.payload as number[]);\n break;\n\n case 'inspectedElement':\n this.handleInspectedElement(msg.payload);\n break;\n\n case 'profilingData':\n this.handleProfilingData(msg.payload);\n break;\n\n case 'renderer': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'rendererAttached': {\n const payload = msg.payload as { id: number };\n this.rendererIds.add(payload.id);\n break;\n }\n\n case 'shutdown':\n ws.close();\n break;\n\n // Silently ignore known but unhandled events\n case 'hookSettings':\n case 'isBackendStorageAPISupported':\n case 'isReactNativeEnvironment':\n case 'isReloadAndProfileSupportedByBackend':\n case 'isSynchronousXHRSupported':\n case 'syncSelectionFromNativeElementsPanel':\n case 'unsupportedRendererVersion':\n break;\n\n default:\n break;\n }\n }\n\n private handleOperations(ws: WebSocket, operations: number[]): void {\n if (operations.length >= 2) {\n // Track renderer ID (first element of every operations array)\n this.rendererIds.add(operations[0]);\n\n // Track which root fiber IDs belong to this connection\n const rootFiberId = operations[1];\n let roots = this.connectionRoots.get(ws);\n if (!roots) {\n roots = new Set();\n this.connectionRoots.set(ws, roots);\n }\n roots.add(rootFiberId);\n }\n const added = this.tree.applyOperations(operations);\n\n // Cache display names during profiling so unmounted components are still identifiable\n if (this.profiler.isActive()) {\n for (const node of added) {\n this.profiler.trackComponent(node.id, node.displayName);\n }\n }\n\n this.notifyStateChange();\n }\n\n private cleanupConnection(ws: WebSocket): void {\n this.connections.delete(ws);\n // Remove all root trees that belonged to this connection\n const roots = this.connectionRoots.get(ws);\n if (roots) {\n for (const rootId of roots) {\n this.tree.removeRoot(rootId);\n }\n this.connectionRoots.delete(ws);\n }\n this.lastDisconnectAt = Date.now();\n this.pushEvent({ type: 'disconnected', timestamp: Date.now() });\n this.notifyStateChange();\n }\n\n private handleInspectedElement(payload: unknown): void {\n const data = payload as {\n type: string;\n id: number;\n value?: {\n id: number;\n displayName: string;\n type: number;\n key: string | null;\n props: Record<string, unknown>;\n state: Record<string, unknown> | null;\n hooks: unknown[] | { data: unknown[]; cleaned: unknown[]; unserializable: unknown[] } | null;\n };\n };\n\n if (data.type !== 'full-data' && data.type !== 'hydrated-path') {\n // No data available\n const pending = this.pendingInspections.get(data.id);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n pending.resolve(null);\n }\n return;\n }\n\n const pending = this.pendingInspections.get(data.id);\n if (!pending || !data.value) return;\n\n clearTimeout(pending.timer);\n this.pendingInspections.delete(data.id);\n\n const node = this.tree.getNode(data.id);\n const inspected: InspectedElement = {\n id: data.id,\n displayName: data.value.displayName || node?.displayName || 'Unknown',\n type: node?.type || 'other',\n key: data.value.key,\n props: cleanDehydrated(data.value.props) as Record<string, unknown>,\n state: data.value.state\n ? (cleanDehydrated(data.value.state) as Record<string, unknown>)\n : null,\n hooks: data.value.hooks\n ? parseHooks(extractHooksArray(data.value.hooks))\n : null,\n renderedAt: null,\n };\n\n pending.resolve(inspected);\n }\n\n private handleProfilingData(payload: unknown): void {\n // React DevTools sends profiling data as a complex nested structure.\n // We forward it to the profiler for processing.\n this.profiler.processProfilingData(payload);\n\n // Resolve once all expected renderer responses have arrived\n if (this.pendingProfilingCollect) {\n this.pendingProfilingCollect.remaining--;\n if (this.pendingProfilingCollect.remaining <= 0) {\n clearTimeout(this.pendingProfilingCollect.timer);\n const pending = this.pendingProfilingCollect;\n this.pendingProfilingCollect = null;\n pending.resolve();\n }\n }\n }\n\n getConnectionHealth(): ConnectionHealth {\n return {\n connectedApps: this.connections.size,\n hasEverConnected: this.hasEverConnected,\n lastDisconnectAt: this.lastDisconnectAt,\n recentEvents: [...this.recentEvents],\n };\n }\n\n onStateChange(listener: () => void): () => void {\n this.stateChangeListeners.add(listener);\n return () => { this.stateChangeListeners.delete(listener); };\n }\n\n private pushEvent(event: ConnectionEvent): void {\n this.recentEvents.push(event);\n if (this.recentEvents.length > 20) {\n this.recentEvents = this.recentEvents.slice(-20);\n }\n }\n\n private notifyStateChange(): void {\n for (const listener of this.stateChangeListeners) {\n listener();\n }\n }\n\n private sendTo(ws: WebSocket, msg: DevToolsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n }\n\n private sendToAll(msg: DevToolsMessage): void {\n const raw = JSON.stringify(msg);\n for (const conn of this.connections) {\n if (conn.readyState === WebSocket.OPEN) {\n conn.send(raw);\n }\n }\n }\n}\n\n/**\n * React DevTools uses \"dehydrated\" values for complex objects.\n * These appear as objects with `type: 'string'` and other metadata.\n * We simplify them for display.\n */\nfunction cleanDehydrated(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj !== 'object') return obj;\n if (Array.isArray(obj)) return obj.map(cleanDehydrated);\n\n const record = obj as Record<string, unknown>;\n\n // Dehydrated value markers from React DevTools\n if ('type' in record && 'preview_short' in record) {\n return record['preview_short'];\n }\n\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(record)) {\n cleaned[key] = cleanDehydrated(value);\n }\n return cleaned;\n}\n\n/**\n * React DevTools may send hooks as a plain array or as a dehydrated object\n * with { data: unknown[], cleaned: unknown[], unserializable: unknown[] }.\n * Extract the array in either case.\n */\nfunction extractHooksArray(hooks: unknown): unknown[] {\n if (Array.isArray(hooks)) return hooks;\n if (hooks && typeof hooks === 'object' && 'data' in hooks && Array.isArray((hooks as Record<string, unknown>).data)) {\n return (hooks as Record<string, unknown>).data as unknown[];\n }\n return [];\n}\n\nfunction parseHooks(hooks: unknown[]): { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] }[] {\n return hooks.map((hook) => {\n const h = hook as {\n id: number | null;\n isStateEditable: boolean;\n name: string;\n value: unknown;\n subHooks?: unknown[];\n };\n const result: { name: string; value: unknown; subHooks?: { name: string; value: unknown }[] } = {\n name: h.name,\n value: cleanDehydrated(h.value),\n };\n if (h.subHooks && h.subHooks.length > 0) {\n result.subHooks = parseHooks(h.subHooks) as { name: string; value: unknown }[];\n }\n return result;\n });\n}\n","import type { ComponentNode, ComponentType } from './types.js';\n\n/**\n * React DevTools operations encoding (protocol v2):\n * Operations is a flat array of numbers representing tree mutations.\n *\n * Format: [rendererID, rootFiberID, stringTableSize, ...stringTable, ...ops]\n *\n * The string table encodes display names and keys. Each entry is:\n * [length, ...charCodes]\n * String ID 0 = null. String ID 1 = first entry, etc.\n *\n * Operation types (from React DevTools source):\n */\nconst TREE_OPERATION_ADD = 1;\nconst TREE_OPERATION_REMOVE = 2;\nconst TREE_OPERATION_REORDER_CHILDREN = 3;\nconst TREE_OPERATION_UPDATE_TREE_BASE_DURATION = 4;\nconst TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS = 5;\nconst TREE_OPERATION_REMOVE_ROOT = 6;\nconst TREE_OPERATION_SET_SUBTREE_MODE = 7;\n\n/**\n * Suspense tree operations (newer React DevTools backends, e.g. browser extension):\n */\nconst SUSPENSE_TREE_OPERATION_ADD = 8;\nconst SUSPENSE_TREE_OPERATION_REMOVE = 9;\nconst SUSPENSE_TREE_OPERATION_REORDER_CHILDREN = 10;\nconst SUSPENSE_TREE_OPERATION_RESIZE = 11;\nconst SUSPENSE_TREE_OPERATION_SUSPENDERS = 12;\nconst TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE = 13;\n\n/**\n * Element types from React DevTools (react-devtools-shared/src/frontend/types.js)\n */\nconst ELEMENT_TYPE_CLASS = 1;\n// const ELEMENT_TYPE_CONTEXT = 2;\nconst ELEMENT_TYPE_FUNCTION = 5;\nconst ELEMENT_TYPE_FORWARD_REF = 6;\nconst ELEMENT_TYPE_HOST = 7;\nconst ELEMENT_TYPE_MEMO = 8;\n// const ELEMENT_TYPE_OTHER = 9;\nconst ELEMENT_TYPE_PROFILER = 10;\nconst ELEMENT_TYPE_ROOT = 11;\nconst ELEMENT_TYPE_SUSPENSE = 12;\n\nfunction toComponentType(elementType: number): ComponentType {\n switch (elementType) {\n case ELEMENT_TYPE_CLASS:\n return 'class';\n case ELEMENT_TYPE_FUNCTION:\n return 'function';\n case ELEMENT_TYPE_FORWARD_REF:\n return 'forwardRef';\n case ELEMENT_TYPE_HOST:\n return 'host';\n case ELEMENT_TYPE_MEMO:\n return 'memo';\n case ELEMENT_TYPE_PROFILER:\n return 'profiler';\n case ELEMENT_TYPE_SUSPENSE:\n return 'suspense';\n case ELEMENT_TYPE_ROOT:\n return 'other'; // roots are internal, map to 'other'\n default:\n return 'other';\n }\n}\n\n/**\n * Skip a variable-length rect encoding in the operations array.\n * Rects are encoded as: count, then count * 4 values (x, y, w, h each × 1000).\n * A count of -1 means null (no rects).\n * Returns the new index after skipping.\n */\nfunction skipRects(operations: number[], i: number): number {\n const count = operations[i++];\n if (count === -1) return i;\n return i + count * 4;\n}\n\nexport interface TreeNode {\n id: number;\n label: string;\n displayName: string;\n type: ComponentType;\n key: string | null;\n parentId: number | null;\n children: number[];\n depth: number;\n /** Non-zero error count (omitted when 0) */\n errors?: number;\n /** Non-zero warning count (omitted when 0) */\n warnings?: number;\n}\n\nexport interface GetTreeOptions {\n maxDepth?: number;\n /** When true, filter out host components (unless they have a key or custom element name) */\n noHost?: boolean;\n /** When set, only return the subtree rooted at this component ID */\n rootId?: number;\n}\n\n/**\n * Check if a host component should be kept even when filtering.\n * Custom elements (contain a hyphen) and keyed host components are kept.\n */\nfunction isSignificantHost(node: ComponentNode): boolean {\n if (node.key !== null) return true;\n if (node.displayName.includes('-')) return true; // custom element\n return false;\n}\n\nexport class ComponentTree {\n private nodes = new Map<number, ComponentNode>();\n private roots: number[] = [];\n /** Index: lowercase display name → set of node ids */\n private nameIndex = new Map<string, Set<number>>();\n /** Label → real node ID (e.g., \"@c1\" → 10) */\n private labelToId = new Map<string, number>();\n /** Real node ID → label */\n private idToLabel = new Map<number, string>();\n /**\n * Whether the backend uses the extended ADD format (8 fields with namePropStringID).\n * Auto-detected from the presence of SUSPENSE_TREE_OPERATION opcodes.\n */\n private extendedAddFormat = false;\n\n applyOperations(operations: number[]): Array<{ id: number; displayName: string }> {\n if (operations.length < 2) return [];\n\n const added: Array<{ id: number; displayName: string }> = [];\n const rendererId = operations[0];\n // operations[1] is the root fiber ID\n let i = 2;\n\n // Parse the string table (protocol v2)\n const stringTable: Array<string | null> = [null]; // ID 0 = null\n const stringTableSize = operations[i++];\n const stringTableEnd = i + stringTableSize;\n while (i < stringTableEnd) {\n const strLen = operations[i++];\n let str = '';\n for (let j = 0; j < strLen; j++) {\n str += String.fromCodePoint(operations[i++]);\n }\n stringTable.push(str);\n }\n\n // Parse operations\n while (i < operations.length) {\n const op = operations[i];\n\n switch (op) {\n case TREE_OPERATION_ADD: {\n const id = operations[i + 1];\n const elementType = operations[i + 2];\n i += 3;\n\n if (elementType === ELEMENT_TYPE_ROOT) {\n // Root node: isStrictModeCompliant, supportsProfiling,\n // supportsStrictMode, hasOwnerMetadata\n i += 4;\n\n const node: ComponentNode = {\n id,\n displayName: 'Root',\n type: 'other',\n key: null,\n parentId: null,\n children: [],\n rendererId,\n errors: 0,\n warnings: 0,\n };\n this.nodes.set(id, node);\n added.push({ id, displayName: node.displayName });\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parentId = operations[i++];\n i++; // ownerID\n const displayNameStringId = operations[i++];\n const keyStringId = operations[i++];\n if (this.extendedAddFormat) {\n i++; // namePropStringID (added in newer backends)\n }\n\n const displayName =\n (displayNameStringId > 0 ? stringTable[displayNameStringId] : null) ||\n (elementType === ELEMENT_TYPE_HOST ? 'HostComponent' : 'Anonymous');\n const key = keyStringId > 0 ? stringTable[keyStringId] || null : null;\n\n const node: ComponentNode = {\n id,\n displayName,\n type: toComponentType(elementType),\n key,\n parentId: parentId === 0 ? null : parentId,\n children: [],\n rendererId,\n errors: 0,\n warnings: 0,\n };\n\n this.nodes.set(id, node);\n added.push({ id, displayName });\n\n // Add to parent's children\n if (parentId === 0) {\n if (!this.roots.includes(id)) {\n this.roots.push(id);\n }\n } else {\n const parent = this.nodes.get(parentId);\n if (parent) {\n parent.children.push(id);\n }\n }\n\n // Update name index\n if (displayName) {\n const lower = displayName.toLowerCase();\n let set = this.nameIndex.get(lower);\n if (!set) {\n set = new Set();\n this.nameIndex.set(lower, set);\n }\n set.add(id);\n }\n }\n break;\n }\n\n case TREE_OPERATION_REMOVE: {\n const numRemoved = operations[i + 1];\n for (let j = 0; j < numRemoved; j++) {\n const id = operations[i + 2 + j];\n this.removeNode(id);\n }\n i += 2 + numRemoved;\n break;\n }\n\n case TREE_OPERATION_REORDER_CHILDREN: {\n const id = operations[i + 1];\n const numChildren = operations[i + 2];\n const newChildren: number[] = [];\n for (let j = 0; j < numChildren; j++) {\n newChildren.push(operations[i + 3 + j]);\n }\n const node = this.nodes.get(id);\n if (node) {\n node.children = newChildren;\n }\n i += 3 + numChildren;\n break;\n }\n\n case TREE_OPERATION_UPDATE_TREE_BASE_DURATION: {\n // id, baseDuration — skip\n i += 3;\n break;\n }\n\n case TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS: {\n const id = operations[i + 1];\n const numErrors = operations[i + 2];\n const numWarnings = operations[i + 3];\n const node = this.nodes.get(id);\n if (node) {\n node.errors = numErrors;\n node.warnings = numWarnings;\n }\n i += 4;\n break;\n }\n\n case TREE_OPERATION_REMOVE_ROOT: {\n const rootId = operations[i + 1];\n this.removeNode(rootId);\n i += 2;\n break;\n }\n\n case TREE_OPERATION_SET_SUBTREE_MODE: {\n // id, mode\n i += 3;\n break;\n }\n\n // ── Suspense tree operations (newer backends) ──\n\n case SUSPENSE_TREE_OPERATION_ADD: {\n // Presence of suspense ops means the backend also uses 8-field ADD\n this.extendedAddFormat = true;\n // fiberID, parentID, nameStringID, isSuspended, rects\n i += 5; // opcode + 4 fields\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REMOVE: {\n this.extendedAddFormat = true;\n // numIDs, then that many IDs\n const numIds = operations[i + 1];\n i += 2 + numIds;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_REORDER_CHILDREN: {\n this.extendedAddFormat = true;\n // parentID, numChildren, then that many child IDs\n const numSuspenseChildren = operations[i + 2];\n i += 3 + numSuspenseChildren;\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_RESIZE: {\n this.extendedAddFormat = true;\n // fiberID, rects\n i += 2; // opcode + fiberID\n i = skipRects(operations, i);\n break;\n }\n\n case SUSPENSE_TREE_OPERATION_SUSPENDERS: {\n this.extendedAddFormat = true;\n // numChanges, then numChanges * 4 values\n const numChanges = operations[i + 1];\n i += 2 + numChanges * 4;\n break;\n }\n\n case TREE_OPERATION_APPLIED_ACTIVITY_SLICE_CHANGE: {\n this.extendedAddFormat = true;\n // id\n i += 2;\n break;\n }\n\n default:\n // Unknown operation — skip one value and try to continue.\n // Future protocol additions may cause brief misalignment but\n // subsequent operations batches will self-correct.\n i++;\n break;\n }\n }\n\n return added;\n }\n\n private removeNode(id: number): void {\n const node = this.nodes.get(id);\n if (!node) return;\n\n // Remove from parent's children\n if (node.parentId !== null) {\n const parent = this.nodes.get(node.parentId);\n if (parent) {\n parent.children = parent.children.filter((c) => c !== id);\n }\n }\n\n // Remove from roots\n this.roots = this.roots.filter((r) => r !== id);\n\n // Remove from name index\n if (node.displayName) {\n const lower = node.displayName.toLowerCase();\n const set = this.nameIndex.get(lower);\n if (set) {\n set.delete(id);\n if (set.size === 0) this.nameIndex.delete(lower);\n }\n }\n\n // Recursively remove children\n for (const childId of node.children) {\n this.removeNode(childId);\n }\n\n this.nodes.delete(id);\n }\n\n getNode(id: number): ComponentNode | undefined {\n return this.nodes.get(id);\n }\n\n getTree(maxDepthOrOpts?: number | GetTreeOptions): TreeNode[] {\n const opts: GetTreeOptions =\n typeof maxDepthOrOpts === 'number'\n ? { maxDepth: maxDepthOrOpts }\n : maxDepthOrOpts || {};\n const { maxDepth, noHost, rootId } = opts;\n\n const result: TreeNode[] = [];\n\n // Rebuild label maps on every getTree() call\n this.labelToId.clear();\n this.idToLabel.clear();\n let labelCounter = 1;\n\n // Track effective children when host nodes are skipped (for consistent children arrays)\n const effectiveChildren = noHost ? new Map<number | null, number[]>() : null;\n\n const walk = (id: number, depth: number, effectiveParentId: number | null) => {\n const node = this.nodes.get(id);\n if (!node) return;\n if (maxDepth !== undefined && depth > maxDepth) return;\n\n // Assign label for every node (even skipped hosts) so IDs stay stable\n const label = `@c${labelCounter++}`;\n this.labelToId.set(label, node.id);\n this.idToLabel.set(node.id, label);\n\n // Check if this host node should be filtered out\n // Never skip the explicitly requested subtree root\n const skipThis = noHost && node.type === 'host' && !isSignificantHost(node)\n && !(rootId !== undefined && id === rootId);\n\n if (skipThis) {\n // Promote children to the effective parent at the same depth\n for (const childId of node.children) {\n walk(childId, depth, effectiveParentId);\n }\n } else {\n // Record this node as a child of its effective parent\n if (effectiveChildren) {\n let siblings = effectiveChildren.get(effectiveParentId);\n if (!siblings) {\n siblings = [];\n effectiveChildren.set(effectiveParentId, siblings);\n }\n siblings.push(node.id);\n }\n\n const treeNode: TreeNode = {\n id: node.id,\n label,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: rootId !== undefined && depth === 0 ? null : effectiveParentId,\n children: node.children, // patched below when noHost\n depth,\n };\n if (node.errors > 0) treeNode.errors = node.errors;\n if (node.warnings > 0) treeNode.warnings = node.warnings;\n result.push(treeNode);\n\n for (const childId of node.children) {\n walk(childId, depth + 1, node.id);\n }\n }\n };\n\n if (rootId !== undefined) {\n const rootNode = this.nodes.get(rootId);\n if (rootNode) {\n walk(rootId, 0, null);\n }\n } else {\n for (const rid of this.roots) {\n walk(rid, 0, null);\n }\n }\n\n // Patch children arrays to reflect filtered tree when noHost is active\n if (effectiveChildren) {\n for (const node of result) {\n node.children = effectiveChildren.get(node.id) ?? [];\n }\n }\n\n return result;\n }\n\n findByName(name: string, exact?: boolean): TreeNode[] {\n const results: TreeNode[] = [];\n\n if (exact) {\n const lower = name.toLowerCase();\n const ids = this.nameIndex.get(lower);\n if (ids) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node && node.displayName.toLowerCase() === lower) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n } else {\n const lower = name.toLowerCase();\n for (const [indexName, ids] of this.nameIndex) {\n if (indexName.includes(lower)) {\n for (const id of ids) {\n const node = this.nodes.get(id);\n if (node) {\n results.push(this.toTreeNode(node));\n }\n }\n }\n }\n }\n\n return results;\n }\n\n getComponentCount(): number {\n return this.nodes.size;\n }\n\n getCountByType(): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const node of this.nodes.values()) {\n counts[node.type] = (counts[node.type] || 0) + 1;\n }\n return counts;\n }\n\n getAllNodeIds(): number[] {\n return Array.from(this.nodes.keys());\n }\n\n /**\n * Return all nodes that have non-zero error or warning counts.\n */\n getComponentsWithErrorsOrWarnings(): TreeNode[] {\n const results: TreeNode[] = [];\n for (const node of this.nodes.values()) {\n if (node.errors > 0 || node.warnings > 0) {\n results.push(this.toTreeNode(node));\n }\n }\n return results;\n }\n\n getRootIds(): number[] {\n return [...this.roots];\n }\n\n removeRoot(rootId: number): void {\n this.removeNode(rootId);\n }\n\n /**\n * Look up the @cN label for a given component ID.\n * Returns undefined if the ID has no label assigned.\n */\n getLabel(id: number): string | undefined {\n return this.idToLabel.get(id);\n }\n\n /**\n * Resolve a label like \"@c3\" to a real node ID.\n * Returns undefined if label not found.\n */\n resolveLabel(label: string): number | undefined {\n return this.labelToId.get(label);\n }\n\n /**\n * Resolve either a label string (\"@c3\") or a numeric ID to a real node ID.\n * Also handles the \"@c?(id:N)\" format emitted by find for components outside\n * the labeled tree range.\n */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return this.nodes.has(id) ? id : undefined;\n // Handle @c?(id:N) format for unresolved labels\n const match = id.match(/^@c\\?\\(id:(\\d+)\\)$/);\n if (match) return parseInt(match[1], 10);\n if (id.startsWith('@c')) return this.labelToId.get(id);\n // Try parsing as number\n const num = parseInt(id, 10);\n if (isNaN(num)) return undefined;\n return this.nodes.has(num) ? num : undefined;\n }\n\n private toTreeNode(node: ComponentNode): TreeNode {\n // Calculate depth by walking up the tree\n let depth = 0;\n let current = node;\n while (current.parentId !== null) {\n depth++;\n const parent = this.nodes.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n\n const treeNode: TreeNode = {\n id: node.id,\n label: this.idToLabel.get(node.id) || `@c?`,\n displayName: node.displayName,\n type: node.type,\n key: node.key,\n parentId: node.parentId,\n children: node.children,\n depth,\n };\n if (node.errors > 0) treeNode.errors = node.errors;\n if (node.warnings > 0) treeNode.warnings = node.warnings;\n return treeNode;\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ComponentType,\n ProfilingDataExport,\n ProfilingDataForRootExport,\n CommitDataExport,\n SnapshotNodeExport,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\n\n/**\n * Build a React DevTools Profiler export (version 5) from a profiling session.\n *\n * When raw data from React DevTools is available (collected via\n * processProfilingData), it is passed through to ensure full fidelity —\n * including initialTreeBaseDurations that DevTools needs for correct\n * flame graph rendering. Snapshots are always built from the ComponentTree\n * since the protocol sends them empty.\n */\nexport function buildExportData(\n session: ProfilingSession,\n tree: ComponentTree,\n): ProfilingDataExport | null {\n if (session.commits.length === 0) return null;\n\n if (session.rawRoots.length > 0) {\n return {\n version: 5,\n dataForRoots: session.rawRoots.map((raw) => {\n const subtreeIds = collectSubtreeIds(raw.rootID, tree);\n const snapshots = buildSnapshots(raw.rootID, subtreeIds, tree);\n const operations = raw.operations.length > 0\n ? raw.operations\n : session.commits.map(() => []);\n\n return {\n commitData: raw.commitData as CommitDataExport[],\n displayName: raw.displayName,\n initialTreeBaseDurations: raw.initialTreeBaseDurations,\n operations,\n rootID: raw.rootID,\n snapshots,\n };\n }),\n };\n }\n\n // Fallback: reconstruct from parsed commits (e.g. if data came via flat format)\n return buildFromParsedCommits(session, tree);\n}\n\nfunction buildFromParsedCommits(\n session: ProfilingSession,\n tree: ComponentTree,\n): ProfilingDataExport {\n let rootIds = tree.getRootIds();\n if (rootIds.length === 0) {\n rootIds = [1];\n }\n\n const dataForRoots: ProfilingDataForRootExport[] = [];\n\n for (const rootId of rootIds) {\n const rootNode = tree.getNode(rootId);\n const subtreeIds = collectSubtreeIds(rootId, tree);\n const snapshots = buildSnapshots(rootId, subtreeIds, tree);\n\n const baseDurationMap = new Map<number, number>();\n for (const nodeId of subtreeIds) {\n baseDurationMap.set(nodeId, 0);\n }\n for (const commit of session.commits) {\n for (const [id, duration] of commit.fiberSelfDurations) {\n if (baseDurationMap.has(id)) {\n baseDurationMap.set(id, duration);\n }\n }\n }\n\n const commitData: CommitDataExport[] = session.commits.map(\n (commit) => convertCommit(commit),\n );\n\n dataForRoots.push({\n commitData,\n displayName: rootNode?.displayName || 'Root',\n initialTreeBaseDurations: Array.from(baseDurationMap.entries()),\n operations: session.commits.map(() => []),\n rootID: rootId,\n snapshots,\n });\n }\n\n return {\n version: 5,\n dataForRoots,\n };\n}\n\nfunction convertCommit(commit: ProfilingCommit): CommitDataExport {\n const changeDescriptions: Array<[number, {\n context: null;\n didHooksChange: boolean;\n isFirstMount: boolean;\n props: string[] | null;\n state: string[] | null;\n hooks: number[] | null;\n }]> = [];\n\n for (const [id, desc] of commit.changeDescriptions) {\n changeDescriptions.push([id, {\n context: null,\n didHooksChange: desc.didHooksChange,\n isFirstMount: desc.isFirstMount,\n props: desc.props,\n state: desc.state,\n hooks: desc.hooks,\n }]);\n }\n\n return {\n changeDescriptions: changeDescriptions.length > 0 ? changeDescriptions : null,\n duration: commit.duration,\n effectDuration: commit.effectDuration ?? 0,\n fiberActualDurations: Array.from(commit.fiberActualDurations.entries()),\n fiberSelfDurations: Array.from(commit.fiberSelfDurations.entries()),\n passiveEffectDuration: commit.passiveEffectDuration ?? 0,\n priorityLevel: commit.priorityLevel ?? null,\n timestamp: commit.timestamp,\n updaters: commit.updaters as CommitDataExport['updaters'],\n };\n}\n\nfunction buildSnapshots(\n rootId: number,\n subtreeIds: number[],\n tree: ComponentTree,\n): Array<[number, SnapshotNodeExport]> {\n const snapshots: Array<[number, SnapshotNodeExport]> = [];\n for (const nodeId of subtreeIds) {\n const node = tree.getNode(nodeId);\n if (!node) continue;\n const elementType =\n nodeId === rootId && node.type === 'other'\n ? 11\n : componentTypeToElementType(node.type);\n snapshots.push([nodeId, {\n id: nodeId,\n children: node.children,\n displayName: node.displayName || null,\n hocDisplayNames: null,\n key: node.key,\n type: elementType,\n compiledWithForget: false,\n }]);\n }\n return snapshots;\n}\n\nfunction collectSubtreeIds(rootId: number, tree: ComponentTree): number[] {\n const ids: number[] = [];\n const visit = (id: number) => {\n const node = tree.getNode(id);\n if (!node) return;\n ids.push(id);\n for (const childId of node.children) {\n visit(childId);\n }\n };\n visit(rootId);\n return ids;\n}\n\nfunction componentTypeToElementType(type: ComponentType): number {\n switch (type) {\n case 'class': return 1;\n case 'context': return 2;\n case 'function': return 5;\n case 'forwardRef': return 6;\n case 'host': return 7;\n case 'memo': return 8;\n case 'profiler': return 10;\n case 'suspense': return 12;\n case 'other': return 9;\n default: return 9;\n }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n ChangedKeys,\n ProfilingDataExport,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\nimport { buildExportData } from './profile-export.js';\n\nexport interface ProfileSummary {\n name: string;\n duration: number;\n commitCount: number;\n componentRenderCounts: { id: number; displayName: string; label?: string; type?: string; count: number }[];\n}\n\nexport interface TimelineEntry {\n index: number;\n timestamp: number;\n duration: number;\n componentCount: number;\n}\n\nexport interface TimelineResult {\n entries: TimelineEntry[];\n total: number;\n offset: number;\n}\n\nexport interface CommitDetail {\n index: number;\n timestamp: number;\n duration: number;\n components: Array<{\n id: number;\n displayName: string;\n label?: string;\n type?: string;\n actualDuration: number;\n selfDuration: number;\n causes: RenderCause[];\n changedKeys?: ChangedKeys;\n }>;\n totalComponents: number;\n}\n\nexport class Profiler {\n private session: ProfilingSession | null = null;\n /** Display names captured during profiling (survives unmounts) */\n private displayNames = new Map<number, string>();\n\n isActive(): boolean {\n return this.session !== null && this.session.stoppedAt === null;\n }\n\n start(name?: string): void {\n this.displayNames.clear();\n this.session = {\n name: name || `session-${Date.now()}`,\n startedAt: Date.now(),\n stoppedAt: null,\n commits: [],\n rawRoots: [],\n };\n }\n\n /** Cache a component's display name (call during profiling to survive unmounts) */\n trackComponent(id: number, displayName: string): void {\n this.displayNames.set(id, displayName);\n }\n\n stop(tree?: ComponentTree): ProfileSummary | null {\n if (!this.session) return null;\n this.session.stoppedAt = Date.now();\n\n const duration = this.session.stoppedAt - this.session.startedAt;\n\n // Count renders per component\n const renderCounts = new Map<number, number>();\n for (const commit of this.session.commits) {\n for (const [id] of commit.fiberActualDurations) {\n renderCounts.set(id, (renderCounts.get(id) || 0) + 1);\n }\n }\n\n const componentRenderCounts = Array.from(renderCounts.entries())\n .map(([id, count]) => ({\n id,\n displayName: tree?.getNode(id)?.displayName || this.displayNames.get(id) || '',\n count,\n }))\n .sort((a, b) => b.count - a.count);\n\n return {\n name: this.session.name,\n duration,\n commitCount: this.session.commits.length,\n componentRenderCounts,\n };\n }\n\n /**\n * Process profiling data sent from React DevTools.\n *\n * The data format varies between React versions. We handle the common\n * format where each commit contains:\n * - commitTime\n * - duration\n * - fiberActualDurations: [id, duration, ...]\n * - fiberSelfDurations: [id, duration, ...]\n * - changeDescriptions: Map<id, description>\n */\n processProfilingData(payload: unknown): void {\n if (!this.session) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n rootID?: number;\n commitData?: unknown[];\n operations?: Array<number[]>;\n initialTreeBaseDurations?: Array<[number, number]>;\n snapshots?: Array<[number, unknown]>;\n displayName?: string;\n }>;\n // Alternative flat format\n commitData?: unknown[];\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n // Store raw root data for export passthrough\n this.session.rawRoots.push({\n rootID: root.rootID ?? 1,\n commitData: root.commitData ?? [],\n initialTreeBaseDurations: root.initialTreeBaseDurations ?? [],\n operations: root.operations ?? [],\n snapshots: root.snapshots ?? [],\n displayName: root.displayName ?? 'Root',\n });\n\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData as Record<string, unknown>);\n }\n }\n }\n return;\n }\n\n // Handle flat format\n if (data?.commitData) {\n for (const commitData of data.commitData) {\n this.processCommitData(commitData as Record<string, unknown>);\n }\n }\n }\n\n private processCommitData(commitData: Record<string, unknown>): void {\n const commit: ProfilingCommit = {\n timestamp: (commitData.timestamp as number) || Date.now(),\n duration: (commitData.duration as number) || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n effectDuration: (commitData.effectDuration as number) ?? null,\n passiveEffectDuration: (commitData.passiveEffectDuration as number) ?? null,\n priorityLevel: (commitData.priorityLevel as string) ?? null,\n updaters: (commitData.updaters as unknown[]) ?? null,\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations as Array<[number, number]> | number[], commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations as Array<[number, number]> | number[], commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n const rawDescs = commitData.changeDescriptions as Array<[number, unknown]> | Map<number, unknown> | undefined;\n if (rawDescs) {\n const entries =\n rawDescs instanceof Map\n ? rawDescs.entries()\n : rawDescs[Symbol.iterator]();\n for (const [id, desc] of entries) {\n const d = desc as {\n didHooksChange?: boolean;\n isFirstMount?: boolean;\n props?: string[] | null;\n state?: string[] | null;\n hooks?: number[] | null;\n };\n commit.changeDescriptions.set(id as number, {\n didHooksChange: d.didHooksChange || false,\n isFirstMount: d.isFirstMount || false,\n props: d.props || null,\n state: d.state || null,\n hooks: d.hooks || null,\n });\n }\n }\n\n this.session!.commits.push(commit);\n }\n\n getReport(\n componentId: number,\n tree: ComponentTree,\n ): ComponentRenderReport | null {\n if (!this.session) return null;\n\n const node = tree.getNode(componentId);\n let renderCount = 0;\n let totalDuration = 0;\n let maxDuration = 0;\n const causeSet = new Set<RenderCause>();\n const propsSet = new Set<string>();\n const stateSet = new Set<string>();\n const hooksSet = new Set<number>();\n\n for (const commit of this.session.commits) {\n const duration = commit.fiberActualDurations.get(componentId);\n if (duration !== undefined) {\n renderCount++;\n totalDuration += duration;\n if (duration > maxDuration) maxDuration = duration;\n\n const desc = commit.changeDescriptions.get(componentId);\n if (desc) {\n for (const cause of describeCauses(desc)) {\n causeSet.add(cause);\n }\n const keys = extractChangedKeys(desc);\n for (const p of keys.props) propsSet.add(p);\n for (const s of keys.state) stateSet.add(s);\n for (const h of keys.hooks) hooksSet.add(h);\n }\n }\n }\n\n if (renderCount === 0) return null;\n\n return {\n id: componentId,\n displayName: node?.displayName || this.displayNames.get(componentId) || `Component#${componentId}`,\n renderCount,\n totalDuration,\n avgDuration: totalDuration / renderCount,\n maxDuration,\n causes: Array.from(causeSet),\n changedKeys: {\n props: Array.from(propsSet),\n state: Array.from(stateSet),\n hooks: Array.from(hooksSet),\n },\n };\n }\n\n getSlowest(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.avgDuration - a.avgDuration)\n .slice(0, limit);\n }\n\n getMostRerenders(\n tree: ComponentTree,\n limit = 10,\n ): ComponentRenderReport[] {\n return this.getAllReports(tree)\n .sort((a, b) => b.renderCount - a.renderCount)\n .slice(0, limit);\n }\n\n getCommitDetails(index: number, tree: ComponentTree, limit = 10): CommitDetail | null {\n if (!this.session) return null;\n if (index < 0 || index >= this.session.commits.length) return null;\n\n const commit = this.session.commits[index];\n const components: CommitDetail['components'] = [];\n\n for (const [id, actualDuration] of commit.fiberActualDurations) {\n const selfDuration = commit.fiberSelfDurations.get(id) || 0;\n const desc = commit.changeDescriptions.get(id);\n components.push({\n id,\n displayName: tree.getNode(id)?.displayName || this.displayNames.get(id) || `Component#${id}`,\n actualDuration,\n selfDuration,\n causes: desc ? describeCauses(desc) : [],\n changedKeys: desc ? extractChangedKeys(desc) : { props: [], state: [], hooks: [] },\n });\n }\n\n components.sort((a, b) => b.selfDuration - a.selfDuration);\n\n const totalCount = components.length;\n\n return {\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n components: limit > 0 ? components.slice(0, limit) : components,\n totalComponents: totalCount,\n };\n }\n\n getTimeline(limit: number = 20, offset?: number, sort?: 'duration' | 'timeline'): TimelineResult {\n if (!this.session) return { entries: [], total: 0, offset: offset ?? 0 };\n\n const all = this.session.commits.map((commit, index) => ({\n index,\n timestamp: commit.timestamp,\n duration: commit.duration,\n componentCount: commit.fiberActualDurations.size,\n }));\n\n if (sort === 'duration') all.sort((a, b) => b.duration - a.duration);\n const start = Math.max(0, offset ?? 0);\n return {\n entries: all.slice(start, start + limit),\n total: all.length,\n offset: start,\n };\n }\n\n getExportData(tree: ComponentTree): ProfilingDataExport | null {\n if (!this.session) return null;\n return buildExportData(this.session, tree);\n }\n\n private getAllReports(tree: ComponentTree): ComponentRenderReport[] {\n if (!this.session) return [];\n\n // Collect all component IDs that appear in profiling data\n const componentIds = new Set<number>();\n for (const commit of this.session.commits) {\n for (const id of commit.fiberActualDurations.keys()) {\n componentIds.add(id);\n }\n }\n\n const reports: ComponentRenderReport[] = [];\n for (const id of componentIds) {\n const report = this.getReport(id, tree);\n if (report) reports.push(report);\n }\n return reports;\n }\n}\n\nfunction parseDurations(\n raw: Array<[number, number]> | number[],\n target: Map<number, number>,\n): void {\n if (raw.length === 0) return;\n\n // Check if it's array of tuples or flat array\n if (Array.isArray(raw[0])) {\n // [[id, duration], ...]\n for (const [id, duration] of raw as Array<[number, number]>) {\n target.set(id, duration);\n }\n } else {\n // [id, duration, id, duration, ...]\n const flat = raw as number[];\n for (let i = 0; i < flat.length; i += 2) {\n target.set(flat[i], flat[i + 1]);\n }\n }\n}\n\nfunction describeCauses(desc: ChangeDescription): RenderCause[] {\n const causes: RenderCause[] = [];\n if (desc.isFirstMount) {\n causes.push('first-mount');\n return causes;\n }\n if (desc.props && desc.props.length > 0) causes.push('props-changed');\n if (desc.state && desc.state.length > 0) causes.push('state-changed');\n if (desc.didHooksChange) causes.push('hooks-changed');\n // If no specific cause found, it was likely parent-triggered\n if (causes.length === 0) causes.push('parent-rendered');\n return causes;\n}\n\nfunction extractChangedKeys(desc: ChangeDescription): ChangedKeys {\n return {\n props: desc.props ?? [],\n state: desc.state ?? [],\n hooks: desc.hooks ?? [],\n };\n}\n"],"mappings":"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","names":["port","pending","port"]}