Skip to content

Commit e141b64

Browse files
test: cover Repeat backward slide; add changeset for #2767 offset reset
Supplies the changeset missing from the merged #2784 fix (Repeat offset reset on empty window) and adds a regression test for the backward-slide path (`_offset > from`) that neither #2767 repro exercised — verifying departing rows are disposed and the overlapping row is retained. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 2717fc5 commit e141b64

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solidjs/signals": patch
3+
---
4+
5+
Reset `<Repeat>`'s window offset when its count drops to zero. Previously the empty-window path cleared the row data but left `_offset` stale, so a later nonzero render with a smaller `from` computed a negative local index and disposed `_nodes[-1]`, crashing `updateRepeat`. This is the second symptom of #2767 (the first, wrong-row disposal on a forward slide, was fixed separately).

packages/solid-signals/tests/repeat.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,36 @@ it("recovers when count goes to 0, from changes, and count comes back nonzero (#
313313
flush();
314314
expect(snapshot.map((r: any) => r.index)).toEqual([0]);
315315
});
316+
317+
it("slides the window backwards: disposes departing rows and retains the overlap (#2767)", () => {
318+
const [from, setFrom] = createSignal(3);
319+
const disposed: number[] = [];
320+
321+
const map = repeat(
322+
() => 3,
323+
index => {
324+
onCleanup(() => disposed.push(index));
325+
return { index };
326+
},
327+
{ from }
328+
);
329+
330+
let snapshot: any[] = [];
331+
createRoot(() => {
332+
createEffect(map, rows => {
333+
snapshot = rows.slice();
334+
});
335+
});
336+
flush();
337+
expect(snapshot.map(r => r.index)).toEqual([3, 4, 5]);
338+
const retained = snapshot[0]; // row at global index 3
339+
340+
// window 3-5 -> 1-3: rows 4 and 5 leave, rows 1 and 2 enter, row 3 stays
341+
setFrom(1);
342+
flush();
343+
expect(snapshot.map(r => r.index)).toEqual([1, 2, 3]);
344+
// overlap row is the same instance, now at the tail
345+
expect(snapshot[2]).toBe(retained);
346+
// only the departing rows were disposed
347+
expect(disposed.sort()).toEqual([4, 5]);
348+
});

0 commit comments

Comments
 (0)