[framework] inline casts on Element.widget getter to improve web performance (#97822)

This commit is contained in:
Jonah Williams 2022-02-08 13:05:21 -08:00 committed by GitHub
parent d2b5f34bc4
commit 4f975cbe2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 124 additions and 175 deletions

View file

@ -916,9 +916,6 @@ class _CupertinoDialogRenderElement extends RenderObjectElement {
Element? _contentElement;
Element? _actionsElement;
@override
_CupertinoDialogRenderWidget get widget => super.widget as _CupertinoDialogRenderWidget;
@override
_RenderCupertinoDialog get renderObject => super.renderObject as _RenderCupertinoDialog;
@ -935,8 +932,9 @@ class _CupertinoDialogRenderElement extends RenderObjectElement {
@override
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_contentElement = updateChild(_contentElement, widget.contentSection, _AlertDialogSections.contentSection);
_actionsElement = updateChild(_actionsElement, widget.actionsSection, _AlertDialogSections.actionsSection);
final _CupertinoDialogRenderWidget dialogRenderWidget = widget as _CupertinoDialogRenderWidget;
_contentElement = updateChild(_contentElement, dialogRenderWidget.contentSection, _AlertDialogSections.contentSection);
_actionsElement = updateChild(_actionsElement, dialogRenderWidget.actionsSection, _AlertDialogSections.actionsSection);
}
@override
@ -957,8 +955,9 @@ class _CupertinoDialogRenderElement extends RenderObjectElement {
@override
void update(RenderObjectWidget newWidget) {
super.update(newWidget);
_contentElement = updateChild(_contentElement, widget.contentSection, _AlertDialogSections.contentSection);
_actionsElement = updateChild(_actionsElement, widget.actionsSection, _AlertDialogSections.actionsSection);
final _CupertinoDialogRenderWidget dialogRenderWidget = widget as _CupertinoDialogRenderWidget;
_contentElement = updateChild(_contentElement, dialogRenderWidget.contentSection, _AlertDialogSections.contentSection);
_actionsElement = updateChild(_actionsElement, dialogRenderWidget.actionsSection, _AlertDialogSections.actionsSection);
}
@override

View file

@ -274,36 +274,35 @@ class _CupertinoTextFormFieldRowState extends FormFieldState<String> {
TextEditingController? _controller;
TextEditingController? get _effectiveController =>
widget.controller ?? _controller;
_cupertinoTextFormFieldRow.controller ?? _controller;
@override
CupertinoTextFormFieldRow get widget =>
CupertinoTextFormFieldRow get _cupertinoTextFormFieldRow =>
super.widget as CupertinoTextFormFieldRow;
@override
void initState() {
super.initState();
if (widget.controller == null) {
if (_cupertinoTextFormFieldRow.controller == null) {
_controller = TextEditingController(text: widget.initialValue);
} else {
widget.controller!.addListener(_handleControllerChanged);
_cupertinoTextFormFieldRow.controller!.addListener(_handleControllerChanged);
}
}
@override
void didUpdateWidget(CupertinoTextFormFieldRow oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.controller != oldWidget.controller) {
if (_cupertinoTextFormFieldRow.controller != oldWidget.controller) {
oldWidget.controller?.removeListener(_handleControllerChanged);
widget.controller?.addListener(_handleControllerChanged);
_cupertinoTextFormFieldRow.controller?.addListener(_handleControllerChanged);
if (oldWidget.controller != null && widget.controller == null) {
if (oldWidget.controller != null && _cupertinoTextFormFieldRow.controller == null) {
_controller =
TextEditingController.fromValue(oldWidget.controller!.value);
}
if (widget.controller != null) {
setValue(widget.controller!.text);
if (_cupertinoTextFormFieldRow.controller != null) {
setValue(_cupertinoTextFormFieldRow.controller!.text);
if (oldWidget.controller == null) {
_controller = null;
}
@ -313,7 +312,7 @@ class _CupertinoTextFormFieldRowState extends FormFieldState<String> {
@override
void dispose() {
widget.controller?.removeListener(_handleControllerChanged);
_cupertinoTextFormFieldRow.controller?.removeListener(_handleControllerChanged);
super.dispose();
}

View file

@ -522,9 +522,6 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
// repeatedly to remove children.
final Set<Element> _forgottenChildren = HashSet<Element>();
@override
_CupertinoTextSelectionToolbarItems get widget => super.widget as _CupertinoTextSelectionToolbarItems;
@override
_RenderCupertinoTextSelectionToolbarItems get renderObject => super.renderObject as _RenderCupertinoTextSelectionToolbarItems;
@ -625,15 +622,16 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
// Mount slotted children.
_mountChild(widget.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
_mountChild(widget.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
_mountChild(widget.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
final _CupertinoTextSelectionToolbarItems toolbarItems = widget as _CupertinoTextSelectionToolbarItems;
_mountChild(toolbarItems.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
_mountChild(toolbarItems.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
_mountChild(toolbarItems.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
// Mount list children.
_children = List<Element>.filled(widget.children.length, _NullElement.instance);
_children = List<Element>.filled(toolbarItems.children.length, _NullElement.instance);
Element? previousChild;
for (int i = 0; i < _children.length; i += 1) {
final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element?>(i, previousChild));
final Element newChild = inflateWidget(toolbarItems.children[i], IndexedSlot<Element?>(i, previousChild));
_children[i] = newChild;
previousChild = newChild;
}
@ -659,12 +657,13 @@ class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
assert(widget == newWidget);
// Update slotted children.
_mountChild(widget.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
_mountChild(widget.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
_mountChild(widget.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
final _CupertinoTextSelectionToolbarItems toolbarItems = widget as _CupertinoTextSelectionToolbarItems;
_mountChild(toolbarItems.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
_mountChild(toolbarItems.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
_mountChild(toolbarItems.nextButtonDisabled, _CupertinoTextSelectionToolbarItemsSlot.nextButtonDisabled);
// Update list children.
_children = updateChildren(_children, widget.children, forgottenChildren: _forgottenChildren);
_children = updateChildren(_children, toolbarItems.children, forgottenChildren: _forgottenChildren);
_forgottenChildren.clear();
}
}

View file

@ -1665,14 +1665,13 @@ class DropdownButtonFormField<T> extends FormField<T> {
}
class _DropdownButtonFormFieldState<T> extends FormFieldState<T> {
@override
DropdownButtonFormField<T> get widget => super.widget as DropdownButtonFormField<T>;
@override
void didChange(T? value) {
super.didChange(value);
assert(widget.onChanged != null);
widget.onChanged!(value);
final DropdownButtonFormField<T> dropdownButtonFormField = widget as DropdownButtonFormField<T>;
assert(dropdownButtonFormField.onChanged != null);
dropdownButtonFormField.onChanged!(value);
}
@override

View file

@ -266,10 +266,9 @@ class TextFormField extends FormField<String> {
class _TextFormFieldState extends FormFieldState<String> {
RestorableTextEditingController? _controller;
TextEditingController get _effectiveController => widget.controller ?? _controller!.value;
TextEditingController get _effectiveController => _textFormField.controller ?? _controller!.value;
@override
TextFormField get widget => super.widget as TextFormField;
TextFormField get _textFormField => super.widget as TextFormField;
@override
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
@ -300,26 +299,26 @@ class _TextFormFieldState extends FormFieldState<String> {
@override
void initState() {
super.initState();
if (widget.controller == null) {
if (_textFormField.controller == null) {
_createLocalController(widget.initialValue != null ? TextEditingValue(text: widget.initialValue!) : null);
} else {
widget.controller!.addListener(_handleControllerChanged);
_textFormField.controller!.addListener(_handleControllerChanged);
}
}
@override
void didUpdateWidget(TextFormField oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.controller != oldWidget.controller) {
if (_textFormField.controller != oldWidget.controller) {
oldWidget.controller?.removeListener(_handleControllerChanged);
widget.controller?.addListener(_handleControllerChanged);
_textFormField.controller?.addListener(_handleControllerChanged);
if (oldWidget.controller != null && widget.controller == null) {
if (oldWidget.controller != null && _textFormField.controller == null) {
_createLocalController(oldWidget.controller!.value);
}
if (widget.controller != null) {
setValue(widget.controller!.text);
if (_textFormField.controller != null) {
setValue(_textFormField.controller!.text);
if (oldWidget.controller == null) {
unregisterFromRestoration(_controller!);
_controller!.dispose();
@ -331,7 +330,7 @@ class _TextFormFieldState extends FormFieldState<String> {
@override
void dispose() {
widget.controller?.removeListener(_handleControllerChanged);
_textFormField.controller?.removeListener(_handleControllerChanged);
_controller?.dispose();
super.dispose();
}

View file

@ -3131,12 +3131,9 @@ class Offstage extends SingleChildRenderObjectWidget {
class _OffstageElement extends SingleChildRenderObjectElement {
_OffstageElement(Offstage widget) : super(widget);
@override
Offstage get widget => super.widget as Offstage;
@override
void debugVisitOnstageChildren(ElementVisitor visitor) {
if (!widget.offstage)
if (!(widget as Offstage).offstage)
super.debugVisitOnstageChildren(visitor);
}
}

View file

@ -1138,9 +1138,6 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
/// the render tree, call [RenderObjectToWidgetAdapter.attachToRenderTree].
RenderObjectToWidgetElement(RenderObjectToWidgetAdapter<T> widget) : super(widget);
@override
RenderObjectToWidgetAdapter<T> get widget => super.widget as RenderObjectToWidgetAdapter<T>;
Element? _child;
static const Object _rootChildSlot = Object();
@ -1193,7 +1190,7 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
@pragma('vm:notify-debugger-on-exception')
void _rebuild() {
try {
_child = updateChild(_child, widget.child, _rootChildSlot);
_child = updateChild(_child, (widget as RenderObjectToWidgetAdapter<T>).child, _rootChildSlot);
} catch (exception, stack) {
final FlutterErrorDetails details = FlutterErrorDetails(
exception: exception,

View file

@ -3232,6 +3232,13 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
}
/// The configuration for this element.
///
/// Avoid overriding this field on [Element] subtypes to provide a more
/// specific widget type (i.e. [StatelessElement] and [StatelessWidget]).
/// Instead, cast at any callsites where the more specific type is required.
/// This avoids significant cast overhead on the getter which is accessed
/// throughout the framework internals during the build phase - and for which
/// the more specific type information is not used.
@override
Widget get widget => _widget!;
Widget? _widget;
@ -4021,7 +4028,7 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
assert(depth != null);
assert(owner != null);
// Use the private property to avoid a CastError during hot reload.
final Key? key = _widget!.key;
final Key? key = _widget?.key;
if (key is GlobalKey) {
owner!._unregisterGlobalKey(key, this);
}
@ -4208,7 +4215,7 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
_dependencies ??= HashSet<InheritedElement>();
_dependencies!.add(ancestor);
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
return ancestor.widget as InheritedWidget;
}
@override
@ -4855,10 +4862,7 @@ class StatelessElement extends ComponentElement {
StatelessElement(StatelessWidget widget) : super(widget);
@override
StatelessWidget get widget => super.widget as StatelessWidget;
@override
Widget build() => widget.build(this);
Widget build() => (widget as StatelessWidget).build(this);
@override
void update(StatelessWidget newWidget) {
@ -5125,14 +5129,11 @@ abstract class ProxyElement extends ComponentElement {
ProxyElement(ProxyWidget widget) : super(widget);
@override
ProxyWidget get widget => super.widget as ProxyWidget;
@override
Widget build() => widget.child;
Widget build() => (widget as ProxyWidget).child;
@override
void update(ProxyWidget newWidget) {
final ProxyWidget oldWidget = widget;
final ProxyWidget oldWidget = widget as ProxyWidget;
assert(widget != null);
assert(widget != newWidget);
super.update(newWidget);
@ -5166,9 +5167,6 @@ class ParentDataElement<T extends ParentData> extends ProxyElement {
/// Creates an element that uses the given widget as its configuration.
ParentDataElement(ParentDataWidget<T> widget) : super(widget);
@override
ParentDataWidget<T> get widget => super.widget as ParentDataWidget<T>;
void _applyParentData(ParentDataWidget<T> widget) {
void applyParentDataToChild(Element child) {
if (child is RenderObjectElement) {
@ -5216,13 +5214,13 @@ class ParentDataElement<T extends ParentData> extends ProxyElement {
void applyWidgetOutOfTurn(ParentDataWidget<T> newWidget) {
assert(newWidget != null);
assert(newWidget.debugCanApplyOutOfTurn());
assert(newWidget.child == widget.child);
assert(newWidget.child == (widget as ParentDataWidget<T>).child);
_applyParentData(newWidget);
}
@override
void notifyClients(ParentDataWidget<T> oldWidget) {
_applyParentData(widget);
_applyParentData(widget as ParentDataWidget<T>);
}
}
@ -5231,9 +5229,6 @@ class InheritedElement extends ProxyElement {
/// Creates an element that uses the given widget as its configuration.
InheritedElement(InheritedWidget widget) : super(widget);
@override
InheritedWidget get widget => super.widget as InheritedWidget;
final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
@override
@ -5364,7 +5359,7 @@ class InheritedElement extends ProxyElement {
/// Calls [notifyClients] to actually trigger the notifications.
@override
void updated(InheritedWidget oldWidget) {
if (widget.updateShouldNotify(oldWidget))
if ((widget as InheritedWidget).updateShouldNotify(oldWidget))
super.updated(oldWidget);
}
@ -5433,19 +5428,20 @@ class InheritedElement extends ProxyElement {
/// ### Specializing the getters
///
/// [RenderObjectElement] objects spend much of their time acting as
/// intermediaries between their [widget] and their [renderObject]. To make this
/// more tractable, most [RenderObjectElement] subclasses override these getters
/// so that they return the specific type that the element expects, e.g.:
/// intermediaries between their [widget] and their [renderObject]. It is
/// generally recommended against specializing the [widget] getter and
/// instead casting at the various callsites to avoid adding overhead
/// outside of this particular implementation.
///
/// ```dart
/// class FooElement extends RenderObjectElement {
///
/// @override
/// Foo get widget => super.widget as Foo;
///
/// @override
/// RenderFoo get renderObject => super.renderObject as RenderFoo;
///
/// void _foo() {
/// final Foo foo = widget as Foo;
/// }
/// // ...
/// }
/// ```
@ -5571,9 +5567,6 @@ abstract class RenderObjectElement extends Element {
/// Creates an element that uses the given widget as its configuration.
RenderObjectElement(RenderObjectWidget widget) : super(widget);
@override
RenderObjectWidget get widget => super.widget as RenderObjectWidget;
/// The underlying [RenderObject] for this element.
///
/// If this element has been [unmount]ed, this getter will throw.
@ -5630,7 +5623,7 @@ abstract class RenderObjectElement extends Element {
ErrorSummary('Incorrect use of ParentDataWidget.'),
ErrorDescription('The following ParentDataWidgets are providing parent data to the same RenderObject:'),
for (final ParentDataElement<ParentData> ancestor in badAncestors)
ErrorDescription('- ${ancestor.widget} (typically placed directly inside a ${ancestor.widget.debugTypicalAncestorWidgetClass} widget)'),
ErrorDescription('- ${ancestor.widget} (typically placed directly inside a ${(ancestor.widget as ParentDataWidget<ParentData>).debugTypicalAncestorWidgetClass} widget)'),
ErrorDescription('However, a RenderObject can only receive parent data from at most one ParentDataWidget.'),
ErrorHint('Usually, this indicates that at least one of the offending ParentDataWidgets listed above is not placed directly inside a compatible ancestor widget.'),
ErrorDescription('The ownership chain for the RenderObject that received the parent data was:\n ${debugGetCreatorChain(10)}'),
@ -5651,7 +5644,7 @@ abstract class RenderObjectElement extends Element {
_debugDoingBuild = true;
return true;
}());
_renderObject = widget.createRenderObject(this);
_renderObject = (widget as RenderObjectWidget).createRenderObject(this);
assert(!_renderObject!.debugDisposed!);
assert(() {
_debugDoingBuild = false;
@ -5695,7 +5688,7 @@ abstract class RenderObjectElement extends Element {
_debugDoingBuild = true;
return true;
}());
widget.updateRenderObject(this, renderObject);
(widget as RenderObjectWidget).updateRenderObject(this, renderObject);
assert(() {
_debugDoingBuild = false;
return true;
@ -5931,7 +5924,7 @@ abstract class RenderObjectElement extends Element {
'A RenderObject was disposed prior to its owning element being unmounted: '
'$renderObject',
);
final RenderObjectWidget oldWidget = widget;
final RenderObjectWidget oldWidget = widget as RenderObjectWidget;
super.unmount();
assert(
!renderObject.attached,
@ -5953,7 +5946,7 @@ abstract class RenderObjectElement extends Element {
ErrorSummary('Incorrect use of ParentDataWidget.'),
...parentDataWidget._debugDescribeIncorrectParentDataType(
parentData: renderObject.parentData,
parentDataCreator: _ancestorRenderObjectElement!.widget,
parentDataCreator: _ancestorRenderObjectElement!.widget as RenderObjectWidget,
ownershipChain: ErrorDescription(debugGetCreatorChain(10)),
),
]);
@ -5988,7 +5981,7 @@ abstract class RenderObjectElement extends Element {
_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
final ParentDataElement<ParentData>? parentDataElement = _findAncestorParentDataElement();
if (parentDataElement != null)
_updateParentData(parentDataElement.widget);
_updateParentData(parentDataElement.widget as ParentDataWidget<ParentData>);
}
@override
@ -6290,9 +6283,6 @@ class SingleChildRenderObjectElement extends RenderObjectElement {
/// Creates an element that uses the given widget as its configuration.
SingleChildRenderObjectElement(SingleChildRenderObjectWidget widget) : super(widget);
@override
SingleChildRenderObjectWidget get widget => super.widget as SingleChildRenderObjectWidget;
Element? _child;
@override
@ -6311,14 +6301,14 @@ class SingleChildRenderObjectElement extends RenderObjectElement {
@override
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_child = updateChild(_child, widget.child, null);
_child = updateChild(_child, (widget as SingleChildRenderObjectWidget).child, null);
}
@override
void update(SingleChildRenderObjectWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_child = updateChild(_child, widget.child, null);
_child = updateChild(_child, (widget as SingleChildRenderObjectWidget).child, null);
}
@override
@ -6364,9 +6354,6 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
: assert(!debugChildrenHaveDuplicateKeys(widget, widget.children)),
super(widget);
@override
MultiChildRenderObjectWidget get widget => super.widget as MultiChildRenderObjectWidget;
@override
ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>> get renderObject {
return super.renderObject as ContainerRenderObjectMixin<RenderObject, ContainerParentDataMixin<RenderObject>>;
@ -6457,10 +6444,11 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
@override
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
final List<Element> children = List<Element>.filled(widget.children.length, _NullElement.instance);
final MultiChildRenderObjectWidget multiChildRenderObjectWidget = widget as MultiChildRenderObjectWidget;
final List<Element> children = List<Element>.filled(multiChildRenderObjectWidget.children.length, _NullElement.instance);
Element? previousChild;
for (int i = 0; i < children.length; i += 1) {
final Element newChild = inflateWidget(widget.children[i], IndexedSlot<Element?>(i, previousChild));
final Element newChild = inflateWidget(multiChildRenderObjectWidget.children[i], IndexedSlot<Element?>(i, previousChild));
children[i] = newChild;
previousChild = newChild;
}
@ -6470,9 +6458,10 @@ class MultiChildRenderObjectElement extends RenderObjectElement {
@override
void update(MultiChildRenderObjectWidget newWidget) {
super.update(newWidget);
final MultiChildRenderObjectWidget multiChildRenderObjectWidget = widget as MultiChildRenderObjectWidget;
assert(widget == newWidget);
assert(!debugChildrenHaveDuplicateKeys(widget, widget.children));
_children = updateChildren(_children, widget.children, forgottenChildren: _forgottenChildren);
assert(!debugChildrenHaveDuplicateKeys(widget, multiChildRenderObjectWidget.children));
_children = updateChildren(_children, multiChildRenderObjectWidget.children, forgottenChildren: _forgottenChildren);
_forgottenChildren.clear();
}
}

View file

@ -184,9 +184,6 @@ class InheritedModelElement<T> extends InheritedElement {
/// Creates an element that uses the given widget as its configuration.
InheritedModelElement(InheritedModel<T> widget) : super(widget);
@override
InheritedModel<T> get widget => super.widget as InheritedModel<T>;
@override
void updateDependencies(Element dependent, Object? aspect) {
final Set<T>? dependencies = getDependencies(dependent) as Set<T>?;
@ -206,7 +203,7 @@ class InheritedModelElement<T> extends InheritedElement {
final Set<T>? dependencies = getDependencies(dependent) as Set<T>?;
if (dependencies == null)
return;
if (dependencies.isEmpty || widget.updateShouldNotifyDependent(oldWidget, dependencies))
if (dependencies.isEmpty || (widget as InheritedModel<T>).updateShouldNotifyDependent(oldWidget, dependencies))
dependent.didChangeDependencies();
}
}

View file

@ -95,14 +95,11 @@ class _InheritedNotifierElement<T extends Listenable> extends InheritedElement {
widget.notifier?.addListener(_handleUpdate);
}
@override
InheritedNotifier<T> get widget => super.widget as InheritedNotifier<T>;
bool _dirty = false;
@override
void update(InheritedNotifier<T> newWidget) {
final T? oldNotifier = widget.notifier;
final T? oldNotifier = (widget as InheritedNotifier<T>).notifier;
final T? newNotifier = newWidget.notifier;
if (oldNotifier != newNotifier) {
oldNotifier?.removeListener(_handleUpdate);
@ -114,7 +111,7 @@ class _InheritedNotifierElement<T extends Listenable> extends InheritedElement {
@override
Widget build() {
if (_dirty)
notifyClients(widget);
notifyClients(widget as InheritedNotifier<T>);
return super.build();
}
@ -131,7 +128,7 @@ class _InheritedNotifierElement<T extends Listenable> extends InheritedElement {
@override
void unmount() {
widget.notifier?.removeListener(_handleUpdate);
(widget as InheritedNotifier<T>).notifier?.removeListener(_handleUpdate);
super.unmount();
}
}

View file

@ -57,9 +57,6 @@ abstract class ConstrainedLayoutBuilder<ConstraintType extends Constraints> exte
class _LayoutBuilderElement<ConstraintType extends Constraints> extends RenderObjectElement {
_LayoutBuilderElement(ConstrainedLayoutBuilder<ConstraintType> widget) : super(widget);
@override
ConstrainedLayoutBuilder<ConstraintType> get widget => super.widget as ConstrainedLayoutBuilder<ConstraintType>;
@override
RenderConstrainedLayoutBuilder<ConstraintType, RenderObject> get renderObject => super.renderObject as RenderConstrainedLayoutBuilder<ConstraintType, RenderObject>;
@ -119,7 +116,7 @@ class _LayoutBuilderElement<ConstraintType extends Constraints> extends RenderOb
void layoutCallback() {
Widget built;
try {
built = widget.builder(this, constraints);
built = (widget as ConstrainedLayoutBuilder<ConstraintType>).builder(this, constraints);
debugWidgetBuilderValue(widget, built);
} catch (e, stack) {
built = ErrorWidget.builder(

View file

@ -818,9 +818,6 @@ class ListWheelElement extends RenderObjectElement implements ListWheelChildMana
/// Creates an element that lazily builds children for the given widget.
ListWheelElement(ListWheelViewport widget) : super(widget);
@override
ListWheelViewport get widget => super.widget as ListWheelViewport;
@override
RenderListWheelViewport get renderObject => super.renderObject as RenderListWheelViewport;
@ -840,7 +837,7 @@ class ListWheelElement extends RenderObjectElement implements ListWheelChildMana
@override
void update(ListWheelViewport newWidget) {
final ListWheelViewport oldWidget = widget;
final ListWheelViewport oldWidget = widget as ListWheelViewport;
super.update(newWidget);
final ListWheelChildDelegate newDelegate = newWidget.childDelegate;
final ListWheelChildDelegate oldDelegate = oldWidget.childDelegate;
@ -852,7 +849,7 @@ class ListWheelElement extends RenderObjectElement implements ListWheelChildMana
}
@override
int? get childCount => widget.childDelegate.estimatedChildCount;
int? get childCount => (widget as ListWheelViewport).childDelegate.estimatedChildCount;
@override
void performRebuild() {
@ -880,7 +877,7 @@ class ListWheelElement extends RenderObjectElement implements ListWheelChildMana
/// will be cached. However when the element is rebuilt, the cache will be
/// cleared.
Widget? retrieveWidget(int index) {
return _childWidgets.putIfAbsent(index, () => widget.childDelegate.build(this, index));
return _childWidgets.putIfAbsent(index, () => (widget as ListWheelViewport).childDelegate.build(this, index));
}
@override

View file

@ -62,7 +62,7 @@ abstract class Notification {
@mustCallSuper
bool visitAncestor(Element element) {
if (element is StatelessElement) {
final StatelessWidget widget = element.widget;
final Widget widget = element.widget;
if (widget is NotificationListener<Notification>) {
if (widget._dispatch(this, element)) // that function checks the type dynamically
return false;

View file

@ -578,16 +578,14 @@ class _Theatre extends MultiChildRenderObjectWidget {
class _TheatreElement extends MultiChildRenderObjectElement {
_TheatreElement(_Theatre widget) : super(widget);
@override
_Theatre get widget => super.widget as _Theatre;
@override
_RenderTheatre get renderObject => super.renderObject as _RenderTheatre;
@override
void debugVisitOnstageChildren(ElementVisitor visitor) {
assert(children.length >= widget.skipCount);
children.skip(widget.skipCount).forEach(visitor);
final _Theatre theatre = widget as _Theatre;
assert(children.length >= theatre.skipCount);
children.skip(theatre.skipCount).forEach(visitor);
}
}

View file

@ -1126,15 +1126,12 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
final bool _replaceMovedChildren;
@override
SliverMultiBoxAdaptorWidget get widget => super.widget as SliverMultiBoxAdaptorWidget;
@override
RenderSliverMultiBoxAdaptor get renderObject => super.renderObject as RenderSliverMultiBoxAdaptor;
@override
void update(covariant SliverMultiBoxAdaptorWidget newWidget) {
final SliverMultiBoxAdaptorWidget oldWidget = widget;
final SliverMultiBoxAdaptorWidget oldWidget = widget as SliverMultiBoxAdaptorWidget;
super.update(newWidget);
final SliverChildDelegate newDelegate = newWidget.delegate;
final SliverChildDelegate oldDelegate = oldWidget.delegate;
@ -1155,6 +1152,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
try {
final SplayTreeMap<int, Element?> newChildren = SplayTreeMap<int, Element?>();
final Map<int, double> indexToLayoutOffset = HashMap<int, double>();
final SliverMultiBoxAdaptorWidget adaptorWidget = widget as SliverMultiBoxAdaptorWidget;
void processElement(int index) {
_currentlyUpdatingChildIndex = index;
if (_childElements[index] != null && _childElements[index] != newChildren[index]) {
@ -1162,7 +1160,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
_childElements[index] = updateChild(_childElements[index], null, index);
childrenUpdated = true;
}
final Element? newChild = updateChild(newChildren[index], _build(index), index);
final Element? newChild = updateChild(newChildren[index], _build(index, adaptorWidget), index);
if (newChild != null) {
childrenUpdated = childrenUpdated || _childElements[index] != newChild;
_childElements[index] = newChild;
@ -1181,7 +1179,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
}
for (final int index in _childElements.keys.toList()) {
final Key? key = _childElements[index]!.widget.key;
final int? newIndex = key == null ? null : widget.delegate.findIndexByKey(key);
final int? newIndex = key == null ? null : adaptorWidget.delegate.findIndexByKey(key);
final SliverMultiBoxAdaptorParentData? childParentData =
_childElements[index]!.renderObject?.parentData as SliverMultiBoxAdaptorParentData?;
@ -1228,7 +1226,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
}
}
Widget? _build(int index) {
Widget? _build(int index, SliverMultiBoxAdaptorWidget widget) {
return widget.delegate.build(this, index);
}
@ -1241,8 +1239,9 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
_currentBeforeChild = insertFirst ? null : (_childElements[index-1]!.renderObject as RenderBox?);
Element? newChild;
try {
final SliverMultiBoxAdaptorWidget adaptorWidget = widget as SliverMultiBoxAdaptorWidget;
_currentlyUpdatingChildIndex = index;
newChild = updateChild(_childElements[index], _build(index), index);
newChild = updateChild(_childElements[index], _build(index, adaptorWidget), index);
} finally {
_currentlyUpdatingChildIndex = null;
}
@ -1321,7 +1320,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
final int? childCount = estimatedChildCount;
if (childCount == null)
return double.infinity;
return widget.estimateMaxScrollOffset(
return (widget as SliverMultiBoxAdaptorWidget).estimateMaxScrollOffset(
constraints,
firstIndex!,
lastIndex!,
@ -1345,7 +1344,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
/// See also:
///
/// * [SliverChildDelegate.estimatedChildCount], to which this getter defers.
int? get estimatedChildCount => widget.delegate.estimatedChildCount;
int? get estimatedChildCount => (widget as SliverMultiBoxAdaptorWidget).delegate.estimatedChildCount;
@override
int get childCount {
@ -1358,10 +1357,11 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
// manually.
int lo = 0;
int hi = 1;
final SliverMultiBoxAdaptorWidget adaptorWidget = widget as SliverMultiBoxAdaptorWidget;
const int max = kIsWeb
? 9007199254740992 // max safe integer on JS (from 0 to this number x != x+1)
: ((1 << 63) - 1);
while (_build(hi - 1) != null) {
while (_build(hi - 1, adaptorWidget) != null) {
lo = hi - 1;
if (hi < max ~/ 2) {
hi *= 2;
@ -1369,7 +1369,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
hi = max;
} else {
throw FlutterError(
'Could not find the number of children in ${widget.delegate}.\n'
'Could not find the number of children in ${adaptorWidget.delegate}.\n'
"The childCount getter was called (implying that the delegate's builder returned null "
'for a positive index), but even building the child with index $hi (the maximum '
'possible integer) did not return null. Consider implementing childCount to avoid '
@ -1379,7 +1379,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
}
while (hi - lo > 1) {
final int mid = (hi - lo) ~/ 2 + lo;
if (_build(mid - 1) == null) {
if (_build(mid - 1, adaptorWidget) == null) {
hi = mid;
} else {
lo = mid;
@ -1400,7 +1400,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
assert(debugAssertChildListLocked());
final int firstIndex = _childElements.firstKey() ?? 0;
final int lastIndex = _childElements.lastKey() ?? 0;
widget.delegate.didFinishLayout(firstIndex, lastIndex);
(widget as SliverMultiBoxAdaptorWidget).delegate.didFinishLayout(firstIndex, lastIndex);
}
int? _currentlyUpdatingChildIndex;
@ -1694,12 +1694,9 @@ class SliverOffstage extends SingleChildRenderObjectWidget {
class _SliverOffstageElement extends SingleChildRenderObjectElement {
_SliverOffstageElement(SliverOffstage widget) : super(widget);
@override
SliverOffstage get widget => super.widget as SliverOffstage;
@override
void debugVisitOnstageChildren(ElementVisitor visitor) {
if (!widget.offstage)
if (!(widget as SliverOffstage).offstage)
super.debugVisitOnstageChildren(visitor);
}
}

View file

@ -254,9 +254,6 @@ class _SliverPersistentHeaderElement extends RenderObjectElement {
final bool floating;
@override
_SliverPersistentHeaderRenderObjectWidget get widget => super.widget as _SliverPersistentHeaderRenderObjectWidget;
@override
_RenderSliverPersistentHeaderForWidgetsMixin get renderObject => super.renderObject as _RenderSliverPersistentHeaderForWidgetsMixin;
@ -274,7 +271,7 @@ class _SliverPersistentHeaderElement extends RenderObjectElement {
@override
void update(_SliverPersistentHeaderRenderObjectWidget newWidget) {
final _SliverPersistentHeaderRenderObjectWidget oldWidget = widget;
final _SliverPersistentHeaderRenderObjectWidget oldWidget = widget as _SliverPersistentHeaderRenderObjectWidget;
super.update(newWidget);
final SliverPersistentHeaderDelegate newDelegate = newWidget.delegate;
final SliverPersistentHeaderDelegate oldDelegate = oldWidget.delegate;
@ -293,15 +290,16 @@ class _SliverPersistentHeaderElement extends RenderObjectElement {
void _build(double shrinkOffset, bool overlapsContent) {
owner!.buildScope(this, () {
final _SliverPersistentHeaderRenderObjectWidget sliverPersistentHeaderRenderObjectWidget = widget as _SliverPersistentHeaderRenderObjectWidget;
child = updateChild(
child,
floating
? _FloatingHeader(child: widget.delegate.build(
? _FloatingHeader(child: sliverPersistentHeaderRenderObjectWidget.delegate.build(
this,
shrinkOffset,
overlapsContent
))
: widget.delegate.build(this, shrinkOffset, overlapsContent),
: sliverPersistentHeaderRenderObjectWidget.delegate.build(this, shrinkOffset, overlapsContent),
null,
);
});
@ -371,10 +369,10 @@ mixin _RenderSliverPersistentHeaderForWidgetsMixin on RenderSliverPersistentHead
_SliverPersistentHeaderElement? _element;
@override
double get minExtent => _element!.widget.delegate.minExtent;
double get minExtent => (_element!.widget as _SliverPersistentHeaderRenderObjectWidget).delegate.minExtent;
@override
double get maxExtent => _element!.widget.delegate.maxExtent;
double get maxExtent => (_element!.widget as _SliverPersistentHeaderRenderObjectWidget).delegate.maxExtent;
@override
void updateChild(double shrinkOffset, bool overlapsContent) {

View file

@ -62,9 +62,6 @@ class SliverPrototypeExtentList extends SliverMultiBoxAdaptorWidget {
class _SliverPrototypeExtentListElement extends SliverMultiBoxAdaptorElement {
_SliverPrototypeExtentListElement(SliverPrototypeExtentList widget) : super(widget);
@override
SliverPrototypeExtentList get widget => super.widget as SliverPrototypeExtentList;
@override
_RenderSliverPrototypeExtentList get renderObject => super.renderObject as _RenderSliverPrototypeExtentList;
@ -113,14 +110,14 @@ class _SliverPrototypeExtentListElement extends SliverMultiBoxAdaptorElement {
@override
void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_prototype = updateChild(_prototype, widget.prototypeItem, _prototypeSlot);
_prototype = updateChild(_prototype, (widget as SliverPrototypeExtentList).prototypeItem, _prototypeSlot);
}
@override
void update(SliverPrototypeExtentList newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_prototype = updateChild(_prototype, widget.prototypeItem, _prototypeSlot);
_prototype = updateChild(_prototype, (widget as SliverPrototypeExtentList).prototypeItem, _prototypeSlot);
}
}

View file

@ -191,9 +191,6 @@ class SlottedRenderObjectElement<S> extends RenderObjectElement {
final Map<S, Element> _slotToChild = <S, Element>{};
@override
SlottedMultiChildRenderObjectWidgetMixin<S> get widget => super.widget as SlottedMultiChildRenderObjectWidgetMixin<S>;
@override
SlottedContainerRenderObjectMixin<S> get renderObject => super.renderObject as SlottedContainerRenderObjectMixin<S>;
@ -227,14 +224,15 @@ class SlottedRenderObjectElement<S> extends RenderObjectElement {
List<S>? _debugPreviousSlots;
void _updateChildren() {
final SlottedMultiChildRenderObjectWidgetMixin<S> slottedMultiChildRenderObjectWidgetMixin = widget as SlottedMultiChildRenderObjectWidgetMixin<S>;
assert(() {
_debugPreviousSlots ??= widget.slots.toList();
return listEquals(_debugPreviousSlots, widget.slots.toList());
_debugPreviousSlots ??= slottedMultiChildRenderObjectWidgetMixin.slots.toList();
return listEquals(_debugPreviousSlots, slottedMultiChildRenderObjectWidgetMixin.slots.toList());
}(), '${widget.runtimeType}.slots must not change.');
assert(widget.slots.toSet().length == widget.slots.length, 'slots must be unique');
assert(slottedMultiChildRenderObjectWidgetMixin.slots.toSet().length == slottedMultiChildRenderObjectWidgetMixin.slots.length, 'slots must be unique');
for (final S slot in widget.slots) {
_updateChild(widget.childForSlot(slot), slot);
for (final S slot in slottedMultiChildRenderObjectWidgetMixin.slots) {
_updateChild(slottedMultiChildRenderObjectWidgetMixin.childForSlot(slot), slot);
}
}

View file

@ -284,9 +284,6 @@ class Table extends RenderObjectWidget {
class _TableElement extends RenderObjectElement {
_TableElement(Table widget) : super(widget);
@override
Table get widget => super.widget as Table;
@override
RenderTable get renderObject => super.renderObject as RenderTable;
@ -300,7 +297,7 @@ class _TableElement extends RenderObjectElement {
_doingMountOrUpdate = true;
super.mount(parent, newSlot);
int rowIndex = -1;
_children = widget.children.map<_TableElementRow>((TableRow row) {
_children = (widget as Table).children.map<_TableElementRow>((TableRow row) {
int columnIndex = 0;
rowIndex += 1;
return _TableElementRow(

View file

@ -214,9 +214,6 @@ class _ViewportElement extends MultiChildRenderObjectElement {
bool _doingMountOrUpdate = false;
int? _centerSlotIndex;
@override
Viewport get widget => super.widget as Viewport;
@override
RenderViewport get renderObject => super.renderObject as RenderViewport;
@ -242,10 +239,11 @@ class _ViewportElement extends MultiChildRenderObjectElement {
void _updateCenter() {
// TODO(ianh): cache the keys to make this faster
if (widget.center != null) {
final Viewport viewport = widget as Viewport;
if (viewport.center != null) {
int elementIndex = 0;
for (final Element e in children) {
if (e.widget.key == widget.center) {
if (e.widget.key == viewport.center) {
renderObject.center = e.renderObject as RenderSliver?;
break;
}

View file

@ -709,7 +709,7 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
'therefore no restoration data has been collected to restore from. Did you forget to wrap '
'your widget tree in a RootRestorationScope?',
);
final Widget widget = (binding.renderViewElement! as RenderObjectToWidgetElement<RenderObject>).widget.child!;
final Widget widget = ((binding.renderViewElement! as RenderObjectToWidgetElement<RenderObject>).widget as RenderObjectToWidgetAdapter<RenderObject>).child!;
final TestRestorationData restorationData = binding.restorationManager.restorationData;
runApp(Container(key: UniqueKey()));
await pump();