agent-react-devtools 0.2.2 → 0.3.0-canary-20260212081524
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/CHANGELOG.md +17 -0
- package/README.md +16 -16
- package/dist/cli.js +21 -23
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +29 -10
- package/dist/daemon.js.map +1 -1
- package/package.json +1 -1
- package/skills/react-devtools/SKILL.md +9 -9
- package/skills/react-devtools/references/commands.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# agent-react-devtools
|
|
2
2
|
|
|
3
|
+
## 0.3.0-canary-20260212081524
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 20ce273: Standardize component reference format across all CLI output
|
|
8
|
+
|
|
9
|
+
All formatters now produce consistent `@cN [type] Name` references. Previously, tree and search commands used `@c1 [fn] "Name"` while profiling commands omitted labels, type tags, or both.
|
|
10
|
+
|
|
11
|
+
**Breaking changes to output format:**
|
|
12
|
+
|
|
13
|
+
- Component names are no longer quoted: `@c1 [fn] App` instead of `@c1 [fn] "App"`
|
|
14
|
+
- Keys use `key=value` instead of `key="value"`
|
|
15
|
+
- Profiling commands (`profile slow`, `profile rerenders`, `profile stop`, `profile commit`) now include `@cN` labels and `[type]` tags
|
|
16
|
+
- `profile slow` and `profile rerenders` show all render causes instead of only the first
|
|
17
|
+
- `profile report` now includes a `[type]` tag in the header
|
|
18
|
+
- Column-aligned padding removed from profiling output in favor of consistent `formatRef` formatting
|
|
19
|
+
|
|
3
20
|
## 0.2.2
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -44,15 +44,15 @@ agent-react-devtools get tree --depth 3
|
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
```
|
|
47
|
-
@c1 [fn]
|
|
48
|
-
├─ @c2 [fn]
|
|
49
|
-
│ ├─ @c3 [fn]
|
|
50
|
-
│ └─ @c4 [fn]
|
|
51
|
-
├─ @c5 [fn]
|
|
52
|
-
│ ├─ @c6 [fn]
|
|
53
|
-
│ ├─ @c7 [fn]
|
|
54
|
-
│ └─ @c8 [fn]
|
|
55
|
-
└─ @c9 [fn]
|
|
47
|
+
@c1 [fn] App
|
|
48
|
+
├─ @c2 [fn] Header
|
|
49
|
+
│ ├─ @c3 [fn] Nav
|
|
50
|
+
│ └─ @c4 [fn] SearchBar
|
|
51
|
+
├─ @c5 [fn] TodoList
|
|
52
|
+
│ ├─ @c6 [fn] TodoItem key=1
|
|
53
|
+
│ ├─ @c7 [fn] TodoItem key=2
|
|
54
|
+
│ └─ @c8 [fn] TodoItem key=3
|
|
55
|
+
└─ @c9 [fn] Footer
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
Inspect a component's props, state, and hooks:
|
|
@@ -62,7 +62,7 @@ agent-react-devtools get component @c6
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
```
|
|
65
|
-
@c6 [fn]
|
|
65
|
+
@c6 [fn] TodoItem key=1
|
|
66
66
|
props:
|
|
67
67
|
id: 1
|
|
68
68
|
text: "Buy groceries"
|
|
@@ -80,9 +80,9 @@ agent-react-devtools find TodoItem
|
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
```
|
|
83
|
-
@c6 [fn]
|
|
84
|
-
@c7 [fn]
|
|
85
|
-
@c8 [fn]
|
|
83
|
+
@c6 [fn] TodoItem key=1
|
|
84
|
+
@c7 [fn] TodoItem key=2
|
|
85
|
+
@c8 [fn] TodoItem key=3
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
Profile rendering performance:
|
|
@@ -96,9 +96,9 @@ agent-react-devtools profile slow
|
|
|
96
96
|
|
|
97
97
|
```
|
|
98
98
|
Slowest (by avg render time):
|
|
99
|
-
TodoList
|
|
100
|
-
SearchBar
|
|
101
|
-
Header
|
|
99
|
+
@c5 [fn] TodoList avg:4.2ms max:8.1ms renders:6 causes:props-changed
|
|
100
|
+
@c4 [fn] SearchBar avg:2.1ms max:3.4ms renders:12 causes:hooks-changed
|
|
101
|
+
@c2 [fn] Header avg:0.8ms max:1.2ms renders:3 causes:parent-rendered
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
## Commands
|
package/dist/cli.js
CHANGED
|
@@ -130,6 +130,13 @@ var TYPE_ABBREV = {
|
|
|
130
130
|
function typeTag(type) {
|
|
131
131
|
return TYPE_ABBREV[type] || type;
|
|
132
132
|
}
|
|
133
|
+
function formatRef(opts) {
|
|
134
|
+
const ref = opts.label || "?";
|
|
135
|
+
const tag = typeTag(opts.type || "other");
|
|
136
|
+
let s = `${ref} [${tag}] ${opts.name}`;
|
|
137
|
+
if (opts.key) s += ` key=${opts.key}`;
|
|
138
|
+
return s;
|
|
139
|
+
}
|
|
133
140
|
var PIPE = "\u2502 ";
|
|
134
141
|
var TEE = "\u251C\u2500 ";
|
|
135
142
|
var ELBOW = "\u2514\u2500 ";
|
|
@@ -151,8 +158,7 @@ function formatTree(nodes) {
|
|
|
151
158
|
const node = nodes.find((n) => n.id === nodeId);
|
|
152
159
|
if (!node) return;
|
|
153
160
|
const connector = isRoot ? "" : isLast ? ELBOW : TEE;
|
|
154
|
-
|
|
155
|
-
if (node.key) line += ` key="${node.key}"`;
|
|
161
|
+
const line = formatRef({ label: node.label, type: node.type, name: node.displayName, key: node.key });
|
|
156
162
|
lines.push(`${prefix}${connector}${line}`);
|
|
157
163
|
const children = childrenMap.get(node.id) || [];
|
|
158
164
|
const childPrefix = isRoot ? "" : prefix + (isLast ? SPACE : PIPE);
|
|
@@ -168,10 +174,7 @@ function formatTree(nodes) {
|
|
|
168
174
|
}
|
|
169
175
|
function formatComponent(element, label) {
|
|
170
176
|
const lines = [];
|
|
171
|
-
|
|
172
|
-
let header = `${ref} [${typeTag(element.type)}] "${element.displayName}"`;
|
|
173
|
-
if (element.key) header += ` key="${element.key}"`;
|
|
174
|
-
lines.push(header);
|
|
177
|
+
lines.push(formatRef({ label: label || `#${element.id}`, type: element.type, name: element.displayName, key: element.key }));
|
|
175
178
|
if (element.props && Object.keys(element.props).length > 0) {
|
|
176
179
|
lines.push("props:");
|
|
177
180
|
for (const [key, value] of Object.entries(element.props)) {
|
|
@@ -201,11 +204,7 @@ function formatComponent(element, label) {
|
|
|
201
204
|
}
|
|
202
205
|
function formatSearchResults(results) {
|
|
203
206
|
if (results.length === 0) return "No components found";
|
|
204
|
-
return results.map((n) => {
|
|
205
|
-
let line = `${n.label} [${typeTag(n.type)}] "${n.displayName}"`;
|
|
206
|
-
if (n.key) line += ` key="${n.key}"`;
|
|
207
|
-
return line;
|
|
208
|
-
}).join("\n");
|
|
207
|
+
return results.map((n) => formatRef({ label: n.label, type: n.type, name: n.displayName, key: n.key })).join("\n");
|
|
209
208
|
}
|
|
210
209
|
function formatCount(counts) {
|
|
211
210
|
const total = Object.values(counts).reduce((a, b) => a + b, 0);
|
|
@@ -235,16 +234,15 @@ function formatProfileSummary(summary) {
|
|
|
235
234
|
lines.push("");
|
|
236
235
|
lines.push("Top renders:");
|
|
237
236
|
for (const c of summary.componentRenderCounts.slice(0, 10)) {
|
|
238
|
-
const
|
|
239
|
-
lines.push(` ${
|
|
237
|
+
const ref = formatRef({ label: c.label, type: c.type, name: c.displayName || `#${c.id}` });
|
|
238
|
+
lines.push(` ${ref} ${c.count} renders`);
|
|
240
239
|
}
|
|
241
240
|
}
|
|
242
241
|
return lines.join("\n");
|
|
243
242
|
}
|
|
244
243
|
function formatProfileReport(report, label) {
|
|
245
244
|
const lines = [];
|
|
246
|
-
|
|
247
|
-
lines.push(`${ref} "${report.displayName}"`);
|
|
245
|
+
lines.push(formatRef({ label: label || report.label || `#${report.id}`, type: report.type, name: report.displayName }));
|
|
248
246
|
lines.push(
|
|
249
247
|
`renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`
|
|
250
248
|
);
|
|
@@ -257,9 +255,10 @@ function formatSlowest(reports) {
|
|
|
257
255
|
if (reports.length === 0) return "No profiling data";
|
|
258
256
|
const lines = ["Slowest (by avg render time):"];
|
|
259
257
|
for (const r of reports) {
|
|
260
|
-
const
|
|
258
|
+
const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });
|
|
259
|
+
const causes = r.causes.length > 0 ? r.causes.join(", ") : "?";
|
|
261
260
|
lines.push(
|
|
262
|
-
` ${
|
|
261
|
+
` ${ref} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} causes:${causes}`
|
|
263
262
|
);
|
|
264
263
|
}
|
|
265
264
|
return lines.join("\n");
|
|
@@ -268,9 +267,10 @@ function formatRerenders(reports) {
|
|
|
268
267
|
if (reports.length === 0) return "No profiling data";
|
|
269
268
|
const lines = ["Most re-renders:"];
|
|
270
269
|
for (const r of reports) {
|
|
271
|
-
const
|
|
270
|
+
const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });
|
|
271
|
+
const causes = r.causes.length > 0 ? r.causes.join(", ") : "?";
|
|
272
272
|
lines.push(
|
|
273
|
-
` ${
|
|
273
|
+
` ${ref} ${r.renderCount} renders causes:${causes}`
|
|
274
274
|
);
|
|
275
275
|
}
|
|
276
276
|
return lines.join("\n");
|
|
@@ -290,8 +290,9 @@ function formatCommitDetail(detail) {
|
|
|
290
290
|
lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);
|
|
291
291
|
lines.push("");
|
|
292
292
|
for (const c of detail.components) {
|
|
293
|
+
const ref = formatRef({ label: c.label, type: c.type, name: c.displayName });
|
|
293
294
|
const causes = c.causes.length > 0 ? c.causes.join(", ") : "?";
|
|
294
|
-
lines.push(` ${
|
|
295
|
+
lines.push(` ${ref} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms causes:${causes}`);
|
|
295
296
|
}
|
|
296
297
|
const hidden = detail.totalComponents - detail.components.length;
|
|
297
298
|
if (hidden > 0) {
|
|
@@ -317,9 +318,6 @@ function replacer(_key, value) {
|
|
|
317
318
|
if (typeof value === "function") return "\u0192";
|
|
318
319
|
return value;
|
|
319
320
|
}
|
|
320
|
-
function pad(s, len) {
|
|
321
|
-
return s.length >= len ? s : s + " ".repeat(len - s.length);
|
|
322
|
-
}
|
|
323
321
|
|
|
324
322
|
// src/cli.ts
|
|
325
323
|
function usage() {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon-client.ts","../src/formatters.ts","../src/cli.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IpcCommand, IpcResponse, DaemonInfo } 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 stateDir = DEFAULT_STATE_DIR;\n\nexport function setStateDir(dir: string): void {\n stateDir = dir;\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(stateDir, 'daemon.json');\n}\n\nfunction getSocketPath(): string {\n return path.join(stateDir, 'daemon.sock');\n}\n\nexport function readDaemonInfo(): DaemonInfo | null {\n try {\n const raw = fs.readFileSync(getDaemonInfoPath(), 'utf-8');\n return JSON.parse(raw) as DaemonInfo;\n } catch {\n return null;\n }\n}\n\nfunction isDaemonAlive(info: DaemonInfo): boolean {\n try {\n // Signal 0 doesn't kill, just checks if process exists\n process.kill(info.pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDaemon(port?: number): Promise<void> {\n const info = readDaemonInfo();\n if (info && isDaemonAlive(info)) {\n return; // Already running\n }\n\n // Clean up stale files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n\n // Start daemon as detached child process\n const daemonScript = path.join(\n path.dirname(new URL(import.meta.url).pathname),\n 'daemon.js',\n );\n\n const args = [];\n if (port) args.push(`--port=${port}`);\n if (stateDir !== DEFAULT_STATE_DIR) args.push(`--state-dir=${stateDir}`);\n\n const child = spawn(process.execPath, [daemonScript, ...args], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Wait for daemon to be ready (up to 5 seconds)\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 100));\n try {\n await sendCommand({ type: 'ping' });\n return;\n } catch {\n // not ready yet\n }\n }\n throw new Error('Daemon failed to start within 5 seconds');\n}\n\nexport function stopDaemon(): boolean {\n const info = readDaemonInfo();\n if (!info) return false;\n\n try {\n process.kill(info.pid, 'SIGTERM');\n // Clean up files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function sendCommand(cmd: IpcCommand): Promise<IpcResponse> {\n return new Promise((resolve, reject) => {\n const socketPath = getSocketPath();\n\n const conn = net.createConnection(socketPath, () => {\n conn.write(JSON.stringify(cmd) + '\\n');\n });\n\n let buffer = '';\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const newlineIdx = buffer.indexOf('\\n');\n if (newlineIdx !== -1) {\n const line = buffer.slice(0, newlineIdx);\n conn.end();\n try {\n resolve(JSON.parse(line) as IpcResponse);\n } catch {\n reject(new Error('Invalid response from daemon'));\n }\n }\n });\n\n conn.on('error', (err) => {\n reject(new Error(`Cannot connect to daemon: ${err.message}`));\n });\n\n // Timeout after 30 seconds\n conn.setTimeout(30_000, () => {\n conn.destroy();\n reject(new Error('Command timed out'));\n });\n });\n}\n","import type {\n StatusInfo,\n InspectedElement,\n ComponentRenderReport,\n} from './types.js';\nimport type { TreeNode } from './component-tree.js';\nimport type { ProfileSummary, TimelineEntry, CommitDetail } from './profiler.js';\n\n// ── Abbreviations for component types ──\nconst TYPE_ABBREV: Record<string, string> = {\n function: 'fn',\n class: 'cls',\n host: 'host',\n memo: 'memo',\n forwardRef: 'fRef',\n profiler: 'prof',\n suspense: 'susp',\n context: 'ctx',\n other: '?',\n};\n\nfunction typeTag(type: string): string {\n return TYPE_ABBREV[type] || type;\n}\n\n// ── Tree connector characters ──\nconst PIPE = '│ ';\nconst TEE = '├─ ';\nconst ELBOW = '└─ ';\nconst SPACE = ' ';\n\nexport function formatTree(nodes: TreeNode[]): string {\n if (nodes.length === 0) return 'No components (is a React app connected?)';\n\n // Build tree structure from the flat list\n const childrenMap = new Map<number | null, TreeNode[]>();\n for (const node of nodes) {\n const parentId = node.parentId;\n let siblings = childrenMap.get(parentId);\n if (!siblings) {\n siblings = [];\n childrenMap.set(parentId, siblings);\n }\n siblings.push(node);\n }\n\n const lines: string[] = [];\n\n function walk(nodeId: number, prefix: string, isLast: boolean, isRoot: boolean): void {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const connector = isRoot ? '' : isLast ? ELBOW : TEE;\n let line = `${node.label} [${typeTag(node.type)}] \"${node.displayName}\"`;\n if (node.key) line += ` key=\"${node.key}\"`;\n\n lines.push(`${prefix}${connector}${line}`);\n\n const children = childrenMap.get(node.id) || [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? SPACE : PIPE);\n\n for (let i = 0; i < children.length; i++) {\n walk(children[i].id, childPrefix, i === children.length - 1, false);\n }\n }\n\n // Find root nodes\n const roots = childrenMap.get(null) || [];\n for (let i = 0; i < roots.length; i++) {\n walk(roots[i].id, '', i === roots.length - 1, true);\n }\n\n return lines.join('\\n');\n}\n\nexport function formatComponent(element: InspectedElement, label?: string): string {\n const lines: string[] = [];\n\n const ref = label || `#${element.id}`;\n let header = `${ref} [${typeTag(element.type)}] \"${element.displayName}\"`;\n if (element.key) header += ` key=\"${element.key}\"`;\n lines.push(header);\n\n // Props\n if (element.props && Object.keys(element.props).length > 0) {\n lines.push('props:');\n for (const [key, value] of Object.entries(element.props)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // State\n if (element.state && Object.keys(element.state).length > 0) {\n lines.push('state:');\n for (const [key, value] of Object.entries(element.state)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // Hooks\n if (element.hooks && element.hooks.length > 0) {\n lines.push('hooks:');\n for (const h of element.hooks) {\n const val = formatCompactValue(h.value);\n lines.push(val !== undefined ? ` ${h.name}: ${val}` : ` ${h.name}`);\n if (h.subHooks && h.subHooks.length > 0) {\n for (const sh of h.subHooks) {\n const sval = formatCompactValue(sh.value);\n lines.push(sval !== undefined ? ` ${sh.name}: ${sval}` : ` ${sh.name}`);\n }\n }\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatSearchResults(results: TreeNode[]): string {\n if (results.length === 0) return 'No components found';\n\n return results\n .map((n) => {\n let line = `${n.label} [${typeTag(n.type)}] \"${n.displayName}\"`;\n if (n.key) line += ` key=\"${n.key}\"`;\n return line;\n })\n .join('\\n');\n}\n\nexport function formatCount(counts: Record<string, number>): string {\n const total = Object.values(counts).reduce((a, b) => a + b, 0);\n const parts = Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => `${typeTag(type)}:${count}`)\n .join(' ');\n return `${total} components (${parts})`;\n}\n\nexport function formatStatus(status: StatusInfo): string {\n const lines: string[] = [];\n lines.push(`Daemon: running (port ${status.port})`);\n lines.push(\n `Apps: ${status.connectedApps} connected, ${status.componentCount} components`,\n );\n if (status.profilingActive) {\n lines.push('Profiling: active');\n }\n const upSec = Math.round(status.uptime / 1000);\n lines.push(`Uptime: ${upSec}s`);\n return lines.join('\\n');\n}\n\nexport function formatProfileSummary(summary: ProfileSummary): string {\n const lines: string[] = [];\n const durSec = (summary.duration / 1000).toFixed(1);\n lines.push(\n `Profile \"${summary.name}\" (${durSec}s, ${summary.commitCount} commits)`,\n );\n\n if (summary.componentRenderCounts.length > 0) {\n lines.push('');\n lines.push('Top renders:');\n for (const c of summary.componentRenderCounts.slice(0, 10)) {\n const name = c.displayName || `#${c.id}`;\n lines.push(` ${name} ${c.count} renders`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatProfileReport(report: ComponentRenderReport, label?: string): string {\n const lines: string[] = [];\n const ref = label || `#${report.id}`;\n lines.push(`${ref} \"${report.displayName}\"`);\n lines.push(\n `renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`,\n );\n if (report.causes.length > 0) {\n lines.push(`causes: ${report.causes.join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function formatSlowest(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Slowest (by avg render time):'];\n for (const r of reports) {\n const cause = r.causes[0] || '?';\n lines.push(\n ` ${pad(r.displayName, 20)} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} cause:${cause}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatRerenders(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Most re-renders:'];\n for (const r of reports) {\n const cause = r.causes[0] || '?';\n lines.push(\n ` ${pad(r.displayName, 20)} ${r.renderCount} renders — ${cause}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatTimeline(entries: TimelineEntry[]): string {\n if (entries.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Commit timeline:'];\n for (const e of entries) {\n lines.push(\n ` #${e.index} ${e.duration.toFixed(1)}ms ${e.componentCount} components`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatCommitDetail(detail: CommitDetail): string {\n const lines: string[] = [];\n lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);\n lines.push('');\n for (const c of detail.components) {\n const causes = c.causes.length > 0 ? c.causes.join(', ') : '?';\n lines.push(` ${pad(c.displayName, 24)} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms ${causes}`);\n }\n const hidden = detail.totalComponents - detail.components.length;\n if (hidden > 0) {\n lines.push(` ... ${hidden} more (use --limit to show more)`);\n }\n return lines.join('\\n');\n}\n\n// ── Helpers ──\n\nfunction formatValue(obj: unknown): string {\n try {\n return JSON.stringify(obj, replacer, 0) || 'undefined';\n } catch {\n return String(obj);\n }\n}\n\nfunction formatCompactValue(val: unknown): string | undefined {\n if (val === undefined) return undefined;\n if (val === null) return 'null';\n if (typeof val === 'function') return 'ƒ';\n if (typeof val === 'string') return `\"${val}\"`;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n try {\n const s = JSON.stringify(val, replacer, 0);\n if (s && s.length > 60) return s.slice(0, 57) + '...';\n return s || String(val);\n } catch {\n return String(val);\n }\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'function') return 'ƒ';\n return value;\n}\n\nfunction pad(s: string, len: number): string {\n return s.length >= len ? s : s + ' '.repeat(len - s.length);\n}\n","import {\n ensureDaemon,\n sendCommand,\n stopDaemon,\n readDaemonInfo,\n setStateDir,\n} from './daemon-client.js';\nimport {\n formatTree,\n formatComponent,\n formatSearchResults,\n formatCount,\n formatStatus,\n formatProfileSummary,\n formatProfileReport,\n formatSlowest,\n formatRerenders,\n formatTimeline,\n formatCommitDetail,\n} from './formatters.js';\nimport type { IpcCommand } from './types.js';\n\nfunction usage(): string {\n return `Usage: devtools <command> [options]\n\nSetup:\n init [--dry-run] Auto-configure your React app\n\nDaemon:\n start [--port 8097] Start daemon\n stop Stop daemon\n status Show daemon status\n\nComponents:\n get tree [--depth N] Component hierarchy\n get component <@c1 | id> Props, state, hooks\n find <name> [--exact] Search by display name\n count Component count by type\n\nProfiling:\n profile start [name] Start profiling session\n profile stop Stop profiling, collect data\n profile report <@c1 | id> Render report for component\n profile slow [--limit N] Slowest components (by avg)\n profile rerenders [--limit N] Most re-rendered components\n profile timeline [--limit N] Commit timeline\n profile commit <N | #N> [--limit N] Detail for specific commit`;\n}\n\nfunction parseArgs(argv: string[]): {\n command: string[];\n flags: Record<string, string | boolean>;\n} {\n const command: string[] = [];\n const flags: Record<string, string | boolean> = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const key = arg.slice(2);\n const eqIdx = key.indexOf('=');\n if (eqIdx !== -1) {\n flags[key.slice(0, eqIdx)] = key.slice(eqIdx + 1);\n } else {\n // Check if next arg is a value\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n }\n } else {\n command.push(arg);\n }\n }\n return { command, flags };\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv.slice(2));\n\n if (command.length === 0 || flags['help']) {\n console.log(usage());\n process.exit(0);\n }\n\n // Configure custom state directory (for test isolation)\n if (typeof flags['state-dir'] === 'string') {\n setStateDir(flags['state-dir']);\n }\n\n const cmd0 = command[0];\n const cmd1 = command[1];\n\n try {\n // ── Init ──\n if (cmd0 === 'init') {\n const { runInit } = await import('./init.js');\n await runInit(process.cwd(), flags['dry-run'] === true);\n return;\n }\n\n // ── Daemon management ──\n if (cmd0 === 'start') {\n const port = flags['port'] ? parseInt(flags['port'] as string, 10) : undefined;\n await ensureDaemon(port);\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n }\n return;\n }\n\n if (cmd0 === 'stop') {\n const stopped = stopDaemon();\n console.log(stopped ? 'Daemon stopped' : 'Daemon is not running');\n return;\n }\n\n if (cmd0 === 'status') {\n const info = readDaemonInfo();\n if (!info) {\n console.log('Daemon is not running');\n process.exit(1);\n }\n try {\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n } catch {\n console.log('Daemon is not running (stale info)');\n process.exit(1);\n }\n return;\n }\n\n // ── All other commands require the daemon ──\n await ensureDaemon();\n\n // ── Component inspection ──\n if (cmd0 === 'get' && cmd1 === 'tree') {\n const depth = flags['depth']\n ? parseInt(flags['depth'] as string, 10)\n : undefined;\n const ipcCmd: IpcCommand = { type: 'get-tree', depth };\n const resp = await sendCommand(ipcCmd);\n if (resp.ok) {\n console.log(formatTree(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'get' && cmd1 === 'component') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const id: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof id === 'number' && isNaN(id)) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'get-component', id });\n if (resp.ok) {\n console.log(formatComponent(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'find') {\n const name = command[1];\n if (!name) {\n console.error('Usage: devtools find <name> [--exact]');\n process.exit(1);\n }\n const exact = flags['exact'] === true;\n const resp = await sendCommand({ type: 'find', name, exact });\n if (resp.ok) {\n console.log(formatSearchResults(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'count') {\n const resp = await sendCommand({ type: 'count' });\n if (resp.ok) {\n console.log(formatCount(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n // ── Profiling ──\n if (cmd0 === 'profile' && cmd1 === 'start') {\n const name = command[2];\n const resp = await sendCommand({ type: 'profile-start', name });\n if (resp.ok) {\n console.log(resp.data);\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'stop') {\n const resp = await sendCommand({ type: 'profile-stop' });\n if (resp.ok) {\n console.log(formatProfileSummary(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'report') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const componentId: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof componentId === 'number' && isNaN(componentId)) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'profile-report', componentId });\n if (resp.ok) {\n console.log(formatProfileReport(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'slow') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-slow', limit });\n if (resp.ok) {\n console.log(formatSlowest(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'rerenders') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-rerenders', limit });\n if (resp.ok) {\n console.log(formatRerenders(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'commit') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const index = parseInt(raw.replace(/^#/, ''), 10);\n if (isNaN(index)) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-commit', index, limit });\n if (resp.ok) {\n console.log(formatCommitDetail(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'timeline') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-timeline', limit });\n if (resp.ok) {\n console.log(formatTimeline(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n console.error(`Unknown command: ${command.join(' ')}`);\n console.log(usage());\n process.exit(1);\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/daemon-client.ts","../src/formatters.ts","../src/cli.ts"],"sourcesContent":["import net from 'node:net';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { IpcCommand, IpcResponse, DaemonInfo } 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 stateDir = DEFAULT_STATE_DIR;\n\nexport function setStateDir(dir: string): void {\n stateDir = dir;\n}\n\nfunction getDaemonInfoPath(): string {\n return path.join(stateDir, 'daemon.json');\n}\n\nfunction getSocketPath(): string {\n return path.join(stateDir, 'daemon.sock');\n}\n\nexport function readDaemonInfo(): DaemonInfo | null {\n try {\n const raw = fs.readFileSync(getDaemonInfoPath(), 'utf-8');\n return JSON.parse(raw) as DaemonInfo;\n } catch {\n return null;\n }\n}\n\nfunction isDaemonAlive(info: DaemonInfo): boolean {\n try {\n // Signal 0 doesn't kill, just checks if process exists\n process.kill(info.pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureDaemon(port?: number): Promise<void> {\n const info = readDaemonInfo();\n if (info && isDaemonAlive(info)) {\n return; // Already running\n }\n\n // Clean up stale files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n try {\n fs.unlinkSync(getSocketPath());\n } catch {\n // ignore\n }\n\n // Start daemon as detached child process\n const daemonScript = path.join(\n path.dirname(new URL(import.meta.url).pathname),\n 'daemon.js',\n );\n\n const args = [];\n if (port) args.push(`--port=${port}`);\n if (stateDir !== DEFAULT_STATE_DIR) args.push(`--state-dir=${stateDir}`);\n\n const child = spawn(process.execPath, [daemonScript, ...args], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n\n // Wait for daemon to be ready (up to 5 seconds)\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 100));\n try {\n await sendCommand({ type: 'ping' });\n return;\n } catch {\n // not ready yet\n }\n }\n throw new Error('Daemon failed to start within 5 seconds');\n}\n\nexport function stopDaemon(): boolean {\n const info = readDaemonInfo();\n if (!info) return false;\n\n try {\n process.kill(info.pid, 'SIGTERM');\n // Clean up files\n try {\n fs.unlinkSync(getDaemonInfoPath());\n } catch {\n // ignore\n }\n return true;\n } catch {\n return false;\n }\n}\n\nexport function sendCommand(cmd: IpcCommand): Promise<IpcResponse> {\n return new Promise((resolve, reject) => {\n const socketPath = getSocketPath();\n\n const conn = net.createConnection(socketPath, () => {\n conn.write(JSON.stringify(cmd) + '\\n');\n });\n\n let buffer = '';\n conn.on('data', (chunk) => {\n buffer += chunk.toString();\n const newlineIdx = buffer.indexOf('\\n');\n if (newlineIdx !== -1) {\n const line = buffer.slice(0, newlineIdx);\n conn.end();\n try {\n resolve(JSON.parse(line) as IpcResponse);\n } catch {\n reject(new Error('Invalid response from daemon'));\n }\n }\n });\n\n conn.on('error', (err) => {\n reject(new Error(`Cannot connect to daemon: ${err.message}`));\n });\n\n // Timeout after 30 seconds\n conn.setTimeout(30_000, () => {\n conn.destroy();\n reject(new Error('Command timed out'));\n });\n });\n}\n","import type {\n StatusInfo,\n InspectedElement,\n ComponentRenderReport,\n} from './types.js';\nimport type { TreeNode } from './component-tree.js';\nimport type { ProfileSummary, TimelineEntry, CommitDetail } from './profiler.js';\n\n// ── Abbreviations for component types ──\nconst TYPE_ABBREV: Record<string, string> = {\n function: 'fn',\n class: 'cls',\n host: 'host',\n memo: 'memo',\n forwardRef: 'fRef',\n profiler: 'prof',\n suspense: 'susp',\n context: 'ctx',\n other: '?',\n};\n\nfunction typeTag(type: string): string {\n return TYPE_ABBREV[type] || type;\n}\n\n/**\n * Format a consistent component reference: `@c1 [fn] Name` or `@c1 [fn] Name key=x`\n */\nfunction formatRef(opts: { label?: string; type?: string; name: string; key?: string | null }): string {\n const ref = opts.label || '?';\n const tag = typeTag(opts.type || 'other');\n let s = `${ref} [${tag}] ${opts.name}`;\n if (opts.key) s += ` key=${opts.key}`;\n return s;\n}\n\n// ── Tree connector characters ──\nconst PIPE = '│ ';\nconst TEE = '├─ ';\nconst ELBOW = '└─ ';\nconst SPACE = ' ';\n\nexport function formatTree(nodes: TreeNode[]): string {\n if (nodes.length === 0) return 'No components (is a React app connected?)';\n\n // Build tree structure from the flat list\n const childrenMap = new Map<number | null, TreeNode[]>();\n for (const node of nodes) {\n const parentId = node.parentId;\n let siblings = childrenMap.get(parentId);\n if (!siblings) {\n siblings = [];\n childrenMap.set(parentId, siblings);\n }\n siblings.push(node);\n }\n\n const lines: string[] = [];\n\n function walk(nodeId: number, prefix: string, isLast: boolean, isRoot: boolean): void {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const connector = isRoot ? '' : isLast ? ELBOW : TEE;\n const line = formatRef({ label: node.label, type: node.type, name: node.displayName, key: node.key });\n\n lines.push(`${prefix}${connector}${line}`);\n\n const children = childrenMap.get(node.id) || [];\n const childPrefix = isRoot ? '' : prefix + (isLast ? SPACE : PIPE);\n\n for (let i = 0; i < children.length; i++) {\n walk(children[i].id, childPrefix, i === children.length - 1, false);\n }\n }\n\n // Find root nodes\n const roots = childrenMap.get(null) || [];\n for (let i = 0; i < roots.length; i++) {\n walk(roots[i].id, '', i === roots.length - 1, true);\n }\n\n return lines.join('\\n');\n}\n\nexport function formatComponent(element: InspectedElement, label?: string): string {\n const lines: string[] = [];\n\n lines.push(formatRef({ label: label || `#${element.id}`, type: element.type, name: element.displayName, key: element.key }));\n\n // Props\n if (element.props && Object.keys(element.props).length > 0) {\n lines.push('props:');\n for (const [key, value] of Object.entries(element.props)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // State\n if (element.state && Object.keys(element.state).length > 0) {\n lines.push('state:');\n for (const [key, value] of Object.entries(element.state)) {\n lines.push(` ${key}: ${formatCompactValue(value) ?? 'undefined'}`);\n }\n }\n\n // Hooks\n if (element.hooks && element.hooks.length > 0) {\n lines.push('hooks:');\n for (const h of element.hooks) {\n const val = formatCompactValue(h.value);\n lines.push(val !== undefined ? ` ${h.name}: ${val}` : ` ${h.name}`);\n if (h.subHooks && h.subHooks.length > 0) {\n for (const sh of h.subHooks) {\n const sval = formatCompactValue(sh.value);\n lines.push(sval !== undefined ? ` ${sh.name}: ${sval}` : ` ${sh.name}`);\n }\n }\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatSearchResults(results: TreeNode[]): string {\n if (results.length === 0) return 'No components found';\n\n return results\n .map((n) => formatRef({ label: n.label, type: n.type, name: n.displayName, key: n.key }))\n .join('\\n');\n}\n\nexport function formatCount(counts: Record<string, number>): string {\n const total = Object.values(counts).reduce((a, b) => a + b, 0);\n const parts = Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([type, count]) => `${typeTag(type)}:${count}`)\n .join(' ');\n return `${total} components (${parts})`;\n}\n\nexport function formatStatus(status: StatusInfo): string {\n const lines: string[] = [];\n lines.push(`Daemon: running (port ${status.port})`);\n lines.push(\n `Apps: ${status.connectedApps} connected, ${status.componentCount} components`,\n );\n if (status.profilingActive) {\n lines.push('Profiling: active');\n }\n const upSec = Math.round(status.uptime / 1000);\n lines.push(`Uptime: ${upSec}s`);\n return lines.join('\\n');\n}\n\nexport function formatProfileSummary(summary: ProfileSummary): string {\n const lines: string[] = [];\n const durSec = (summary.duration / 1000).toFixed(1);\n lines.push(\n `Profile \"${summary.name}\" (${durSec}s, ${summary.commitCount} commits)`,\n );\n\n if (summary.componentRenderCounts.length > 0) {\n lines.push('');\n lines.push('Top renders:');\n for (const c of summary.componentRenderCounts.slice(0, 10)) {\n const ref = formatRef({ label: c.label, type: c.type, name: c.displayName || `#${c.id}` });\n lines.push(` ${ref} ${c.count} renders`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function formatProfileReport(report: ComponentRenderReport, label?: string): string {\n const lines: string[] = [];\n lines.push(formatRef({ label: label || report.label || `#${report.id}`, type: report.type, name: report.displayName }));\n lines.push(\n `renders:${report.renderCount} avg:${report.avgDuration.toFixed(1)}ms max:${report.maxDuration.toFixed(1)}ms total:${report.totalDuration.toFixed(1)}ms`,\n );\n if (report.causes.length > 0) {\n lines.push(`causes: ${report.causes.join(', ')}`);\n }\n return lines.join('\\n');\n}\n\nexport function formatSlowest(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Slowest (by avg render time):'];\n for (const r of reports) {\n const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });\n const causes = r.causes.length > 0 ? r.causes.join(', ') : '?';\n lines.push(\n ` ${ref} avg:${r.avgDuration.toFixed(1)}ms max:${r.maxDuration.toFixed(1)}ms renders:${r.renderCount} causes:${causes}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatRerenders(reports: ComponentRenderReport[]): string {\n if (reports.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Most re-renders:'];\n for (const r of reports) {\n const ref = formatRef({ label: r.label, type: r.type, name: r.displayName });\n const causes = r.causes.length > 0 ? r.causes.join(', ') : '?';\n lines.push(\n ` ${ref} ${r.renderCount} renders causes:${causes}`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatTimeline(entries: TimelineEntry[]): string {\n if (entries.length === 0) return 'No profiling data';\n\n const lines: string[] = ['Commit timeline:'];\n for (const e of entries) {\n lines.push(\n ` #${e.index} ${e.duration.toFixed(1)}ms ${e.componentCount} components`,\n );\n }\n return lines.join('\\n');\n}\n\nexport function formatCommitDetail(detail: CommitDetail): string {\n const lines: string[] = [];\n lines.push(`Commit #${detail.index} ${detail.duration.toFixed(1)}ms ${detail.totalComponents} components`);\n lines.push('');\n for (const c of detail.components) {\n const ref = formatRef({ label: c.label, type: c.type, name: c.displayName });\n const causes = c.causes.length > 0 ? c.causes.join(', ') : '?';\n lines.push(` ${ref} self:${c.selfDuration.toFixed(1)}ms total:${c.actualDuration.toFixed(1)}ms causes:${causes}`);\n }\n const hidden = detail.totalComponents - detail.components.length;\n if (hidden > 0) {\n lines.push(` ... ${hidden} more (use --limit to show more)`);\n }\n return lines.join('\\n');\n}\n\n// ── Helpers ──\n\nfunction formatCompactValue(val: unknown): string | undefined {\n if (val === undefined) return undefined;\n if (val === null) return 'null';\n if (typeof val === 'function') return 'ƒ';\n if (typeof val === 'string') return `\"${val}\"`;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n try {\n const s = JSON.stringify(val, replacer, 0);\n if (s && s.length > 60) return s.slice(0, 57) + '...';\n return s || String(val);\n } catch {\n return String(val);\n }\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'function') return 'ƒ';\n return value;\n}\n","import {\n ensureDaemon,\n sendCommand,\n stopDaemon,\n readDaemonInfo,\n setStateDir,\n} from './daemon-client.js';\nimport {\n formatTree,\n formatComponent,\n formatSearchResults,\n formatCount,\n formatStatus,\n formatProfileSummary,\n formatProfileReport,\n formatSlowest,\n formatRerenders,\n formatTimeline,\n formatCommitDetail,\n} from './formatters.js';\nimport type { IpcCommand } from './types.js';\n\nfunction usage(): string {\n return `Usage: devtools <command> [options]\n\nSetup:\n init [--dry-run] Auto-configure your React app\n\nDaemon:\n start [--port 8097] Start daemon\n stop Stop daemon\n status Show daemon status\n\nComponents:\n get tree [--depth N] Component hierarchy\n get component <@c1 | id> Props, state, hooks\n find <name> [--exact] Search by display name\n count Component count by type\n\nProfiling:\n profile start [name] Start profiling session\n profile stop Stop profiling, collect data\n profile report <@c1 | id> Render report for component\n profile slow [--limit N] Slowest components (by avg)\n profile rerenders [--limit N] Most re-rendered components\n profile timeline [--limit N] Commit timeline\n profile commit <N | #N> [--limit N] Detail for specific commit`;\n}\n\nfunction parseArgs(argv: string[]): {\n command: string[];\n flags: Record<string, string | boolean>;\n} {\n const command: string[] = [];\n const flags: Record<string, string | boolean> = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const key = arg.slice(2);\n const eqIdx = key.indexOf('=');\n if (eqIdx !== -1) {\n flags[key.slice(0, eqIdx)] = key.slice(eqIdx + 1);\n } else {\n // Check if next arg is a value\n const next = argv[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n }\n } else {\n command.push(arg);\n }\n }\n return { command, flags };\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv.slice(2));\n\n if (command.length === 0 || flags['help']) {\n console.log(usage());\n process.exit(0);\n }\n\n // Configure custom state directory (for test isolation)\n if (typeof flags['state-dir'] === 'string') {\n setStateDir(flags['state-dir']);\n }\n\n const cmd0 = command[0];\n const cmd1 = command[1];\n\n try {\n // ── Init ──\n if (cmd0 === 'init') {\n const { runInit } = await import('./init.js');\n await runInit(process.cwd(), flags['dry-run'] === true);\n return;\n }\n\n // ── Daemon management ──\n if (cmd0 === 'start') {\n const port = flags['port'] ? parseInt(flags['port'] as string, 10) : undefined;\n await ensureDaemon(port);\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n }\n return;\n }\n\n if (cmd0 === 'stop') {\n const stopped = stopDaemon();\n console.log(stopped ? 'Daemon stopped' : 'Daemon is not running');\n return;\n }\n\n if (cmd0 === 'status') {\n const info = readDaemonInfo();\n if (!info) {\n console.log('Daemon is not running');\n process.exit(1);\n }\n try {\n const resp = await sendCommand({ type: 'status' });\n if (resp.ok) {\n console.log(formatStatus(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n } catch {\n console.log('Daemon is not running (stale info)');\n process.exit(1);\n }\n return;\n }\n\n // ── All other commands require the daemon ──\n await ensureDaemon();\n\n // ── Component inspection ──\n if (cmd0 === 'get' && cmd1 === 'tree') {\n const depth = flags['depth']\n ? parseInt(flags['depth'] as string, 10)\n : undefined;\n const ipcCmd: IpcCommand = { type: 'get-tree', depth };\n const resp = await sendCommand(ipcCmd);\n if (resp.ok) {\n console.log(formatTree(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'get' && cmd1 === 'component') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const id: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof id === 'number' && isNaN(id)) {\n console.error('Usage: devtools get component <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'get-component', id });\n if (resp.ok) {\n console.log(formatComponent(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'find') {\n const name = command[1];\n if (!name) {\n console.error('Usage: devtools find <name> [--exact]');\n process.exit(1);\n }\n const exact = flags['exact'] === true;\n const resp = await sendCommand({ type: 'find', name, exact });\n if (resp.ok) {\n console.log(formatSearchResults(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'count') {\n const resp = await sendCommand({ type: 'count' });\n if (resp.ok) {\n console.log(formatCount(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n // ── Profiling ──\n if (cmd0 === 'profile' && cmd1 === 'start') {\n const name = command[2];\n const resp = await sendCommand({ type: 'profile-start', name });\n if (resp.ok) {\n console.log(resp.data);\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'stop') {\n const resp = await sendCommand({ type: 'profile-stop' });\n if (resp.ok) {\n console.log(formatProfileSummary(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'report') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const componentId: number | string = raw.startsWith('@') ? raw : parseInt(raw, 10);\n if (typeof componentId === 'number' && isNaN(componentId)) {\n console.error('Usage: devtools profile report <@c1 | id>');\n process.exit(1);\n }\n const resp = await sendCommand({ type: 'profile-report', componentId });\n if (resp.ok) {\n console.log(formatProfileReport(resp.data as any, resp.label));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'slow') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-slow', limit });\n if (resp.ok) {\n console.log(formatSlowest(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'rerenders') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-rerenders', limit });\n if (resp.ok) {\n console.log(formatRerenders(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'commit') {\n const raw = command[2];\n if (!raw) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const index = parseInt(raw.replace(/^#/, ''), 10);\n if (isNaN(index)) {\n console.error('Usage: devtools profile commit <N | #N>');\n process.exit(1);\n }\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-commit', index, limit });\n if (resp.ok) {\n console.log(formatCommitDetail(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n if (cmd0 === 'profile' && cmd1 === 'timeline') {\n const limit = flags['limit'] ? parseInt(flags['limit'] as string, 10) : undefined;\n const resp = await sendCommand({ type: 'profile-timeline', limit });\n if (resp.ok) {\n console.log(formatTimeline(resp.data as any));\n } else {\n console.error(resp.error);\n process.exit(1);\n }\n return;\n }\n\n console.error(`Unknown command: ${command.join(' ')}`);\n console.log(usage());\n process.exit(1);\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
|
package/dist/daemon.js
CHANGED
|
@@ -613,6 +613,13 @@ var ComponentTree = class {
|
|
|
613
613
|
removeRoot(rootId) {
|
|
614
614
|
this.removeNode(rootId);
|
|
615
615
|
}
|
|
616
|
+
/**
|
|
617
|
+
* Look up the @cN label for a given component ID.
|
|
618
|
+
* Returns undefined if the ID has no label assigned.
|
|
619
|
+
*/
|
|
620
|
+
getLabel(id) {
|
|
621
|
+
return this.idToLabel.get(id);
|
|
622
|
+
}
|
|
616
623
|
/**
|
|
617
624
|
* Resolve a label like "@c3" to a real node ID.
|
|
618
625
|
* Returns undefined if label not found.
|
|
@@ -883,6 +890,15 @@ function getSocketPath() {
|
|
|
883
890
|
function getDaemonInfoPath() {
|
|
884
891
|
return path.join(STATE_DIR, "daemon.json");
|
|
885
892
|
}
|
|
893
|
+
function enrichWithLabels(items, tree) {
|
|
894
|
+
for (const item of items) {
|
|
895
|
+
if (!item.label) item.label = tree.getLabel(item.id);
|
|
896
|
+
if (!item.type) {
|
|
897
|
+
const node = tree.getNode(item.id);
|
|
898
|
+
if (node) item.type = node.type;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
886
902
|
var Daemon = class {
|
|
887
903
|
ipcServer = null;
|
|
888
904
|
bridge;
|
|
@@ -1011,6 +1027,7 @@ var Daemon = class {
|
|
|
1011
1027
|
if (!session) {
|
|
1012
1028
|
return { ok: false, error: "No active profiling session" };
|
|
1013
1029
|
}
|
|
1030
|
+
enrichWithLabels(session.componentRenderCounts, this.tree);
|
|
1014
1031
|
return { ok: true, data: session };
|
|
1015
1032
|
}
|
|
1016
1033
|
case "profile-report": {
|
|
@@ -1025,19 +1042,20 @@ var Daemon = class {
|
|
|
1025
1042
|
error: `No profiling data for component ${cmd.componentId}`
|
|
1026
1043
|
};
|
|
1027
1044
|
}
|
|
1045
|
+
enrichWithLabels([report], this.tree);
|
|
1028
1046
|
const compLabel = typeof cmd.componentId === "string" ? cmd.componentId : void 0;
|
|
1029
1047
|
return { ok: true, data: report, label: compLabel };
|
|
1030
1048
|
}
|
|
1031
|
-
case "profile-slow":
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
case "profile-rerenders":
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1049
|
+
case "profile-slow": {
|
|
1050
|
+
const slowest = this.profiler.getSlowest(this.tree, cmd.limit);
|
|
1051
|
+
enrichWithLabels(slowest, this.tree);
|
|
1052
|
+
return { ok: true, data: slowest };
|
|
1053
|
+
}
|
|
1054
|
+
case "profile-rerenders": {
|
|
1055
|
+
const rerenders = this.profiler.getMostRerenders(this.tree, cmd.limit);
|
|
1056
|
+
enrichWithLabels(rerenders, this.tree);
|
|
1057
|
+
return { ok: true, data: rerenders };
|
|
1058
|
+
}
|
|
1041
1059
|
case "profile-timeline":
|
|
1042
1060
|
return {
|
|
1043
1061
|
ok: true,
|
|
@@ -1048,6 +1066,7 @@ var Daemon = class {
|
|
|
1048
1066
|
if (!detail) {
|
|
1049
1067
|
return { ok: false, error: `Commit #${cmd.index} not found` };
|
|
1050
1068
|
}
|
|
1069
|
+
enrichWithLabels(detail.components, this.tree);
|
|
1051
1070
|
return { ok: true, data: detail };
|
|
1052
1071
|
}
|
|
1053
1072
|
default:
|
package/dist/daemon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon.ts","../src/devtools-bridge.ts","../src/component-tree.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\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 const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\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).then((response) => {\n conn.write(JSON.stringify(response) + '\\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): 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 } satisfies StatusInfo,\n };\n\n case 'get-tree':\n return {\n ok: true,\n data: this.tree.getTree(cmd.depth),\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 the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: element, 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 '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 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 const compLabel = typeof cmd.componentId === 'string' ? cmd.componentId : undefined;\n return { ok: true, data: report, label: compLabel };\n }\n\n case 'profile-slow':\n return {\n ok: true,\n data: this.profiler.getSlowest(this.tree, cmd.limit),\n };\n\n case 'profile-rerenders':\n return {\n ok: true,\n data: this.profiler.getMostRerenders(this.tree, cmd.limit),\n };\n\n case 'profile-timeline':\n return {\n ok: true,\n data: this.profiler.getTimeline(cmd.limit),\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 return { ok: true, data: detail };\n }\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 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 } 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\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 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\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 }\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[] | 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(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 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\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}\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 };\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 };\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 // id, numErrors, numWarnings\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 result.push({\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\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 getRootIds(): number[] {\n return [...this.roots];\n }\n\n removeRoot(rootId: number): void {\n this.removeNode(rootId);\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 */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return id;\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 return {\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 }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.js';\n\nexport interface ProfileSummary {\n name: string;\n duration: number;\n commitCount: number;\n componentRenderCounts: { id: number; displayName: string; count: number }[];\n}\n\nexport interface TimelineEntry {\n index: number;\n timestamp: number;\n duration: number;\n componentCount: 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 actualDuration: number;\n selfDuration: number;\n causes: RenderCause[];\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 };\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 || this.session.stoppedAt !== null) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n operations?: unknown[];\n }>;\n // Alternative flat format\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData);\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);\n }\n }\n }\n\n private processCommitData(commitData: {\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }): void {\n const commit: ProfilingCommit = {\n timestamp: commitData.timestamp || Date.now(),\n duration: commitData.duration || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations, commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations, commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n if (commitData.changeDescriptions) {\n const entries =\n commitData.changeDescriptions instanceof Map\n ? commitData.changeDescriptions.entries()\n : commitData.changeDescriptions[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\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 }\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 };\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 });\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): TimelineEntry[] {\n if (!this.session) return [];\n\n const entries = 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 (limit) return entries.slice(0, limit);\n return entries;\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"],"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/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 const info: DaemonInfo = {\n pid: process.pid,\n port: this.port,\n socketPath,\n startedAt: this.startedAt,\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).then((response) => {\n conn.write(JSON.stringify(response) + '\\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): 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 } satisfies StatusInfo,\n };\n\n case 'get-tree':\n return {\n ok: true,\n data: this.tree.getTree(cmd.depth),\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 the label if the request used one\n const label = typeof cmd.id === 'string' ? cmd.id : undefined;\n return { ok: true, data: element, 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 '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),\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 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 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 } 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\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 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\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 }\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[] | 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(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 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\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}\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 };\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 };\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 // id, numErrors, numWarnings\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 result.push({\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\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 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 */\n resolveId(id: number | string): number | undefined {\n if (typeof id === 'number') return id;\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 return {\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 }\n}\n","import type {\n ProfilingSession,\n ProfilingCommit,\n ChangeDescription,\n ComponentRenderReport,\n RenderCause,\n} from './types.js';\nimport type { ComponentTree } from './component-tree.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 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 }>;\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 };\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 || this.session.stoppedAt !== null) return;\n\n const data = payload as {\n dataForRoots?: Array<{\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n operations?: unknown[];\n }>;\n // Alternative flat format\n commitData?: Array<{\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }>;\n };\n\n // Handle nested format (dataForRoots)\n const roots = data?.dataForRoots;\n if (roots) {\n for (const root of roots) {\n if (root.commitData) {\n for (const commitData of root.commitData) {\n this.processCommitData(commitData);\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);\n }\n }\n }\n\n private processCommitData(commitData: {\n changeDescriptions?: Array<[number, unknown]> | Map<number, unknown>;\n duration?: number;\n fiberActualDurations?: Array<[number, number]> | number[];\n fiberSelfDurations?: Array<[number, number]> | number[];\n timestamp?: number;\n }): void {\n const commit: ProfilingCommit = {\n timestamp: commitData.timestamp || Date.now(),\n duration: commitData.duration || 0,\n fiberActualDurations: new Map(),\n fiberSelfDurations: new Map(),\n changeDescriptions: new Map(),\n };\n\n // Parse fiber durations (can be [id, duration, id, duration, ...] or [[id, duration], ...])\n if (commitData.fiberActualDurations) {\n parseDurations(commitData.fiberActualDurations, commit.fiberActualDurations);\n }\n if (commitData.fiberSelfDurations) {\n parseDurations(commitData.fiberSelfDurations, commit.fiberSelfDurations);\n }\n\n // Parse change descriptions\n if (commitData.changeDescriptions) {\n const entries =\n commitData.changeDescriptions instanceof Map\n ? commitData.changeDescriptions.entries()\n : commitData.changeDescriptions[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\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 }\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 };\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 });\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): TimelineEntry[] {\n if (!this.session) return [];\n\n const entries = 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 (limit) return entries.slice(0, limit);\n return entries;\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"],"mappings":"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","names":["port","pending","port"]}
|
package/package.json
CHANGED
|
@@ -56,12 +56,12 @@ agent-react-devtools profile commit 3 # Detail for commit #3
|
|
|
56
56
|
Every component gets a stable label like `@c1`, `@c2`. Use these to reference components in follow-up commands:
|
|
57
57
|
|
|
58
58
|
```
|
|
59
|
-
@c1 [fn]
|
|
60
|
-
├─ @c2 [fn]
|
|
61
|
-
├─ @c3 [fn]
|
|
62
|
-
│ ├─ @c4 [fn]
|
|
63
|
-
│ └─ @c5 [fn]
|
|
64
|
-
└─ @c6 [host]
|
|
59
|
+
@c1 [fn] App
|
|
60
|
+
├─ @c2 [fn] Header
|
|
61
|
+
├─ @c3 [fn] TodoList
|
|
62
|
+
│ ├─ @c4 [fn] TodoItem key=1
|
|
63
|
+
│ └─ @c5 [fn] TodoItem key=2
|
|
64
|
+
└─ @c6 [host] div
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Type abbreviations: `fn` = function, `cls` = class, `host` = DOM element, `memo` = React.memo, `fRef` = forwardRef, `susp` = Suspense, `ctx` = context.
|
|
@@ -69,7 +69,7 @@ Type abbreviations: `fn` = function, `cls` = class, `host` = DOM element, `memo`
|
|
|
69
69
|
### Inspected Component
|
|
70
70
|
|
|
71
71
|
```
|
|
72
|
-
@c3 [fn]
|
|
72
|
+
@c3 [fn] TodoList
|
|
73
73
|
props:
|
|
74
74
|
items: [{"id":1,"text":"Buy milk"},{"id":2,"text":"Walk dog"}]
|
|
75
75
|
onDelete: ƒ
|
|
@@ -87,8 +87,8 @@ hooks:
|
|
|
87
87
|
|
|
88
88
|
```
|
|
89
89
|
Slowest (by avg render time):
|
|
90
|
-
ExpensiveList
|
|
91
|
-
TodoItem
|
|
90
|
+
@c3 [fn] ExpensiveList avg:12.3ms max:18.1ms renders:47 causes:props-changed
|
|
91
|
+
@c4 [fn] TodoItem avg:2.1ms max:5.0ms renders:94 causes:parent-rendered, props-changed
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Render causes: `props-changed`, `state-changed`, `hooks-changed`, `parent-rendered`, `force-update`, `first-mount`.
|
|
@@ -58,12 +58,12 @@ Stop profiling and collect data from React. Shows a summary with duration, commi
|
|
|
58
58
|
### `agent-react-devtools profile slow [--limit N]`
|
|
59
59
|
Rank components by average render duration (slowest first). Default limit: 10.
|
|
60
60
|
|
|
61
|
-
Output columns: component name, avg duration, max duration, render count,
|
|
61
|
+
Output columns: label, type tag, component name, avg duration, max duration, render count, all causes.
|
|
62
62
|
|
|
63
63
|
### `agent-react-devtools profile rerenders [--limit N]`
|
|
64
64
|
Rank components by render count (most re-renders first). Default limit: 10.
|
|
65
65
|
|
|
66
|
-
Output columns: component name, render count,
|
|
66
|
+
Output columns: label, type tag, component name, render count, all causes.
|
|
67
67
|
|
|
68
68
|
### `agent-react-devtools profile report <@cN | id>`
|
|
69
69
|
Detailed render report for a single component: render count, avg/max/total duration, all render causes.
|