diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index e14d158032d07..b109c8f699f66 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -251,6 +251,35 @@ describe(' - Row grouping', () => { '', ]); }); + + // Regression test for https://github.com/mui/mui-x/issues/22310 + it('should not crash when grouping values match Object.prototype property names', () => { + render( + , + ); + + expect(getColumnValues(0)).to.deep.equal([ + 'constructor (2)', + '', + '', + '__proto__ (1)', + '', + 'toString (1)', + '', + 'hasOwnProperty (1)', + '', + ]); + }); }); describe('colDef: groupingValueGetter & valueGetter', () => { diff --git a/packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts b/packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts index 8b32c5b6c0015..36bf2ea9d75dd 100644 --- a/packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts +++ b/packages/x-data-grid-pro/src/hooks/features/treeData/treeDataReorderExecutor.ts @@ -381,7 +381,7 @@ class DropOnLeafOperation extends BaseReorderOperation { ...targetNode, type: 'group', children: [sourceNode.id], - childrenFromPath: {}, + childrenFromPath: Object.create(null), groupingField: null, isAutoGenerated: false, childrenExpanded: true, diff --git a/packages/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx index 27ef828be66ac..7e5ecc7df76b5 100644 --- a/packages/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx @@ -231,6 +231,21 @@ describe(' - Tree data', () => { 'C', ]); }); + + // Regression test for https://github.com/mui/mui-x/issues/22310 + it('should not crash when path segments match Object.prototype property names', () => { + render( + row.id} + defaultGroupingExpansionDepth={-1} + />, + ); + expect(getColumnValues(1)).to.deep.equal(['', 'constructor.leaf1', 'constructor.leaf2']); + }); }); describe('prop: defaultGroupingExpansionDepth', () => { diff --git a/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts b/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts index d597e90e7ef74..e47b57b1f9636 100644 --- a/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts +++ b/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts @@ -105,7 +105,7 @@ export const insertDataRowInTree = ({ groupingKey: key, groupingField: field, children: [], - childrenFromPath: {}, + childrenFromPath: Object.create(null), childrenExpanded: false, serverChildrenCount, }; @@ -172,7 +172,7 @@ export const insertDataRowInTree = ({ groupingKey: key, groupingField: field, children: [], - childrenFromPath: {}, + childrenFromPath: Object.create(null), childrenExpanded: false, }; @@ -207,7 +207,7 @@ export const insertDataRowInTree = ({ groupingKey: key, groupingField: field, children: [], - childrenFromPath: {}, + childrenFromPath: Object.create(null), childrenExpanded: false, }; tree[existingNodeIdWithPartialPath] = updateGroupDefaultExpansion( diff --git a/packages/x-data-grid-pro/src/utils/tree/utils.ts b/packages/x-data-grid-pro/src/utils/tree/utils.ts index 6d59f74c8d701..0000fcb798e24 100644 --- a/packages/x-data-grid-pro/src/utils/tree/utils.ts +++ b/packages/x-data-grid-pro/src/utils/tree/utils.ts @@ -125,9 +125,9 @@ export const insertNodeInTree = ( } if (groupingField == null) { - parentNode.childrenFromPath[groupingFieldName] = { - [groupingKeyName.toString()]: node.id, - }; + const newGroupingField = Object.create(null); + newGroupingField[groupingKeyName.toString()] = node.id; + parentNode.childrenFromPath[groupingFieldName] = newGroupingField; } else { groupingField[groupingKeyName.toString()] = node.id; } diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts index 5931a5ace0ee7..62d7f6670b61e 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts @@ -41,7 +41,9 @@ export const buildRootGroup = (): GridGroupNode => ({ groupingKey: null, isAutoGenerated: true, children: [], - childrenFromPath: {}, + // Prototype-less so user-supplied grouping values like `'constructor'` + // or `'__proto__'` cannot collide with `Object.prototype` properties. + childrenFromPath: Object.create(null), childrenExpanded: true, parent: null, });