ReviewOS

also looking at this

stacks/stx

fix(native): preserve authored keys in mutation nodes

#2084
Closed chris wants to merge codex/native-mutation-authored-keys into main
3 files +77 -3

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/stx/src/native/bridge/protocol.tsmodified+3-1
Changes to packages/stx/src/native/bridge/protocol.ts
@@ -112,6 +112,8 @@ export interface RenderPayload {
112112
113113export interface NativeMutationNode {
114114 type: string
115 /** Authored reconciliation identity, retained across native mutations. */
116 key?: string
115117 props?: Record<string, unknown>
116118 style?: Partial<import('../compiler/ir').STXStyle>
117119 events?: Record<string, string>
@@ -121,7 +123,7 @@ export interface NativeMutationNode {
121123
122124export type NativeMutationOperation
123125 = | { op: 'createNode', id: string, node: NativeMutationNode, root?: boolean }
124 | { op: 'updateNode', id: string, patch: Omit<NativeMutationNode, 'type'> }
126 | { op: 'updateNode', id: string, patch: Omit<NativeMutationNode, 'type' | 'key'> }
125127 | { op: 'insertChild', parentId: string, childId: string, index: number }
126128 | { op: 'moveChild', parentId: string, childId: string, index: number }
127129 | { op: 'removeNode', id: string }
packages/stx/src/native/runtime/native-host.tsmodified+6-2
Changes to packages/stx/src/native/runtime/native-host.ts
@@ -52,6 +52,7 @@ export interface NativeNode {
5252
5353interface NodeRecord {
5454 type: string
55 key?: string
5556 props: Record<string, unknown>
5657 style: Record<string, unknown>
5758 baseStyle: Record<string, unknown>
@@ -131,7 +132,7 @@ export interface NativeHost {
131132 descendants: (node: NativeNode) => NativeNode[]
132133 scopesIn: (node: NativeNode) => string[]
133134 /** Register a node the native side already created, so the host can track it. */
134 adopt: (node: NativeNode, type: string, owner?: NativeNode | null, descriptor?: Pick<STXNode, 'props' | 'style' | 'events' | 'children' | '_classes' | '_inlineStyle'>) => NativeNode
135 adopt: (node: NativeNode, type: string, owner?: NativeNode | null, descriptor?: Pick<STXNode, 'key' | 'props' | 'style' | 'events' | 'children' | '_classes' | '_inlineStyle'>) => NativeNode
135136 /** Send whatever is pending now, rather than waiting for the scheduled flush. */
136137 flush: () => void
137138 /** Dispatch an event the native side reported, by the id handed to it. */
@@ -291,6 +292,7 @@ export function createNativeHost(options: NativeHostOptions): NativeHost {
291292 id: node.__stxId,
292293 node: {
293294 type: record.type,
295 ...(record.key === undefined ? {} : { key: record.key }),
294296 props: { ...record.props },
295297 style: { ...record.style },
296298 ...(Object.keys(record.events).length ? { events: { ...record.events } } : {}),
@@ -408,7 +410,7 @@ export function createNativeHost(options: NativeHostOptions): NativeHost {
408410 }
409411 }
410412
411 function adopt(node: NativeNode, type: string, owner?: NativeNode | null, descriptor?: Pick<STXNode, 'props' | 'style' | 'events' | 'children' | '_classes' | '_inlineStyle'>): NativeNode {
413 function adopt(node: NativeNode, type: string, owner?: NativeNode | null, descriptor?: Pick<STXNode, 'key' | 'props' | 'style' | 'events' | 'children' | '_classes' | '_inlineStyle'>): NativeNode {
412414 const suffix = /(?:^|\D)(\d+)$/.exec(node.__stxId)?.[1]
413415 if (suffix)
414416 counter = Math.max(counter, Number(suffix))
@@ -417,6 +419,7 @@ export function createNativeHost(options: NativeHostOptions): NativeHost {
417419 const baseStyle = descriptor?._inlineStyle ? { ...descriptor._inlineStyle } : Object.fromEntries(Object.entries(descriptor?.style ?? {}).filter(([key, value]) => classStyle[key] !== value))
418420 const record: NodeRecord = {
419421 type,
422 key: descriptor?.key,
420423 props: { ...(descriptor?.props ?? {}) },
421424 style: { ...(descriptor?.style ?? {}) },
422425 baseStyle,
@@ -660,6 +663,7 @@ export function createNativeHost(options: NativeHostOptions): NativeHost {
660663 }
661664 records.set(copy.__stxId, {
662665 type: descriptor.type,
666 key: descriptor.key,
663667 props: { ...descriptor.props, __stxId: copy.__stxId },
664668 style: { ...descriptor.style },
665669 baseStyle: { ...descriptor.baseStyle },