Merge "Change transitions in progress back to a Set" into androidx-main
diff --git a/navigation/navigation-common/api/2.4.0-beta01.txt b/navigation/navigation-common/api/2.4.0-beta01.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/2.4.0-beta01.txt
+++ b/navigation/navigation-common/api/2.4.0-beta01.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/api/current.txt b/navigation/navigation-common/api/current.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/current.txt
+++ b/navigation/navigation-common/api/current.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/api/public_plus_experimental_2.4.0-beta01.txt b/navigation/navigation-common/api/public_plus_experimental_2.4.0-beta01.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/public_plus_experimental_2.4.0-beta01.txt
+++ b/navigation/navigation-common/api/public_plus_experimental_2.4.0-beta01.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/api/public_plus_experimental_current.txt b/navigation/navigation-common/api/public_plus_experimental_current.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-common/api/public_plus_experimental_current.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/api/restricted_2.4.0-beta01.txt b/navigation/navigation-common/api/restricted_2.4.0-beta01.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/restricted_2.4.0-beta01.txt
+++ b/navigation/navigation-common/api/restricted_2.4.0-beta01.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/api/restricted_current.txt b/navigation/navigation-common/api/restricted_current.txt
index a169ec7..067333a 100644
--- a/navigation/navigation-common/api/restricted_current.txt
+++ b/navigation/navigation-common/api/restricted_current.txt
@@ -497,7 +497,7 @@
     ctor public NavigatorState();
     method public abstract androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
     method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getBackStack();
-    method public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
+    method public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> getTransitionsInProgress();
     method public void markTransitionComplete(androidx.navigation.NavBackStackEntry entry);
     method @CallSuper public void onLaunchSingleTop(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pop(androidx.navigation.NavBackStackEntry popUpTo, boolean saveState);
@@ -505,7 +505,7 @@
     method public void push(androidx.navigation.NavBackStackEntry backStackEntry);
     method public void pushWithTransition(androidx.navigation.NavBackStackEntry backStackEntry);
     property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> backStack;
-    property public final kotlinx.coroutines.flow.StateFlow<java.util.List<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
+    property public final kotlinx.coroutines.flow.StateFlow<java.util.Set<androidx.navigation.NavBackStackEntry>> transitionsInProgress;
   }
 
   @androidx.navigation.NavOptionsDsl public final class PopUpToBuilder {
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorState.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorState.kt
index 9c0772b..a6e420d 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorState.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorState.kt
@@ -32,8 +32,8 @@
 public abstract class NavigatorState {
     private val backStackLock = ReentrantLock(true)
     private val _backStack: MutableStateFlow<List<NavBackStackEntry>> = MutableStateFlow(listOf())
-    private val _transitionsInProgress: MutableStateFlow<List<NavBackStackEntry>> =
-        MutableStateFlow(listOf())
+    private val _transitionsInProgress: MutableStateFlow<Set<NavBackStackEntry>> =
+        MutableStateFlow(setOf())
 
     /**
      * @hide
@@ -54,7 +54,7 @@
      * This is the set of currently running transitions. Use this set to retrieve the entry and call
      * [markTransitionComplete] once the transition is complete.
      */
-    public val transitionsInProgress: StateFlow<List<NavBackStackEntry>> =
+    public val transitionsInProgress: StateFlow<Set<NavBackStackEntry>> =
         _transitionsInProgress.asStateFlow()
 
     /**
diff --git a/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavigatorStateTest.kt b/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavigatorStateTest.kt
index 0203eda..faa7248 100644
--- a/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavigatorStateTest.kt
+++ b/navigation/navigation-testing/src/androidTest/java/androidx/navigation/testing/TestNavigatorStateTest.kt
@@ -17,11 +17,14 @@
 package androidx.navigation.testing
 
 import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
 import androidx.navigation.FloatingWindow
 import androidx.navigation.NavBackStackEntry
 import androidx.navigation.NavDestination
 import androidx.navigation.NavOptions
 import androidx.navigation.Navigator
+import androidx.navigation.navOptions
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
@@ -190,6 +193,41 @@
             .isEqualTo(Lifecycle.State.DESTROYED)
     }
 
+    @Test
+    fun testNewInstanceBeforeComplete() {
+        val navigator = TestTransitionNavigator()
+        navigator.onAttach(state)
+        val firstEntry = state.createBackStackEntry(navigator.createDestination(), null)
+        firstEntry.destination.route = "first"
+
+        navigator.navigate(listOf(firstEntry), null, null)
+        state.markTransitionComplete(firstEntry)
+
+        val secondEntry = state.createBackStackEntry(navigator.createDestination(), null)
+        secondEntry.destination.route = "second"
+        navigator.navigate(listOf(secondEntry), navOptions {
+            popUpTo("first") { saveState = true }
+            launchSingleTop = true
+            restoreState = true
+        }, null)
+
+        val viewModel = ViewModelProvider(secondEntry).get(TestViewModel::class.java)
+
+        navigator.popBackStack(secondEntry, true)
+        val restoredSecondEntry = state.restoreBackStackEntry(secondEntry)
+        navigator.navigate(listOf(restoredSecondEntry), navOptions {
+            popUpTo("first") { saveState = true }
+            launchSingleTop = true
+            restoreState = true
+        }, null)
+
+        state.transitionsInProgress.value.forEach {
+            state.markTransitionComplete(it)
+        }
+
+        assertThat(viewModel.wasCleared).isFalse()
+    }
+
     @Navigator.Name("test")
     internal class TestNavigator : Navigator<NavDestination>() {
         override fun createDestination(): NavDestination = NavDestination(this)
@@ -222,4 +260,13 @@
     internal class FloatingTestDestination(
         navigator: Navigator<out NavDestination>
     ) : NavDestination(navigator), FloatingWindow
+
+    class TestViewModel : ViewModel() {
+        var wasCleared = false
+
+        override fun onCleared() {
+            super.onCleared()
+            wasCleared = true
+        }
+    }
 }
\ No newline at end of file
diff --git a/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt b/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
index c146ce31..5a86fae 100644
--- a/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
+++ b/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
@@ -145,6 +145,7 @@
                         entry.maxLifecycle = Lifecycle.State.DESTROYED
                         if (!saveState) {
                             savedStates.remove(entry.id)
+                            viewModelStoreProvider.getViewModelStore(entry.id).clear()
                         }
                     } else {
                         entry.maxLifecycle = Lifecycle.State.CREATED