Skip to content

Commit 48bb12d

Browse files
authored
Make Element tree root generic (#123352)
Make Element tree root generic
1 parent 66e6acb commit 48bb12d

File tree

19 files changed

+95
-55
lines changed

19 files changed

+95
-55
lines changed

dev/benchmarks/microbenchmarks/lib/foundation/all_elements_bench.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,19 @@ Future<void> main() async {
5656

5757
final Stopwatch watch = Stopwatch();
5858

59-
print('flutter_test allElements benchmark... (${WidgetsBinding.instance.renderViewElement})');
59+
print('flutter_test allElements benchmark... (${WidgetsBinding.instance.rootElement})');
6060
// Make sure we get enough elements to process for consistent benchmark runs
61-
int elementCount = collectAllElementsFrom(WidgetsBinding.instance.renderViewElement!, skipOffstage: false).length;
61+
int elementCount = collectAllElementsFrom(WidgetsBinding.instance.rootElement!, skipOffstage: false).length;
6262
while (elementCount < 2458) {
6363
await Future<void>.delayed(Duration.zero);
64-
elementCount = collectAllElementsFrom(WidgetsBinding.instance.renderViewElement!, skipOffstage: false).length;
64+
elementCount = collectAllElementsFrom(WidgetsBinding.instance.rootElement!, skipOffstage: false).length;
6565
}
6666
print('element count: $elementCount');
6767

6868
watch.start();
6969
for (int i = 0; i < _kNumIters; i += 1) {
7070
final List<Element> allElements = collectAllElementsFrom(
71-
WidgetsBinding.instance.renderViewElement!,
71+
WidgetsBinding.instance.rootElement!,
7272
skipOffstage: false,
7373
).toList();
7474
allElements.clear();

dev/integration_tests/flutter_gallery/test/smoke_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async {
7878

7979
// Verify that the dumps are pretty.
8080
final String routeName = demo.routeName;
81-
verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance.renderViewElement!.toStringDeep());
81+
verifyToStringOutput('debugDumpApp', routeName, WidgetsBinding.instance.rootElement!.toStringDeep());
8282
verifyToStringOutput('debugDumpRenderTree', routeName, RendererBinding.instance.renderView.toStringDeep());
8383
verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance.renderView.debugLayer?.toStringDeep() ?? '');
8484

packages/flutter/lib/fix_data/fix_widgets/fix_widgets.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@
2323
# * ListWheelScrollView: fix_list_wheel_scroll_view.yaml
2424
version: 1
2525
transforms:
26+
# Changes made in https://github.com/flutter/flutter/pull/123352
27+
- title: "Migrate to 'rootElement'"
28+
date: 2023-03-13
29+
element:
30+
uris: [ 'widgets.dart', 'material.dart', 'cupertino.dart' ]
31+
field: 'renderViewElement'
32+
inClass: 'WidgetsBinding'
33+
changes:
34+
- kind: 'rename'
35+
newName: 'rootElement'
36+
2637
# Changes made in https://github.com/flutter/flutter/pull/122555
2738
- title: "Migrate to 'decorationClipBehavior'"
2839
date: 2023-03-13

packages/flutter/lib/src/widgets/binding.dart

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,8 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
479479
}
480480

481481
Future<void> _forceRebuild() {
482-
if (renderViewElement != null) {
483-
buildOwner!.reassemble(renderViewElement!, null);
482+
if (rootElement != null) {
483+
buildOwner!.reassemble(rootElement!, null);
484484
return endOfFrame;
485485
}
486486
return Future<void>.value();
@@ -889,8 +889,8 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
889889
}
890890

891891
try {
892-
if (renderViewElement != null) {
893-
buildOwner!.buildScope(renderViewElement!);
892+
if (rootElement != null) {
893+
buildOwner!.buildScope(rootElement!);
894894
}
895895
super.drawFrame();
896896
buildOwner!.finalizeTree();
@@ -914,12 +914,20 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
914914
}
915915
}
916916

917-
/// The [Element] that is at the root of the hierarchy (and which wraps the
918-
/// [RenderView] object at the root of the rendering hierarchy).
917+
/// The [Element] that is at the root of the element tree hierarchy.
919918
///
920919
/// This is initialized the first time [runApp] is called.
921-
Element? get renderViewElement => _renderViewElement;
922-
Element? _renderViewElement;
920+
Element? get rootElement => _rootElement;
921+
Element? _rootElement;
922+
923+
/// Deprecated. Will be removed in a future version of Flutter.
924+
///
925+
/// Use [rootElement] instead.
926+
@Deprecated(
927+
'Use rootElement instead. '
928+
'This feature was deprecated after v3.9.0-16.0.pre.'
929+
)
930+
Element? get renderViewElement => rootElement;
923931

924932
bool _readyToProduceFrames = false;
925933

@@ -951,7 +959,7 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
951959
});
952960
}
953961

954-
/// Takes a widget and attaches it to the [renderViewElement], creating it if
962+
/// Takes a widget and attaches it to the [rootElement], creating it if
955963
/// necessary.
956964
///
957965
/// This is called by [runApp] to configure the widget tree.
@@ -961,23 +969,23 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
961969
/// * [RenderObjectToWidgetAdapter.attachToRenderTree], which inflates a
962970
/// widget and attaches it to the render tree.
963971
void attachRootWidget(Widget rootWidget) {
964-
final bool isBootstrapFrame = renderViewElement == null;
972+
final bool isBootstrapFrame = rootElement == null;
965973
_readyToProduceFrames = true;
966-
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
974+
_rootElement = RenderObjectToWidgetAdapter<RenderBox>(
967975
container: renderView,
968976
debugShortDescription: '[root]',
969977
child: rootWidget,
970-
).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElement<RenderBox>?);
978+
).attachToRenderTree(buildOwner!, rootElement as RenderObjectToWidgetElement<RenderBox>?);
971979
if (isBootstrapFrame) {
972980
SchedulerBinding.instance.ensureVisualUpdate();
973981
}
974982
}
975983

976-
/// Whether the [renderViewElement] has been initialized.
984+
/// Whether the [rootElement] has been initialized.
977985
///
978986
/// This will be false until [runApp] is called (or [WidgetTester.pumpWidget]
979987
/// is called in the context of a [TestWidgetsFlutterBinding]).
980-
bool get isRootWidgetAttached => _renderViewElement != null;
988+
bool get isRootWidgetAttached => _rootElement != null;
981989

982990
@override
983991
Future<void> performReassemble() {
@@ -986,8 +994,8 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
986994
return true;
987995
}());
988996

989-
if (renderViewElement != null) {
990-
buildOwner!.reassemble(renderViewElement!, BindingBase.debugReassembleConfig);
997+
if (rootElement != null) {
998+
buildOwner!.reassemble(rootElement!, BindingBase.debugReassembleConfig);
991999
}
9921000
return super.performReassemble();
9931001
}
@@ -1069,8 +1077,8 @@ String _debugDumpAppString() {
10691077
const String mode = kDebugMode ? 'DEBUG MODE' : kReleaseMode ? 'RELEASE MODE' : 'PROFILE MODE';
10701078
final StringBuffer buffer = StringBuffer();
10711079
buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode');
1072-
if (WidgetsBinding.instance.renderViewElement != null) {
1073-
buffer.writeln(WidgetsBinding.instance.renderViewElement!.toStringDeep());
1080+
if (WidgetsBinding.instance.rootElement != null) {
1081+
buffer.writeln(WidgetsBinding.instance.rootElement!.toStringDeep());
10741082
} else {
10751083
buffer.writeln('<no tree currently mounted>');
10761084
}
@@ -1148,7 +1156,7 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
11481156
String toStringShort() => debugShortDescription ?? super.toStringShort();
11491157
}
11501158

1151-
/// A [RootRenderObjectElement] that is hosted by a [RenderObject].
1159+
/// The root of the element tree that is hosted by a [RenderObject].
11521160
///
11531161
/// This element class is the instantiation of a [RenderObjectToWidgetAdapter]
11541162
/// widget. It can be used only as the root of an [Element] tree (it cannot be
@@ -1158,7 +1166,7 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
11581166
/// whose container is the [RenderView] that connects to the Flutter engine. In
11591167
/// this usage, it is normally instantiated by the bootstrapping logic in the
11601168
/// [WidgetsFlutterBinding] singleton created by [runApp].
1161-
class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObjectElement {
1169+
class RenderObjectToWidgetElement<T extends RenderObject> extends RenderObjectElement with RootElementMixin {
11621170
/// Creates an element that is hosted by a [RenderObject].
11631171
///
11641172
/// The [RenderObject] created by this element is not automatically set as a

packages/flutter/lib/src/widgets/framework.dart

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,7 +2499,7 @@ abstract class BuildContext {
24992499
/// Additional build owners can be built to manage off-screen widget trees.
25002500
///
25012501
/// To assign a build owner to a tree, use the
2502-
/// [RootRenderObjectElement.assignOwner] method on the root element of the
2502+
/// [RootElementMixin.assignOwner] method on the root element of the
25032503
/// widget tree.
25042504
///
25052505
/// {@tool dartpad}
@@ -6323,14 +6323,29 @@ abstract class RenderObjectElement extends Element {
63236323
}
63246324
}
63256325

6326-
/// The element at the root of the tree.
6326+
/// Deprecated. Unused in the framework and will be removed in a future version
6327+
/// of Flutter.
63276328
///
6328-
/// Only root elements may have their owner set explicitly. All other
6329-
/// elements inherit their owner from their parent.
6330-
abstract class RootRenderObjectElement extends RenderObjectElement {
6329+
/// Classes that extend this class can extend [RenderObjectElement] and mixin
6330+
/// [RootElementMixin] instead.
6331+
@Deprecated(
6332+
'Use RootElementMixin instead. '
6333+
'This feature was deprecated after v3.9.0-16.0.pre.'
6334+
)
6335+
abstract class RootRenderObjectElement extends RenderObjectElement with RootElementMixin {
63316336
/// Initializes fields for subclasses.
6337+
@Deprecated(
6338+
'Use RootElementMixin instead. '
6339+
'This feature was deprecated after v3.9.0-16.0.pre.'
6340+
)
63326341
RootRenderObjectElement(super.widget);
6342+
}
63336343

6344+
/// Mixin for the element at the root of the tree.
6345+
///
6346+
/// Only root elements may have their owner set explicitly. All other
6347+
/// elements inherit their owner from their parent.
6348+
mixin RootElementMixin on Element {
63346349
/// Set the owner of the element. The owner will be propagated to all the
63356350
/// descendants of this element.
63366351
///

packages/flutter/lib/src/widgets/widget_inspector.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -914,8 +914,8 @@ mixin WidgetInspectorService {
914914
@protected
915915
Future<void> forceRebuild() {
916916
final WidgetsBinding binding = WidgetsBinding.instance;
917-
if (binding.renderViewElement != null) {
918-
binding.buildOwner!.reassemble(binding.renderViewElement!, null);
917+
if (binding.rootElement != null) {
918+
binding.buildOwner!.reassemble(binding.rootElement!, null);
919919
return binding.endOfFrame;
920920
}
921921
return Future<void>.value();
@@ -1832,7 +1832,7 @@ mixin WidgetInspectorService {
18321832
}
18331833

18341834
Map<String, Object?>? _getRootWidget(String groupName) {
1835-
return _nodeToJson(WidgetsBinding.instance.renderViewElement?.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this));
1835+
return _nodeToJson(WidgetsBinding.instance.rootElement?.toDiagnosticsNode(), InspectorSerializationDelegate(groupName: groupName, service: this));
18361836
}
18371837

18381838
/// Returns a JSON representation of the [DiagnosticsNode] for the root
@@ -1846,7 +1846,7 @@ mixin WidgetInspectorService {
18461846
Map<String, Object>? Function(DiagnosticsNode, InspectorSerializationDelegate)? addAdditionalPropertiesCallback,
18471847
}) {
18481848
return _nodeToJson(
1849-
WidgetsBinding.instance.renderViewElement?.toDiagnosticsNode(),
1849+
WidgetsBinding.instance.rootElement?.toDiagnosticsNode(),
18501850
InspectorSerializationDelegate(
18511851
groupName: groupName,
18521852
subtreeDepth: 1000000,

packages/flutter/test/widgets/fast_reassemble_test.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,34 @@ void main() {
1717
expect(Fizz.count, 0);
1818

1919
DebugReassembleConfig config = DebugReassembleConfig(widgetName: 'Bar');
20-
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config);
20+
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config);
2121

2222
expect(Foo.count, 0);
2323
expect(Bar.count, 1);
2424
expect(Fizz.count, 1);
2525

2626
config = DebugReassembleConfig(widgetName: 'Fizz');
27-
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config);
27+
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config);
2828

2929
expect(Foo.count, 0);
3030
expect(Bar.count, 1);
3131
expect(Fizz.count, 2);
3232

3333
config = DebugReassembleConfig(widgetName: 'NoMatch');
34-
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config);
34+
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config);
3535

3636
expect(Foo.count, 0);
3737
expect(Bar.count, 1);
3838
expect(Fizz.count, 2);
3939

4040
config = DebugReassembleConfig();
41-
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, config);
41+
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, config);
4242

4343
expect(Foo.count, 1);
4444
expect(Bar.count, 2);
4545
expect(Fizz.count, 3);
4646

47-
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.renderViewElement!, null);
47+
WidgetsBinding.instance.buildOwner!.reassemble(WidgetsBinding.instance.rootElement!, null);
4848

4949
expect(Foo.count, 2);
5050
expect(Bar.count, 3);

packages/flutter/test/widgets/memory_allocations_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class _TestLeafRenderObjectWidget extends LeafRenderObjectWidget {
5858
}
5959
}
6060

61-
class _TestElement extends RootRenderObjectElement{
61+
class _TestElement extends RenderObjectElement with RootElementMixin {
6262
_TestElement(): super(_TestLeafRenderObjectWidget());
6363

6464
void makeInactive() {

packages/flutter/test/widgets/run_app_async_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ void main() {
5050
),
5151
);
5252
// Rendering tree is not built synchronously.
53-
expect(WidgetsBinding.instance.renderViewElement, isNull);
53+
expect(WidgetsBinding.instance.rootElement, isNull);
5454
fakeAsync.flushTimers();
55-
expect(WidgetsBinding.instance.renderViewElement, isNotNull);
55+
expect(WidgetsBinding.instance.rootElement, isNotNull);
5656
});
5757
});
5858
}

packages/flutter/test/widgets/widget_inspector_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
873873
final List<Object?> chainElements = jsonList! as List<Object?>;
874874
final List<Element> expectedChain = elementB.debugGetDiagnosticChain().reversed.toList();
875875
// Sanity check that the chain goes back to the root.
876-
expect(expectedChain.first, tester.binding.renderViewElement);
876+
expect(expectedChain.first, tester.binding.rootElement);
877877

878878
expect(chainElements.length, equals(expectedChain.length));
879879
for (int i = 0; i < expectedChain.length; i += 1) {
@@ -2081,7 +2081,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
20812081
final List<Object?> chainElements = jsonList! as List<Object?>;
20822082
final List<Element> expectedChain = elementB.debugGetDiagnosticChain().reversed.toList();
20832083
// Sanity check that the chain goes back to the root.
2084-
expect(expectedChain.first, tester.binding.renderViewElement);
2084+
expect(expectedChain.first, tester.binding.rootElement);
20852085

20862086
expect(chainElements.length, equals(expectedChain.length));
20872087
for (int i = 0; i < expectedChain.length; i += 1) {
@@ -2327,7 +2327,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
23272327
// directories so we get an empty tree other than the root that is always
23282328
// included.
23292329
final Object? rootWidget = service.toObject(rootJson['valueId']! as String);
2330-
expect(rootWidget, equals(WidgetsBinding.instance.renderViewElement));
2330+
expect(rootWidget, equals(WidgetsBinding.instance.rootElement));
23312331
List<Object?> childrenJson = rootJson['children']! as List<Object?>;
23322332
// There are no summary tree children.
23332333
expect(childrenJson.length, equals(0));

packages/flutter/test/widgets/widget_inspector_test_utils.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
106106
rebuildCount++;
107107
final WidgetsBinding binding = WidgetsBinding.instance;
108108

109-
if (binding.renderViewElement != null) {
110-
binding.buildOwner!.reassemble(binding.renderViewElement!, null);
109+
if (binding.rootElement != null) {
110+
binding.buildOwner!.reassemble(binding.rootElement!, null);
111111
}
112112
}
113113

packages/flutter/test_fixes/widgets/widgets.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ void main() {
1212
Object object;
1313
TickerProvider vsync;
1414

15+
// Changes made in https://github.com/flutter/flutter/pull/123352
16+
WidgetsBinding.instance.renderViewElement;
17+
1518
// Changes made in https://github.com/flutter/flutter/pull/119647
1619
MediaQueryData.fromWindow(View.of(context));
1720

packages/flutter/test_fixes/widgets/widgets.dart.expect

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ void main() {
1212
Object object;
1313
TickerProvider vsync;
1414

15+
// Changes made in https://github.com/flutter/flutter/pull/123352
16+
WidgetsBinding.instance.rootElement;
17+
1518
// Changes made in https://github.com/flutter/flutter/pull/119647
1619
MediaQueryData.fromView(View.of(context));
1720

packages/flutter/test_release/widgets/memory_allocations_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class _TestRenderObject extends RenderObject {
5555
Rect get semanticBounds => throw UnimplementedError();
5656
}
5757

58-
class _TestElement extends RootRenderObjectElement{
58+
class _TestElement extends RenderObjectElement with RootElementMixin {
5959
_TestElement(): super(_TestLeafRenderObjectWidget());
6060

6161
void makeInactive() {

packages/flutter_test/lib/src/_matchers_web.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class MatchesGoldenFile extends AsyncMatcher {
5757
final RenderObject renderObject = _findRepaintBoundary(element);
5858
final Size size = renderObject.paintBounds.size;
5959
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.instance;
60-
final Element e = binding.renderViewElement!;
60+
final Element e = binding.rootElement!;
6161
final ui.FlutterView view = binding.platformDispatcher.implicitView!;
6262

6363
// Unlike `flutter_tester`, we don't have the ability to render an element

0 commit comments

Comments
 (0)