mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
feat: Add additional params to get_heapsnapshot_edges (#2561)
Add additional parameters to get_heapsnapshot_edges for filtering and sorting the emitted edges. By default this tool now does not print edges to primitive values like true/false/null/undefined anymore unless explicitly enabled. Edges are also sorted by retained size by default.
This commit is contained in:
@@ -544,8 +544,11 @@ in the DevTools Elements panel (if any).
|
||||
|
||||
- **filePath** (string) **(required)**: A path to a .heapsnapshot file to read.
|
||||
- **nodeId** (number) **(required)**: The node ID to get outgoing edges for.
|
||||
- **excludePrimitives** (boolean) _(optional)_: Whether to exclude primitive target nodes. Default is true.
|
||||
- **minRetainedSize** (number) _(optional)_: Minimum retained size in bytes for target nodes.
|
||||
- **pageIdx** (number) _(optional)_: The page index for pagination.
|
||||
- **pageSize** (number) _(optional)_: The page size for pagination.
|
||||
- **sortBy** (enum: "retainedSize", "selfSize", "name") _(optional)_: Sort order for edges. Default is retainedSize.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@ export interface HeapSnapshotDetailedClassDiff extends HeapSnapshotClassDiff {
|
||||
export type DuplicateStringGroup =
|
||||
DevTools.HeapSnapshotModel.HeapSnapshotModel.DuplicateStringGroup;
|
||||
|
||||
export type HeapQueryOptions =
|
||||
DevTools.HeapSnapshotModel.HeapSnapshotModel.HeapQueryOptions;
|
||||
|
||||
export type HeapEdgesQueryOptions =
|
||||
DevTools.HeapSnapshotModel.HeapSnapshotModel.HeapEdgesQueryOptions;
|
||||
|
||||
export class HeapSnapshotManager {
|
||||
#snapshotIdGenerator = createIdGenerator();
|
||||
#snapshots = new Map<
|
||||
@@ -241,13 +247,14 @@ export class HeapSnapshotManager {
|
||||
async getEdges(
|
||||
filePath: string,
|
||||
nodeId: number,
|
||||
options?: HeapEdgesQueryOptions,
|
||||
): Promise<DevTools.HeapSnapshotModel.HeapSnapshotModel.ItemsRange> {
|
||||
const snapshot = await this.getSnapshot(filePath);
|
||||
const nodeIndex = await snapshot.nodeIndexForId(nodeId);
|
||||
if (nodeIndex === undefined) {
|
||||
throw new Error(`Node with ID ${nodeId} not found`);
|
||||
}
|
||||
const provider = snapshot.createEdgesProvider(nodeIndex);
|
||||
const provider = snapshot.createEdgesProvider(nodeIndex, options);
|
||||
return await provider.serializeItemsRange(0, Infinity);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -16,6 +16,7 @@ import type {
|
||||
HeapSnapshotClassDiff,
|
||||
HeapSnapshotDetailedClassDiff,
|
||||
DuplicateStringGroup,
|
||||
HeapEdgesQueryOptions,
|
||||
} from './HeapSnapshotManager.js';
|
||||
import {McpPage} from './McpPage.js';
|
||||
import {type UncaughtError} from './PageCollector.js';
|
||||
@@ -869,8 +870,9 @@ export class McpContext implements Context {
|
||||
async getHeapSnapshotEdges(
|
||||
filePath: string,
|
||||
nodeId: number,
|
||||
options?: HeapEdgesQueryOptions,
|
||||
): Promise<DevTools.HeapSnapshotModel.HeapSnapshotModel.ItemsRange> {
|
||||
return await this.#heapSnapshotManager.getEdges(filePath, nodeId);
|
||||
return await this.#heapSnapshotManager.getEdges(filePath, nodeId, options);
|
||||
}
|
||||
|
||||
async getHeapSnapshotClassDiffs(
|
||||
|
||||
@@ -500,6 +500,26 @@ export const commands: Commands = {
|
||||
description: 'The node ID to get outgoing edges for.',
|
||||
required: true,
|
||||
},
|
||||
sortBy: {
|
||||
name: 'sortBy',
|
||||
type: 'string',
|
||||
description: 'Sort order for edges. Default is retainedSize.',
|
||||
required: false,
|
||||
enum: ['retainedSize', 'selfSize', 'name'],
|
||||
},
|
||||
minRetainedSize: {
|
||||
name: 'minRetainedSize',
|
||||
type: 'number',
|
||||
description: 'Minimum retained size in bytes for target nodes.',
|
||||
required: false,
|
||||
},
|
||||
excludePrimitives: {
|
||||
name: 'excludePrimitives',
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Whether to exclude primitive target nodes. Default is true.',
|
||||
required: false,
|
||||
},
|
||||
pageIdx: {
|
||||
name: 'pageIdx',
|
||||
type: 'number',
|
||||
|
||||
@@ -824,6 +824,18 @@
|
||||
{
|
||||
"name": "page_size",
|
||||
"argType": "number"
|
||||
},
|
||||
{
|
||||
"name": "sort_by",
|
||||
"argType": "string"
|
||||
},
|
||||
{
|
||||
"name": "min_retained_size",
|
||||
"argType": "number"
|
||||
},
|
||||
{
|
||||
"name": "exclude_primitives",
|
||||
"argType": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
HeapSnapshotClassDiff,
|
||||
HeapSnapshotDetailedClassDiff,
|
||||
DuplicateStringGroup,
|
||||
HeapEdgesQueryOptions,
|
||||
} from '../HeapSnapshotManager.js';
|
||||
import type {McpPage} from '../McpPage.js';
|
||||
import {zod} from '../third_party/index.js';
|
||||
@@ -290,6 +291,7 @@ export type Context = Readonly<{
|
||||
getHeapSnapshotEdges(
|
||||
filePath: string,
|
||||
nodeId: number,
|
||||
options?: HeapEdgesQueryOptions,
|
||||
): Promise<DevTools.HeapSnapshotModel.HeapSnapshotModel.ItemsRange>;
|
||||
getHeapSnapshotClassDiffs(
|
||||
baseFilePath: string,
|
||||
|
||||
@@ -276,6 +276,18 @@ export const getHeapSnapshotEdges = defineTool({
|
||||
schema: {
|
||||
filePath: zod.string().describe('A path to a .heapsnapshot file to read.'),
|
||||
nodeId: zod.number().describe('The node ID to get outgoing edges for.'),
|
||||
sortBy: zod
|
||||
.enum(['retainedSize', 'selfSize', 'name'])
|
||||
.optional()
|
||||
.describe('Sort order for edges. Default is retainedSize.'),
|
||||
minRetainedSize: zod
|
||||
.number()
|
||||
.optional()
|
||||
.describe('Minimum retained size in bytes for target nodes.'),
|
||||
excludePrimitives: zod
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe('Whether to exclude primitive target nodes. Default is true.'),
|
||||
pageIdx: zod.number().optional().describe('The page index for pagination.'),
|
||||
pageSize: zod.number().optional().describe('The page size for pagination.'),
|
||||
},
|
||||
@@ -283,6 +295,11 @@ export const getHeapSnapshotEdges = defineTool({
|
||||
const edges = await context.getHeapSnapshotEdges(
|
||||
request.params.filePath,
|
||||
request.params.nodeId,
|
||||
{
|
||||
sortBy: request.params.sortBy ?? 'retainedSize',
|
||||
minRetainedSize: request.params.minRetainedSize,
|
||||
excludePrimitives: request.params.excludePrimitives ?? true,
|
||||
},
|
||||
);
|
||||
|
||||
response.setHeapSnapshotNodes(edges, {
|
||||
|
||||
@@ -296,8 +296,8 @@ value,count,totalSelfSize,totalRetainedSize,truncated,nodeIds
|
||||
exports[`memory > get_heapsnapshot_edges > with pagination 1`] = `
|
||||
## Heap Snapshot Data
|
||||
name,type,nodeId,nodeName,selfSize,retainedSize
|
||||
map,internal,25577,system / Map,0.0 kB,0.7 kB
|
||||
constructor,property,25575,String,0.1 kB,0.4 kB
|
||||
anchor,property,29295,anchor,0.0 kB,0.0 kB
|
||||
Showing 1-2 of 56 (Page 1 of 28).
|
||||
Next page: 1
|
||||
`;
|
||||
@@ -305,7 +305,10 @@ Next page: 1
|
||||
exports[`memory > get_heapsnapshot_edges > with valid nodeId 1`] = `
|
||||
## Heap Snapshot Data
|
||||
name,type,nodeId,nodeName,selfSize,retainedSize
|
||||
map,internal,25577,system / Map,0.0 kB,0.7 kB
|
||||
constructor,property,25575,String,0.1 kB,0.4 kB
|
||||
__proto__,property,25329,{constructor, __defineGetter__, __defineSetter__, …, get __proto__, set __proto__, toLocaleString},0.1 kB,0.3 kB
|
||||
<symbol Symbol.iterator>,property,29391,[Symbol.iterator],0.0 kB,0.0 kB
|
||||
anchor,property,29295,anchor,0.0 kB,0.0 kB
|
||||
at,property,29297,at,0.0 kB,0.0 kB
|
||||
big,property,29299,big,0.0 kB,0.0 kB
|
||||
@@ -316,9 +319,9 @@ charCodeAt,property,29307,charCodeAt,0.0 kB,0.0 kB
|
||||
codePointAt,property,29309,codePointAt,0.0 kB,0.0 kB
|
||||
concat,property,29311,concat,0.0 kB,0.0 kB
|
||||
endsWith,property,29313,endsWith,0.0 kB,0.0 kB
|
||||
fixed,property,29319,fixed,0.0 kB,0.0 kB
|
||||
fontcolor,property,29315,fontcolor,0.0 kB,0.0 kB
|
||||
fontsize,property,29317,fontsize,0.0 kB,0.0 kB
|
||||
fixed,property,29319,fixed,0.0 kB,0.0 kB
|
||||
includes,property,29321,includes,0.0 kB,0.0 kB
|
||||
indexOf,property,29323,indexOf,0.0 kB,0.0 kB
|
||||
isWellFormed,property,29325,isWellFormed,0.0 kB,0.0 kB
|
||||
@@ -338,28 +341,25 @@ search,property,29351,search,0.0 kB,0.0 kB
|
||||
slice,property,29353,slice,0.0 kB,0.0 kB
|
||||
small,property,29355,small,0.0 kB,0.0 kB
|
||||
split,property,29357,split,0.0 kB,0.0 kB
|
||||
startsWith,property,29369,startsWith,0.0 kB,0.0 kB
|
||||
strike,property,29359,strike,0.0 kB,0.0 kB
|
||||
sub,property,29361,sub,0.0 kB,0.0 kB
|
||||
substr,property,29363,substr,0.0 kB,0.0 kB
|
||||
substring,property,29365,substring,0.0 kB,0.0 kB
|
||||
sup,property,29367,sup,0.0 kB,0.0 kB
|
||||
startsWith,property,29369,startsWith,0.0 kB,0.0 kB
|
||||
toString,property,29371,toString,0.0 kB,0.0 kB
|
||||
toWellFormed,property,29373,toWellFormed,0.0 kB,0.0 kB
|
||||
trim,property,29375,trim,0.0 kB,0.0 kB
|
||||
trimStart,property,29377,trimStart,0.0 kB,0.0 kB
|
||||
trimLeft,property,29377,trimStart,0.0 kB,0.0 kB
|
||||
trimEnd,property,29379,trimEnd,0.0 kB,0.0 kB
|
||||
trimRight,property,29379,trimEnd,0.0 kB,0.0 kB
|
||||
toLocaleLowerCase,property,29381,toLocaleLowerCase,0.0 kB,0.0 kB
|
||||
toLocaleUpperCase,property,29383,toLocaleUpperCase,0.0 kB,0.0 kB
|
||||
toLowerCase,property,29385,toLowerCase,0.0 kB,0.0 kB
|
||||
toString,property,29371,toString,0.0 kB,0.0 kB
|
||||
toUpperCase,property,29387,toUpperCase,0.0 kB,0.0 kB
|
||||
toWellFormed,property,29373,toWellFormed,0.0 kB,0.0 kB
|
||||
trim,property,29375,trim,0.0 kB,0.0 kB
|
||||
trimEnd,property,29379,trimEnd,0.0 kB,0.0 kB
|
||||
trimLeft,property,29377,trimStart,0.0 kB,0.0 kB
|
||||
trimRight,property,29379,trimEnd,0.0 kB,0.0 kB
|
||||
trimStart,property,29377,trimStart,0.0 kB,0.0 kB
|
||||
valueOf,property,29389,valueOf,0.0 kB,0.0 kB
|
||||
<symbol Symbol.iterator>,property,29391,[Symbol.iterator],0.0 kB,0.0 kB
|
||||
__proto__,property,25329,{constructor, __defineGetter__, __defineSetter__, …, get __proto__, set __proto__, toLocaleString},0.1 kB,0.3 kB
|
||||
properties,internal,29393,system / PropertyArray,0.0 kB,0.0 kB
|
||||
map,internal,25577,system / Map,0.0 kB,0.7 kB
|
||||
1,hidden,71,,0.0 kB,0.0 kB
|
||||
Showing 1-56 of 56 (Page 1 of 1).
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user