@petukhovart/agent-view 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +31 -3
- package/dist/cdp/transport.d.ts.map +1 -1
- package/dist/cdp/transport.js +15 -0
- package/dist/cdp/transport.js.map +1 -1
- package/dist/cdp/types.d.ts +5 -0
- package/dist/cdp/types.d.ts.map +1 -1
- package/dist/cdp/types.js.map +1 -1
- package/dist/cli/commands/heap.d.ts +14 -0
- package/dist/cli/commands/heap.d.ts.map +1 -0
- package/dist/cli/commands/heap.js +25 -0
- package/dist/cli/commands/heap.js.map +1 -0
- package/dist/cli/index.js +62 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/inspectors/coverage/index.d.ts.map +1 -1
- package/dist/inspectors/coverage/index.js +2 -5
- package/dist/inspectors/coverage/index.js.map +1 -1
- package/dist/inspectors/format.d.ts +6 -0
- package/dist/inspectors/format.d.ts.map +1 -0
- package/dist/inspectors/format.js +17 -0
- package/dist/inspectors/format.js.map +1 -0
- package/dist/inspectors/heap/index.d.ts +65 -0
- package/dist/inspectors/heap/index.d.ts.map +1 -0
- package/dist/inspectors/heap/index.js +269 -0
- package/dist/inspectors/heap/index.js.map +1 -0
- package/dist/server/server.d.ts +12 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +80 -7
- package/dist/server/server.js.map +1 -1
- package/package.json +2 -1
- package/skills/verify/SKILL.md +2 -0
- package/skills/verify/references/commands.md +26 -0
- package/skills/verify/references/memory-leaks.md +94 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { capLines } from '../format.js';
|
|
1
2
|
/**
|
|
2
3
|
* Scripts nobody reviews: the runtime's own bundles, third-party packages, and
|
|
3
4
|
* code with no URL at all (`eval`, `new Function`) which cannot be pointed at in
|
|
@@ -56,10 +57,6 @@ export function formatCoverage(scripts, options = {}) {
|
|
|
56
57
|
if (hidden > 0 && !options.all) {
|
|
57
58
|
lines.push(`… ${hidden} script${hidden === 1 ? '' : 's'} hidden (--all to show)`);
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
const text = maxLines !== undefined && lines.length > maxLines
|
|
61
|
-
? [...lines.slice(0, maxLines - 1), `… ${lines.length - (maxLines - 1)} more lines`].join('\n')
|
|
62
|
-
: lines.join('\n');
|
|
63
|
-
return { text, functions: total };
|
|
60
|
+
return { text: capLines(lines, options.maxLines), functions: total };
|
|
64
61
|
}
|
|
65
62
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/inspectors/coverage/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/inspectors/coverage/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Output helpers every inspector prints with, so the tails and units read the same across commands. */
|
|
2
|
+
/** Keep the first `maxLines - 1` lines and say how many were cut. */
|
|
3
|
+
export declare function capLines(lines: string[], maxLines?: number): string;
|
|
4
|
+
/** `512 B`, `12.3 KB`, `1.5 MB`; negatives keep their sign, for deltas. */
|
|
5
|
+
export declare function formatBytes(n: number): string;
|
|
6
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/inspectors/format.ts"],"names":[],"mappings":"AAAA,wGAAwG;AAExG,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Output helpers every inspector prints with, so the tails and units read the same across commands. */
|
|
2
|
+
/** Keep the first `maxLines - 1` lines and say how many were cut. */
|
|
3
|
+
export function capLines(lines, maxLines) {
|
|
4
|
+
if (maxLines === undefined || lines.length <= maxLines)
|
|
5
|
+
return lines.join('\n');
|
|
6
|
+
return [...lines.slice(0, maxLines - 1), `… ${lines.length - (maxLines - 1)} more lines`].join('\n');
|
|
7
|
+
}
|
|
8
|
+
/** `512 B`, `12.3 KB`, `1.5 MB`; negatives keep their sign, for deltas. */
|
|
9
|
+
export function formatBytes(n) {
|
|
10
|
+
const abs = Math.abs(n);
|
|
11
|
+
if (abs < 1024)
|
|
12
|
+
return `${n} B`;
|
|
13
|
+
if (abs < 1024 * 1024)
|
|
14
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
15
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/inspectors/format.ts"],"names":[],"mappings":"AAAA,wGAAwG;AAExG,qEAAqE;AACrE,MAAM,UAAU,QAAQ,CAAC,KAAe,EAAE,QAAiB;IACzD,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/E,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACtG,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACvB,IAAI,GAAG,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAA;IAC/B,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IAC3D,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V8 `.heapsnapshot` reader, sized for one question: what grew between two
|
|
3
|
+
* snapshots, and who holds it. Retained sizes and dominator trees are out of
|
|
4
|
+
* scope on purpose — they are where the DevTools engine spends its 5,000 lines,
|
|
5
|
+
* and "which class grew, is it detached DOM, what retains it" needs neither.
|
|
6
|
+
*/
|
|
7
|
+
export type ClassStat = {
|
|
8
|
+
count: number;
|
|
9
|
+
size: number;
|
|
10
|
+
};
|
|
11
|
+
export type HeapSnapshot = {
|
|
12
|
+
name: string;
|
|
13
|
+
target: string;
|
|
14
|
+
nodeCount: number;
|
|
15
|
+
totalSize: number;
|
|
16
|
+
classes: Map<string, ClassStat>;
|
|
17
|
+
/** Retainer lookup needs the graph itself; kept as typed arrays, not as parsed JSON. */
|
|
18
|
+
graph: HeapGraph;
|
|
19
|
+
};
|
|
20
|
+
type HeapGraph = {
|
|
21
|
+
nodes: Uint32Array;
|
|
22
|
+
edges: Uint32Array;
|
|
23
|
+
strings: string[];
|
|
24
|
+
nodeFieldCount: number;
|
|
25
|
+
edgeFieldCount: number;
|
|
26
|
+
nodeTypes: string[];
|
|
27
|
+
edgeTypes: string[];
|
|
28
|
+
/** Field offsets inside one node / edge record. `detachedness` is -1 on V8 builds that predate it. */
|
|
29
|
+
nType: number;
|
|
30
|
+
nName: number;
|
|
31
|
+
nSize: number;
|
|
32
|
+
nEdgeCount: number;
|
|
33
|
+
nDetached: number;
|
|
34
|
+
eType: number;
|
|
35
|
+
eName: number;
|
|
36
|
+
eTo: number;
|
|
37
|
+
};
|
|
38
|
+
export declare function parseHeapSnapshot(json: string, name: string, target: string): HeapSnapshot;
|
|
39
|
+
export declare function isDetachedClass(cls: string): boolean;
|
|
40
|
+
export type ListOptions = {
|
|
41
|
+
filter?: string;
|
|
42
|
+
detached?: boolean;
|
|
43
|
+
maxLines?: number;
|
|
44
|
+
};
|
|
45
|
+
export declare function describeSnapshot(s: HeapSnapshot): string;
|
|
46
|
+
export declare function formatSummary(s: HeapSnapshot, options?: ListOptions): string;
|
|
47
|
+
export declare function formatDiff(a: HeapSnapshot, b: HeapSnapshot, options?: ListOptions): string;
|
|
48
|
+
/**
|
|
49
|
+
* Who holds the instances of `cls`: one row per `<retainer class> <edge>`,
|
|
50
|
+
* counting distinct instances, not edges. Element indices collapse to `[]`, so
|
|
51
|
+
* an array of 200 leaks is one row. Weak edges keep nothing alive and are
|
|
52
|
+
* skipped.
|
|
53
|
+
*
|
|
54
|
+
* V8 reports an array's items twice, once from the `Array` and once from its
|
|
55
|
+
* `(object elements)` backing store, and a Map's entries only from the store.
|
|
56
|
+
* Stores name nothing a developer wrote, so an edge from one is attributed to
|
|
57
|
+
* the store's owner; counting instances makes the duplicate collapse. Still one
|
|
58
|
+
* named hop, no path to a GC root: the first owner is usually the map, list or
|
|
59
|
+
* closure at fault. Instances holding each other (DOM sibling links, list
|
|
60
|
+
* nodes) are left out: they never explain why the group is alive.
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatRetainers(s: HeapSnapshot, cls: string, options?: Pick<ListOptions, 'maxLines'>): string;
|
|
63
|
+
export declare function formatList(snapshots: HeapSnapshot[]): string;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/inspectors/heap/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC/B,wFAAwF;IACxF,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,WAAW,CAAA;IAClB,KAAK,EAAE,WAAW,CAAA;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,sGAAsG;IACtG,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAKD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAmC1F;AAgCD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAQD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAIxD;AAUD,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAQhF;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAwB9F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAM,GAAG,MAAM,CAyDjH;AAyCD,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,CAG5D"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V8 `.heapsnapshot` reader, sized for one question: what grew between two
|
|
3
|
+
* snapshots, and who holds it. Retained sizes and dominator trees are out of
|
|
4
|
+
* scope on purpose — they are where the DevTools engine spends its 5,000 lines,
|
|
5
|
+
* and "which class grew, is it detached DOM, what retains it" needs neither.
|
|
6
|
+
*/
|
|
7
|
+
import { capLines, formatBytes as fmtBytes } from '../format.js';
|
|
8
|
+
const DETACHED = 2;
|
|
9
|
+
const DETACHED_PREFIX = 'Detached ';
|
|
10
|
+
export function parseHeapSnapshot(json, name, target) {
|
|
11
|
+
const raw = JSON.parse(json);
|
|
12
|
+
const { meta } = raw.snapshot;
|
|
13
|
+
const graph = {
|
|
14
|
+
nodes: Uint32Array.from(raw.nodes),
|
|
15
|
+
edges: Uint32Array.from(raw.edges),
|
|
16
|
+
strings: raw.strings,
|
|
17
|
+
nodeFieldCount: meta.node_fields.length,
|
|
18
|
+
edgeFieldCount: meta.edge_fields.length,
|
|
19
|
+
nodeTypes: meta.node_types[0],
|
|
20
|
+
edgeTypes: meta.edge_types[0],
|
|
21
|
+
nType: meta.node_fields.indexOf('type'),
|
|
22
|
+
nName: meta.node_fields.indexOf('name'),
|
|
23
|
+
nSize: meta.node_fields.indexOf('self_size'),
|
|
24
|
+
nEdgeCount: meta.node_fields.indexOf('edge_count'),
|
|
25
|
+
nDetached: meta.node_fields.indexOf('detachedness'),
|
|
26
|
+
eType: meta.edge_fields.indexOf('type'),
|
|
27
|
+
eName: meta.edge_fields.indexOf('name_or_index'),
|
|
28
|
+
eTo: meta.edge_fields.indexOf('to_node'),
|
|
29
|
+
};
|
|
30
|
+
const classes = new Map();
|
|
31
|
+
let totalSize = 0;
|
|
32
|
+
const nodeCount = graph.nodes.length / graph.nodeFieldCount;
|
|
33
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
34
|
+
const off = i * graph.nodeFieldCount;
|
|
35
|
+
const cls = classOf(graph, off);
|
|
36
|
+
const size = graph.nodes[off + graph.nSize];
|
|
37
|
+
const stat = classes.get(cls) ?? { count: 0, size: 0 };
|
|
38
|
+
stat.count++;
|
|
39
|
+
stat.size += size;
|
|
40
|
+
classes.set(cls, stat);
|
|
41
|
+
totalSize += size;
|
|
42
|
+
}
|
|
43
|
+
return { name, target, nodeCount, totalSize, classes, graph };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* DevTools' grouping, minus its per-constructor heuristics: objects and DOM
|
|
47
|
+
* wrappers by name, everything else by V8 type. A detached DOM wrapper becomes
|
|
48
|
+
* its own class so it stands out in a diff instead of hiding among the
|
|
49
|
+
* attached ones.
|
|
50
|
+
*/
|
|
51
|
+
function classOf(g, off) {
|
|
52
|
+
const type = g.nodeTypes[g.nodes[off + g.nType]];
|
|
53
|
+
const name = g.strings[g.nodes[off + g.nName]];
|
|
54
|
+
switch (type) {
|
|
55
|
+
case 'object':
|
|
56
|
+
case 'native':
|
|
57
|
+
case 'synthetic': {
|
|
58
|
+
if (name.startsWith(DETACHED_PREFIX))
|
|
59
|
+
return name;
|
|
60
|
+
const detached = g.nDetached >= 0 && g.nodes[off + g.nDetached] === DETACHED;
|
|
61
|
+
return detached ? DETACHED_PREFIX + name : name;
|
|
62
|
+
}
|
|
63
|
+
case 'closure':
|
|
64
|
+
return name ? `${name}()` : '(closure)';
|
|
65
|
+
case 'string':
|
|
66
|
+
case 'concatenated string':
|
|
67
|
+
case 'sliced string':
|
|
68
|
+
return '(string)';
|
|
69
|
+
case 'code':
|
|
70
|
+
return '(compiled code)';
|
|
71
|
+
default:
|
|
72
|
+
return `(${type})`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function isDetachedClass(cls) {
|
|
76
|
+
return cls.startsWith(DETACHED_PREFIX);
|
|
77
|
+
}
|
|
78
|
+
function keep(cls, options) {
|
|
79
|
+
if (options.detached && !isDetachedClass(cls))
|
|
80
|
+
return false;
|
|
81
|
+
if (options.filter && !cls.toLowerCase().includes(options.filter.toLowerCase()))
|
|
82
|
+
return false;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
export function describeSnapshot(s) {
|
|
86
|
+
const detached = sumDetached(s.classes);
|
|
87
|
+
return `Snapshot "${s.name}" (${s.target}): ${fmtCount(s.nodeCount)} nodes, ${fmtBytes(s.totalSize)}, `
|
|
88
|
+
+ `${fmtCount(detached.count)} detached DOM nodes (${fmtBytes(detached.size)})`;
|
|
89
|
+
}
|
|
90
|
+
function sumDetached(classes) {
|
|
91
|
+
const out = { count: 0, size: 0 };
|
|
92
|
+
for (const [cls, stat] of classes) {
|
|
93
|
+
if (isDetachedClass(cls)) {
|
|
94
|
+
out.count += stat.count;
|
|
95
|
+
out.size += stat.size;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
export function formatSummary(s, options = {}) {
|
|
101
|
+
const rows = [...s.classes].filter(([cls]) => keep(cls, options)).sort((a, b) => b[1].size - a[1].size);
|
|
102
|
+
if (rows.length === 0)
|
|
103
|
+
return `(no class matching ${describeFilter(options)} in "${s.name}")`;
|
|
104
|
+
const lines = [describeSnapshot(s), ...table(['class', 'count', 'size'], rows.map(([cls, st]) => [cls, fmtCount(st.count), fmtBytes(st.size)]))];
|
|
105
|
+
return capLines(lines, options.maxLines);
|
|
106
|
+
}
|
|
107
|
+
export function formatDiff(a, b, options = {}) {
|
|
108
|
+
const rows = [];
|
|
109
|
+
for (const cls of new Set([...a.classes.keys(), ...b.classes.keys()])) {
|
|
110
|
+
if (!keep(cls, options))
|
|
111
|
+
continue;
|
|
112
|
+
const before = a.classes.get(cls) ?? { count: 0, size: 0 };
|
|
113
|
+
const after = b.classes.get(cls) ?? { count: 0, size: 0 };
|
|
114
|
+
const dCount = after.count - before.count;
|
|
115
|
+
const dSize = after.size - before.size;
|
|
116
|
+
if (dCount !== 0 || dSize !== 0)
|
|
117
|
+
rows.push([cls, dCount, dSize, after.count]);
|
|
118
|
+
}
|
|
119
|
+
if (rows.length === 0) {
|
|
120
|
+
const scope = options.filter || options.detached ? ` matching ${describeFilter(options)}` : '';
|
|
121
|
+
return `(no class changed between "${a.name}" and "${b.name}"${scope})`;
|
|
122
|
+
}
|
|
123
|
+
rows.sort((x, y) => y[2] - x[2] || y[1] - x[1]);
|
|
124
|
+
const dA = sumDetached(a.classes);
|
|
125
|
+
const dB = sumDetached(b.classes);
|
|
126
|
+
const head = `${a.name} → ${b.name} (${b.target}): ${fmtDelta(b.nodeCount - a.nodeCount)} nodes, `
|
|
127
|
+
+ `${fmtDelta(b.totalSize - a.totalSize, true)}, detached ${fmtDelta(dB.count - dA.count)} (${fmtDelta(dB.size - dA.size, true)})`;
|
|
128
|
+
const lines = [head, ...table(['class', 'Δcount', 'Δsize', 'count'], rows.map(([cls, dc, ds, c]) => [cls, fmtDelta(dc), fmtDelta(ds, true), fmtCount(c)]))];
|
|
129
|
+
return capLines(lines, options.maxLines);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Who holds the instances of `cls`: one row per `<retainer class> <edge>`,
|
|
133
|
+
* counting distinct instances, not edges. Element indices collapse to `[]`, so
|
|
134
|
+
* an array of 200 leaks is one row. Weak edges keep nothing alive and are
|
|
135
|
+
* skipped.
|
|
136
|
+
*
|
|
137
|
+
* V8 reports an array's items twice, once from the `Array` and once from its
|
|
138
|
+
* `(object elements)` backing store, and a Map's entries only from the store.
|
|
139
|
+
* Stores name nothing a developer wrote, so an edge from one is attributed to
|
|
140
|
+
* the store's owner; counting instances makes the duplicate collapse. Still one
|
|
141
|
+
* named hop, no path to a GC root: the first owner is usually the map, list or
|
|
142
|
+
* closure at fault. Instances holding each other (DOM sibling links, list
|
|
143
|
+
* nodes) are left out: they never explain why the group is alive.
|
|
144
|
+
*/
|
|
145
|
+
export function formatRetainers(s, cls, options = {}) {
|
|
146
|
+
const g = s.graph;
|
|
147
|
+
const nodeCount = g.nodes.length / g.nodeFieldCount;
|
|
148
|
+
const classCache = new Map();
|
|
149
|
+
const clsAt = (off) => {
|
|
150
|
+
let c = classCache.get(off);
|
|
151
|
+
if (c === undefined) {
|
|
152
|
+
c = classOf(g, off);
|
|
153
|
+
classCache.set(off, c);
|
|
154
|
+
}
|
|
155
|
+
return c;
|
|
156
|
+
};
|
|
157
|
+
const weak = g.edgeTypes.indexOf('weak');
|
|
158
|
+
const indexed = new Set([g.edgeTypes.indexOf('element'), g.edgeTypes.indexOf('hidden')]);
|
|
159
|
+
const stores = new Set([g.nodeTypes.indexOf('array'), g.nodeTypes.indexOf('hidden')]);
|
|
160
|
+
const isStore = (off) => stores.has(g.nodes[off + g.nType]);
|
|
161
|
+
const edgeName = (edgeOff) => {
|
|
162
|
+
if (indexed.has(g.edges[edgeOff + g.eType]))
|
|
163
|
+
return '[]';
|
|
164
|
+
const name = g.strings[g.edges[edgeOff + g.eName]];
|
|
165
|
+
return /^\d+$/.test(name) ? '[]' : `.${name}`;
|
|
166
|
+
};
|
|
167
|
+
const held = new Map();
|
|
168
|
+
const hold = (key, instance) => {
|
|
169
|
+
const set = held.get(key) ?? new Set();
|
|
170
|
+
set.add(instance);
|
|
171
|
+
held.set(key, set);
|
|
172
|
+
};
|
|
173
|
+
/** Store node → its edges into `cls`, awaiting the store's owner. */
|
|
174
|
+
const pending = new Map();
|
|
175
|
+
let instances = 0;
|
|
176
|
+
let edgeOff = 0;
|
|
177
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
178
|
+
const off = i * g.nodeFieldCount;
|
|
179
|
+
if (clsAt(off) === cls)
|
|
180
|
+
instances++;
|
|
181
|
+
const edgeCount = g.nodes[off + g.nEdgeCount];
|
|
182
|
+
for (let e = 0; e < edgeCount; e++, edgeOff += g.edgeFieldCount) {
|
|
183
|
+
if (g.edges[edgeOff + g.eType] === weak)
|
|
184
|
+
continue;
|
|
185
|
+
const to = g.edges[edgeOff + g.eTo];
|
|
186
|
+
if (clsAt(to) !== cls || clsAt(off) === cls)
|
|
187
|
+
continue;
|
|
188
|
+
if (isStore(off)) {
|
|
189
|
+
const list = pending.get(off) ?? [];
|
|
190
|
+
list.push([edgeName(edgeOff), to]);
|
|
191
|
+
pending.set(off, list);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
hold(`${clsAt(off)} ${edgeName(edgeOff)}`, to);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
foldStores(g, pending, isStore, weak, (owner, name, to) => hold(`${clsAt(owner)} ${name}`, to));
|
|
199
|
+
if (instances === 0)
|
|
200
|
+
return `(no instances of "${cls}" in "${s.name}")`;
|
|
201
|
+
if (held.size === 0)
|
|
202
|
+
return `${cls} ×${fmtCount(instances)} in "${s.name}": no strong retainers (GC roots only)`;
|
|
203
|
+
const rows = [...held].map(([k, set]) => [k, set.size]).sort((a, b) => b[1] - a[1]);
|
|
204
|
+
const lines = [
|
|
205
|
+
`${cls} ×${fmtCount(instances)} in "${s.name}", retained by:`,
|
|
206
|
+
...table(['retainer', 'instances'], rows.map(([k, n]) => [k, fmtCount(n)])),
|
|
207
|
+
];
|
|
208
|
+
return capLines(lines, options.maxLines);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Attribute edges out of V8 stores to the nearest non-store owner. A store's
|
|
212
|
+
* owner may itself be a store (a Map's table behind its `(object elements)`),
|
|
213
|
+
* so the walk repeats, bounded so a cycle of internals cannot spin it. What is
|
|
214
|
+
* still unowned after that is reported under the store's own name: honest, if
|
|
215
|
+
* unhelpful.
|
|
216
|
+
*/
|
|
217
|
+
function foldStores(g, pending, isStore, weak, attribute) {
|
|
218
|
+
const nodeCount = g.nodes.length / g.nodeFieldCount;
|
|
219
|
+
for (let hop = 0; hop < 3 && pending.size > 0; hop++) {
|
|
220
|
+
const next = new Map();
|
|
221
|
+
let edgeOff = 0;
|
|
222
|
+
for (let i = 0; i < nodeCount; i++) {
|
|
223
|
+
const off = i * g.nodeFieldCount;
|
|
224
|
+
const edgeCount = g.nodes[off + g.nEdgeCount];
|
|
225
|
+
for (let e = 0; e < edgeCount; e++, edgeOff += g.edgeFieldCount) {
|
|
226
|
+
if (g.edges[edgeOff + g.eType] === weak)
|
|
227
|
+
continue;
|
|
228
|
+
const list = pending.get(g.edges[edgeOff + g.eTo]);
|
|
229
|
+
if (!list)
|
|
230
|
+
continue;
|
|
231
|
+
if (isStore(off)) {
|
|
232
|
+
next.set(off, [...(next.get(off) ?? []), ...list]);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
for (const [name, to] of list)
|
|
236
|
+
attribute(off, name, to);
|
|
237
|
+
}
|
|
238
|
+
pending.delete(g.edges[edgeOff + g.eTo]);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
for (const [off, list] of pending)
|
|
242
|
+
next.set(off, [...(next.get(off) ?? []), ...list]);
|
|
243
|
+
pending = next;
|
|
244
|
+
}
|
|
245
|
+
for (const [off, list] of pending)
|
|
246
|
+
for (const [name, to] of list)
|
|
247
|
+
attribute(off, name, to);
|
|
248
|
+
}
|
|
249
|
+
export function formatList(snapshots) {
|
|
250
|
+
if (snapshots.length === 0)
|
|
251
|
+
return '(no heap snapshots taken)';
|
|
252
|
+
return snapshots.map(describeSnapshot).join('\n');
|
|
253
|
+
}
|
|
254
|
+
function describeFilter(options) {
|
|
255
|
+
return options.filter ? `"${options.filter}"` : 'detached';
|
|
256
|
+
}
|
|
257
|
+
function table(header, rows) {
|
|
258
|
+
const widths = header.map((h, i) => Math.max(h.length, ...rows.map(r => r[i].length)));
|
|
259
|
+
const line = (r) => r.map((c, i) => i === 0 ? c.padEnd(widths[i]) : c.padStart(widths[i])).join(' ');
|
|
260
|
+
return [line(header), ...rows.map(line)];
|
|
261
|
+
}
|
|
262
|
+
function fmtCount(n) {
|
|
263
|
+
return n.toLocaleString('en-US');
|
|
264
|
+
}
|
|
265
|
+
function fmtDelta(n, bytes = false) {
|
|
266
|
+
const sign = n > 0 ? '+' : '';
|
|
267
|
+
return sign + (bytes ? fmtBytes(n) : fmtCount(n));
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/inspectors/heap/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export declare class AgentViewServer {
|
|
|
30
30
|
private idleTimer;
|
|
31
31
|
private sceneCache;
|
|
32
32
|
private domTextCache;
|
|
33
|
+
/** Named, insertion-ordered; dropped with the server. Raw JSON is never kept, only the parsed graph. */
|
|
34
|
+
private heapSnapshots;
|
|
33
35
|
private axTreeCache;
|
|
34
36
|
private portStates;
|
|
35
37
|
private token;
|
|
@@ -98,6 +100,16 @@ export declare class AgentViewServer {
|
|
|
98
100
|
* that *this* action did not reach the code, never that nothing can.
|
|
99
101
|
*/
|
|
100
102
|
private handleCoverage;
|
|
103
|
+
/**
|
|
104
|
+
* Memory growth between named snapshots. `take` parses the snapshot inside
|
|
105
|
+
* the server and keeps only the graph, so the multi-hundred-MB JSON never
|
|
106
|
+
* reaches the CLI. `diff` without names compares the two most recent.
|
|
107
|
+
*/
|
|
108
|
+
private handleHeap;
|
|
109
|
+
/** `s1`, `s2`, … skipping names already taken by hand. */
|
|
110
|
+
private freeHeapSnapshotName;
|
|
111
|
+
/** Named snapshot, or the most recent one. Throws the user-facing error; the dispatcher turns it into `{ ok: false }`. */
|
|
112
|
+
private pickHeapSnapshot;
|
|
101
113
|
/** Which handlers are wired to a node, and where each was declared. */
|
|
102
114
|
private handleListeners;
|
|
103
115
|
private handleWait;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAcA,OAAO,EAKL,KAAK,WAAW,EAEhB,KAAK,UAAU,EAKhB,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server/server.js
CHANGED
|
@@ -20,6 +20,8 @@ import { formatNetworkList, formatNetworkDetail } from '../inspectors/network/in
|
|
|
20
20
|
import { formatDialogStatus, describePolicy, describeArm } from '../inspectors/dialog/index.js';
|
|
21
21
|
import { formatCoverage } from '../inspectors/coverage/index.js';
|
|
22
22
|
import { formatListeners } from '../inspectors/listeners/index.js';
|
|
23
|
+
import { parseHeapSnapshot, describeSnapshot, formatSummary, formatDiff, formatRetainers, formatList } from '../inspectors/heap/index.js';
|
|
24
|
+
import { formatBytes } from '../inspectors/format.js';
|
|
23
25
|
import { buildTauriArmScript, buildTauriStatusScript, TauriShimResult } from './tauri-dialog-shim.js';
|
|
24
26
|
import { NetworkResourceType } from '../cdp/types.js';
|
|
25
27
|
import { AxTreeCache } from '../cdp/ax-cache.js';
|
|
@@ -165,6 +167,8 @@ export class AgentViewServer {
|
|
|
165
167
|
idleTimer = null;
|
|
166
168
|
sceneCache = new Map();
|
|
167
169
|
domTextCache = new Map();
|
|
170
|
+
/** Named, insertion-ordered; dropped with the server. Raw JSON is never kept, only the parsed graph. */
|
|
171
|
+
heapSnapshots = new Map();
|
|
168
172
|
axTreeCache = new AxTreeCache();
|
|
169
173
|
portStates = new Map();
|
|
170
174
|
token = '';
|
|
@@ -189,6 +193,7 @@ export class AgentViewServer {
|
|
|
189
193
|
dialog: (req) => this.handleDialog(req),
|
|
190
194
|
coverage: (req) => this.handleCoverage(req),
|
|
191
195
|
listeners: (req) => this.handleListeners(req),
|
|
196
|
+
heap: (req) => this.handleHeap(req),
|
|
192
197
|
stop: () => this.handleStop(),
|
|
193
198
|
};
|
|
194
199
|
streamingCommands = new Set(['watch']);
|
|
@@ -915,6 +920,81 @@ export class AgentViewServer {
|
|
|
915
920
|
return { ok: true, data: String(result.functions) };
|
|
916
921
|
return { ok: true, data: result.text };
|
|
917
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Memory growth between named snapshots. `take` parses the snapshot inside
|
|
925
|
+
* the server and keeps only the graph, so the multi-hundred-MB JSON never
|
|
926
|
+
* reaches the CLI. `diff` without names compares the two most recent.
|
|
927
|
+
*/
|
|
928
|
+
async handleHeap(req) {
|
|
929
|
+
const action = argStr(req.args, 'action');
|
|
930
|
+
const listOptions = () => ({
|
|
931
|
+
filter: argStr(req.args, 'filter'),
|
|
932
|
+
detached: argBool(req.args, 'detached'),
|
|
933
|
+
maxLines: argNum(req.args, 'maxLines'),
|
|
934
|
+
});
|
|
935
|
+
switch (action) {
|
|
936
|
+
case 'take': {
|
|
937
|
+
const target = await this.resolveTarget(req);
|
|
938
|
+
const conn = await this.getRuntimeSession(req, target);
|
|
939
|
+
const name = argStr(req.args, 'name') ?? this.freeHeapSnapshotName();
|
|
940
|
+
const json = await conn.takeHeapSnapshot();
|
|
941
|
+
const label = `${target.type}:${target.title || target.url}`;
|
|
942
|
+
const snapshot = parseHeapSnapshot(json, name, label);
|
|
943
|
+
// Re-taking a name moves it to the end: "most recent" is insertion order, and `diff` defaults to the last two.
|
|
944
|
+
this.heapSnapshots.delete(name);
|
|
945
|
+
this.heapSnapshots.set(name, snapshot);
|
|
946
|
+
return { ok: true, data: describeSnapshot(snapshot) };
|
|
947
|
+
}
|
|
948
|
+
case 'summary':
|
|
949
|
+
return { ok: true, data: formatSummary(this.pickHeapSnapshot(argStr(req.args, 'name')), listOptions()) };
|
|
950
|
+
case 'diff': {
|
|
951
|
+
const names = argStrArray(req.args, 'names') ?? [...this.heapSnapshots.keys()].slice(-2);
|
|
952
|
+
if (names.length < 2) {
|
|
953
|
+
return { ok: false, error: 'heap diff needs two snapshots. Run `agent-view heap take` twice, or name them: `heap diff <a> <b>`.' };
|
|
954
|
+
}
|
|
955
|
+
const [a, b] = names.map((n) => this.pickHeapSnapshot(n));
|
|
956
|
+
return { ok: true, data: formatDiff(a, b, listOptions()) };
|
|
957
|
+
}
|
|
958
|
+
case 'retainers': {
|
|
959
|
+
const cls = argStr(req.args, 'class');
|
|
960
|
+
if (!cls)
|
|
961
|
+
return { ok: false, error: 'heap retainers requires a class name, as printed by `heap diff`' };
|
|
962
|
+
const snapshot = this.pickHeapSnapshot(argStr(req.args, 'name'));
|
|
963
|
+
return { ok: true, data: formatRetainers(snapshot, cls, listOptions()) };
|
|
964
|
+
}
|
|
965
|
+
case 'list':
|
|
966
|
+
return { ok: true, data: formatList([...this.heapSnapshots.values()]) };
|
|
967
|
+
case 'clear': {
|
|
968
|
+
const n = this.heapSnapshots.size;
|
|
969
|
+
this.heapSnapshots.clear();
|
|
970
|
+
return { ok: true, data: `Dropped ${n} heap snapshot${n === 1 ? '' : 's'}` };
|
|
971
|
+
}
|
|
972
|
+
default:
|
|
973
|
+
return { ok: false, error: `Unknown heap action: ${action}` };
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
/** `s1`, `s2`, … skipping names already taken by hand. */
|
|
977
|
+
freeHeapSnapshotName() {
|
|
978
|
+
for (let i = this.heapSnapshots.size + 1;; i++) {
|
|
979
|
+
if (!this.heapSnapshots.has(`s${i}`))
|
|
980
|
+
return `s${i}`;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
/** Named snapshot, or the most recent one. Throws the user-facing error; the dispatcher turns it into `{ ok: false }`. */
|
|
984
|
+
pickHeapSnapshot(name) {
|
|
985
|
+
if (name === undefined) {
|
|
986
|
+
const last = [...this.heapSnapshots.values()].at(-1);
|
|
987
|
+
if (!last)
|
|
988
|
+
throw new Error('No heap snapshots taken. Run `agent-view heap take` first.');
|
|
989
|
+
return last;
|
|
990
|
+
}
|
|
991
|
+
const found = this.heapSnapshots.get(name);
|
|
992
|
+
if (!found) {
|
|
993
|
+
const taken = [...this.heapSnapshots.keys()].map(k => `"${k}"`).join(', ') || 'none';
|
|
994
|
+
throw new Error(`No heap snapshot named "${name}". Taken: ${taken}.`);
|
|
995
|
+
}
|
|
996
|
+
return found;
|
|
997
|
+
}
|
|
918
998
|
/** Which handlers are wired to a node, and where each was declared. */
|
|
919
999
|
async handleListeners(req) {
|
|
920
1000
|
const { targetId } = await this.resolveWindow(req);
|
|
@@ -1772,13 +1852,6 @@ function formatIdleFeed(file) {
|
|
|
1772
1852
|
'start with `agent-view logs start` — `logs tail` still reads the existing feed',
|
|
1773
1853
|
].join('\n');
|
|
1774
1854
|
}
|
|
1775
|
-
function formatBytes(bytes) {
|
|
1776
|
-
if (bytes < 1024)
|
|
1777
|
-
return `${bytes} B`;
|
|
1778
|
-
if (bytes < 1024 * 1024)
|
|
1779
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1780
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1781
|
-
}
|
|
1782
1855
|
function formatElapsed(ms) {
|
|
1783
1856
|
const total = Math.max(0, Math.round(ms / 1000));
|
|
1784
1857
|
const h = Math.floor(total / 3600);
|