Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

virtual-core: desktop Safari drops the prepend anchor write when history lands during the top rubber-band bounce

Aperta
#1,287 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
38/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
react, typescript

Direzione di ricerca

Riprodurre con pnpm --filter tanstack-react-virtual-example-chat dev in Safari desktop usando un prepend rapido durante il rubber-band superiore. Leggere setOptions, _willUpdate e _flushIosDeferredIfReady, confrontando il percorso di scrittura desktop con la gestione dell’overscroll di iOS e le tecniche citate in #1189 e #1280. Il lavoro è completato quando una lista ancorata alla fine mantiene la riga del lettore durante il rimbalzo senza renderizzare un viewport vuoto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the bug

On macOS Safari (18.4, navigator.maxTouchPoints 0, so none of the iOS deferral is involved), an end-anchored list loses its reading position when a prepend lands while the scroller is rubber-banding past its top edge.

Sequence, from a per-frame trace of the react chat example (anchorTo: 'end', directDomUpdates: true, 180 ms mock history load):

 1283ms st=159  off=159  range=1-10 count=45 top=1
 1300ms st=0    off=0    range=0-9  count=45 top=0   <- auto history load triggers
 1316ms st=-20  off=-20  range=0-8  count=45 top=0   <- Safari rubber band, scrollTop negative
 1383ms st=-69  off=-69  range=0-8  count=45 top=0
 1466ms st=-51  off=-51  range=0-8  count=45 top=0
 1484ms st=-46  off=-46  range=0-10 count=57 top=-12 <- 12 rows prepended, anchor write lost

setOptions resolves the anchor and _willUpdate writes scrollTop = 842 to keep row 0 in place. WebKit discards a scrollTop write made during an elastic bounce and animates back to 0. The next bounce scroll event reports the DOM value, the tracked offset follows it, and the viewport now shows the newly prepended rows: the reader is exactly one prepend away from where they were. While the eagerly bumped offset and the DOM disagree the viewport can also render blank, since the range is computed for a position the DOM never reaches.

The iOS flush path already treats the overscroll zone as unwritable (_flushIosDeferredIfReady, "Phase 2b"). The desktop write path has no such guard.

Steps to reproduce
  1. pnpm --filter tanstack-react-virtual-example-chat dev, open in desktop Safari with a trackpad.
  2. Fling upward hard enough to hit the top and bounce.
  3. The 180 ms mock load lands during the bounce. The list shows the newly loaded rows instead of the row you were reading.

With a slower (real) backend the load usually lands after the bounce has settled and the write goes through, so this needs a fast prepend to trigger. Cached or prefetched history makes that common.

What was tried

A deferral of writes made while scrollOffset < 0, replayed on the first in-bounds scroll event, lands on the correct row but shows the new rows for the duration of the bounce and then snaps back. That reads as a glitch every time and was dropped from #1280. On WebKit the reader's row cannot be held still through the bounce with scrollTop at all.

Options
  • App level, to verify first: overscroll-behavior: none on the scroll container. Safari 16+ supports it and per spec none suppresses the boundary bounce. If it removes the rubber band, the failure window disappears and the chat docs can recommend it next to overflow-anchor: none.
  • Core: a CSS offset on the container for the bounce window, swapped for a real scrollTop write once the offset is back in bounds. This is the technique from #1189, scoped to this one case.
  • Example: the auto-load fires on every bounce scroll event below 120 px, so after the first load finishes the bounce triggers a second one. Independent of the core issue, but it amplifies it.
Platform
  • macOS, Safari 18.4 (20621.1.15.11.10)
  • @tanstack/virtual-core at main (also reproduces with #1280 applied; unrelated to the iOS path)

Related: #1280, #1189, #884.

Lingua principale
TypeScript
Stelle
7.1k
Fork
466
Merge medio
2g 31m
PR unite (30g)
13

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di TanStack/virtual

Tutte le issue di TanStack/virtual

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.