refactor(virtual): 滚动写入事务化 + origin 锚定,根治长会话滚动空白带 - #607
Merged
Conversation
滚动位置回归 DOM 单一事实源,根治"滚轮滑动出现空白、再滚一下才恢复": - 收编 @tanstack/virtual-core@3.17.4 为 workspace 包(pnpm override workspace:*),源码/类型/测试就地管理,registry 的 react-virtual 包 透明复用; - Phase 1 写入事务化:每次程序化 scrollTo 一帧后读回校验,被合成器 吞掉的写入以 DOM 真值回滚镜像并重算区间(WKWebView 滚轮手势期间 主线程写入会被静默拒绝,镜像偏离导致渲染窗口错位、视口顶部露白); - Phase 2 origin 偏移锚定:视口上方估高修正与 prepend 键锚定改为吸收 进布局原点,可见行 DOM 位置零移动、滚动中零写入,债务在空闲/超限/ 近顶时由单次受校验写入结算; - Phase 3 方向性像素 overscan(粘滞于最近滚动方向,免除落定churn) 与 dev 态镜像-DOM 不变量断言; - 13 个核心回归测试覆盖吞写自愈、origin 吸收、rebase 触发与自愈闭环。 Co-authored-by: Cursor <cursoragent@cursor.com>
- GUI/WebUI 会话虚拟列表启用 scrollAnchoring=origin(滚动中零程序化 写入)与 480px 方向性 overscan(合成器先行滚动时露出预渲染内容而非 空白); - 行高测量 LRU 支持 localStorage 持久化(按宿主命名空间),重访会话跨 重启直接以精确行高布局,消解首滚估高误差这一补偿源头;损坏/超额存 储静默降级为纯内存,新增持久化回归测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
iOS 动量滚动期间 nearTop/overCap 强制 rebase 会先平移布局, 而配套的 scrollTop 写入被 iOS 延迟分支吞掉,布局与镜像短暂错位 并产生二次跳动;改为手势完全落定后再 rebase(touchend 宽限计时 器到期时补触发一次)。持久化层只存 [key, size] 二元组,localStorage 配额余量约提升 4 倍。 Co-authored-by: Cursor <cursoragent@cursor.com>
StackCairn
marked this pull request as draft
August 23, 2026 14:48
Contributor
|
PR governance checks failed — this PR has been converted to draft.
Fix the items above, then click Ready for review to re-run the checks. |
su-fen
marked this pull request as ready for review
August 23, 2026 15:05
@tanstack/virtual-core 经 pnpm overrides 指向 workspace 后, 镜像内缺少该包导致 react-virtual 的类型再导出全部失效, Gateway Docker Smoke 在 tsc 阶段失败。 Co-authored-by: Cursor <cursoragent@cursor.com>
复审发现 origin 锚定在目标平台上留有一个会复现 #606 的洞: maybeRebaseOrigin 只对 iOS 推迟手势期结算,macOS WKWebView 在 nearTop/overCap 强制路径下仍会滚动中写 scrollTop;写入被合成器 吞掉时 verifyScrollWriteLanded 只回滚 scrollOffset 镜像,已平移 的布局不回滚——可见行相对视口跳 |debt| 像素,先露白一帧再错位。 - 手势期强制 rebase 的推迟从 isIOSWebKit 扩大到整个 WebKit 家族 (macOS WKWebView/桌面 Safari 同样会吞主线程滚动写入);落定后 的 rebase 写入能可靠落地,视觉上是无操作。Blink/Gecko 尊重手势 期写入,强制路径保持原行为; - rebase 改为事务:记录结算的债务与写前偏移,滚动事件回声或校验 帧确认视口实际位移后结清;未被确认的部分回归 originOffset, 布局与镜像在同一趟内一起回滚,吞写/截断退化为"缩小的 rebase" 而非跳动,债务留待下一个安全时机结算; - 新增回归测试:WebKit 手势期推迟、滚动中吞写整帧回滚+重试自愈, 并按新契约收紧原吞写自愈测试(断言行位置逐像素不动)。 另修复两处持久化边角: - 超过 5000 行的快照此前直接跳过 localStorage 写入,旧的过期快照 会存活到下次重启被还原;改为写入时过滤超额条目,顺带清掉陈旧 副本(新增回归测试); - WebUI 持久化 layout key 补上行模型版本(对齐 GUI 的版本化 key), 避免行结构跨版本变化后错误行高穿透刷新继续污染布局。 Co-authored-by: Cursor <cursoragent@cursor.com>
Member
Author
|
对本 PR 做了一轮深度复审(结合收编源码逐段核对 + 可控 harness 复现),确认了一个会在目标平台上复现 #606 的洞和两处持久化边角问题,已修复并推送 bf78043。 已确认并修复1. macOS WKWebView 上强制 rebase 仍会滚动中写入,吞写后布局不回滚(核心)
修复(bf780436):
2. 超大会话跳过持久化后遗留过期快照
3. WebUI 持久化 layout key 缺行模型版本GUI 的 key 带 核查后降级(不改代码)
验证
仍建议合入前完成
|
unplugin-icons 经 local-pkg 的 import('@svgr/core') 编译 ~icons/*。
Node ESM 从 local-pkg 自身路径解析该包名,pnpm 又未把它提升到仓库
根 node_modules,Vite 8 worker 因此报 ERR_MODULE_NOT_FOUND。
- 用 packageExtensions 把 @svgr/core / plugin-jsx 挂到 local-pkg 旁;
- .npmrc 提升 @svgr/* 供向上查找兜底;
- overrides 同步到 pnpm-workspace.yaml,避免 pnpm 11 忽略
package.json#pnpm 后丢掉 virtual-core workspace 覆盖。
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #606
概要
crates/virtual-core,经 pnpm overrides 接管@tanstack/virtual-core解析),核心滚动逻辑纳入本仓库源码管理、类型检查与测试门禁;scrollTop写入后下一帧读回校验,被 WKWebView 吞掉的写入立即回滚镜像、采用 DOM 真值,消除scrollOffset镜像与真实滚动位置的持久发散(空白带的直接成因);originOffset),滚动进行中零scrollTop写入、可见行位置零移动;债务在滚动空闲、超额或接近顶部时以单次校验写入结算。iOS 手势期推迟结算,避免与动量滚动竞态;[key, size]格式)、dev 模式镜像不变量断言(节流 1s);scrollAnchoring: "origin"+ 方向性 overscan + 测量持久化。测试
scripts/check.mjs门禁 14/14 通过;GUI 前端测试 2492 项、WebUI 631 项全部通过。验证清单
Made with Cursor