Skip to content

Commit b5e635f

Browse files
fix
1 parent bfae00a commit b5e635f

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

src/McpResponse.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,7 @@ Call ${handleDialog.name} to handle it before continuing.`);
912912
}
913913
const aggregates = this.#heapSnapshotOptions.aggregates;
914914
if (aggregates) {
915-
const entries = Object.entries(aggregates);
916-
const sortedEntries = entries.sort((a, b) => b[1].self - a[1].self);
915+
const sortedEntries = HeapSnapshotFormatter.sort(aggregates);
917916

918917
const paginationData = this.#dataWithPagination(
919918
sortedEntries,

src/formatters/HeapSnapshotFormatter.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,15 @@ export class HeapSnapshotFormatter {
5353
retainedSize: info.maxRet,
5454
}));
5555
}
56+
57+
static sort(
58+
aggregates: Record<
59+
string,
60+
DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo
61+
>,
62+
): Array<
63+
[string, DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo]
64+
> {
65+
return Object.entries(aggregates).sort((a, b) => b[1].self - a[1].self);
66+
}
5667
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import assert from 'node:assert';
8+
import {describe, it} from 'node:test';
9+
10+
import {HeapSnapshotFormatter} from '../../src/formatters/HeapSnapshotFormatter.js';
11+
import type {DevTools} from '../../src/third_party/index.js';
12+
13+
describe('HeapSnapshotFormatter', () => {
14+
const mockAggregates: Record<
15+
string,
16+
DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo
17+
> = {
18+
ObjectA: {
19+
name: 'ObjectA',
20+
count: 10,
21+
self: 100,
22+
maxRet: 1000,
23+
distance: 1,
24+
idxs: [],
25+
} as unknown as DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo,
26+
ObjectB: {
27+
name: 'ObjectB',
28+
count: 5,
29+
self: 50,
30+
maxRet: 500,
31+
distance: 2,
32+
idxs: [],
33+
} as unknown as DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo,
34+
};
35+
36+
describe('toString', () => {
37+
it('formats data as CSV and sorts by self size', () => {
38+
const formatter = new HeapSnapshotFormatter(mockAggregates);
39+
const result = formatter.toString();
40+
const expected = [
41+
'className,count,selfSize,maxRetainedSize',
42+
'"ObjectA",10,100,1000',
43+
'"ObjectB",5,50,500',
44+
].join('\n');
45+
assert.strictEqual(result, expected);
46+
});
47+
});
48+
49+
describe('toJSON', () => {
50+
it('returns structured data sorted by self size', () => {
51+
const formatter = new HeapSnapshotFormatter(mockAggregates);
52+
const result = formatter.toJSON();
53+
assert.deepStrictEqual(result, [
54+
{
55+
className: 'ObjectA',
56+
count: 10,
57+
selfSize: 100,
58+
retainedSize: 1000,
59+
},
60+
{
61+
className: 'ObjectB',
62+
count: 5,
63+
selfSize: 50,
64+
retainedSize: 500,
65+
},
66+
]);
67+
});
68+
});
69+
70+
describe('sort', () => {
71+
it('sorts aggregates by self size descending', () => {
72+
const unsortedAggregates: Record<
73+
string,
74+
DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo
75+
> = {
76+
ObjectB: {
77+
name: 'ObjectB',
78+
self: 50,
79+
} as unknown as DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo,
80+
ObjectA: {
81+
name: 'ObjectA',
82+
self: 100,
83+
} as unknown as DevTools.HeapSnapshotModel.HeapSnapshotModel.AggregatedInfo,
84+
};
85+
86+
const result = HeapSnapshotFormatter.sort(unsortedAggregates);
87+
assert.strictEqual(result.length, 2);
88+
assert.strictEqual(result[0][0], 'ObjectA');
89+
assert.strictEqual(result[1][0], 'ObjectB');
90+
});
91+
});
92+
});

0 commit comments

Comments
 (0)