From 2052c8507491c9c4039ef10c29696f15b209b1b4 Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Fri, 8 Nov 2024 14:03:52 -0500 Subject: [PATCH] Switch back to MutableMap to avoid scatter map bug Sometimes the scatter-based maps can return values from other keys when inserting a new key. See https://issuetracker.google.com/issues/378077858. --- .../protocol/host/HostProtocolAdapter.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/redwood-protocol-host/src/commonMain/kotlin/app/cash/redwood/protocol/host/HostProtocolAdapter.kt b/redwood-protocol-host/src/commonMain/kotlin/app/cash/redwood/protocol/host/HostProtocolAdapter.kt index 1b5649d4d8..faa5bada9e 100644 --- a/redwood-protocol-host/src/commonMain/kotlin/app/cash/redwood/protocol/host/HostProtocolAdapter.kt +++ b/redwood-protocol-host/src/commonMain/kotlin/app/cash/redwood/protocol/host/HostProtocolAdapter.kt @@ -36,6 +36,7 @@ import app.cash.redwood.protocol.RedwoodVersion import app.cash.redwood.protocol.WidgetTag import app.cash.redwood.widget.ChangeListener import app.cash.redwood.widget.Widget +import kotlin.collections.mutableMapOf import kotlin.native.ObjCName /** @@ -61,7 +62,7 @@ public class HostProtocolAdapter( } private val nodes = - mutableIntObjectMapOf>(Id.Root.value, RootProtocolNode(container)) + mutableMapOf>(Id.Root.value to RootProtocolNode(container)) private val removeNodeById = IdVisitor { nodes.remove(it.value) } @@ -173,7 +174,7 @@ public class HostProtocolAdapter( public fun close() { closed = true - nodes.forEachValue { node -> + nodes.values.forEach { node -> node.detach() } nodes.clear() @@ -235,9 +236,10 @@ public class HostProtocolAdapter( // Must have a Create node that precedes it. if (lastCreatedId != change.id) continue - idToNode[change.id.value] = ReuseNode( - widgetId = change.id, - childrenTag = ChildrenTag.Root, + idToNode[lastCreatedId.value] = ReuseNode( + widgetId = lastCreatedId, + // This is the root of the reuse tree, so it will never have a children tag from a parent. + childrenTag = ChildrenTag(-1), ) } @@ -359,19 +361,17 @@ public class HostProtocolAdapter( * descendants into the nodes map. */ fun assignPooledNodeRecursive( - nodes: MutableIntObjectMap>, + nodes: MutableMap>, changesAndNulls: Array, pooled: ProtocolNode, ) { // Reuse the node. + pooled.id = widgetId val old = nodes.put(widgetId.value, pooled) require(old == null) { "Insert attempted to replace existing widget with ID ${widgetId.value}" } - val skippedCreate = changesAndNulls[changeIndexForCreate] as Create - pooled.id = skippedCreate.id - // Remove the corresponding changes that we avoided by node reuse. We don't clear the 'Add' // that adds the node to its new parent. changesAndNulls[changeIndexForCreate] = null