Fix division by zero in RenderTable intrinsic size methods When RenderTable has 0 columns and intrinsic size methods are called with non-zero width constraints, the _computeColumnWidths() method attempts to divide by zero at line 1140: final double delta = (minWidthConstraint - tableWidth) / columns; This adds early return checks for empty tables (rows * columns == 0) to four intrinsic size methods: - computeMinIntrinsicWidth - computeMaxIntrinsicWidth - computeMinIntrinsicHeight - computeMaxIntrinsicHeight This matches the pattern already used by other methods that call _computeColumnWidths(), such as computeDryLayout (line 1274), performLayout (line 1318), and paint (line 1461). All four methods now return 0.0 for empty tables, which is consistent with the behavior of other dimension methods. Added comprehensive test coverage to verify that empty tables handle intrinsic size queries without crashing.
diff --git a/packages/flutter/lib/src/rendering/table.dart b/packages/flutter/lib/src/rendering/table.dart index 5cafdd2..03626d0 100644 --- a/packages/flutter/lib/src/rendering/table.dart +++ b/packages/flutter/lib/src/rendering/table.dart
@@ -960,8 +960,11 @@ @override double computeMinIntrinsicWidth(double height) { assert(_children.length == rows * columns); - var totalMinWidth = 0.0; - for (var x = 0; x < columns; x += 1) { + if (rows * columns == 0) { + return 0.0; + } + double totalMinWidth = 0.0; + for (int x = 0; x < columns; x += 1) { final TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth; final Iterable<RenderBox> columnCells = column(x); totalMinWidth += columnWidth.minIntrinsicWidth(columnCells, double.infinity); @@ -972,8 +975,11 @@ @override double computeMaxIntrinsicWidth(double height) { assert(_children.length == rows * columns); - var totalMaxWidth = 0.0; - for (var x = 0; x < columns; x += 1) { + if (rows * columns == 0) { + return 0.0; + } + double totalMaxWidth = 0.0; + for (int x = 0; x < columns; x += 1) { final TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth; final Iterable<RenderBox> columnCells = column(x); totalMaxWidth += columnWidth.maxIntrinsicWidth(columnCells, double.infinity); @@ -986,6 +992,9 @@ // winner of the 2016 world's most expensive intrinsic dimension function award // honorable mention, most likely to improve if taught about memoization award assert(_children.length == rows * columns); + if (rows * columns == 0) { + return 0.0; + } final List<double> widths = _computeColumnWidths(BoxConstraints.tightForFinite(width: width)); var rowTop = 0.0; for (var y = 0; y < rows; y += 1) { @@ -1004,6 +1013,10 @@ @override double computeMaxIntrinsicHeight(double width) { + assert(_children.length == rows * columns); + if (rows * columns == 0) { + return 0.0; + } return getMinIntrinsicHeight(width); }
diff --git a/packages/flutter/test/rendering/table_test.dart b/packages/flutter/test/rendering/table_test.dart index c8d4ef8..fa52a66 100644 --- a/packages/flutter/test/rendering/table_test.dart +++ b/packages/flutter/test/rendering/table_test.dart
@@ -401,4 +401,27 @@ expect(table.size, equals(size)); expect(table.defaultVerticalAlignment, TableCellVerticalAlignment.intrinsicHeight); }); + + test('Empty table intrinsic dimensions should not crash', () { + // Test that empty tables (0 rows x 0 columns) don't cause division by zero + // when intrinsic size methods are called with non-zero constraints. + // See: https://github.com/flutter/flutter/issues/XXXXX + final RenderTable table = RenderTable(textDirection: TextDirection.ltr); + + // Verify table is empty + expect(table.rows, equals(0)); + expect(table.columns, equals(0)); + + // These should all return 0.0 without crashing (previously caused division by zero) + expect(table.getMinIntrinsicWidth(100.0), equals(0.0)); + expect(table.getMaxIntrinsicWidth(100.0), equals(0.0)); + expect(table.getMinIntrinsicHeight(100.0), equals(0.0)); + expect(table.getMaxIntrinsicHeight(100.0), equals(0.0)); + + // Also test with infinite constraints + expect(table.getMinIntrinsicWidth(double.infinity), equals(0.0)); + expect(table.getMaxIntrinsicWidth(double.infinity), equals(0.0)); + expect(table.getMinIntrinsicHeight(double.infinity), equals(0.0)); + expect(table.getMaxIntrinsicHeight(double.infinity), equals(0.0)); + }); }