Check if MultiChildRenderObjectElement
has an associated RO (#78854)
This commit is contained in:
parent
e007cad2cf
commit
74eb9df21a
@ -6176,6 +6176,35 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
|
||||
super.forgetChild(child);
|
||||
}
|
||||
|
||||
bool _debugCheckHasAssociatedRenderObject(Element newChild) {
|
||||
assert(() {
|
||||
if (newChild.renderObject == null) {
|
||||
FlutterError.reportError(
|
||||
FlutterErrorDetails(
|
||||
exception: FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('The children of `MultiChildRenderObjectElement` must each has an associated render object.'),
|
||||
ErrorHint(
|
||||
'This typically means that the `${newChild.widget}` or its children\n'
|
||||
'are not a subtype of `RenderObjectWidget`.'
|
||||
),
|
||||
newChild.describeElement('The following element does not have an associated render object'),
|
||||
DiagnosticsDebugCreator(DebugCreator(newChild)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Element inflateWidget(Widget newWidget, Object? newSlot) {
|
||||
final Element newChild = super.inflateWidget(newWidget, newSlot);
|
||||
assert(_debugCheckHasAssociatedRenderObject(newChild));
|
||||
return newChild;
|
||||
}
|
||||
|
||||
@override
|
||||
void mount(Element? parent, Object? newSlot) {
|
||||
super.mount(parent, newSlot);
|
||||
|
@ -1172,6 +1172,64 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - mount', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Container(),
|
||||
const _EmptyWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final dynamic exception = tester.takeException();
|
||||
expect(exception, isFlutterError);
|
||||
expect(
|
||||
exception.toString(),
|
||||
equalsIgnoringHashCodes(
|
||||
'The children of `MultiChildRenderObjectElement` must each has an associated render object.\n'
|
||||
'This typically means that the `_EmptyWidget` or its children\n'
|
||||
'are not a subtype of `RenderObjectWidget`.\n'
|
||||
'The following element does not have an associated render object:\n'
|
||||
' _EmptyWidget\n'
|
||||
'debugCreator: _EmptyWidget ← Column ← [root]'
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Can not attach a non-RenderObjectElement to the MultiChildRenderObjectElement - update', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Container(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Container(),
|
||||
const _EmptyWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final dynamic exception = tester.takeException();
|
||||
expect(exception, isFlutterError);
|
||||
expect(
|
||||
exception.toString(),
|
||||
equalsIgnoringHashCodes(
|
||||
'The children of `MultiChildRenderObjectElement` must each has an associated render object.\n'
|
||||
'This typically means that the `_EmptyWidget` or its children\n'
|
||||
'are not a subtype of `RenderObjectWidget`.\n'
|
||||
'The following element does not have an associated render object:\n'
|
||||
' _EmptyWidget\n'
|
||||
'debugCreator: _EmptyWidget ← Column ← [root]'
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Element diagnostics', (WidgetTester tester) async {
|
||||
GlobalKey key0;
|
||||
await tester.pumpWidget(Column(
|
||||
@ -1849,3 +1907,20 @@ class FakeLeafRenderObject extends RenderBox {
|
||||
class TestRenderObjectElement extends RenderObjectElement {
|
||||
TestRenderObjectElement() : super(Table());
|
||||
}
|
||||
|
||||
class _EmptyWidget extends Widget {
|
||||
const _EmptyWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Element createElement() => _EmptyElement(this);
|
||||
}
|
||||
|
||||
class _EmptyElement extends Element {
|
||||
_EmptyElement(_EmptyWidget widget) : super(widget);
|
||||
|
||||
@override
|
||||
bool get debugDoingBuild => false;
|
||||
|
||||
@override
|
||||
void performRebuild() {}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user