[flutter_releases] Flutter Framework 1.26.0-17.5.pre Beta Cherrypicks (#75804)

* Added a ReorderableListView.builder constructor (#74697)

Added constructor parameters to the ReorderableList that were missing from ScrollView. Also replace a lot of doc comments with macro templates to reduce duplication.

* [flutter_tools] handle further devtools NPE (#74764)

* [flutter_tools] skip web renderer defines unless web target is picked (#75160)

* Catch VM Service disappearance from run/attach handler code (#75298)

* [flutter_tools] handle null package (#75336)

* Return an empty FlutterViews list when the service disappears (#75301)

* fix analyzer

* Apply Engine Cherrypicks

Co-authored-by: Darren Austin <darrenaustin@google.com>
Co-authored-by: Jonah Williams <jonahwilliams@google.com>
Co-authored-by: Jenn Magder <magder@google.com>
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index ccceb04..190b5ff 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-2c527d6c7e70e2f51bca1a46f1174b250f84c5da
+d4453f601890ec682bbf8f5659b70f15cce1d67d
diff --git a/packages/flutter/lib/src/material/reorderable_list.dart b/packages/flutter/lib/src/material/reorderable_list.dart
index 0b87797..905bcbd 100644
--- a/packages/flutter/lib/src/material/reorderable_list.dart
+++ b/packages/flutter/lib/src/material/reorderable_list.dart
@@ -4,6 +4,7 @@
 
 import 'dart:ui' show lerpDouble;
 
+import 'package:flutter/gestures.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/widgets.dart';
 
@@ -20,7 +21,7 @@
 /// child that could possibly be displayed in the list view instead of just
 /// those children that are actually visible.
 ///
-/// All [children] must have a key.
+/// All list items must have a key.
 ///
 /// {@youtube 560 315 https://www.youtube.com/watch?v=3fB1mxOsqJE}
 ///
@@ -64,18 +65,32 @@
 ///
 ///{@end-tool}
 class ReorderableListView extends StatefulWidget {
-  /// Creates a reorderable list.
+  /// Creates a reorderable list from a pre-built list of widgets.
+  ///
+  /// See also:
+  ///
+  ///   * [ReorderableListView.builder], which allows you to build a reorderable
+  ///     list where the items are built as needed when scrolling the list.
   ReorderableListView({
     Key? key,
-    this.header,
-    required this.children,
+    required List<Widget> children,
     required this.onReorder,
-    this.scrollController,
-    this.scrollDirection = Axis.vertical,
-    this.padding,
-    this.reverse = false,
-    this.buildDefaultDragHandles = true,
     this.proxyDecorator,
+    this.buildDefaultDragHandles = true,
+    this.padding,
+    this.header,
+    this.scrollDirection = Axis.vertical,
+    this.reverse = false,
+    this.scrollController,
+    this.primary,
+    this.physics,
+    this.shrinkWrap = false,
+    this.anchor = 0.0,
+    this.cacheExtent,
+    this.dragStartBehavior = DragStartBehavior.start,
+    this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
+    this.restorationId,
+    this.clipBehavior = Clip.hardEdge,
   }) : assert(scrollDirection != null),
        assert(onReorder != null),
        assert(children != null),
@@ -84,54 +99,70 @@
          'All children of this widget must have a key.',
        ),
        assert(buildDefaultDragHandles != null),
+       itemBuilder = ((BuildContext context, int index) => children[index]),
+       itemCount = children.length,
        super(key: key);
 
-  /// A non-reorderable header widget to show before the list.
+  /// Creates a reorderable list from widget items that are created on demand.
   ///
-  /// If null, no header will appear before the list.
-  final Widget? header;
+  /// This constructor is appropriate for list views with a large number of
+  /// children because the builder is called only for those children
+  /// that are actually visible.
+  ///
+  /// The `itemBuilder` callback will be called only with indices greater than
+  /// or equal to zero and less than `itemCount`.
+  ///
+  /// The `itemBuilder` should always return a non-null widget, and actually
+  /// create the widget instances when called. Avoid using a builder that
+  /// returns a previously-constructed widget; if the list view's children are
+  /// created in advance, or all at once when the [ReorderableListView] itself
+  /// is created, it is more efficient to use the [ReorderableListView]
+  /// constructor. Even more efficient, however, is to create the instances
+  /// on demand using this constructor's `itemBuilder` callback.
+  ///
+  /// See also:
+  ///
+  ///   * [ReorderableListView], which allows you to build a reorderable
+  ///     list with all the items passed into the constructor.
+  const ReorderableListView.builder({
+    Key? key,
+    required this.itemBuilder,
+    required this.itemCount,
+    required this.onReorder,
+    this.proxyDecorator,
+    this.buildDefaultDragHandles = true,
+    this.padding,
+    this.header,
+    this.scrollDirection = Axis.vertical,
+    this.reverse = false,
+    this.scrollController,
+    this.primary,
+    this.physics,
+    this.shrinkWrap = false,
+    this.anchor = 0.0,
+    this.cacheExtent,
+    this.dragStartBehavior = DragStartBehavior.start,
+    this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
+    this.restorationId,
+    this.clipBehavior = Clip.hardEdge,
+  }) : assert(scrollDirection != null),
+       assert(itemCount >= 0),
+       assert(onReorder != null),
+       assert(buildDefaultDragHandles != null),
+       super(key: key);
 
-  /// The widgets to display.
-  final List<Widget> children;
+  /// {@macro flutter.widgets.reorderable_list.itemBuilder}
+  final IndexedWidgetBuilder itemBuilder;
 
-  /// The [Axis] along which the list scrolls.
-  ///
-  /// List [children] can only drag along this [Axis].
-  final Axis scrollDirection;
+  /// {@macro flutter.widgets.reorderable_list.itemCount}
+  final int itemCount;
 
-  /// Creates a [ScrollPosition] to manage and determine which portion
-  /// of the content is visible in the scroll view.
-  ///
-  /// This can be used in many ways, such as setting an initial scroll offset,
-  /// (via [ScrollController.initialScrollOffset]), reading the current scroll position
-  /// (via [ScrollController.offset]), or changing it (via [ScrollController.jumpTo] or
-  /// [ScrollController.animateTo]).
-  final ScrollController? scrollController;
-
-  /// The amount of space by which to inset the [children].
-  final EdgeInsets? padding;
-
-  /// Whether the scroll view scrolls in the reading direction.
-  ///
-  /// For example, if the reading direction is left-to-right and
-  /// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
-  /// left to right when [reverse] is false and from right to left when
-  /// [reverse] is true.
-  ///
-  /// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
-  /// scrolls from top to bottom when [reverse] is false and from bottom to top
-  /// when [reverse] is true.
-  ///
-  /// Defaults to false.
-  final bool reverse;
-
-  /// Called when a list child is dropped into a new position to shuffle the
-  /// underlying list.
-  ///
-  /// This [ReorderableListView] calls [onReorder] after a list child is dropped
-  /// into a new position.
+  /// {@macro flutter.widgets.reorderable_list.onReorder}
   final ReorderCallback onReorder;
 
+  /// {@macro flutter.widgets.reorderable_list.proxyDecorator}
+  final ReorderItemProxyDecorator? proxyDecorator;
+
   /// If true: on desktop platforms, a drag handle is stacked over the
   /// center of each item's trailing edge; on mobile platforms, a long
   /// press anywhere on the item starts a drag.
@@ -201,12 +232,56 @@
   ///{@end-tool}
   final bool buildDefaultDragHandles;
 
-  /// A callback that allows the app to add an animated decoration around
-  /// an item when it is being dragged.
+  /// {@macro flutter.widgets.reorderable_list.padding}
+  final EdgeInsets? padding;
+
+  /// A non-reorderable header item to show before the items of the list.
   ///
-  /// If this is null, a default decoration of a Material widget with
-  /// an animated elevation will be used.
-  final ReorderItemProxyDecorator? proxyDecorator;
+  /// If null, no header will appear before the list.
+  final Widget? header;
+
+  /// {@macro flutter.widgets.scroll_view.scrollDirection}
+  final Axis scrollDirection;
+
+  /// {@macro flutter.widgets.scroll_view.reverse}
+  final bool reverse;
+
+  /// {@macro flutter.widgets.scroll_view.controller}
+  final ScrollController? scrollController;
+
+  /// {@macro flutter.widgets.scroll_view.primary}
+
+  /// Defaults to true when [scrollDirection] is [Axis.vertical] and
+  /// [scrollController] is null.
+  final bool? primary;
+
+  /// {@macro flutter.widgets.scroll_view.physics}
+  final ScrollPhysics? physics;
+
+  /// {@macro flutter.widgets.scroll_view.shrinkWrap}
+  final bool shrinkWrap;
+
+  /// {@macro flutter.widgets.scroll_view.anchor}
+  final double anchor;
+
+  /// {@macro flutter.rendering.RenderViewportBase.cacheExtent}
+  final double? cacheExtent;
+
+  /// {@macro flutter.widgets.scrollable.dragStartBehavior}
+  final DragStartBehavior dragStartBehavior;
+
+  /// {@macro flutter.widgets.scroll_view.keyboardDismissBehavior}
+  ///
+  /// The default is [ScrollViewKeyboardDismissBehavior.manual]
+  final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
+
+  /// {@macro flutter.widgets.scrollable.restorationId}
+  final String? restorationId;
+
+  /// {@macro flutter.material.Material.clipBehavior}
+  ///
+  /// Defaults to [Clip.hardEdge].
+  final Clip clipBehavior;
 
   @override
   _ReorderableListViewState createState() => _ReorderableListViewState();
@@ -230,15 +305,25 @@
       opaque: true,
       builder: (BuildContext context) {
         return _ReorderableListContent(
-          header: widget.header,
-          children: widget.children,
-          scrollController: widget.scrollController,
-          scrollDirection: widget.scrollDirection,
-          padding: widget.padding,
+          itemBuilder: widget.itemBuilder,
+          itemCount: widget.itemCount,
           onReorder: widget.onReorder,
-          reverse: widget.reverse,
-          buildDefaultDragHandles: widget.buildDefaultDragHandles,
           proxyDecorator: widget.proxyDecorator,
+          buildDefaultDragHandles: widget.buildDefaultDragHandles,
+          padding: widget.padding,
+          header: widget.header,
+          scrollDirection: widget.scrollDirection,
+          reverse: widget.reverse,
+          scrollController: widget.scrollController,
+          primary: widget.primary,
+          physics: widget.physics,
+          shrinkWrap: widget.shrinkWrap,
+          anchor: widget.anchor,
+          cacheExtent: widget.cacheExtent,
+          dragStartBehavior: widget.dragStartBehavior,
+          keyboardDismissBehavior: widget.keyboardDismissBehavior,
+          restorationId: widget.restorationId,
+          clipBehavior: widget.clipBehavior,
         );
       },
     );
@@ -265,26 +350,46 @@
 
 class _ReorderableListContent extends StatefulWidget {
   const _ReorderableListContent({
-    required this.header,
-    required this.children,
-    required this.scrollController,
-    required this.scrollDirection,
-    required this.padding,
+    required this.itemBuilder,
+    required this.itemCount,
     required this.onReorder,
-    required this.reverse,
-    required this.buildDefaultDragHandles,
     required this.proxyDecorator,
+    required this.buildDefaultDragHandles,
+    required this.padding,
+    required this.header,
+    required this.scrollDirection,
+    required this.reverse,
+    required this.scrollController,
+    required this.primary,
+    required this.physics,
+    required this.shrinkWrap,
+    required this.anchor,
+    required this.cacheExtent,
+    required this.dragStartBehavior,
+    required this.keyboardDismissBehavior,
+    required this.restorationId,
+    required this.clipBehavior,
   });
 
-  final Widget? header;
-  final List<Widget> children;
-  final ScrollController? scrollController;
-  final Axis scrollDirection;
-  final EdgeInsets? padding;
+  final IndexedWidgetBuilder itemBuilder;
+  final int itemCount;
   final ReorderCallback onReorder;
-  final bool reverse;
-  final bool buildDefaultDragHandles;
   final ReorderItemProxyDecorator? proxyDecorator;
+  final bool buildDefaultDragHandles;
+  final EdgeInsets? padding;
+  final Widget? header;
+  final Axis scrollDirection;
+  final bool reverse;
+  final ScrollController? scrollController;
+  final bool? primary;
+  final ScrollPhysics? physics;
+  final bool shrinkWrap;
+  final double anchor;
+  final double? cacheExtent;
+  final DragStartBehavior dragStartBehavior;
+  final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
+  final String? restorationId;
+  final Clip clipBehavior;
 
   @override
   _ReorderableListContentState createState() => _ReorderableListContentState();
@@ -302,7 +407,7 @@
 
     // Create the appropriate semantics actions.
     void moveToStart() => reorder(index, 0);
-    void moveToEnd() => reorder(index, widget.children.length);
+    void moveToEnd() => reorder(index, widget.itemCount);
     void moveBefore() => reorder(index, index - 1);
     // To move after, we go to index+2 because we are moving it to the space
     // before index+2, which is after the space at index+1.
@@ -323,7 +428,7 @@
     }
 
     // If the item can move to after its current position in the list.
-    if (index < widget.children.length - 1) {
+    if (index < widget.itemCount - 1) {
       String reorderItemAfter = localizations.reorderItemDown;
       if (widget.scrollDirection == Axis.horizontal) {
         reorderItemAfter = Directionality.of(context) == TextDirection.ltr
@@ -349,7 +454,7 @@
   }
 
   Widget _itemBuilder(BuildContext context, int index) {
-    final Widget item = widget.children[index];
+    final Widget item = widget.itemBuilder(context, index);
 
     // TODO(goderbauer): The semantics stuff should probably happen inside
     //   _ReorderableItem so the widget versions can have them as well.
@@ -450,6 +555,15 @@
         scrollDirection: widget.scrollDirection,
         reverse: widget.reverse,
         controller: widget.scrollController,
+        primary: widget.primary,
+        physics: widget.physics,
+        shrinkWrap: widget.shrinkWrap,
+        anchor: widget.anchor,
+        cacheExtent: widget.cacheExtent,
+        dragStartBehavior: widget.dragStartBehavior,
+        keyboardDismissBehavior: widget.keyboardDismissBehavior,
+        restorationId: widget.restorationId,
+        clipBehavior: widget.clipBehavior,
         slivers: <Widget>[
           if (widget.header != null)
             SliverToBoxAdapter(child: widget.header!),
@@ -457,7 +571,7 @@
             padding: listPadding,
             sliver: SliverReorderableList(
               itemBuilder: _itemBuilder,
-              itemCount: widget.children.length,
+              itemCount: widget.itemCount,
               onReorder: widget.onReorder,
               proxyDecorator: widget.proxyDecorator ?? _proxyDecorator,
             ),
diff --git a/packages/flutter/lib/src/widgets/reorderable_list.dart b/packages/flutter/lib/src/widgets/reorderable_list.dart
index cbba955..e47ea0e 100644
--- a/packages/flutter/lib/src/widgets/reorderable_list.dart
+++ b/packages/flutter/lib/src/widgets/reorderable_list.dart
@@ -68,10 +68,10 @@
 /// The [child] will be the item that is being dragged, and [index] is the
 /// position of the item in the list.
 ///
-/// The [animation] will be driven from 0 to 1.0 while the item is being picked
-/// up during a drag operation, and reversed from 1.0 to 0 when the item is
-/// dropped. This can be used to animate properties of the proxy like an
-/// elevation or border.
+/// The [animation] will be driven forward from 0.0 to 1.0 while the item is
+/// being picked up during a drag operation, and reversed from 1.0 to 0.0 when
+/// the item is dropped. This can be used to animate properties of the proxy
+/// like an elevation or border.
 ///
 /// The returned value will typically be the [child] wrapped in other widgets.
 typedef ReorderItemProxyDecorator = Widget Function(Widget child, int index, Animation<double> animation);
@@ -113,16 +113,23 @@
     required this.itemCount,
     required this.onReorder,
     this.proxyDecorator,
+    this.padding,
     this.scrollDirection = Axis.vertical,
     this.reverse = false,
     this.controller,
     this.primary,
     this.physics,
     this.shrinkWrap = false,
-    this.padding,
+    this.anchor = 0.0,
+    this.cacheExtent,
+    this.dragStartBehavior = DragStartBehavior.start,
+    this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
+    this.restorationId,
+    this.clipBehavior = Clip.hardEdge,
   }) : assert(itemCount >= 0),
        super(key: key);
 
+  /// {@template flutter.widgets.reorderable_list.itemBuilder}
   /// Called, as needed, to build list item widgets.
   ///
   /// List items are only built when they're scrolled into view.
@@ -133,91 +140,76 @@
   /// unique [Key], and should have some kind of listener to start the drag
   /// (usually a [ReorderableDragStartListener] or
   /// [ReorderableDelayedDragStartListener]).
+  /// {@endtemplate}
   final IndexedWidgetBuilder itemBuilder;
 
+  /// {@template flutter.widgets.reorderable_list.itemCount}
   /// The number of items in the list.
   ///
   /// It must be a non-negative integer. When zero, nothing is displayed and
   /// the widget occupies no space.
+  /// {@endtemplate}
   final int itemCount;
 
+  /// {@template flutter.widgets.reorderable_list.onReorder}
   /// A callback used by the list to report that a list item has been dragged
   /// to a new location in the list and the application should update the order
   /// of the items.
+  /// {@endtemplate}
   final ReorderCallback onReorder;
 
+  /// {@template flutter.widgets.reorderable_list.proxyDecorator}
   /// A callback that allows the app to add an animated decoration around
   /// an item when it is being dragged.
+  /// {@endtemplate}
   final ReorderItemProxyDecorator? proxyDecorator;
 
-  /// The axis along which the list of items scrolls.
+  /// {@template flutter.widgets.reorderable_list.padding}
+  /// The amount of space by which to inset the list contents.
   ///
-  /// Defaults to [Axis.vertical].
+  /// It defaults to `EdgeInsets.all(0)`.
+  /// {@endtemplate}
+  final EdgeInsetsGeometry? padding;
+
+  /// {@macro flutter.widgets.scroll_view.scrollDirection}
   final Axis scrollDirection;
 
-  /// Whether the scroll view scrolls in the reading direction.
-  ///
-  /// For example, if the reading direction is left-to-right and
-  /// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
-  /// left to right when [reverse] is false and from right to left when
-  /// [reverse] is true.
-  ///
-  /// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
-  /// scrolls from top to bottom when [reverse] is false and from bottom to top
-  /// when [reverse] is true.
-  ///
-  /// Defaults to false.
+  /// {@macro flutter.widgets.scroll_view.reverse}
   final bool reverse;
 
-  /// An object that can be used to control the scroll view's scroll offset.
-  ///
-  /// Must be null if [primary] is true.
-  ///
-  /// A [ScrollController] serves several purposes. It can be used to control
-  /// the initial scroll position (see [ScrollController.initialScrollOffset]).
-  /// It can be used to control whether the scroll view should automatically
-  /// save and restore its scroll position in the [PageStorage] (see
-  /// [ScrollController.keepScrollOffset]). It can be used to read the current
-  /// scroll position (see [ScrollController.offset]), or change it (see
-  /// [ScrollController.animateTo]).
+  /// {@macro flutter.widgets.scroll_view.controller}
   final ScrollController? controller;
 
-  /// Whether this is the primary scroll view associated with the parent
-  /// [PrimaryScrollController].
-  ///
-  /// On iOS, this identifies the scroll view that will scroll to top in
-  /// response to a tap in the status bar.
-  ///
-  /// Defaults to true when [scrollDirection] is [Axis.vertical] and
-  /// [controller] is null.
+  /// {@macro flutter.widgets.scroll_view.primary}
   final bool? primary;
 
-  /// How the scroll view should respond to user input.
-  ///
-  /// For example, determines how the scroll view continues to animate after the
-  /// user stops dragging the scroll view.
-  ///
-  /// Defaults to matching platform conventions.
+  /// {@macro flutter.widgets.scroll_view.physics}
   final ScrollPhysics? physics;
 
-  /// Whether the extent of the scroll view in the [scrollDirection] should be
-  /// determined by the contents being viewed.
-  ///
-  /// If the scroll view does not shrink wrap, then the scroll view will expand
-  /// to the maximum allowed size in the [scrollDirection]. If the scroll view
-  /// has unbounded constraints in the [scrollDirection], then [shrinkWrap] must
-  /// be true.
-  ///
-  /// Shrink wrapping the content of the scroll view is significantly more
-  /// expensive than expanding to the maximum allowed size because the content
-  /// can expand and contract during scrolling, which means the size of the
-  /// scroll view needs to be recomputed whenever the scroll position changes.
-  ///
-  /// Defaults to false.
+  /// {@macro flutter.widgets.scroll_view.shrinkWrap}
   final bool shrinkWrap;
 
-  /// The amount of space by which to inset the children.
-  final EdgeInsetsGeometry? padding;
+  /// {@macro flutter.widgets.scroll_view.anchor}
+  final double anchor;
+
+  /// {@macro flutter.rendering.RenderViewportBase.cacheExtent}
+  final double? cacheExtent;
+
+  /// {@macro flutter.widgets.scrollable.dragStartBehavior}
+  final DragStartBehavior dragStartBehavior;
+
+  /// {@macro flutter.widgets.scroll_view.keyboardDismissBehavior}
+  ///
+  /// The default is [ScrollViewKeyboardDismissBehavior.manual]
+  final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
+
+  /// {@macro flutter.widgets.scrollable.restorationId}
+  final String? restorationId;
+
+  /// {@macro flutter.material.Material.clipBehavior}
+  ///
+  /// Defaults to [Clip.hardEdge].
+  final Clip clipBehavior;
 
   /// The state from the closest instance of this class that encloses the given
   /// context.
@@ -334,6 +326,12 @@
       primary: widget.primary,
       physics: widget.physics,
       shrinkWrap: widget.shrinkWrap,
+      anchor: widget.anchor,
+      cacheExtent: widget.cacheExtent,
+      dragStartBehavior: widget.dragStartBehavior,
+      keyboardDismissBehavior: widget.keyboardDismissBehavior,
+      restorationId: widget.restorationId,
+      clipBehavior: widget.clipBehavior,
       slivers: <Widget>[
         SliverPadding(
           padding: widget.padding ?? EdgeInsets.zero,
@@ -386,28 +384,16 @@
   }) : assert(itemCount >= 0),
        super(key: key);
 
-  /// Called, as needed, to build list item widgets.
-  ///
-  /// List items are only built when they're scrolled into view.
-  ///
-  /// The [IndexedWidgetBuilder] index parameter indicates the item's
-  /// position in the list. The value of the index parameter will be between
-  /// zero and one less than [itemCount]. All items in the list should have a
-  /// unique [Key], and should have some kind of listener to start the drag
-  /// (usually a [ReorderableDragStartListener] or
-  /// [ReorderableDelayedDragStartListener]).
+  /// {@macro flutter.widgets.reorderable_list.itemBuilder}
   final IndexedWidgetBuilder itemBuilder;
 
-  /// The number of items in the list.
+  /// {@macro flutter.widgets.reorderable_list.itemCount}
   final int itemCount;
 
-  /// A callback used by the list to report that a list item has been dragged
-  /// to a new location in the list and the application should update the order
-  /// of the items.
+  /// {@macro flutter.widgets.reorderable_list.onReorder}
   final ReorderCallback onReorder;
 
-  /// A callback that allows the app to add an animated decoration around
-  /// an item when it is being dragged.
+  /// {@macro flutter.widgets.reorderable_list.proxyDecorator}
   final ReorderItemProxyDecorator? proxyDecorator;
 
   @override
diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart
index 29e27db..03558cb 100644
--- a/packages/flutter/lib/src/widgets/scroll_view.dart
+++ b/packages/flutter/lib/src/widgets/scroll_view.dart
@@ -109,11 +109,14 @@
        physics = physics ?? (primary == true || (primary == null && controller == null && identical(scrollDirection, Axis.vertical)) ? const AlwaysScrollableScrollPhysics() : null),
        super(key: key);
 
+  /// {@template flutter.widgets.scroll_view.scrollDirection}
   /// The axis along which the scroll view scrolls.
   ///
   /// Defaults to [Axis.vertical].
+  /// {@endtemplate}
   final Axis scrollDirection;
 
+  /// {@template flutter.widgets.scroll_view.reverse}
   /// Whether the scroll view scrolls in the reading direction.
   ///
   /// For example, if the reading direction is left-to-right and
@@ -126,8 +129,10 @@
   /// when [reverse] is true.
   ///
   /// Defaults to false.
+  /// {@endtemplate}
   final bool reverse;
 
+  /// {@template flutter.widgets.scroll_view.controller}
   /// An object that can be used to control the position to which this scroll
   /// view is scrolled.
   ///
@@ -140,8 +145,10 @@
   /// [ScrollController.keepScrollOffset]). It can be used to read the current
   /// scroll position (see [ScrollController.offset]), or change it (see
   /// [ScrollController.animateTo]).
+  /// {@endtemplate}
   final ScrollController? controller;
 
+  /// {@template flutter.widgets.scroll_view.primary}
   /// Whether this is the primary scroll view associated with the parent
   /// [PrimaryScrollController].
   ///
@@ -156,11 +163,13 @@
   ///
   /// On iOS, this also identifies the scroll view that will scroll to top in
   /// response to a tap in the status bar.
+  /// {@endtemplate}
   ///
   /// Defaults to true when [scrollDirection] is [Axis.vertical] and
   /// [controller] is null.
   final bool primary;
 
+  /// {@template flutter.widgets.scroll_view.physics}
   /// How the scroll view should respond to user input.
   ///
   /// For example, determines how the scroll view continues to animate after the
@@ -195,8 +204,10 @@
   /// dynamically, which can be relatively expensive, and it would be
   /// inefficient to speculatively create this object each frame to see if the
   /// physics should be updated.)
+  /// {@endtemplate}
   final ScrollPhysics? physics;
 
+  /// {@template flutter.widgets.scroll_view.shrinkWrap}
   /// Whether the extent of the scroll view in the [scrollDirection] should be
   /// determined by the contents being viewed.
   ///
@@ -211,6 +222,7 @@
   /// scroll view needs to be recomputed whenever the scroll position changes.
   ///
   /// Defaults to false.
+  /// {@endtemplate}
   final bool shrinkWrap;
 
   /// The first child in the [GrowthDirection.forward] growth direction.
@@ -232,6 +244,7 @@
   ///  * [anchor], which controls where the [center] as aligned in the viewport.
   final Key? center;
 
+  /// {@template flutter.widgets.scroll_view.anchor}
   /// The relative position of the zero scroll offset.
   ///
   /// For example, if [anchor] is 0.5 and the [AxisDirection] determined by
@@ -240,6 +253,7 @@
   /// within the viewport. If the [anchor] is 1.0, and the axis direction is
   /// [AxisDirection.right], then the zero scroll offset is on the left edge of
   /// the viewport.
+  /// {@endtemplate}
   final double anchor;
 
   /// {@macro flutter.rendering.RenderViewportBase.cacheExtent}
@@ -263,8 +277,10 @@
   /// {@macro flutter.widgets.scrollable.dragStartBehavior}
   final DragStartBehavior dragStartBehavior;
 
+  /// {@template flutter.widgets.scroll_view.keyboardDismissBehavior}
   /// [ScrollViewKeyboardDismissBehavior] the defines how this [ScrollView] will
   /// dismiss the keyboard automatically.
+  /// {@endtemplate}
   final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
 
   /// {@macro flutter.widgets.scrollable.restorationId}
diff --git a/packages/flutter/test/material/reorderable_list_test.dart b/packages/flutter/test/material/reorderable_list_test.dart
index 49bda2c..ee43af2 100644
--- a/packages/flutter/test/material/reorderable_list_test.dart
+++ b/packages/flutter/test/material/reorderable_list_test.dart
@@ -1153,6 +1153,34 @@
 
     });
 
+
+    testWidgets('ReorderableListView.builder asserts on negative childCount', (WidgetTester tester) async {
+      expect(() => ReorderableListView.builder(
+        itemBuilder: (BuildContext context, int index) {
+          return const SizedBox();
+        },
+        itemCount: -1,
+        onReorder: (int from, int to) {},
+      ), throwsAssertionError);
+    });
+
+    testWidgets('ReorderableListView.builder only creates the children it needs', (WidgetTester tester) async {
+      final Set<int> itemsCreated = <int>{};
+      await tester.pumpWidget(MaterialApp(
+        home: ReorderableListView.builder(
+          itemBuilder: (BuildContext context, int index) {
+            itemsCreated.add(index);
+            return Text(index.toString(), key: ValueKey<int>(index));
+          },
+          itemCount: 1000,
+          onReorder: (int from, int to) {},
+        ),
+      ));
+
+      // Should have only created the first 18 items.
+      expect(itemsCreated, <int>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17});
+    });
+
     testWidgets('ReorderableListView can be reversed', (WidgetTester tester) async {
       final Widget reorderableListView = ReorderableListView(
         children: const <Widget>[
diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart
index ddc877b..4bf7a1a 100644
--- a/packages/flutter_tools/lib/src/commands/attach.dart
+++ b/packages/flutter_tools/lib/src/commands/attach.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:meta/meta.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../android/android_device.dart';
 import '../artifacts.dart';
@@ -27,6 +28,7 @@
 import '../run_cold.dart';
 import '../run_hot.dart';
 import '../runner/flutter_command.dart';
+import '../vmservice.dart';
 
 /// A Flutter-command that attaches to applications that have been launched
 /// without `flutter run`.
@@ -374,6 +376,11 @@
         }
         globals.printStatus('Waiting for a new connection from Flutter on ${device.name}...');
       }
+    } on RPCError catch (err) {
+      if (err.code == RPCErrorCodes.kServiceDisappeared) {
+        throwToolExit('Lost connection to device.');
+      }
+      rethrow;
     } finally {
       final List<ForwardedPort> ports = device.portForwarder.forwardedPorts.toList();
       for (final ForwardedPort port in ports) {
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index 8b8b343..86a1dd5 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -196,7 +196,7 @@
     ) ?? PackageConfig.empty;
     final DriverService driverService = _flutterDriverFactory.createDriverService(web);
     final BuildInfo buildInfo = await getBuildInfo();
-    final DebuggingOptions debuggingOptions = await createDebuggingOptions();
+    final DebuggingOptions debuggingOptions = await createDebuggingOptions(web);
     final File applicationBinary = stringArg('use-application-binary') == null
       ? null
       : _fileSystem.file(stringArg('use-application-binary'));
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index e9cf68b..af9c4a9 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -4,6 +4,9 @@
 
 import 'dart:async';
 
+import 'package:meta/meta.dart';
+import 'package:vm_service/vm_service.dart';
+
 import '../android/android_device.dart';
 import '../base/common.dart';
 import '../base/file_system.dart';
@@ -20,6 +23,7 @@
 import '../run_hot.dart';
 import '../runner/flutter_command.dart';
 import '../tracing.dart';
+import '../vmservice.dart';
 import '../web/web_runner.dart';
 import 'daemon.dart';
 
@@ -157,8 +161,8 @@
   String get traceAllowlist => stringArg('trace-allowlist');
 
   /// Create a debugging options instance for the current `run` or `drive` invocation.
-  Future<DebuggingOptions> createDebuggingOptions() async {
-    final BuildInfo buildInfo = await getBuildInfo();
+  Future<DebuggingOptions> createDebuggingOptions(bool webMode) async {
+    final BuildInfo buildInfo = await getBuildInfo(updateWebDefines: webMode);
     final int browserDebugPort = featureFlags.isWebEnabled && argResults.wasParsed('web-browser-debug-port')
       ? int.parse(stringArg('web-browser-debug-port'))
       : null;
@@ -320,6 +324,7 @@
   final String description = 'Run your Flutter app on an attached device.';
 
   List<Device> devices;
+  bool webMode = false;
 
   String get userIdentifier => stringArg(FlutterOptions.kDeviceUser);
 
@@ -391,7 +396,7 @@
       }
     }
 
-    final BuildInfo buildInfo = await getBuildInfo();
+    final BuildInfo buildInfo = await getBuildInfo(updateWebDefines: webMode);
     final String modeName = buildInfo.modeName;
     return <CustomDimensions, String>{
       CustomDimensions.commandRunIsEmulator: '$isEmulator',
@@ -446,13 +451,64 @@
         '--${FlutterOptions.kDeviceUser} is only supported for Android. At least one Android device is required.'
       );
     }
+    // Only support "web mode" with a single web device due to resident runner
+    // refactoring required otherwise.
+    webMode = featureFlags.isWebEnabled &&
+      devices.length == 1  &&
+      await devices.single.targetPlatform == TargetPlatform.web_javascript;
+  }
+
+  @visibleForTesting
+  Future<ResidentRunner> createRunner({
+    @required bool hotMode,
+    @required List<FlutterDevice> flutterDevices,
+    @required String applicationBinaryPath,
+    @required FlutterProject flutterProject,
+  }) async {
+    if (hotMode && !webMode) {
+      return HotRunner(
+        flutterDevices,
+        target: targetFile,
+        debuggingOptions: await createDebuggingOptions(webMode),
+        benchmarkMode: boolArg('benchmark'),
+        applicationBinary: applicationBinaryPath == null
+            ? null
+            : globals.fs.file(applicationBinaryPath),
+        projectRootPath: stringArg('project-root'),
+        dillOutputPath: stringArg('output-dill'),
+        stayResident: stayResident,
+        ipv6: ipv6,
+      );
+    } else if (webMode) {
+      return webRunnerFactory.createWebRunner(
+        flutterDevices.single,
+        target: targetFile,
+        flutterProject: flutterProject,
+        ipv6: ipv6,
+        debuggingOptions: await createDebuggingOptions(webMode),
+        stayResident: stayResident,
+        urlTunneller: null,
+      );
+    }
+    return ColdRunner(
+      flutterDevices,
+      target: targetFile,
+      debuggingOptions: await createDebuggingOptions(webMode),
+      traceStartup: traceStartup,
+      awaitFirstFrameWhenTracing: awaitFirstFrameWhenTracing,
+      applicationBinary: applicationBinaryPath == null
+          ? null
+          : globals.fs.file(applicationBinaryPath),
+      ipv6: ipv6,
+      stayResident: stayResident,
+    );
   }
 
   @override
   Future<FlutterCommandResult> runCommand() async {
     // Enable hot mode by default if `--no-hot` was not passed and we are in
     // debug mode.
-    final BuildInfo buildInfo = await getBuildInfo();
+    final BuildInfo buildInfo = await getBuildInfo(updateWebDefines: webMode);
     final bool hotMode = shouldUseHotMode(buildInfo);
     final String applicationBinaryPath = stringArg('use-application-binary');
 
@@ -474,7 +530,7 @@
       try {
         app = await daemon.appDomain.startApp(
           devices.first, globals.fs.currentDirectory.path, targetFile, route,
-          await createDebuggingOptions(), hotMode,
+          await createDebuggingOptions(webMode), hotMode,
           applicationBinary: applicationBinaryPath == null
               ? null
               : globals.fs.file(applicationBinaryPath),
@@ -548,51 +604,13 @@
           platform: globals.platform,
         ),
     ];
-    // Only support "web mode" with a single web device due to resident runner
-    // refactoring required otherwise.
-    final bool webMode = featureFlags.isWebEnabled &&
-                         devices.length == 1  &&
-                         await devices.single.targetPlatform == TargetPlatform.web_javascript;
 
-    ResidentRunner runner;
-    if (hotMode && !webMode) {
-      runner = HotRunner(
-        flutterDevices,
-        target: targetFile,
-        debuggingOptions: await createDebuggingOptions(),
-        benchmarkMode: boolArg('benchmark'),
-        applicationBinary: applicationBinaryPath == null
-            ? null
-            : globals.fs.file(applicationBinaryPath),
-        projectRootPath: stringArg('project-root'),
-        dillOutputPath: stringArg('output-dill'),
-        stayResident: stayResident,
-        ipv6: ipv6,
-      );
-    } else if (webMode) {
-      runner = webRunnerFactory.createWebRunner(
-        flutterDevices.single,
-        target: targetFile,
-        flutterProject: flutterProject,
-        ipv6: ipv6,
-        debuggingOptions: await createDebuggingOptions(),
-        stayResident: stayResident,
-        urlTunneller: null,
-      );
-    } else {
-      runner = ColdRunner(
-        flutterDevices,
-        target: targetFile,
-        debuggingOptions: await createDebuggingOptions(),
-        traceStartup: traceStartup,
-        awaitFirstFrameWhenTracing: awaitFirstFrameWhenTracing,
-        applicationBinary: applicationBinaryPath == null
-            ? null
-            : globals.fs.file(applicationBinaryPath),
-        ipv6: ipv6,
-        stayResident: stayResident,
-      );
-    }
+    final ResidentRunner runner = await createRunner(
+      applicationBinaryPath: applicationBinaryPath,
+      flutterDevices: flutterDevices,
+      flutterProject: flutterProject,
+      hotMode: hotMode,
+    );
 
     DateTime appStartedTime;
     // Sync completer so the completing agent attaching to the resident doesn't
@@ -617,12 +635,19 @@
       }
     ));
 
-    final int result = await runner.run(
-      appStartedCompleter: appStartedTimeRecorder,
-      route: route,
-    );
-    if (result != 0) {
-      throwToolExit(null, exitCode: result);
+    try {
+      final int result = await runner.run(
+        appStartedCompleter: appStartedTimeRecorder,
+        route: route,
+      );
+      if (result != 0) {
+        throwToolExit(null, exitCode: result);
+      }
+    } on RPCError catch (err) {
+      if (err.code == RPCErrorCodes.kServiceDisappeared) {
+        throwToolExit('Lost connection to device.');
+      }
+      rethrow;
     }
     return FlutterCommandResult(
       ExitStatus.success,
diff --git a/packages/flutter_tools/lib/src/dart/language_version.dart b/packages/flutter_tools/lib/src/dart/language_version.dart
index b36faeb..9d60ab8 100644
--- a/packages/flutter_tools/lib/src/dart/language_version.dart
+++ b/packages/flutter_tools/lib/src/dart/language_version.dart
@@ -84,7 +84,7 @@
 
   // If the language version cannot be found, use the package version.
   if (package != null) {
-    return package.languageVersion;
+    return package.languageVersion ?? nullSafeVersion;
   }
   // Default to 2.12
   return nullSafeVersion;
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 005ac07..b2d6c15 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -1301,6 +1301,9 @@
     }
     await waitForExtension(device.vmService, 'ext.flutter.activeDevToolsServerAddress');
     try {
+      if (_devToolsLauncher == null) {
+        return;
+      }
       unawaited(invokeFlutterExtensionRpcRawOnFirstIsolate(
         'ext.flutter.activeDevToolsServerAddress',
         device: device,
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 1d926b3..3f5e9bc 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -803,7 +803,7 @@
   ///
   /// Throws a [ToolExit] if the current set of options is not compatible with
   /// each other.
-  Future<BuildInfo> getBuildInfo({ BuildMode forcedBuildMode }) async {
+  Future<BuildInfo> getBuildInfo({ BuildMode forcedBuildMode, bool updateWebDefines = true }) async {
     final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') &&
       boolArg('track-widget-creation');
 
@@ -923,7 +923,7 @@
         ? stringsArg(FlutterOptions.kDartDefinesOption)
         : <String>[];
 
-    if (argParser.options.containsKey('web-renderer')) {
+    if (argParser.options.containsKey('web-renderer') && updateWebDefines) {
       dartDefines = updateDartDefines(dartDefines, stringArg('web-renderer'));
     }
 
diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart
index 9e45e55..5178606 100644
--- a/packages/flutter_tools/lib/src/vmservice.dart
+++ b/packages/flutter_tools/lib/src/vmservice.dart
@@ -777,7 +777,10 @@
         kListViewsMethod,
       );
       if (response == null) {
-        return null;
+        // The service may have disappeared mid-request.
+        // Return an empty list now, and let the shutdown logic elsewhere deal
+        // with cleaning up.
+        return <FlutterView>[];
       }
       final List<Object> rawViews = response.json['views'] as List<Object>;
       final List<FlutterView> views = <FlutterView>[
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
index 1b69f13..1cd71cb 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -631,6 +631,82 @@
       FileSystem: () => testFileSystem,
       ProcessManager: () => FakeProcessManager.any(),
     });
+
+    testUsingContext('Catches service disappeared error', () async {
+      final MockAndroidDevice device = MockAndroidDevice();
+      final MockHotRunner mockHotRunner = MockHotRunner();
+      final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory();
+      when(device.portForwarder).thenReturn(const NoOpDevicePortForwarder());
+
+      when(mockHotRunner.attach(
+        appStartedCompleter: anyNamed('appStartedCompleter'),
+        allowExistingDdsInstance: true,
+      )).thenAnswer((_) async {
+        await null;
+        throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kServiceDisappeared, '');
+      });
+      when(mockHotRunnerFactory.build(
+        any,
+        target: anyNamed('target'),
+        debuggingOptions: anyNamed('debuggingOptions'),
+        packagesFilePath: anyNamed('packagesFilePath'),
+        flutterProject: anyNamed('flutterProject'),
+        ipv6: false,
+      )).thenReturn(mockHotRunner);
+
+      testDeviceManager.addDevice(device);
+      when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
+        .thenAnswer((_) {
+          return NoOpDeviceLogReader('test');
+        });
+      testFileSystem.file('lib/main.dart').createSync();
+
+      final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory);
+      await expectLater(createTestCommandRunner(command).run(<String>[
+        'attach',
+      ]), throwsToolExit(message: 'Lost connection to device.'));
+    }, overrides: <Type, Generator>{
+      FileSystem: () => testFileSystem,
+      ProcessManager: () => FakeProcessManager.any(),
+    });
+
+    testUsingContext('Does not catch generic RPC error', () async {
+      final MockAndroidDevice device = MockAndroidDevice();
+      final MockHotRunner mockHotRunner = MockHotRunner();
+      final MockHotRunnerFactory mockHotRunnerFactory = MockHotRunnerFactory();
+      when(device.portForwarder).thenReturn(const NoOpDevicePortForwarder());
+
+      when(mockHotRunner.attach(
+        appStartedCompleter: anyNamed('appStartedCompleter'),
+        allowExistingDdsInstance: true,
+      )).thenAnswer((_) async {
+        await null;
+        throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kInvalidParams, '');
+      });
+      when(mockHotRunnerFactory.build(
+        any,
+        target: anyNamed('target'),
+        debuggingOptions: anyNamed('debuggingOptions'),
+        packagesFilePath: anyNamed('packagesFilePath'),
+        flutterProject: anyNamed('flutterProject'),
+        ipv6: false,
+      )).thenReturn(mockHotRunner);
+
+      testDeviceManager.addDevice(device);
+      when(device.getLogReader(includePastLogs: anyNamed('includePastLogs')))
+        .thenAnswer((_) {
+          return NoOpDeviceLogReader('test');
+        });
+      testFileSystem.file('lib/main.dart').createSync();
+
+      final AttachCommand command = AttachCommand(hotRunnerFactory: mockHotRunnerFactory);
+      await expectLater(createTestCommandRunner(command).run(<String>[
+        'attach',
+      ]), throwsA(isA<vm_service.RPCError>()));
+    }, overrides: <Type, Generator>{
+      FileSystem: () => testFileSystem,
+      ProcessManager: () => FakeProcessManager.any(),
+    });
   });
 }
 
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index 8506b83..b3d1276 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -17,11 +17,17 @@
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/commands/run.dart';
+import 'package:flutter_tools/src/convert.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
+import 'package:flutter_tools/src/project.dart';
 import 'package:flutter_tools/src/reporting/reporting.dart';
+import 'package:flutter_tools/src/resident_runner.dart';
 import 'package:flutter_tools/src/runner/flutter_command.dart';
+import 'package:flutter_tools/src/vmservice.dart';
+import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -387,6 +393,66 @@
         ProcessManager: () => mockProcessManager,
         Usage: () => usage,
       });
+
+      testUsingContext('No web renderer options are added to non web device', () async {
+        final FakeApplicationPackageFactory applicationPackageFactory = ApplicationPackageFactory.instance as FakeApplicationPackageFactory;
+        final RunCommand command = RunCommand();
+        final MockDevice mockDevice = MockDevice(TargetPlatform.ios);
+        when(mockDevice.supportsRuntimeMode(any)).thenAnswer((Invocation invocation) => true);
+        when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) => Future<bool>.value(false));
+        when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(FakeDeviceLogReader());
+        when(mockDevice.supportsFastStart).thenReturn(true);
+        when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) => Future<String>.value('iOS 13'));
+        applicationPackageFactory.package = PrebuiltIOSApp(projectBundleId: 'test');
+
+        DebuggingOptions debuggingOptions;
+
+        when(mockDevice.startApp(
+          any,
+          mainPath: anyNamed('mainPath'),
+          debuggingOptions: anyNamed('debuggingOptions'),
+          platformArgs: anyNamed('platformArgs'),
+          route: anyNamed('route'),
+          prebuiltApplication: anyNamed('prebuiltApplication'),
+          ipv6: anyNamed('ipv6'),
+          userIdentifier: anyNamed('userIdentifier'),
+        )).thenAnswer((Invocation invocation) {
+          debuggingOptions = invocation.namedArguments[#debuggingOptions] as DebuggingOptions;
+          return Future<LaunchResult>.value(LaunchResult.failed());
+        });
+
+        when(mockDeviceManager.getDevices()).thenAnswer(
+          (Invocation invocation) => Future<List<Device>>.value(<Device>[mockDevice])
+        );
+
+        when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
+          (Invocation invocation) => Future<List<Device>>.value(<Device>[mockDevice])
+        );
+
+        final Directory tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_run_test.');
+        tempDir.childDirectory('ios').childFile('AppDelegate.swift').createSync(recursive: true);
+        tempDir.childFile('.dart_tool/package_config')
+          ..createSync(recursive: true)
+          ..writeAsStringSync(json.encode(<String, Object>{'configVersion': 2, 'packages': <Object>[]}));
+        tempDir.childDirectory('lib').childFile('main.dart').createSync(recursive: true);
+        tempDir.childFile('pubspec.yaml').writeAsStringSync('name: test');
+        globals.fs.currentDirectory = tempDir;
+
+        await expectToolExitLater(createTestCommandRunner(command).run(<String>[
+          'run',
+          '--no-pub',
+          '--no-hot',
+        ]), isNull);
+        // No web renderer options are added.
+        expect(debuggingOptions.buildInfo.dartDefines, isEmpty);
+      }, overrides: <Type, Generator>{
+        Artifacts: () => artifacts,
+        Cache: () => mockCache,
+        DeviceManager: () => mockDeviceManager,
+        FileSystem: () => fs,
+        ProcessManager: () => mockProcessManager,
+        ApplicationPackageFactory: () => FakeApplicationPackageFactory(),
+      });
     });
 
     testUsingContext('should only request artifacts corresponding to connected devices', () async {
@@ -480,6 +546,30 @@
       expect(dartDefines, <String>['FLUTTER_WEB_AUTO_DETECT=false','FLUTTER_WEB_USE_SKIA=false']);
     });
   });
+
+  testUsingContext('Flutter run catches service has disappear errors and throws a tool exit', () async {
+    final FakeResidentRunner residentRunner = FakeResidentRunner();
+    residentRunner.rpcError = RPCError('flutter._listViews', RPCErrorCodes.kServiceDisappeared, '');
+    final TestRunCommandWithFakeResidentRunner command = TestRunCommandWithFakeResidentRunner();
+    command.fakeResidentRunner = residentRunner;
+
+    await expectToolExitLater(createTestCommandRunner(command).run(<String>[
+      'run',
+      '--no-pub',
+    ]), contains('Lost connection to device.'));
+  });
+
+  testUsingContext('Flutter run does not catch other RPC errors', () async {
+    final FakeResidentRunner residentRunner = FakeResidentRunner();
+    residentRunner.rpcError = RPCError('flutter._listViews', RPCErrorCodes.kInvalidParams, '');
+    final TestRunCommandWithFakeResidentRunner command = TestRunCommandWithFakeResidentRunner();
+    command.fakeResidentRunner = residentRunner;
+
+    await expectLater(() => createTestCommandRunner(command).run(<String>[
+      'run',
+      '--no-pub',
+    ]), throwsA(isA<RPCError>()));
+  });
 }
 
 class MockCache extends Mock implements Cache {}
@@ -524,7 +614,7 @@
   bool supportsRuntimeMode(BuildMode mode) => true;
 
   @override
-  bool get supportsHotReload => false;
+  bool supportsHotReload = false;
 
   @override
   bool get supportsFastStart => false;
@@ -579,3 +669,54 @@
     return null;
   }
 }
+
+class FakeApplicationPackageFactory extends Fake implements ApplicationPackageFactory {
+  ApplicationPackage package;
+
+  @override
+  Future<ApplicationPackage> getPackageForPlatform(
+    TargetPlatform platform, {
+    BuildInfo buildInfo,
+    File applicationBinary,
+  }) async {
+    return package;
+  }
+}
+
+class TestRunCommandWithFakeResidentRunner extends RunCommand {
+  FakeResidentRunner fakeResidentRunner;
+
+  @override
+  Future<ResidentRunner> createRunner({
+    @required bool hotMode,
+    @required List<FlutterDevice> flutterDevices,
+    @required String applicationBinaryPath,
+    @required FlutterProject flutterProject,
+  }) async {
+    return fakeResidentRunner;
+  }
+
+  @override
+  // ignore: must_call_super
+  Future<void> validateCommand() async {
+    devices = <Device>[FakeDevice()..supportsHotReload = true];
+  }
+}
+
+class FakeResidentRunner extends Fake implements ResidentRunner {
+  RPCError rpcError;
+
+  @override
+  Future<int> run({
+    Completer<DebugConnectionInfo> connectionInfoCompleter,
+    Completer<void> appStartedCompleter,
+    bool enableDevTools = false,
+    String route,
+  }) async {
+    await null;
+    if (rpcError != null) {
+      throw rpcError;
+    }
+    return 0;
+  }
+}
diff --git a/packages/flutter_tools/test/general.shard/dart/language_version_test.dart b/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
index 1abebfc..47bb5a0 100644
--- a/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
+++ b/packages/flutter_tools/test/general.shard/dart/language_version_test.dart
@@ -252,6 +252,20 @@
     expect(determineLanguageVersion(file, package), LanguageVersion(2, 7));
   });
 
+  testWithoutContext('defaults to null safe version if package lookup returns null', () {
+    final FileSystem fileSystem = MemoryFileSystem.test();
+    final File file = fileSystem.file('example.dart')
+      ..writeAsStringSync('''
+// Some license
+''');
+    final Package package = Package(
+      'foo',
+      Uri.parse('file://foo/'),
+      languageVersion: null,
+    );
+
+    expect(determineLanguageVersion(file, package), LanguageVersion(2, 12));
+  });
 
   testWithoutContext('Returns null safe error if reading the file throws a FileSystemException', () {
     final Package package = Package(
diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart
index 2edce09..57b1547 100644
--- a/packages/flutter_tools/test/general.shard/vmservice_test.dart
+++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart
@@ -354,7 +354,7 @@
     expect(skSLs, isNull);
 
     final List<FlutterView> views = await fakeVmServiceHost.vmService.getFlutterViews();
-    expect(views, isNull);
+    expect(views, isEmpty);
 
     final vm_service.Response screenshot = await fakeVmServiceHost.vmService.screenshot();
     expect(screenshot, isNull);