diff --git a/packages/grafana-flamegraph/src/FlameGraph/dataTransform.test.ts b/packages/grafana-flamegraph/src/FlameGraph/dataTransform.test.ts index 8128544abb8..b3e62ba1efa 100644 --- a/packages/grafana-flamegraph/src/FlameGraph/dataTransform.test.ts +++ b/packages/grafana-flamegraph/src/FlameGraph/dataTransform.test.ts @@ -75,6 +75,30 @@ describe('nestedSetToLevels', () => { expect(levels[0]).toEqual([n1]); expect(levels[1]).toEqual([n2, n3, n4]); }); + + it('handles strings that collide with inherited prototype method names', () => { + const frame = createDataFrame({ + fields: [ + { name: 'level', values: [0, 1, 1, 1] }, + { name: 'value', values: [10, 5, 3, 1] }, + { name: 'label', values: ['toString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf'], type: FieldType.string }, + { name: 'self', values: [10, 5, 3, 1] }, + ], + }); + const [levels] = nestedSetToLevels(new FlameGraphDataContainer(frame, { collapsing: true })); + + const n4: LevelItem = { itemIndexes: [3], start: 8, children: [], value: 1, level: 1 }; + const n3: LevelItem = { itemIndexes: [2], start: 5, children: [], value: 3, level: 1 }; + const n2: LevelItem = { itemIndexes: [1], start: 0, children: [], value: 5, level: 1 }; + const n1: LevelItem = { itemIndexes: [0], start: 0, children: [n2, n3, n4], value: 10, level: 0 }; + + n2.parents = [n1]; + n3.parents = [n1]; + n4.parents = [n1]; + + expect(levels[0]).toEqual([n1]); + expect(levels[1]).toEqual([n2, n3, n4]); + }); }); describe('FlameGraphDataContainer', () => { diff --git a/packages/grafana-flamegraph/src/FlameGraph/dataTransform.ts b/packages/grafana-flamegraph/src/FlameGraph/dataTransform.ts index 51b41f97397..b4d545e90de 100644 --- a/packages/grafana-flamegraph/src/FlameGraph/dataTransform.ts +++ b/packages/grafana-flamegraph/src/FlameGraph/dataTransform.ts @@ -46,7 +46,7 @@ export function nestedSetToLevels( let offset = 0; let parent: LevelItem | undefined = undefined; - const uniqueLabels: Record = {}; + const uniqueLabels: Record = Object.create(null); for (let i = 0; i < container.data.length; i++) { const currentLevel = container.getLevel(i); diff --git a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx index 1ee3f172fa4..b3a1be9a3b3 100644 --- a/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx +++ b/packages/grafana-flamegraph/src/TopTable/FlameGraphTopTableContainer.tsx @@ -56,7 +56,7 @@ const FlameGraphTopTableContainer = memo( const table = useMemo(() => { // Group the data by label, we show only one row per label and sum the values // TODO: should be by filename + funcName + linenumber? - let filteredTable: { [key: string]: TableData } = {}; + let filteredTable: { [key: string]: TableData } = Object.create(null); for (let i = 0; i < data.data.length; i++) { const value = data.getValue(i); const valueRight = data.getValueRight(i);