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;