Add MediaQuery to View (#118004)

* Add MediaQuery to View

* unify API

* fix test

* add test

* comment

* better doc

* Apply suggestions from code review

Co-authored-by: Greg Spencer <gspencergoog@users.noreply.github.com>

Co-authored-by: Greg Spencer <gspencergoog@users.noreply.github.com>
diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart
index 931623c..9e915a7 100644
--- a/packages/flutter/lib/src/widgets/app.dart
+++ b/packages/flutter/lib/src/widgets/app.dart
@@ -1730,8 +1730,7 @@
       child: title,
     );
 
-    final MediaQueryData? data = MediaQuery.maybeOf(context);
-    if (!widget.useInheritedMediaQuery || data == null) {
+    if (!widget.useInheritedMediaQuery || MediaQuery.maybeOf(context) == null) {
       child = MediaQuery.fromWindow(
         child: child,
       );
diff --git a/packages/flutter/lib/src/widgets/media_query.dart b/packages/flutter/lib/src/widgets/media_query.dart
index 890dd98..68f38b6 100644
--- a/packages/flutter/lib/src/widgets/media_query.dart
+++ b/packages/flutter/lib/src/widgets/media_query.dart
@@ -138,8 +138,8 @@
 class MediaQueryData {
   /// Creates data for a media query with explicit values.
   ///
-  /// Consider using [MediaQueryData.fromWindow] to create data based on a
-  /// [dart:ui.PlatformDispatcher].
+  /// Consider using [MediaQueryData.fromView] to create data based on a
+  /// [dart:ui.FlutterView].
   const MediaQueryData({
     this.size = Size.zero,
     this.devicePixelRatio = 1.0,
@@ -167,24 +167,60 @@
   /// window's metrics change. For example, see
   /// [WidgetsBindingObserver.didChangeMetrics] or
   /// [dart:ui.PlatformDispatcher.onMetricsChanged].
-  MediaQueryData.fromWindow(ui.FlutterView window)
-    : size = window.physicalSize / window.devicePixelRatio,
-      devicePixelRatio = window.devicePixelRatio,
-      textScaleFactor = window.platformDispatcher.textScaleFactor,
-      platformBrightness = window.platformDispatcher.platformBrightness,
-      padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio),
-      viewPadding = EdgeInsets.fromWindowPadding(window.viewPadding, window.devicePixelRatio),
-      viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio),
-      systemGestureInsets = EdgeInsets.fromWindowPadding(window.systemGestureInsets, window.devicePixelRatio),
-      accessibleNavigation = window.platformDispatcher.accessibilityFeatures.accessibleNavigation,
-      invertColors = window.platformDispatcher.accessibilityFeatures.invertColors,
-      disableAnimations = window.platformDispatcher.accessibilityFeatures.disableAnimations,
-      boldText = window.platformDispatcher.accessibilityFeatures.boldText,
-      highContrast = window.platformDispatcher.accessibilityFeatures.highContrast,
-      alwaysUse24HourFormat = window.platformDispatcher.alwaysUse24HourFormat,
-      navigationMode = NavigationMode.traditional,
-      gestureSettings = DeviceGestureSettings.fromWindow(window),
-      displayFeatures = window.displayFeatures;
+  factory MediaQueryData.fromWindow(ui.FlutterView window) => MediaQueryData.fromView(window);
+
+  /// Creates data for a [MediaQuery] based on the given `view`.
+  ///
+  /// If provided, the `platformData` is used to fill in the platform-specific
+  /// aspects of the newly created [MediaQueryData]. If `platformData` is null,
+  /// the `view`'s [PlatformDispatcher] is consulted to construct the
+  /// platform-specific data.
+  ///
+  /// Data which is exposed directly on the [FlutterView] is considered
+  /// view-specific. Data which is only exposed via the
+  /// [FlutterView.platformDispatcher] property is considered platform-specific.
+  ///
+  /// Callers of this method should ensure that they also register for
+  /// notifications so that the [MediaQueryData] can be updated when any data
+  /// used to construct it changes. Notifications to consider are:
+  ///
+  ///  * [WidgetsBindingObserver.didChangeMetrics] or
+  ///    [dart:ui.PlatformDispatcher.onMetricsChanged],
+  ///  * [WidgetsBindingObserver.didChangeAccessibilityFeatures] or
+  ///    [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged],
+  ///  * [WidgetsBindingObserver.didChangeTextScaleFactor] or
+  ///    [dart:ui.PlatformDispatcher.onTextScaleFactorChanged],
+  ///  * [WidgetsBindingObserver.didChangePlatformBrightness] or
+  ///    [dart:ui.PlatformDispatcher.onPlatformBrightnessChanged].
+  ///
+  /// The last three notifications are only relevant if no `platformData` is
+  /// provided. If `platformData` is provided, callers should ensure to call
+  /// this method again when it changes to keep the constructed [MediaQueryData]
+  /// updated.
+  ///
+  /// See also:
+  ///
+  ///  * [MediaQuery.fromView], which constructs [MediaQueryData] from a provided
+  ///    [FlutterView], makes it available to descendant widgets, and sets up
+  ///    the appropriate notification listeners to keep the data updated.
+  MediaQueryData.fromView(ui.FlutterView view, {MediaQueryData? platformData})
+    : size = view.physicalSize / view.devicePixelRatio,
+      devicePixelRatio = view.devicePixelRatio,
+      textScaleFactor = platformData?.textScaleFactor ?? view.platformDispatcher.textScaleFactor,
+      platformBrightness = platformData?.platformBrightness ?? view.platformDispatcher.platformBrightness,
+      padding = EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio),
+      viewPadding = EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio),
+      viewInsets = EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio),
+      systemGestureInsets = EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio),
+      accessibleNavigation = platformData?.accessibleNavigation ?? view.platformDispatcher.accessibilityFeatures.accessibleNavigation,
+      invertColors = platformData?.invertColors ?? view.platformDispatcher.accessibilityFeatures.invertColors,
+      disableAnimations = platformData?.disableAnimations ?? view.platformDispatcher.accessibilityFeatures.disableAnimations,
+      boldText = platformData?.boldText ?? view.platformDispatcher.accessibilityFeatures.boldText,
+      highContrast = platformData?.highContrast ?? view.platformDispatcher.accessibilityFeatures.highContrast,
+      alwaysUse24HourFormat = platformData?.alwaysUse24HourFormat ?? view.platformDispatcher.alwaysUse24HourFormat,
+      navigationMode = platformData?.navigationMode ?? NavigationMode.traditional,
+      gestureSettings = DeviceGestureSettings.fromWindow(view),
+      displayFeatures = view.displayFeatures;
 
   /// The size of the media in logical pixels (e.g, the size of the screen).
   ///
@@ -889,17 +925,43 @@
   /// and its dependents are updated when `window` changes, instead of
   /// rebuilding the whole widget tree.
   ///
-  /// This should be inserted into the widget tree when the [MediaQuery] view
-  /// padding is consumed by a widget in such a way that the view padding is no
-  /// longer exposed to the widget's descendants or siblings.
-  ///
   /// The [child] argument is required and must not be null.
   static Widget fromWindow({
     Key? key,
     required Widget child,
   }) {
-    return _MediaQueryFromWindow(
+    return _MediaQueryFromView(
       key: key,
+      view: WidgetsBinding.instance.window,
+      ignoreParentData: true,
+      child: child,
+    );
+  }
+
+  /// Wraps the [child] in a [MediaQuery] which is built using data from the
+  /// provided [view].
+  ///
+  /// The [MediaQuery] is constructed using the platform-specific data of the
+  /// surrounding [MediaQuery] and the view-specific data of the provided
+  /// [view]. If no surrounding [MediaQuery] exists, the platform-specific data
+  /// is generated from the [PlatformDispatcher] associated with the provided
+  /// [view]. Any information that's exposed via the [PlatformDispatcher] is
+  /// considered platform-specific. Data exposed directly on the [FlutterView]
+  /// (excluding its [FlutterView.platformDispatcher] property) is considered
+  /// view-specific.
+  ///
+  /// The injected [MediaQuery] automatically updates when any of the data used
+  /// to construct it changes.
+  ///
+  /// The [view] and [child] argument is required and must not be null.
+  static Widget fromView({
+    Key? key,
+    required FlutterView view,
+    required Widget child,
+  }) {
+    return _MediaQueryFromView(
+      key: key,
+      view: view,
       child: child,
     );
   }
@@ -1399,94 +1461,102 @@
   directional,
 }
 
-/// Provides a [MediaQuery] which is built and updated using the latest
-/// [WidgetsBinding.window] values.
-///
-/// Receives `window` updates by listening to [WidgetsBinding].
-///
-/// The standalone widget ensures that it rebuilds **only** [MediaQuery] and
-/// its dependents when `window` changes, instead of rebuilding the entire
-/// widget tree.
-///
-/// It is used by [WidgetsApp] if no other [MediaQuery] is available above it.
-///
-/// See also:
-///
-///  * [MediaQuery], which establishes a subtree in which media queries resolve
-///    to a [MediaQueryData].
-class _MediaQueryFromWindow extends StatefulWidget {
-  /// Creates a [_MediaQueryFromWindow] that provides a [MediaQuery] to its
-  /// descendants using the `window` to keep [MediaQueryData] up to date.
-  ///
-  /// The [child] must not be null.
-  const _MediaQueryFromWindow({
+class _MediaQueryFromView extends StatefulWidget {
+  const _MediaQueryFromView({
     super.key,
+    required this.view,
+    this.ignoreParentData = false,
     required this.child,
   });
 
-  /// {@macro flutter.widgets.ProxyWidget.child}
+  final FlutterView view;
+  final bool ignoreParentData;
   final Widget child;
 
   @override
-  State<_MediaQueryFromWindow> createState() => _MediaQueryFromWindowState();
+  State<_MediaQueryFromView> createState() => _MediaQueryFromViewState();
 }
 
-class _MediaQueryFromWindowState extends State<_MediaQueryFromWindow> with WidgetsBindingObserver {
+class _MediaQueryFromViewState extends State<_MediaQueryFromView> with WidgetsBindingObserver {
+  MediaQueryData? _parentData;
+  MediaQueryData? _data;
+
   @override
   void initState() {
     super.initState();
     WidgetsBinding.instance.addObserver(this);
   }
 
-  // ACCESSIBILITY
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    _updateParentData();
+    _updateData();
+    assert(_data != null);
+  }
+
+  @override
+  void didUpdateWidget(_MediaQueryFromView oldWidget) {
+    super.didUpdateWidget(oldWidget);
+    if (widget.ignoreParentData != oldWidget.ignoreParentData) {
+      _updateParentData();
+    }
+    if (_data == null || oldWidget.view != widget.view) {
+      _updateData();
+    }
+    assert(_data != null);
+  }
+
+  void _updateParentData() {
+    _parentData = widget.ignoreParentData ? null : MediaQuery.maybeOf(context);
+    _data = null; // _updateData must be called again after changing parent data.
+  }
+
+  void _updateData() {
+    final MediaQueryData newData = MediaQueryData.fromView(widget.view, platformData: _parentData);
+    if (newData != _data) {
+      setState(() {
+        _data = newData;
+      });
+    }
+  }
 
   @override
   void didChangeAccessibilityFeatures() {
-    setState(() {
-      // The properties of window have changed. We use them in our build
-      // function, so we need setState(), but we don't cache anything locally.
-    });
+    // If we have a parent, it dictates our accessibility features. If we don't
+    // have a parent, we get our accessibility features straight from the
+    // PlatformDispatcher and need to update our data in response to the
+    // PlatformDispatcher changing its accessibility features setting.
+    if (_parentData == null) {
+      _updateData();
+    }
   }
 
-  // METRICS
-
   @override
   void didChangeMetrics() {
-    setState(() {
-      // The properties of window have changed. We use them in our build
-      // function, so we need setState(), but we don't cache anything locally.
-    });
+    _updateData();
   }
 
   @override
   void didChangeTextScaleFactor() {
-    setState(() {
-      // The textScaleFactor property of window has changed. We reference
-      // window in our build function, so we need to call setState(), but
-      // we don't need to cache anything locally.
-    });
+    // If we have a parent, it dictates our text scale factor. If we don't have
+    // a parent, we get our text scale factor from the PlatformDispatcher and
+    // need to update our data in response to the PlatformDispatcher changing
+    // its text scale factor setting.
+    if (_parentData == null) {
+      _updateData();
+    }
   }
 
-  // RENDERING
   @override
   void didChangePlatformBrightness() {
-    setState(() {
-      // The platformBrightness property of window has changed. We reference
-      // window in our build function, so we need to call setState(), but
-      // we don't need to cache anything locally.
-    });
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
-    if (!kReleaseMode) {
-      data = data.copyWith(platformBrightness: debugBrightnessOverride);
+    // If we have a parent, it dictates our platform brightness. If we don't
+    // have a parent, we get our platform brightness from the PlatformDispatcher
+    // and need to update our data in response to the PlatformDispatcher
+    // changing its platform brightness setting.
+    if (_parentData == null) {
+      _updateData();
     }
-    return MediaQuery(
-      data: data,
-      child: widget.child,
-    );
   }
 
   @override
@@ -1494,4 +1564,18 @@
     WidgetsBinding.instance.removeObserver(this);
     super.dispose();
   }
+
+  @override
+  Widget build(BuildContext context) {
+    MediaQueryData effectiveData = _data!;
+    // If we get our platformBrightness from the PlatformDispatcher (i.e. we have no parentData) replace it
+    // with the debugBrightnessOverride in non-release mode.
+    if (!kReleaseMode && _parentData == null && effectiveData.platformBrightness != debugBrightnessOverride) {
+      effectiveData = effectiveData.copyWith(platformBrightness: debugBrightnessOverride);
+    }
+    return MediaQuery(
+      data: effectiveData,
+      child: widget.child,
+    );
+  }
 }
diff --git a/packages/flutter/lib/src/widgets/view.dart b/packages/flutter/lib/src/widgets/view.dart
index 0a20685..14f87c6 100644
--- a/packages/flutter/lib/src/widgets/view.dart
+++ b/packages/flutter/lib/src/widgets/view.dart
@@ -6,10 +6,14 @@
 
 import 'framework.dart';
 import 'lookup_boundary.dart';
+import 'media_query.dart';
 
 /// Injects a [FlutterView] into the tree and makes it available to descendants
 /// within the same [LookupBoundary] via [View.of] and [View.maybeOf].
 ///
+/// The provided [child] is wrapped in a [MediaQuery] constructed from the given
+/// [view].
+///
 /// In a future version of Flutter, the functionality of this widget will be
 /// extended to actually bootstrap the render tree that is going to be rendered
 /// into the provided [view]. This will enable rendering content into multiple
@@ -20,15 +24,26 @@
 /// [FlutterView] must never exist within the same widget tree at the same time.
 /// Internally, this limitation is enforced by a [GlobalObjectKey] that derives
 /// its identity from the [view] provided to this widget.
-class View extends InheritedWidget {
+class View extends StatelessWidget {
   /// Injects the provided [view] into the widget tree.
-  View({required this.view, required super.child}) : super(key: GlobalObjectKey(view));
+  View({required this.view, required this.child}) : super(key: GlobalObjectKey(view));
 
   /// The [FlutterView] to be injected into the tree.
   final FlutterView view;
 
+  /// {@macro flutter.widgets.ProxyWidget.child}
+  final Widget child;
+
   @override
-  bool updateShouldNotify(View oldWidget) => view != oldWidget.view;
+  Widget build(BuildContext context) {
+    return _ViewScope(
+      view: view,
+      child: MediaQuery.fromView(
+        view: view,
+        child: child,
+      ),
+    );
+  }
 
   /// Returns the [FlutterView] that the provided `context` will render into.
   ///
@@ -47,7 +62,7 @@
   ///  * [View.of], which throws instead of returning null if no [FlutterView]
   ///    is found.
   static FlutterView? maybeOf(BuildContext context) {
-    return LookupBoundary.dependOnInheritedWidgetOfExactType<View>(context)?.view;
+    return LookupBoundary.dependOnInheritedWidgetOfExactType<_ViewScope>(context)?.view;
   }
 
   /// Returns the [FlutterView] that the provided `context` will render into.
@@ -70,7 +85,7 @@
     final FlutterView? result = maybeOf(context);
     assert(() {
       if (result == null) {
-        final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<View>(context);
+        final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<_ViewScope>(context);
         final List<DiagnosticsNode> information = <DiagnosticsNode>[
           if (hiddenByBoundary) ...<DiagnosticsNode>[
             ErrorSummary('View.of() was called with a context that does not have access to a View widget.'),
@@ -92,3 +107,12 @@
     return result!;
   }
 }
+
+class _ViewScope extends InheritedWidget {
+  const _ViewScope({required this.view, required super.child});
+
+  final FlutterView view;
+
+  @override
+  bool updateShouldNotify(_ViewScope oldWidget) => view != oldWidget.view;
+}
diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart
index b955a1c..c9f7a3b 100644
--- a/packages/flutter/test/material/debug_test.dart
+++ b/packages/flutter/test/material/debug_test.dart
@@ -193,7 +193,7 @@
       '     Semantics\n'
       '     Localizations\n'
       '     MediaQuery\n'
-      '     _MediaQueryFromWindow\n'
+      '     _MediaQueryFromView\n'
       '     Semantics\n'
       '     _FocusInheritedScope\n'
       '     Focus\n'
@@ -235,6 +235,9 @@
       '     HeroControllerScope\n'
       '     ScrollConfiguration\n'
       '     MaterialApp\n'
+      '     MediaQuery\n'
+      '     _MediaQueryFromView\n'
+      '     _ViewScope\n'
       '     View-[GlobalObjectKey TestWindow#00000]\n'
       '     [root]\n'
       '   Typically, the Scaffold widget is introduced by the MaterialApp\n'
@@ -251,18 +254,15 @@
     );
     await tester.pumpWidget(Directionality(
       textDirection: TextDirection.ltr,
-      child: MediaQuery(
-        data: const MediaQueryData(),
-        child: ScaffoldMessenger(
-          key: scaffoldMessengerKey,
-          child: Builder(
-            builder: (BuildContext context) {
-              return Scaffold(
-                key: scaffoldKey,
-                body: Container(),
-              );
-            },
-          ),
+      child: ScaffoldMessenger(
+        key: scaffoldMessengerKey,
+        child: Builder(
+          builder: (BuildContext context) {
+            return Scaffold(
+              key: scaffoldKey,
+              body: Container(),
+            );
+          },
         ),
       ),
     ));
@@ -278,12 +278,9 @@
     // Pump widget to rebuild without ScaffoldMessenger
     await tester.pumpWidget(Directionality(
       textDirection: TextDirection.ltr,
-      child: MediaQuery(
-        data: const MediaQueryData(),
-        child: Scaffold(
-          key: scaffoldKey,
-          body: Container(),
-        ),
+      child: Scaffold(
+        key: scaffoldKey,
+        body: Container(),
       ),
     ));
     // Tap SnackBarAction to dismiss.
@@ -378,8 +375,10 @@
       '     ScrollNotificationObserver\n'
       '     _ScaffoldScope\n'
       '     Scaffold-[LabeledGlobalKey<ScaffoldState>#00000]\n'
-      '     MediaQuery\n'
       '     Directionality\n'
+      '     MediaQuery\n'
+      '     _MediaQueryFromView\n'
+      '     _ViewScope\n'
       '     View-[GlobalObjectKey TestWindow#00000]\n'
       '     [root]\n'
       '   Typically, the ScaffoldMessenger widget is introduced by the\n'
diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart
index 12709de..f905d0c 100644
--- a/packages/flutter/test/material/scaffold_test.dart
+++ b/packages/flutter/test/material/scaffold_test.dart
@@ -136,12 +136,6 @@
         ),
       );
     }
-    await tester.pumpWidget(boilerplate(Scaffold(
-        appBar: AppBar(title: const Text('Title')),
-        body: Container(key: bodyKey),
-      ),
-    ));
-    expect(tester.takeException(), isFlutterError);
 
     await tester.pumpWidget(MaterialApp(
       home: Scaffold(
@@ -2391,24 +2385,21 @@
 
     await tester.pumpWidget(Directionality(
       textDirection: TextDirection.ltr,
-      child: MediaQuery(
-        data: const MediaQueryData(),
-        child: Scaffold(
-          body: Builder(
-            builder: (BuildContext context) {
-              return GestureDetector(
-                key: tapTarget,
-                onTap: () {
-                  ScaffoldMessenger.of(context);
-                },
-                behavior: HitTestBehavior.opaque,
-                child: const SizedBox(
-                  height: 100.0,
-                  width: 100.0,
-                ),
-              );
-            },
-          ),
+      child: Scaffold(
+        body: Builder(
+          builder: (BuildContext context) {
+            return GestureDetector(
+              key: tapTarget,
+              onTap: () {
+                ScaffoldMessenger.of(context);
+              },
+              behavior: HitTestBehavior.opaque,
+              child: const SizedBox(
+                height: 100.0,
+                width: 100.0,
+              ),
+            );
+          },
         ),
       ),
     ));
@@ -2459,8 +2450,10 @@
       '     ScrollNotificationObserver\n'
       '     _ScaffoldScope\n'
       '     Scaffold\n'
-      '     MediaQuery\n'
       '     Directionality\n'
+      '     MediaQuery\n'
+      '     _MediaQueryFromView\n'
+      '     _ViewScope\n'
       '     View-[GlobalObjectKey TestWindow#e6136]\n'
       '     [root]\n'
       '   Typically, the ScaffoldMessenger widget is introduced by the\n'
diff --git a/packages/flutter/test/widgets/animated_container_test.dart b/packages/flutter/test/widgets/animated_container_test.dart
index 476df62..ce9f17c 100644
--- a/packages/flutter/test/widgets/animated_container_test.dart
+++ b/packages/flutter/test/widgets/animated_container_test.dart
@@ -77,7 +77,7 @@
         ' │ decoration: BoxDecoration:\n'
         ' │   color: Color(0xff0000ff)\n'
         ' │ configuration: ImageConfiguration(bundle:\n'
-        ' │   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        ' │   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         ' │   android)\n'
         ' │\n'
         ' └─child: RenderLimitedBox#00000\n'
diff --git a/packages/flutter/test/widgets/app_test.dart b/packages/flutter/test/widgets/app_test.dart
index 6bcf5c1..6d58a4a 100644
--- a/packages/flutter/test/widgets/app_test.dart
+++ b/packages/flutter/test/widgets/app_test.dart
@@ -644,6 +644,32 @@
     expect(MediaQuery.of(capturedContext), isNotNull);
   });
 
+  testWidgets("WidgetsApp doesn't have dependency on MediaQuery", (WidgetTester tester) async {
+    int routeBuildCount = 0;
+
+    final Widget widget = WidgetsApp(
+      color: const Color.fromARGB(255, 255, 255, 255),
+      onGenerateRoute: (_) {
+        return PageRouteBuilder<void>(pageBuilder: (_, __, ___) {
+          routeBuildCount++;
+          return const Placeholder();
+        });
+      },
+    );
+
+    await tester.pumpWidget(
+      MediaQuery(data: const MediaQueryData(textScaleFactor: 10), child: widget),
+    );
+
+    expect(routeBuildCount, equals(1));
+
+    await tester.pumpWidget(
+      MediaQuery(data: const MediaQueryData(textScaleFactor: 20), child: widget),
+    );
+
+    expect(routeBuildCount, equals(1));
+  });
+
   testWidgets('WidgetsApp provides meta based shortcuts for iOS and macOS', (WidgetTester tester) async {
     final FocusNode focusNode = FocusNode();
     final SelectAllSpy selectAllSpy = SelectAllSpy();
diff --git a/packages/flutter/test/widgets/container_test.dart b/packages/flutter/test/widgets/container_test.dart
index 7e3a507..28c3ef6 100644
--- a/packages/flutter/test/widgets/container_test.dart
+++ b/packages/flutter/test/widgets/container_test.dart
@@ -78,7 +78,7 @@
         '     │ decoration: BoxDecoration:\n'
         '     │   color: Color(0x7f0000ff)\n'
         '     │ configuration: ImageConfiguration(bundle:\n'
-        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         '     │   android)\n'
         '     │\n'
         '     └─child: _RenderColoredBox#00000\n'
@@ -114,7 +114,7 @@
         '                 decoration: BoxDecoration:\n'
         '                   color: Color(0xffffff00)\n'
         '                 configuration: ImageConfiguration(bundle:\n'
-        '                   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        '                   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         '                   android)\n',
       ),
     );
@@ -123,7 +123,8 @@
       box.toStringDeep(),
       equalsIgnoringHashCodes(
         'RenderPadding#00000 relayoutBoundary=up1\n'
-        ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+        ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+        ' │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
         ' │   TestWindow#00000] ← [root]\n'
         ' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
         ' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -132,6 +133,7 @@
         ' │\n'
         ' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
         '   │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+        '   │   MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
         '   │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '   │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
         '   │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -140,20 +142,21 @@
         '   │\n'
         '   └─child: RenderDecoratedBox#00000\n'
         '     │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
-        '     │   Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '     │   Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+        '     │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '     │ parentData: <none> (can use size)\n'
         '     │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '     │ size: Size(53.0, 78.0)\n'
         '     │ decoration: BoxDecoration:\n'
         '     │   color: Color(0x7f0000ff)\n'
         '     │ configuration: ImageConfiguration(bundle:\n'
-        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         '     │   android)\n'
         '     │\n'
         '     └─child: _RenderColoredBox#00000\n'
         '       │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
-        '       │   Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
-        '       │   [root]\n'
+        '       │   Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+        '       │   _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '       │ parentData: <none> (can use size)\n'
         '       │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '       │ size: Size(53.0, 78.0)\n'
@@ -161,8 +164,8 @@
         '       │\n'
         '       └─child: RenderPadding#00000\n'
         '         │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
-        '         │   Padding ← Container ← Align ← View-[GlobalObjectKey\n'
-        '         │   TestWindow#00000] ← [root]\n'
+        '         │   Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+        '         │   ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '         │ parentData: <none> (can use size)\n'
         '         │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '         │ size: Size(53.0, 78.0)\n'
@@ -170,8 +173,9 @@
         '         │\n'
         '         └─child: RenderPositionedBox#00000\n'
         '           │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '           │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '           │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '           │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '           │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+        '           │   TestWindow#00000] ← ⋯\n'
         '           │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
         '           │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
         '           │ size: Size(39.0, 64.0)\n'
@@ -181,8 +185,8 @@
         '           │\n'
         '           └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
         '             │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '             │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '             │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '             │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '             │   _MediaQueryFromView ← _ViewScope ← ⋯\n'
         '             │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
         '             │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
         '             │ size: Size(25.0, 33.0)\n'
@@ -191,15 +195,15 @@
         '             └─child: RenderDecoratedBox#00000\n'
         '                 creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
         '                   DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '                   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '                   MediaQuery ← _MediaQueryFromView ← ⋯\n'
         '                 parentData: <none> (can use size)\n'
         '                 constraints: BoxConstraints(w=25.0, h=33.0)\n'
         '                 size: Size(25.0, 33.0)\n'
         '                 decoration: BoxDecoration:\n'
         '                   color: Color(0xffffff00)\n'
         '                 configuration: ImageConfiguration(bundle:\n'
-        '                   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
-        '                   android)\n'
+        '                   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+        '                   android)\n',
       ),
     );
 
@@ -207,7 +211,8 @@
       box.toStringDeep(minLevel: DiagnosticLevel.fine),
       equalsIgnoringHashCodes(
         'RenderPadding#00000 relayoutBoundary=up1\n'
-        ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+        ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+        ' │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
         ' │   TestWindow#00000] ← [root]\n'
         ' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
         ' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -219,6 +224,7 @@
         ' │\n'
         ' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
         '   │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+        '   │   MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
         '   │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '   │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
         '   │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -229,7 +235,8 @@
         '   │\n'
         '   └─child: RenderDecoratedBox#00000\n'
         '     │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
-        '     │   Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '     │   Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+        '     │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '     │ parentData: <none> (can use size)\n'
         '     │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '     │ layer: null\n'
@@ -244,13 +251,13 @@
         '     │   gradient: null\n'
         '     │   shape: rectangle\n'
         '     │ configuration: ImageConfiguration(bundle:\n'
-        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         '     │   android)\n'
         '     │\n'
         '     └─child: _RenderColoredBox#00000\n'
         '       │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
-        '       │   Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
-        '       │   [root]\n'
+        '       │   Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+        '       │   _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '       │ parentData: <none> (can use size)\n'
         '       │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '       │ layer: null\n'
@@ -260,8 +267,8 @@
         '       │\n'
         '       └─child: RenderPadding#00000\n'
         '         │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
-        '         │   Padding ← Container ← Align ← View-[GlobalObjectKey\n'
-        '         │   TestWindow#00000] ← [root]\n'
+        '         │   Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+        '         │   ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '         │ parentData: <none> (can use size)\n'
         '         │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '         │ layer: null\n'
@@ -272,8 +279,9 @@
         '         │\n'
         '         └─child: RenderPositionedBox#00000\n'
         '           │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '           │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '           │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '           │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '           │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+        '           │   TestWindow#00000] ← ⋯\n'
         '           │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
         '           │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
         '           │ layer: null\n'
@@ -286,8 +294,8 @@
         '           │\n'
         '           └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
         '             │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '             │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '             │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '             │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '             │   _MediaQueryFromView ← _ViewScope ← ⋯\n'
         '             │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
         '             │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
         '             │ layer: null\n'
@@ -298,7 +306,7 @@
         '             └─child: RenderDecoratedBox#00000\n'
         '                 creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
         '                   DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '                   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '                   MediaQuery ← _MediaQueryFromView ← ⋯\n'
         '                 parentData: <none> (can use size)\n'
         '                 constraints: BoxConstraints(w=25.0, h=33.0)\n'
         '                 layer: null\n'
@@ -313,8 +321,8 @@
         '                   gradient: null\n'
         '                   shape: rectangle\n'
         '                 configuration: ImageConfiguration(bundle:\n'
-        '                   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
-        '                   android)\n'
+        '                   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+        '                   android)\n',
       ),
     );
 
@@ -323,7 +331,8 @@
       equalsIgnoringHashCodes(
         'RenderPadding#00000 relayoutBoundary=up1\n'
         ' │ needsCompositing: false\n'
-        ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+        ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+        ' │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
         ' │   TestWindow#00000] ← [root]\n'
         ' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
         ' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -338,6 +347,7 @@
         ' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
         '   │ needsCompositing: false\n'
         '   │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+        '   │   MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
         '   │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '   │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
         '   │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -351,7 +361,8 @@
         '   └─child: RenderDecoratedBox#00000\n'
         '     │ needsCompositing: false\n'
         '     │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
-        '     │   Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '     │   Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+        '     │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '     │ parentData: <none> (can use size)\n'
         '     │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '     │ layer: null\n'
@@ -368,14 +379,14 @@
         '     │   gradient: null\n'
         '     │   shape: rectangle\n'
         '     │ configuration: ImageConfiguration(bundle:\n'
-        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+        '     │   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
         '     │   android)\n'
         '     │\n'
         '     └─child: _RenderColoredBox#00000\n'
         '       │ needsCompositing: false\n'
         '       │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
-        '       │   Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
-        '       │   [root]\n'
+        '       │   Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+        '       │   _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '       │ parentData: <none> (can use size)\n'
         '       │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '       │ layer: null\n'
@@ -388,8 +399,8 @@
         '       └─child: RenderPadding#00000\n'
         '         │ needsCompositing: false\n'
         '         │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
-        '         │   Padding ← Container ← Align ← View-[GlobalObjectKey\n'
-        '         │   TestWindow#00000] ← [root]\n'
+        '         │   Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+        '         │   ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '         │ parentData: <none> (can use size)\n'
         '         │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
         '         │ layer: null\n'
@@ -403,8 +414,9 @@
         '         └─child: RenderPositionedBox#00000\n'
         '           │ needsCompositing: false\n'
         '           │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '           │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '           │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '           │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '           │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+        '           │   TestWindow#00000] ← ⋯\n'
         '           │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
         '           │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
         '           │ layer: null\n'
@@ -420,8 +432,8 @@
         '           └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
         '             │ needsCompositing: false\n'
         '             │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
-        '             │   ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '             │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '             │   ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+        '             │   _MediaQueryFromView ← _ViewScope ← ⋯\n'
         '             │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
         '             │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
         '             │ layer: null\n'
@@ -435,7 +447,7 @@
         '                 needsCompositing: false\n'
         '                 creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
         '                   DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
-        '                   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        '                   MediaQuery ← _MediaQueryFromView ← ⋯\n'
         '                 parentData: <none> (can use size)\n'
         '                 constraints: BoxConstraints(w=25.0, h=33.0)\n'
         '                 layer: null\n'
@@ -452,8 +464,8 @@
         '                   gradient: null\n'
         '                   shape: rectangle\n'
         '                 configuration: ImageConfiguration(bundle:\n'
-        '                   PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
-        '                   android)\n'
+        '                   PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+        '                   android)\n',
       ),
     );
 
diff --git a/packages/flutter/test/widgets/custom_multi_child_layout_test.dart b/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
index 5fd8c04..732ae02 100644
--- a/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
+++ b/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
@@ -372,7 +372,8 @@
           '   in its parent data.\n'
           '   The following child has no ID: RenderConstrainedBox#00000 NEEDS-LAYOUT NEEDS-PAINT:\n'
           '     creator: ConstrainedBox ← Container ← LayoutWithMissingId ←\n'
-          '       CustomMultiChildLayout ← Center ← View-[GlobalObjectKey\n'
+          '       CustomMultiChildLayout ← Center ← MediaQuery ←\n'
+          '       _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
           '       TestWindow#00000] ← [root]\n'
           '     parentData: offset=Offset(0.0, 0.0); id=null\n'
           '     constraints: MISSING\n'
diff --git a/packages/flutter/test/widgets/debug_test.dart b/packages/flutter/test/widgets/debug_test.dart
index 30e2329..ee38464 100644
--- a/packages/flutter/test/widgets/debug_test.dart
+++ b/packages/flutter/test/widgets/debug_test.dart
@@ -96,8 +96,11 @@
   });
 
   testWidgets('debugCheckHasMediaQuery control test', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Builder(
+    // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+    // which introduces a MediaQuery ancestor.
+    await pumpWidgetWithoutViewWrapper(
+      tester: tester,
+      widget: Builder(
         builder: (BuildContext context) {
           late FlutterError error;
           try {
@@ -339,3 +342,9 @@
     expect(renderObject.debugLayer?.debugCreator, isNotNull);
   });
 }
+
+Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required  Widget widget}) {
+  tester.binding.attachRootWidget(widget);
+  tester.binding.scheduleFrame();
+  return tester.binding.pump();
+}
diff --git a/packages/flutter/test/widgets/focus_manager_test.dart b/packages/flutter/test/widgets/focus_manager_test.dart
index dd36f86..53501fc 100644
--- a/packages/flutter/test/widgets/focus_manager_test.dart
+++ b/packages/flutter/test/widgets/focus_manager_test.dart
@@ -1228,8 +1228,9 @@
         equalsIgnoringHashCodes(
           'FocusManager#00000\n'
           ' │ primaryFocus: FocusNode#00000(Child 4 [PRIMARY FOCUS])\n'
-          ' │ primaryFocusCreator: Container-[GlobalKey#00000] ←\n'
-          ' │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+          ' │ primaryFocusCreator: Container-[GlobalKey#00000] ← MediaQuery ←\n'
+          ' │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+          ' │   TestWindow#00000] ← [root]\n'
           ' │\n'
           ' └─rootScope: FocusScopeNode#00000(Root Focus Scope [IN FOCUS PATH])\n'
           '   │ IN FOCUS PATH\n'
diff --git a/packages/flutter/test/widgets/init_state_test.dart b/packages/flutter/test/widgets/init_state_test.dart
index 828893d..e70267e 100644
--- a/packages/flutter/test/widgets/init_state_test.dart
+++ b/packages/flutter/test/widgets/init_state_test.dart
@@ -30,7 +30,7 @@
 void main() {
   testWidgets('initState() is called when we are in the tree', (WidgetTester tester) async {
     await tester.pumpWidget(const Parent(child: TestWidget()));
-    expect(ancestors, equals(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
+    expect(ancestors, containsAllInOrder(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
   });
 }
 
diff --git a/packages/flutter/test/widgets/keep_alive_test.dart b/packages/flutter/test/widgets/keep_alive_test.dart
index 5249f5c..3b5f9e6 100644
--- a/packages/flutter/test/widgets/keep_alive_test.dart
+++ b/packages/flutter/test/widgets/keep_alive_test.dart
@@ -303,7 +303,7 @@
       '                     │   ScrollDirection.idle)\n'
       '                     │ anchor: 0.0\n'
       '                     │\n'
-      '                     └─center child: RenderSliverFixedExtentList#00000 relayoutBoundary=up1\n'
+      '                     └─center child: RenderSliverPadding#00000 relayoutBoundary=up1\n'
       '                       │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
       '                       │ constraints: SliverConstraints(AxisDirection.down,\n'
       '                       │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
@@ -314,49 +314,63 @@
       '                       │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
       '                       │   600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
       '                       │   cacheExtent: 850.0)\n'
-      '                       │ currently live children: 0 to 2\n'
+      '                       │ padding: EdgeInsets.zero\n'
+      '                       │ textDirection: ltr\n'
       '                       │\n'
-      '                       ├─child with index 0: RenderLimitedBox#00000\n'
-      '                       │ │ parentData: index=0; layoutOffset=0.0\n'
-      '                       │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │ │ size: Size(800.0, 400.0)\n'
-      '                       │ │ maxWidth: 400.0\n'
-      '                       │ │ maxHeight: 400.0\n'
-      '                       │ │\n'
-      '                       │ └─child: RenderCustomPaint#00000\n'
-      '                       │     parentData: <none> (can use size)\n'
-      '                       │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │     size: Size(800.0, 400.0)\n'
-      '                       │     painter: _PlaceholderPainter#00000()\n'
-      '                       │     preferredSize: Size(Infinity, Infinity)\n'
-      '                       │\n'
-      '                       ├─child with index 1: RenderLimitedBox#00000\n'                                     // <----- no dashed line starts here
-      '                       │ │ parentData: index=1; layoutOffset=400.0\n'
-      '                       │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │ │ size: Size(800.0, 400.0)\n'
-      '                       │ │ maxWidth: 400.0\n'
-      '                       │ │ maxHeight: 400.0\n'
-      '                       │ │\n'
-      '                       │ └─child: RenderCustomPaint#00000\n'
-      '                       │     parentData: <none> (can use size)\n'
-      '                       │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │     size: Size(800.0, 400.0)\n'
-      '                       │     painter: _PlaceholderPainter#00000()\n'
-      '                       │     preferredSize: Size(Infinity, Infinity)\n'
-      '                       │\n'
-      '                       └─child with index 2: RenderLimitedBox#00000 NEEDS-PAINT\n'
-      '                         │ parentData: index=2; layoutOffset=800.0\n'
-      '                         │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                         │ size: Size(800.0, 400.0)\n'
-      '                         │ maxWidth: 400.0\n'
-      '                         │ maxHeight: 400.0\n'
+      '                       └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
+      '                         │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
+      '                         │ constraints: SliverConstraints(AxisDirection.down,\n'
+      '                         │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
+      '                         │   0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
+      '                         │   crossAxisDirection: AxisDirection.right,\n'
+      '                         │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0,\n'
+      '                         │   cacheOrigin: 0.0)\n'
+      '                         │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
+      '                         │   600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
+      '                         │   cacheExtent: 850.0)\n'
+      '                         │ currently live children: 0 to 2\n'
       '                         │\n'
-      '                         └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
-      '                             parentData: <none> (can use size)\n'
-      '                             constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                             size: Size(800.0, 400.0)\n'
-      '                             painter: _PlaceholderPainter#00000()\n'
-      '                             preferredSize: Size(Infinity, Infinity)\n',
+      '                         ├─child with index 0: RenderLimitedBox#00000\n'
+      '                         │ │ parentData: index=0; layoutOffset=0.0\n'
+      '                         │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │ │ size: Size(800.0, 400.0)\n'
+      '                         │ │ maxWidth: 400.0\n'
+      '                         │ │ maxHeight: 400.0\n'
+      '                         │ │\n'
+      '                         │ └─child: RenderCustomPaint#00000\n'
+      '                         │     parentData: <none> (can use size)\n'
+      '                         │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │     size: Size(800.0, 400.0)\n'
+      '                         │     painter: _PlaceholderPainter#00000()\n'
+      '                         │     preferredSize: Size(Infinity, Infinity)\n'
+      '                         │\n'
+      '                         ├─child with index 1: RenderLimitedBox#00000\n'                                      // <----- no dashed line starts here
+      '                         │ │ parentData: index=1; layoutOffset=400.0\n'
+      '                         │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │ │ size: Size(800.0, 400.0)\n'
+      '                         │ │ maxWidth: 400.0\n'
+      '                         │ │ maxHeight: 400.0\n'
+      '                         │ │\n'
+      '                         │ └─child: RenderCustomPaint#00000\n'
+      '                         │     parentData: <none> (can use size)\n'
+      '                         │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │     size: Size(800.0, 400.0)\n'
+      '                         │     painter: _PlaceholderPainter#00000()\n'
+      '                         │     preferredSize: Size(Infinity, Infinity)\n'
+      '                         │\n'
+      '                         └─child with index 2: RenderLimitedBox#00000 NEEDS-PAINT\n'
+      '                           │ parentData: index=2; layoutOffset=800.0\n'
+      '                           │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                           │ size: Size(800.0, 400.0)\n'
+      '                           │ maxWidth: 400.0\n'
+      '                           │ maxHeight: 400.0\n'
+      '                           │\n'
+      '                           └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+      '                               parentData: <none> (can use size)\n'
+      '                               constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                               size: Size(800.0, 400.0)\n'
+      '                               painter: _PlaceholderPainter#00000()\n'
+      '                               preferredSize: Size(Infinity, Infinity)\n',
     ));
     const GlobalObjectKey<_LeafState>(0).currentState!.setKeepAlive(true);
     await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0));
@@ -463,7 +477,7 @@
       '                     │   ScrollDirection.idle)\n'
       '                     │ anchor: 0.0\n'
       '                     │\n'
-      '                     └─center child: RenderSliverFixedExtentList#00000 relayoutBoundary=up1\n'
+      '                     └─center child: RenderSliverPadding#00000 relayoutBoundary=up1\n'
       '                       │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
       '                       │ constraints: SliverConstraints(AxisDirection.down,\n'
       '                       │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
@@ -474,92 +488,105 @@
       '                       │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
       '                       │   600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
       '                       │   cacheExtent: 1100.0)\n'
-      '                       │ currently live children: 4 to 7\n'
+      '                       │ padding: EdgeInsets.zero\n'
+      '                       │ textDirection: ltr\n'
       '                       │\n'
-      '                       ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
-      '                       │ │ parentData: index=4; layoutOffset=1600.0\n'
-      '                       │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │ │ size: Size(800.0, 400.0)\n'
-      '                       │ │ maxWidth: 400.0\n'
-      '                       │ │ maxHeight: 400.0\n'
-      '                       │ │\n'
-      '                       │ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
-      '                       │     parentData: <none> (can use size)\n'
-      '                       │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │     size: Size(800.0, 400.0)\n'
-      '                       │     painter: _PlaceholderPainter#00000()\n'
-      '                       │     preferredSize: Size(Infinity, Infinity)\n'
-      '                       │\n'
-      '                       ├─child with index 5: RenderLimitedBox#00000\n'                                     // <----- this is index 5, not 0
-      '                       │ │ parentData: index=5; layoutOffset=2000.0\n'
-      '                       │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │ │ size: Size(800.0, 400.0)\n'
-      '                       │ │ maxWidth: 400.0\n'
-      '                       │ │ maxHeight: 400.0\n'
-      '                       │ │\n'
-      '                       │ └─child: RenderCustomPaint#00000\n'
-      '                       │     parentData: <none> (can use size)\n'
-      '                       │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │     size: Size(800.0, 400.0)\n'
-      '                       │     painter: _PlaceholderPainter#00000()\n'
-      '                       │     preferredSize: Size(Infinity, Infinity)\n'
-      '                       │\n'
-      '                       ├─child with index 6: RenderLimitedBox#00000\n'
-      '                       │ │ parentData: index=6; layoutOffset=2400.0\n'
-      '                       │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │ │ size: Size(800.0, 400.0)\n'
-      '                       │ │ maxWidth: 400.0\n'
-      '                       │ │ maxHeight: 400.0\n'
-      '                       │ │\n'
-      '                       │ └─child: RenderCustomPaint#00000\n'
-      '                       │     parentData: <none> (can use size)\n'
-      '                       │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       │     size: Size(800.0, 400.0)\n'
-      '                       │     painter: _PlaceholderPainter#00000()\n'
-      '                       │     preferredSize: Size(Infinity, Infinity)\n'
-      '                       │\n'
-      '                       ├─child with index 7: RenderLimitedBox#00000 NEEDS-PAINT\n'
-      '                       ╎ │ parentData: index=7; layoutOffset=2800.0\n'
-      '                       ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       ╎ │ size: Size(800.0, 400.0)\n'
-      '                       ╎ │ maxWidth: 400.0\n'
-      '                       ╎ │ maxHeight: 400.0\n'
-      '                       ╎ │\n'
-      '                       ╎ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
-      '                       ╎     parentData: <none> (can use size)\n'
-      '                       ╎     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       ╎     size: Size(800.0, 400.0)\n'
-      '                       ╎     painter: _PlaceholderPainter#00000()\n'
-      '                       ╎     preferredSize: Size(Infinity, Infinity)\n'
-      '                       ╎\n'
-      '                       ╎╌child with index 0 (kept alive but not laid out): RenderLimitedBox#00000\n'               // <----- this one is index 0 and is marked as being kept alive but not laid out
-      '                       ╎ │ parentData: index=0; keepAlive; layoutOffset=0.0\n'
-      '                       ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       ╎ │ size: Size(800.0, 400.0)\n'
-      '                       ╎ │ maxWidth: 400.0\n'
-      '                       ╎ │ maxHeight: 400.0\n'
-      '                       ╎ │\n'
-      '                       ╎ └─child: RenderCustomPaint#00000\n'
-      '                       ╎     parentData: <none> (can use size)\n'
-      '                       ╎     constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                       ╎     size: Size(800.0, 400.0)\n'
-      '                       ╎     painter: _PlaceholderPainter#00000()\n'
-      '                       ╎     preferredSize: Size(Infinity, Infinity)\n'
-      '                       ╎\n'                                                                                // <----- dashed line ends here
-      '                       └╌child with index 3 (kept alive but not laid out): RenderLimitedBox#00000\n'
-      '                         │ parentData: index=3; keepAlive; layoutOffset=1200.0\n'
-      '                         │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                         │ size: Size(800.0, 400.0)\n'
-      '                         │ maxWidth: 400.0\n'
-      '                         │ maxHeight: 400.0\n'
+      '                       └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
+      '                         │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
+      '                         │ constraints: SliverConstraints(AxisDirection.down,\n'
+      '                         │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
+      '                         │   2000.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
+      '                         │   crossAxisDirection: AxisDirection.right,\n'
+      '                         │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 1100.0,\n'
+      '                         │   cacheOrigin: -250.0)\n'
+      '                         │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
+      '                         │   600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
+      '                         │   cacheExtent: 1100.0)\n'
+      '                         │ currently live children: 4 to 7\n'
       '                         │\n'
-      '                         └─child: RenderCustomPaint#00000\n'
-      '                             parentData: <none> (can use size)\n'
-      '                             constraints: BoxConstraints(w=800.0, h=400.0)\n'
-      '                             size: Size(800.0, 400.0)\n'
-      '                             painter: _PlaceholderPainter#00000()\n'
-      '                             preferredSize: Size(Infinity, Infinity)\n',
+      '                         ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
+      '                         │ │ parentData: index=4; layoutOffset=1600.0\n'
+      '                         │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │ │ size: Size(800.0, 400.0)\n'
+      '                         │ │ maxWidth: 400.0\n'
+      '                         │ │ maxHeight: 400.0\n'
+      '                         │ │\n'
+      '                         │ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+      '                         │     parentData: <none> (can use size)\n'
+      '                         │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │     size: Size(800.0, 400.0)\n'
+      '                         │     painter: _PlaceholderPainter#00000()\n'
+      '                         │     preferredSize: Size(Infinity, Infinity)\n'
+      '                         │\n'
+      '                         ├─child with index 5: RenderLimitedBox#00000\n'                                     // <----- this is index 5, not 0
+      '                         │ │ parentData: index=5; layoutOffset=2000.0\n'
+      '                         │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │ │ size: Size(800.0, 400.0)\n'
+      '                         │ │ maxWidth: 400.0\n'
+      '                         │ │ maxHeight: 400.0\n'
+      '                         │ │\n'
+      '                         │ └─child: RenderCustomPaint#00000\n'
+      '                         │     parentData: <none> (can use size)\n'
+      '                         │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │     size: Size(800.0, 400.0)\n'
+      '                         │     painter: _PlaceholderPainter#00000()\n'
+      '                         │     preferredSize: Size(Infinity, Infinity)\n'
+      '                         │\n'
+      '                         ├─child with index 6: RenderLimitedBox#00000\n'
+      '                         │ │ parentData: index=6; layoutOffset=2400.0\n'
+      '                         │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │ │ size: Size(800.0, 400.0)\n'
+      '                         │ │ maxWidth: 400.0\n'
+      '                         │ │ maxHeight: 400.0\n'
+      '                         │ │\n'
+      '                         │ └─child: RenderCustomPaint#00000\n'
+      '                         │     parentData: <none> (can use size)\n'
+      '                         │     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         │     size: Size(800.0, 400.0)\n'
+      '                         │     painter: _PlaceholderPainter#00000()\n'
+      '                         │     preferredSize: Size(Infinity, Infinity)\n'
+      '                         │\n'
+      '                         ├─child with index 7: RenderLimitedBox#00000 NEEDS-PAINT\n'
+      '                         ╎ │ parentData: index=7; layoutOffset=2800.0\n'
+      '                         ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         ╎ │ size: Size(800.0, 400.0)\n'
+      '                         ╎ │ maxWidth: 400.0\n'
+      '                         ╎ │ maxHeight: 400.0\n'
+      '                         ╎ │\n'
+      '                         ╎ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+      '                         ╎     parentData: <none> (can use size)\n'
+      '                         ╎     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         ╎     size: Size(800.0, 400.0)\n'
+      '                         ╎     painter: _PlaceholderPainter#00000()\n'
+      '                         ╎     preferredSize: Size(Infinity, Infinity)\n'
+      '                         ╎\n'
+      '                         ╎╌child with index 0 (kept alive but not laid out): RenderLimitedBox#00000\n'               // <----- this one is index 0 and is marked as being kept alive but not laid out
+      '                         ╎ │ parentData: index=0; keepAlive; layoutOffset=0.0\n'
+      '                         ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         ╎ │ size: Size(800.0, 400.0)\n'
+      '                         ╎ │ maxWidth: 400.0\n'
+      '                         ╎ │ maxHeight: 400.0\n'
+      '                         ╎ │\n'
+      '                         ╎ └─child: RenderCustomPaint#00000\n'
+      '                         ╎     parentData: <none> (can use size)\n'
+      '                         ╎     constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                         ╎     size: Size(800.0, 400.0)\n'
+      '                         ╎     painter: _PlaceholderPainter#00000()\n'
+      '                         ╎     preferredSize: Size(Infinity, Infinity)\n'
+      '                         ╎\n'
+      '                         └╌child with index 3 (kept alive but not laid out): RenderLimitedBox#00000\n'
+      '                           │ parentData: index=3; keepAlive; layoutOffset=1200.0\n'
+      '                           │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                           │ size: Size(800.0, 400.0)\n'
+      '                           │ maxWidth: 400.0\n'
+      '                           │ maxHeight: 400.0\n'
+      '                           │\n'
+      '                           └─child: RenderCustomPaint#00000\n'
+      '                               parentData: <none> (can use size)\n'
+      '                               constraints: BoxConstraints(w=800.0, h=400.0)\n'
+      '                               size: Size(800.0, 400.0)\n'
+      '                               painter: _PlaceholderPainter#00000()\n'
+      '                               preferredSize: Size(Infinity, Infinity)\n',
     ));
   }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87876
-
 }
diff --git a/packages/flutter/test/widgets/list_view_viewporting_test.dart b/packages/flutter/test/widgets/list_view_viewporting_test.dart
index 11a7906..277b20e 100644
--- a/packages/flutter/test/widgets/list_view_viewporting_test.dart
+++ b/packages/flutter/test/widgets/list_view_viewporting_test.dart
@@ -326,7 +326,7 @@
     expect(
       list.toStringDeep(minLevel: DiagnosticLevel.info),
       equalsIgnoringHashCodes(
-        'RenderSliverList#00000 relayoutBoundary=up1\n'
+        'RenderSliverList#00000 relayoutBoundary=up2\n'
         ' │ needs compositing\n'
         ' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
         ' │ constraints: SliverConstraints(AxisDirection.down,\n'
@@ -339,7 +339,7 @@
         ' │   maxPaintExtent: 300.0, cacheExtent: 300.0)\n'
         ' │ currently live children: 0 to 2\n'
         ' │\n'
-        ' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+        ' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
         ' │ │ needs compositing\n'
         ' │ │ parentData: index=0; layoutOffset=0.0 (can use size)\n'
         ' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -349,7 +349,7 @@
         ' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
         ' │ │   repaints)\n'
         ' │ │\n'
-        ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+        ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
         ' │   │ parentData: <none> (can use size)\n'
         ' │   │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
         ' │   │ size: Size(800.0, 100.0)\n'
@@ -368,7 +368,7 @@
         ' │         size: Size(800.0, 100.0)\n'
         ' │         additionalConstraints: BoxConstraints(biggest)\n'
         ' │\n'
-        ' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+        ' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
         ' │ │ needs compositing\n'
         ' │ │ parentData: index=1; layoutOffset=100.0 (can use size)\n'
         ' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -378,7 +378,7 @@
         ' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
         ' │ │   repaints)\n'
         ' │ │\n'
-        ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+        ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
         ' │   │ parentData: <none> (can use size)\n'
         ' │   │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
         ' │   │ size: Size(800.0, 100.0)\n'
@@ -397,7 +397,7 @@
         ' │         size: Size(800.0, 100.0)\n'
         ' │         additionalConstraints: BoxConstraints(biggest)\n'
         ' │\n'
-        ' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+        ' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
         '   │ needs compositing\n'
         '   │ parentData: index=2; layoutOffset=200.0 (can use size)\n'
         '   │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -407,7 +407,7 @@
         '   │ diagnosis: insufficient data to draw conclusion (less than five\n'
         '   │   repaints)\n'
         '   │\n'
-        '   └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+        '   └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
         '     │ parentData: <none> (can use size)\n'
         '     │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
         '     │ size: Size(800.0, 100.0)\n'
diff --git a/packages/flutter/test/widgets/media_query_test.dart b/packages/flutter/test/widgets/media_query_test.dart
index 0dea109..5cecc50 100644
--- a/packages/flutter/test/widgets/media_query_test.dart
+++ b/packages/flutter/test/widgets/media_query_test.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' show Brightness, DisplayFeature, DisplayFeatureState, DisplayFeatureType, GestureSettings, ViewConfiguration;
+import 'dart:ui' show Brightness, DisplayFeature, DisplayFeatureState, DisplayFeatureType, GestureSettings, PlatformDispatcher, ViewConfiguration, WindowPadding;
 
 import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
@@ -45,8 +45,11 @@
 void main() {
   testWidgets('MediaQuery does not have a default', (WidgetTester tester) async {
     bool tested = false;
-    await tester.pumpWidget(
-      Builder(
+    // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+    // which introduces a MediaQuery ancestor.
+    await pumpWidgetWithoutViewWrapper(
+      tester: tester,
+      widget: Builder(
         builder: (BuildContext context) {
           tested = true;
           MediaQuery.of(context); // should throw
@@ -108,8 +111,11 @@
 
   testWidgets('MediaQuery.maybeOf defaults to null', (WidgetTester tester) async {
     bool tested = false;
-    await tester.pumpWidget(
-      Builder(
+    // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+    // which introduces a MediaQuery ancestor.
+    await pumpWidgetWithoutViewWrapper(
+      tester: tester,
+      widget: Builder(
         builder: (BuildContext context) {
           final MediaQueryData? data = MediaQuery.maybeOf(context);
           expect(data, isNull);
@@ -154,6 +160,358 @@
     expect(data.displayFeatures, isEmpty);
   });
 
+  testWidgets('MediaQueryData.fromView uses platformData if provided', (WidgetTester tester) async {
+    const MediaQueryData platformData = MediaQueryData(
+      textScaleFactor: 1234,
+      platformBrightness: Brightness.dark,
+      accessibleNavigation: true,
+      invertColors: true,
+      disableAnimations: true,
+      boldText: true,
+      highContrast: true,
+      alwaysUse24HourFormat: true,
+      navigationMode: NavigationMode.directional,
+    );
+
+    final TestView view = TestView(
+      physicalSize: const Size(300, 600),
+      devicePixelRatio: 3.0,
+      padding: const TestWindowPadding(15),
+      viewPadding: const TestWindowPadding(75),
+      viewInsets: const TestWindowPadding(45),
+      systemGestureInsets: const TestWindowPadding(9),
+    );
+
+    final MediaQueryData data = MediaQueryData.fromView(view, platformData: platformData);
+    expect(data, hasOneLineDescription);
+    expect(data.hashCode, data.copyWith().hashCode);
+    expect(data.size, view.physicalSize / view.devicePixelRatio);
+    expect(data.devicePixelRatio, view.devicePixelRatio);
+    expect(data.textScaleFactor, platformData.textScaleFactor);
+    expect(data.platformBrightness, platformData.platformBrightness);
+    expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+    expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+    expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+    expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+    expect(data.accessibleNavigation, platformData.accessibleNavigation);
+    expect(data.invertColors, platformData.invertColors);
+    expect(data.disableAnimations, platformData.disableAnimations);
+    expect(data.boldText, platformData.boldText);
+    expect(data.highContrast, platformData.highContrast);
+    expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
+    expect(data.navigationMode, platformData.navigationMode);
+    expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+    expect(data.displayFeatures, view.displayFeatures);
+  });
+
+  testWidgets('MediaQueryData.fromView uses data from platformDispatcher if no platformData is provided', (WidgetTester tester) async {
+    final TestPlatformDispatcher platformDispatcher = TestPlatformDispatcher(platformDispatcher: tester.binding.platformDispatcher);
+    platformDispatcher
+      ..textScaleFactorTestValue = 123
+      ..platformBrightnessTestValue = Brightness.dark
+      ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+    addTearDown(() => platformDispatcher.clearAllTestValues());
+
+    final TestView view = TestView(
+      platformDispatcher: platformDispatcher,
+      physicalSize: const Size(300, 600),
+      devicePixelRatio: 3.0,
+      padding: const TestWindowPadding(15),
+      viewPadding: const TestWindowPadding(75),
+      viewInsets: const TestWindowPadding(45),
+      systemGestureInsets: const TestWindowPadding(9),
+    );
+
+    final MediaQueryData data = MediaQueryData.fromView(view);
+    expect(data, hasOneLineDescription);
+    expect(data.hashCode, data.copyWith().hashCode);
+    expect(data.size, view.physicalSize / view.devicePixelRatio);
+    expect(data.devicePixelRatio, view.devicePixelRatio);
+    expect(data.textScaleFactor, platformDispatcher.textScaleFactor);
+    expect(data.platformBrightness, platformDispatcher.platformBrightness);
+    expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+    expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+    expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+    expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+    expect(data.accessibleNavigation, platformDispatcher.accessibilityFeatures.accessibleNavigation);
+    expect(data.invertColors, platformDispatcher.accessibilityFeatures.invertColors);
+    expect(data.disableAnimations, platformDispatcher.accessibilityFeatures.disableAnimations);
+    expect(data.boldText, platformDispatcher.accessibilityFeatures.boldText);
+    expect(data.highContrast, platformDispatcher.accessibilityFeatures.highContrast);
+    expect(data.alwaysUse24HourFormat, platformDispatcher.alwaysUse24HourFormat);
+    expect(data.navigationMode, NavigationMode.traditional);
+    expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+    expect(data.displayFeatures, view.displayFeatures);
+  });
+
+  testWidgets('MediaQuery.fromView injects a new MediaQuery with data from view, preserving platform-specific data', (WidgetTester tester) async {
+    const MediaQueryData platformData = MediaQueryData(
+      textScaleFactor: 1234,
+      platformBrightness: Brightness.dark,
+      accessibleNavigation: true,
+      invertColors: true,
+      disableAnimations: true,
+      boldText: true,
+      highContrast: true,
+      alwaysUse24HourFormat: true,
+      navigationMode: NavigationMode.directional,
+    );
+
+    final TestView view = TestView(
+      physicalSize: const Size(300, 600),
+      devicePixelRatio: 3.0,
+      padding: const TestWindowPadding(15),
+      viewPadding: const TestWindowPadding(75),
+      viewInsets: const TestWindowPadding(45),
+      systemGestureInsets: const TestWindowPadding(9),
+    );
+
+    late MediaQueryData data;
+    await tester.pumpWidget(MediaQuery(
+      data: platformData,
+      child: MediaQuery.fromView(
+        view: view,
+        child: Builder(
+          builder: (BuildContext context) {
+            data = MediaQuery.of(context);
+            return const Placeholder();
+          },
+        )
+      )
+    ));
+
+    expect(data, isNot(platformData));
+    expect(data.size, view.physicalSize / view.devicePixelRatio);
+    expect(data.devicePixelRatio, view.devicePixelRatio);
+    expect(data.textScaleFactor, platformData.textScaleFactor);
+    expect(data.platformBrightness, platformData.platformBrightness);
+    expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+    expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+    expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+    expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+    expect(data.accessibleNavigation, platformData.accessibleNavigation);
+    expect(data.invertColors, platformData.invertColors);
+    expect(data.disableAnimations, platformData.disableAnimations);
+    expect(data.boldText, platformData.boldText);
+    expect(data.highContrast, platformData.highContrast);
+    expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
+    expect(data.navigationMode, platformData.navigationMode);
+    expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+    expect(data.displayFeatures, view.displayFeatures);
+  });
+
+  testWidgets('MediaQuery.fromView injects a new MediaQuery with data from view when no sourrounding MediaQuery exists', (WidgetTester tester) async {
+    final TestPlatformDispatcher platformDispatcher = TestPlatformDispatcher(platformDispatcher: tester.binding.platformDispatcher);
+    platformDispatcher
+      ..textScaleFactorTestValue = 123
+      ..platformBrightnessTestValue = Brightness.dark
+      ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+    addTearDown(() => platformDispatcher.clearAllTestValues());
+
+    final TestView view = TestView(
+      platformDispatcher: platformDispatcher,
+      physicalSize: const Size(300, 600),
+      devicePixelRatio: 3.0,
+      padding: const TestWindowPadding(15),
+      viewPadding: const TestWindowPadding(75),
+      viewInsets: const TestWindowPadding(45),
+      systemGestureInsets: const TestWindowPadding(9),
+    );
+
+    late MediaQueryData data;
+    MediaQueryData? outerData;
+    await pumpWidgetWithoutViewWrapper(
+      tester: tester,
+      widget: Builder(
+        builder: (BuildContext context) {
+          outerData = MediaQuery.maybeOf(context);
+          return MediaQuery.fromView(
+              view: view,
+              child: Builder(
+                builder: (BuildContext context) {
+                  data = MediaQuery.of(context);
+                  return const Placeholder();
+                },
+              )
+          );
+        },
+      ),
+    );
+
+    expect(outerData, isNull);
+    expect(data.size, view.physicalSize / view.devicePixelRatio);
+    expect(data.devicePixelRatio, view.devicePixelRatio);
+    expect(data.textScaleFactor, platformDispatcher.textScaleFactor);
+    expect(data.platformBrightness, platformDispatcher.platformBrightness);
+    expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+    expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+    expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+    expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+    expect(data.accessibleNavigation, platformDispatcher.accessibilityFeatures.accessibleNavigation);
+    expect(data.invertColors, platformDispatcher.accessibilityFeatures.invertColors);
+    expect(data.disableAnimations, platformDispatcher.accessibilityFeatures.disableAnimations);
+    expect(data.boldText, platformDispatcher.accessibilityFeatures.boldText);
+    expect(data.highContrast, platformDispatcher.accessibilityFeatures.highContrast);
+    expect(data.alwaysUse24HourFormat, platformDispatcher.alwaysUse24HourFormat);
+    expect(data.navigationMode, NavigationMode.traditional);
+    expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+    expect(data.displayFeatures, view.displayFeatures);
+  });
+
+  testWidgets('MediaQuery.fromView updates on notifications (no parent data)', (WidgetTester tester) async {
+    tester.binding.platformDispatcher
+      ..textScaleFactorTestValue = 123
+      ..platformBrightnessTestValue = Brightness.dark
+      ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+    addTearDown(() => tester.binding.platformDispatcher.clearAllTestValues());
+    tester.binding.window.devicePixelRatioTestValue = 44;
+    addTearDown(() => tester.binding.window.clearAllTestValues());
+
+    late MediaQueryData data;
+    MediaQueryData? outerData;
+    int rebuildCount = 0;
+    await pumpWidgetWithoutViewWrapper(
+      tester: tester,
+      widget: Builder(
+        builder: (BuildContext context) {
+          outerData = MediaQuery.maybeOf(context);
+          return MediaQuery.fromView(
+              view: tester.binding.window,
+              child: Builder(
+                builder: (BuildContext context) {
+                  rebuildCount++;
+                  data = MediaQuery.of(context);
+                  return const Placeholder();
+                },
+              ),
+          );
+        },
+      ),
+    );
+
+    expect(outerData, isNull);
+    expect(rebuildCount, 1);
+
+    expect(data.textScaleFactor, 123);
+    tester.binding.platformDispatcher.textScaleFactorTestValue = 456;
+    await tester.pump();
+    expect(data.textScaleFactor, 456);
+    expect(rebuildCount, 2);
+
+    expect(data.platformBrightness, Brightness.dark);
+    tester.binding.platformDispatcher.platformBrightnessTestValue = Brightness.light;
+    await tester.pump();
+    expect(data.platformBrightness, Brightness.light);
+    expect(rebuildCount, 3);
+
+    expect(data.accessibleNavigation, true);
+    tester.binding.platformDispatcher.accessibilityFeaturesTestValue = const FakeAccessibilityFeatures();
+    await tester.pump();
+    expect(data.accessibleNavigation, false);
+    expect(rebuildCount, 4);
+
+    expect(data.devicePixelRatio, 44);
+    tester.binding.window.devicePixelRatioTestValue = 55;
+    await tester.pump();
+    expect(data.devicePixelRatio, 55);
+    expect(rebuildCount, 5);
+  });
+
+  testWidgets('MediaQuery.fromView updates on notifications (with parent data)', (WidgetTester tester) async {
+    tester.binding.platformDispatcher
+      ..textScaleFactorTestValue = 123
+      ..platformBrightnessTestValue = Brightness.dark
+      ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+    addTearDown(() => tester.binding.platformDispatcher.clearAllTestValues());
+    tester.binding.window.devicePixelRatioTestValue = 44;
+    addTearDown(() => tester.binding.window.clearAllTestValues());
+
+    late MediaQueryData data;
+    int rebuildCount = 0;
+    await tester.pumpWidget(
+      MediaQuery(
+        data: const MediaQueryData(
+          textScaleFactor: 44,
+          platformBrightness: Brightness.dark,
+          accessibleNavigation: true,
+        ),
+        child: MediaQuery.fromView(
+          view: tester.binding.window,
+          child: Builder(
+            builder: (BuildContext context) {
+              rebuildCount++;
+              data = MediaQuery.of(context);
+              return const Placeholder();
+            },
+          ),
+        ),
+      ),
+    );
+
+    expect(rebuildCount, 1);
+
+    expect(data.textScaleFactor, 44);
+    tester.binding.platformDispatcher.textScaleFactorTestValue = 456;
+    await tester.pump();
+    expect(data.textScaleFactor, 44);
+    expect(rebuildCount, 1);
+
+    expect(data.platformBrightness, Brightness.dark);
+    tester.binding.platformDispatcher.platformBrightnessTestValue = Brightness.light;
+    await tester.pump();
+    expect(data.platformBrightness, Brightness.dark);
+    expect(rebuildCount, 1);
+
+    expect(data.accessibleNavigation, true);
+    tester.binding.platformDispatcher.accessibilityFeaturesTestValue = const FakeAccessibilityFeatures();
+    await tester.pump();
+    expect(data.accessibleNavigation, true);
+    expect(rebuildCount, 1);
+
+    expect(data.devicePixelRatio, 44);
+    tester.binding.window.devicePixelRatioTestValue = 55;
+    await tester.pump();
+    expect(data.devicePixelRatio, 55);
+    expect(rebuildCount, 2);
+  });
+
+  testWidgets('MediaQuery.fromView updates when parent data changes', (WidgetTester tester) async {
+    late MediaQueryData data;
+    int rebuildCount = 0;
+    double textScaleFactor = 55;
+    late StateSetter stateSetter;
+    await tester.pumpWidget(
+      StatefulBuilder(
+        builder: (BuildContext context, StateSetter setState) {
+          stateSetter = setState;
+          return MediaQuery(
+            data: MediaQueryData(textScaleFactor: textScaleFactor),
+            child: MediaQuery.fromView(
+              view: tester.binding.window,
+              child: Builder(
+                builder: (BuildContext context) {
+                  rebuildCount++;
+                  data = MediaQuery.of(context);
+                  return const Placeholder();
+                },
+              ),
+            ),
+          );
+        },
+      ),
+    );
+
+    expect(rebuildCount, 1);
+    expect(data.textScaleFactor, 55);
+
+    stateSetter(() {
+      textScaleFactor = 66;
+    });
+    await tester.pump();
+    expect(data.textScaleFactor, 66);
+    expect(rebuildCount, 2);
+  });
+
   testWidgets('MediaQueryData.copyWith defaults to source', (WidgetTester tester) async {
     final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
     final MediaQueryData copied = data.copyWith();
@@ -753,19 +1111,17 @@
   });
 
   testWidgets('MediaQuery.fromWindow creates a MediaQuery', (WidgetTester tester) async {
-    bool hasMediaQueryAsParentOutside = false;
-    bool hasMediaQueryAsParentInside = false;
+    MediaQuery? mediaQueryOutside;
+    MediaQuery? mediaQueryInside;
 
     await tester.pumpWidget(
       Builder(
         builder: (BuildContext context) {
-          hasMediaQueryAsParentOutside =
-              context.findAncestorWidgetOfExactType<MediaQuery>() != null;
+          mediaQueryOutside = context.findAncestorWidgetOfExactType<MediaQuery>();
           return MediaQuery.fromWindow(
             child: Builder(
               builder: (BuildContext context) {
-                hasMediaQueryAsParentInside =
-                    context.findAncestorWidgetOfExactType<MediaQuery>() != null;
+                mediaQueryInside = context.findAncestorWidgetOfExactType<MediaQuery>();
                 return const SizedBox();
               },
             ),
@@ -774,8 +1130,8 @@
       ),
     );
 
-    expect(hasMediaQueryAsParentOutside, false);
-    expect(hasMediaQueryAsParentInside, true);
+    expect(mediaQueryInside, isNotNull);
+    expect(mediaQueryOutside, isNot(mediaQueryInside));
   });
 
   testWidgets('MediaQueryData.fromWindow is created using window values', (WidgetTester tester) async {
@@ -1150,3 +1506,58 @@
     ]
   ));
 }
+
+Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required  Widget widget}) {
+  tester.binding.attachRootWidget(widget);
+  tester.binding.scheduleFrame();
+  return tester.binding.pump();
+}
+
+class TestView implements FlutterView {
+  TestView({
+    PlatformDispatcher? platformDispatcher,
+    required this.physicalSize,
+    required this.devicePixelRatio,
+    required this.padding,
+    required this.viewPadding,
+    required this.viewInsets,
+    required this.systemGestureInsets,
+  }) : _platformDispatcher = platformDispatcher;
+
+  @override
+  PlatformDispatcher get platformDispatcher => _platformDispatcher!;
+  final PlatformDispatcher? _platformDispatcher;
+  @override
+  final Size physicalSize;
+  @override
+  final double devicePixelRatio;
+  @override
+  final WindowPadding padding;
+  @override
+  final WindowPadding viewPadding;
+  @override
+  final WindowPadding viewInsets;
+  @override
+  final WindowPadding systemGestureInsets;
+  @override
+  final ViewConfiguration viewConfiguration = const ViewConfiguration();
+  @override
+  final List<DisplayFeature> displayFeatures = <DisplayFeature>[];
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class TestWindowPadding implements WindowPadding {
+  const TestWindowPadding(this.value);
+  final double value;
+
+  @override
+  double get bottom => value;
+  @override
+  double get left => value;
+  @override
+  double get right => value;
+  @override
+  double get top => value;
+}
diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart
index a3cc298..a1fdd05 100644
--- a/packages/flutter/test/widgets/selectable_text_test.dart
+++ b/packages/flutter/test/widgets/selectable_text_test.dart
@@ -2707,14 +2707,6 @@
     semantics.dispose();
   });
 
-  testWidgets('SelectableText throws when not descended from a MediaQuery widget', (WidgetTester tester) async {
-    const Widget selectableText = SelectableText('something');
-    await tester.pumpWidget(selectableText);
-    final dynamic exception = tester.takeException();
-    expect(exception, isFlutterError);
-    expect(exception.toString(), startsWith('No MediaQuery widget ancestor found.\nSelectableText widgets require a MediaQuery widget ancestor.'));
-  });
-
   testWidgets('onTap is called upon tap', (WidgetTester tester) async {
     int tapCount = 0;
     await tester.pumpWidget(
diff --git a/packages/flutter/test/widgets/slotted_render_object_widget_test.dart b/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
index 257951a..b8816d7 100644
--- a/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
+++ b/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
@@ -221,14 +221,16 @@
       tester.renderObject(find.byType(_Diagonal)).toStringDeep(),
       equalsIgnoringHashCodes(
         '_RenderDiagonal#00000 relayoutBoundary=up1\n'
-        ' │ creator: _Diagonal ← Align ← Directionality ←\n'
-        ' │   View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+        ' │ creator: _Diagonal ← Align ← Directionality ← MediaQuery ←\n'
+        ' │   _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+        ' │   TestWindow#00000] ← [root]\n'
         ' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
         ' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
         ' │ size: Size(190.0, 220.0)\n'
         ' │\n'
         ' ├─topLeft: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
         ' │   creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
+        ' │     MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
         ' │     View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         ' │   parentData: offset=Offset(0.0, 0.0) (can use size)\n'
         ' │   constraints: BoxConstraints(unconstrained)\n'
@@ -237,6 +239,7 @@
         ' │\n'
         ' └─bottomRight: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
         '     creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
+        '       MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
         '       View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
         '     parentData: offset=Offset(80.0, 100.0) (can use size)\n'
         '     constraints: BoxConstraints(unconstrained)\n'
diff --git a/packages/flutter/test/widgets/table_test.dart b/packages/flutter/test/widgets/table_test.dart
index 345c941..ea9fc30 100644
--- a/packages/flutter/test/widgets/table_test.dart
+++ b/packages/flutter/test/widgets/table_test.dart
@@ -879,24 +879,24 @@
     expect(
       element.toStringDeep(minLevel: DiagnosticLevel.info),
       equalsIgnoringHashCodes(
-        'Table-[GlobalKey#00000](dependencies: [Directionality], renderObject: RenderTable#00000)\n'
-        '├Text("A")\n'
+        'Table-[GlobalKey#00000](dependencies: [Directionality, MediaQuery], renderObject: RenderTable#00000)\n'
+        '├Text("A", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "A", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("B")\n'
+        '├Text("B", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "B", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("C")\n'
+        '├Text("C", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "C", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("D")\n'
+        '├Text("D", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "D", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("EEE")\n'
+        '├Text("EEE", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "EEE", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("F")\n'
+        '├Text("F", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "F", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("G")\n'
+        '├Text("G", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "G", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '├Text("H")\n'
+        '├Text("H", dependencies: [MediaQuery])\n'
         '│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "H", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
-        '└Text("III")\n'
+        '└Text("III", dependencies: [MediaQuery])\n'
         ' └RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "III", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n',
       ),
     );
diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart
index a0b4f8a..713406e 100644
--- a/packages/flutter_test/test/widget_tester_test.dart
+++ b/packages/flutter_test/test/widget_tester_test.dart
@@ -99,7 +99,7 @@
       final String? message = failure.message;
 
       expect(message, contains('Expected: no matching nodes in the widget tree\n'));
-      expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo": Text("foo", textDirection: ltr)>\n'));
+      expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo": Text("foo", textDirection: ltr, dependencies: [MediaQuery])>\n'));
       expect(message, contains('Which: means one was found but none were expected\n'));
     });
 
@@ -117,7 +117,7 @@
       final String? message = failure.message;
 
       expect(message, contains('Expected: no matching nodes in the widget tree\n'));
-      expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo" (ignoring offstage widgets): Text("foo", textDirection: ltr)>\n'));
+      expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo" (ignoring offstage widgets): Text("foo", textDirection: ltr, dependencies: [MediaQuery])>\n'));
       expect(message, contains('Which: means one was found but none were expected\n'));
     });
   });