Prevents infinite loop in Table._computeColumnWidths (#36262)
This commit is contained in:
parent
9946f7cff9
commit
1b57006c82
@ -918,10 +918,7 @@ class RenderTable extends RenderBox {
|
||||
// columns shrinking them proportionally until we have no
|
||||
// available columns, then do the same to the non-flexible ones.
|
||||
int availableColumns = columns;
|
||||
// Handle double precision errors which causes this loop to become
|
||||
// stuck in certain configurations.
|
||||
const double minimumDeficit = precisionErrorTolerance;
|
||||
while (deficit > minimumDeficit && totalFlex > minimumDeficit) {
|
||||
while (deficit > precisionErrorTolerance && totalFlex > precisionErrorTolerance) {
|
||||
double newTotalFlex = 0.0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
if (flexes[x] != null) {
|
||||
@ -943,14 +940,14 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
totalFlex = newTotalFlex;
|
||||
}
|
||||
if (deficit > 0.0) {
|
||||
while (deficit > precisionErrorTolerance && availableColumns > 0) {
|
||||
// Now we have to take out the remaining space from the
|
||||
// columns that aren't minimum sized.
|
||||
// To make this fair, we repeatedly remove equal amounts from
|
||||
// each column, clamped to the minimum width, until we run out
|
||||
// of columns that aren't at their minWidth.
|
||||
do {
|
||||
final double delta = deficit / availableColumns;
|
||||
assert(delta != 0);
|
||||
int newAvailableColumns = 0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
final double availableDelta = widths[x] - minWidths[x];
|
||||
@ -967,7 +964,6 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
}
|
||||
availableColumns = newAvailableColumns;
|
||||
} while (deficit > 0.0 && availableColumns > 0);
|
||||
}
|
||||
}
|
||||
return widths;
|
||||
|
@ -217,4 +217,30 @@ void main() {
|
||||
pumpFrame();
|
||||
expect(table, paints..path()..path()..path()..path()..path()..path());
|
||||
});
|
||||
|
||||
test('Table flex sizing', () {
|
||||
const BoxConstraints cellConstraints =
|
||||
BoxConstraints.tightFor(width: 100, height: 100);
|
||||
final RenderTable table = RenderTable(
|
||||
textDirection: TextDirection.rtl,
|
||||
children: <List<RenderBox>>[
|
||||
List<RenderBox>.generate(
|
||||
7,
|
||||
(int _) => RenderConstrainedBox(additionalConstraints: cellConstraints),
|
||||
),
|
||||
],
|
||||
columnWidths: const <int, TableColumnWidth>{
|
||||
0: FlexColumnWidth(1.0),
|
||||
1: FlexColumnWidth(0.123),
|
||||
2: FlexColumnWidth(0.123),
|
||||
3: FlexColumnWidth(0.123),
|
||||
4: FlexColumnWidth(0.123),
|
||||
5: FlexColumnWidth(0.123),
|
||||
6: FlexColumnWidth(0.123),
|
||||
},
|
||||
);
|
||||
|
||||
layout(table, constraints: BoxConstraints.tight(const Size(800.0, 600.0)));
|
||||
expect(table.hasSize, true);
|
||||
});
|
||||
}
|
||||
|
@ -376,6 +376,36 @@ void main() {
|
||||
// If the above bug is present this test will never terminate.
|
||||
});
|
||||
|
||||
testWidgets('Calculating flex columns with small width deficit', (WidgetTester tester) async {
|
||||
const SizedBox cell = SizedBox(width: 1, height: 1);
|
||||
// If the error is present, pumpWidget() will fail due to an unsatisfied
|
||||
// assertion during the layout phase.
|
||||
await tester.pumpWidget(
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints.tight(const Size(600, 800)),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Table(
|
||||
columnWidths: const <int, TableColumnWidth>{
|
||||
0: FlexColumnWidth(1.0),
|
||||
1: FlexColumnWidth(0.123),
|
||||
2: FlexColumnWidth(0.123),
|
||||
3: FlexColumnWidth(0.123),
|
||||
4: FlexColumnWidth(0.123),
|
||||
5: FlexColumnWidth(0.123),
|
||||
6: FlexColumnWidth(0.123),
|
||||
},
|
||||
children: <TableRow>[
|
||||
TableRow(children: List<Widget>.filled(7, cell)),
|
||||
TableRow(children: List<Widget>.filled(7, cell)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(tester.takeException(), null);
|
||||
});
|
||||
|
||||
testWidgets('Table widget - repump test', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
Loading…
x
Reference in New Issue
Block a user