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..0a0af0f43d 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 /** @@ -60,8 +61,9 @@ public class HostProtocolAdapter( is GeneratedHostProtocol -> factory } + // TODO Use MutableIntObjectMap once https://issuetracker.google.com/issues/378077858 is fixed. 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 +175,7 @@ public class HostProtocolAdapter( public fun close() { closed = true - nodes.forEachValue { node -> + nodes.values.forEach { node -> node.detach() } nodes.clear() @@ -235,9 +237,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 +362,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