Merge "Fix and re-enable providers optimization" into androidx-main
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index 31650af..5427f4e 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -2006,18 +2006,14 @@
if (inserting) {
providers = parentScope.putValue(local, state)
invalid = false
+ writerHasAProvider = true
} else {
val oldScope = reader.groupAux(reader.currentGroup) as PersistentCompositionLocalMap
providers =
if ((!skipping || change) && (value.canOverride || !parentScope.contains(local)))
parentScope.putValue(local, state)
else oldScope
- if (oldScope !== providers) {
- invalid = true
- writerHasAProvider = true
- } else {
- invalid = false
- }
+ invalid = reusing || oldScope !== providers
}
if (invalid && !inserting) {
providerUpdates[reader.currentGroup] = providers
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
index cde9d7c..1073e39 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionLocal.kt
@@ -244,10 +244,9 @@
@Composable
@OptIn(InternalComposeApi::class)
fun CompositionLocalProvider(value: ProvidedValue<*>, content: @Composable () -> Unit) {
- // TODO(b/292224893): Switch this to the higher-performance startProvider()
- currentComposer.startProviders(arrayOf(value))
+ currentComposer.startProvider(value)
content()
- currentComposer.endProviders()
+ currentComposer.endProvider()
}
/**
diff --git a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
index 1289e49..4144ccd 100644
--- a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
+++ b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/CompositionLocalTests.kt
@@ -568,6 +568,44 @@
}
}
+ @Suppress("UNUSED_EXPRESSION")
+ @Test // Regression for b/292224893
+ fun testSingleInvalidatedProvider() = compositionTest {
+ val local1 = compositionLocalOf { 10 }
+ val local2 = compositionLocalOf { 20 }
+ val local3 = compositionLocalOf { 30 }
+ var state by mutableStateOf(0)
+
+ compose {
+ state
+ CompositionLocalProvider(local1 provides 11) {
+ state
+ CompositionLocalProvider(local2 provides 22) {
+ state
+ CompositionLocalProvider(local3 provides 33) {
+ state
+ assertEquals(11, local1.current)
+ assertEquals(22, local2.current)
+ assertEquals(33, local3.current)
+ }
+ assertEquals(11, local1.current)
+ assertEquals(22, local2.current)
+ assertEquals(30, local3.current)
+ }
+ assertEquals(11, local1.current)
+ assertEquals(20, local2.current)
+ assertEquals(30, local3.current)
+ }
+ assertEquals(10, local1.current)
+ assertEquals(20, local2.current)
+ assertEquals(30, local3.current)
+ }
+
+ state++
+
+ advance()
+ }
+
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testProvideAllLocals() = compositionTest {