V1.9.1 hotfix (#43288)

This fixes the issue described in https://github.com/flutter/flutter/issues/40239:

* Restore offstage and ticker mode after hero pop and the from hero is null (#40306)
diff --git a/packages/flutter/lib/src/widgets/heroes.dart b/packages/flutter/lib/src/widgets/heroes.dart
index a4299df..eb84423 100644
--- a/packages/flutter/lib/src/widgets/heroes.dart
+++ b/packages/flutter/lib/src/widgets/heroes.dart
@@ -359,7 +359,8 @@
   }
 
   // When `keepPlaceholder` is true, the placeholder will continue to be shown
-  // after the flight ends.
+  // after the flight ends. Otherwise the child of the Hero will become visible
+  // and its TickerMode will be re-enabled.
   void endFlight({ bool keepPlaceholder = false }) {
     if (!keepPlaceholder) {
       ensurePlaceholderIsHidden();
@@ -828,6 +829,13 @@
         _flights[tag].abort();
       }
     }
+
+    // If the from hero is gone, the flight won't start and the to hero needs to
+    // be put on stage again.
+    for (Object tag in toHeroes.keys) {
+      if (fromHeroes[tag] == null)
+        toHeroes[tag].ensurePlaceholderIsHidden();
+    }
   }
 
   void _handleFlightEnded(_HeroFlight flight) {
diff --git a/packages/flutter/test/widgets/heroes_test.dart b/packages/flutter/test/widgets/heroes_test.dart
index 42390ed..0a013ac 100644
--- a/packages/flutter/test/widgets/heroes_test.dart
+++ b/packages/flutter/test/widgets/heroes_test.dart
@@ -2255,4 +2255,54 @@
       moreOrLessEquals(tester.getTopLeft(find.text('1')).dx, epsilon: 0.01)
     );
   });
+
+  // Regression test for https://github.com/flutter/flutter/issues/40239.
+  testWidgets(
+    'In a pop transition, when fromHero is null, the to hero should eventually become visible',
+    (WidgetTester tester) async {
+      final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
+      StateSetter setState;
+      bool shouldDisplayHero = true;
+      await tester.pumpWidget(
+        CupertinoApp(
+          navigatorKey: navigatorKey,
+          home: Hero(
+            tag: navigatorKey,
+            child: const Placeholder(),
+          ),
+        ),
+      );
+
+      final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
+        builder: (BuildContext context) {
+          return CupertinoPageScaffold(
+            child: StatefulBuilder(
+              builder: (BuildContext context, StateSetter setter) {
+                setState = setter;
+                return shouldDisplayHero
+                  ? Hero(tag: navigatorKey, child: const Text('text'))
+                  : const SizedBox();
+              },
+            ),
+          );
+        },
+      );
+
+      navigatorKey.currentState.push(route2);
+      await tester.pumpAndSettle();
+
+      expect(find.text('text'), findsOneWidget);
+      expect(find.byType(Placeholder), findsNothing);
+
+      setState(() { shouldDisplayHero = false; });
+      await tester.pumpAndSettle();
+
+      expect(find.text('text'), findsNothing);
+
+      navigatorKey.currentState.pop();
+      await tester.pumpAndSettle();
+
+      expect(find.byType(Placeholder), findsOneWidget);
+    },
+  );
 }