Commit 5cb6524
Summary:
Fixes #53542
**Problem:** `maintainVisibleContentPosition` fails when FlatList data is updated rapidly with prepends in quick succession (e.g., chat receiving messages). After 2 prepends before native scroll drains, render window stays frozen, `onViewableItemsChanged` suppressed, `onEndReached` never fires.
**Root cause:** `pendingScrollUpdateCount` assumption is structurally unsound – it increments by 1 per prepend in `getDerivedStateFromProps` (0→1→2) but native scroll events are dispatched as unique events that coalesce. Verified in C++:
- `ScrollViewEventEmitter.cpp:13` – `onScroll` dispatched with `dispatchUniqueEvent("scroll", ...)`
- `EventQueue.cpp:29-50` – unique event whose target+type matches existing replaces in place (line 49) instead of appending
So N scroll events emitted before queue flush deliver exactly 1 to JS. Single coalesced event drains 2→1 leaving blocked. Also leak when JS predicate fires (old key found at new index) but native declines to adjust (tag recycled, view deleted, delta ≤0.5, clamped).
**Fix (1 file, 2 lines core):** Clamp pending to at most 1 and drain to 0 on any scroll:
- `pendingScrollUpdateCount: 1` instead of `prev+1` – prevents accumulation during rapid prepends
- `setState({pendingScrollUpdateCount: 0})` instead of `-1` – single coalesced scroll unblocks
This turns "stuck at N" into unblocked after next scroll, fixing frozen window / viewability / onEndReached for rapid updates. For leak path where native declines (no scroll ever), flag would still be stranded at 1 – addressed by boolean rename + escape hatch in follow-up, but this PR already strictly improves and matches existing tests that drain 0→1→0.
## Changelog:
[GENERAL] [FIXED] - Fix maintainVisibleContentPosition with rapid data updates (#53542)
Pull Request resolved: #57955
Test Plan:
**Jest (VirtualizedList):**
```bash
yarn jest --watchman=false packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js --no-coverage --ci
# Before: new coalesced test fails with pending 1
# After: 83 passed (82 existing + 1 new rapid prepends with coalesced scroll), 1 skipped, 59 snapshots
```
**New test ( regression for #53542 ):**
- Simulates 2 rapid prepends WITHOUT intermediate scroll (5 + 3 items)
- Only 1 coalesced scroll event (delta 8*ITEM_HEIGHT)
- Asserts `pendingScrollUpdateCount === 0` (fails on main with 1) and `firstVisibleItemKey` not null
**Existing MVCP tests still pass:**
- `handles maintainVisibleContentPosition`
- `handles multiple rapid prepends` (separate scroll per prepend)
- `delta stays bounded`
- `minIndexForVisible >0` and `inverted`
**Lint:**
```bash
yarn lint
# Done (max-warnings 0)
```
Closes #53542
Reviewed By: javache
Differential Revision: D115907610
Pulled By: fabriziocucci
fbshipit-source-id: 0cd59b35d7c43803a000b93779cd84c9c4202053
1 parent f63b2a1 commit 5cb6524
2 files changed
Lines changed: 79 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
777 | 777 | | |
778 | 778 | | |
779 | 779 | | |
780 | | - | |
| 780 | + | |
781 | 781 | | |
782 | 782 | | |
783 | 783 | | |
| |||
1760 | 1760 | | |
1761 | 1761 | | |
1762 | 1762 | | |
1763 | | - | |
1764 | | - | |
1765 | | - | |
| 1763 | + | |
1766 | 1764 | | |
1767 | 1765 | | |
1768 | 1766 | | |
| |||
Lines changed: 77 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2877 | 2877 | | |
2878 | 2878 | | |
2879 | 2879 | | |
| 2880 | + | |
| 2881 | + | |
| 2882 | + | |
| 2883 | + | |
| 2884 | + | |
| 2885 | + | |
| 2886 | + | |
| 2887 | + | |
| 2888 | + | |
| 2889 | + | |
| 2890 | + | |
| 2891 | + | |
| 2892 | + | |
| 2893 | + | |
| 2894 | + | |
| 2895 | + | |
| 2896 | + | |
| 2897 | + | |
| 2898 | + | |
| 2899 | + | |
| 2900 | + | |
| 2901 | + | |
| 2902 | + | |
| 2903 | + | |
| 2904 | + | |
| 2905 | + | |
| 2906 | + | |
| 2907 | + | |
| 2908 | + | |
| 2909 | + | |
| 2910 | + | |
| 2911 | + | |
| 2912 | + | |
| 2913 | + | |
| 2914 | + | |
| 2915 | + | |
| 2916 | + | |
| 2917 | + | |
| 2918 | + | |
| 2919 | + | |
| 2920 | + | |
| 2921 | + | |
| 2922 | + | |
| 2923 | + | |
| 2924 | + | |
| 2925 | + | |
| 2926 | + | |
| 2927 | + | |
| 2928 | + | |
| 2929 | + | |
| 2930 | + | |
| 2931 | + | |
| 2932 | + | |
| 2933 | + | |
| 2934 | + | |
| 2935 | + | |
| 2936 | + | |
| 2937 | + | |
| 2938 | + | |
| 2939 | + | |
| 2940 | + | |
| 2941 | + | |
| 2942 | + | |
| 2943 | + | |
| 2944 | + | |
| 2945 | + | |
| 2946 | + | |
| 2947 | + | |
| 2948 | + | |
| 2949 | + | |
| 2950 | + | |
| 2951 | + | |
| 2952 | + | |
| 2953 | + | |
| 2954 | + | |
| 2955 | + | |
| 2956 | + | |
2880 | 2957 | | |
2881 | 2958 | | |
2882 | 2959 | | |
| |||
0 commit comments