diff --git a/.changeset/few-shirts-laugh.md b/.changeset/few-shirts-laugh.md new file mode 100644 index 0000000000..853d812bb3 --- /dev/null +++ b/.changeset/few-shirts-laugh.md @@ -0,0 +1,3 @@ +--- + +--- diff --git a/packages/react/runtime/__test__/basic.test.jsx b/packages/react/runtime/__test__/basic.test.jsx index acbf8df003..ede6922cd9 100644 --- a/packages/react/runtime/__test__/basic.test.jsx +++ b/packages/react/runtime/__test__/basic.test.jsx @@ -136,6 +136,103 @@ describe('insertBefore', () => { `); }); + it('keeps __current_slot_index stable when removing content inside slot wrappers', async function() { + const snapshot1 = __SNAPSHOT__( + + + {HOLE}!!!{HOLE} + + , + ); + + const snapshot2 = __SNAPSHOT__( + + Hello World + , + ); + + const a = new SnapshotInstance(snapshot1); + a.ensureElements(); + + // Insert two wrappers for stable slot index + const b = new SnapshotInstance('wrapper'); + const c = new SnapshotInstance('wrapper'); + expect(a.__current_slot_index).toBe(0); + a.insertBefore(b); + expect(a.__current_slot_index).toBe(1); + a.insertBefore(c); + expect(a.__current_slot_index).toBe(2); + expect(a.__element_root).toMatchInlineSnapshot(` + + + + + + + + `); + + const d = new SnapshotInstance(snapshot2); + const e = new SnapshotInstance(snapshot2); + + b.insertBefore(d); + c.insertBefore(e); + + expect(a.__current_slot_index).toBe(2); + expect(a.__element_root).toMatchInlineSnapshot(` + + + + + + + + + + + + + + + + + + + + `); + + b.removeChild(d); + + expect(a.__current_slot_index).toBe(2); + expect(a.__element_root).toMatchInlineSnapshot(` + + + + + + + + + + + + + + `); + }); + it('snapshot slot count = 2 - delayed ensureElements', async function() { const snapshot1 = __SNAPSHOT__( diff --git a/packages/react/runtime/src/snapshot/snapshot.ts b/packages/react/runtime/src/snapshot/snapshot.ts index be32ed7b1f..62ea06d52a 100644 --- a/packages/react/runtime/src/snapshot/snapshot.ts +++ b/packages/react/runtime/src/snapshot/snapshot.ts @@ -80,6 +80,10 @@ export class SnapshotInstance { __elements?: FiberElement[] | undefined; __element_root?: FiberElement | undefined; __values?: unknown[] | undefined; + // current slot index for dynamic parts + // only increment when inserting dynamic parts + // when removing dynamic parts, the slot index will not change + // cause there would be a wrapper to keep the slot index stable __current_slot_index = 0; __worklet_ref_set?: Set | Worklet>; __listItemPlatformInfo?: PlatformInfo;