Skip to content

fix(virtual-core): honor resize veto for end anchoring - #1365

Draft
davidfant wants to merge 2 commits into
TanStack:mainfrom
davidfant:energy/resize-ownership-current-main-20261103
Draft

davidfant wants to merge 2 commits into
TanStack:mainfrom
davidfant:energy/resize-ownership-current-main-20261103

Conversation

@davidfant

@davidfant davidfant commented Nov 4, 2026 •

Copy link
Copy Markdown

🎯 Changes

Before

A consumer's item-resize callback could return false and still receive a scroll correction from the separate end-anchor branch. A controller coordinating its own bottom-follow scroll could therefore lose ownership during a late measurement.

In the reduced application diagnostic, the other controller moved the viewport to 27813 while the virtualizer still cached 22537. A +122 item resize compensated from the stale cache and wrote 22659. The application interpreted that backward movement as leaving the bottom.

After

The callback can return undefined to delegate to the complete existing default policy, including end anchoring. Explicit false gates both new synchronous resize-correction branches. Explicit true still overrides the default predicate, subject to the existing smooth-scroll and pending command-readback guards.

Compatibility change: an explicit false now prevents an end-anchor resize correction that previously bypassed the callback. The current batching, readback, layout-total, structural and iOS machinery is retained. This is not a global scroll mutex: structural anchoring, explicit navigation/reconciliation and already queued iOS, held or clamped work remain outside the veto.

Why needed

A consumer cannot coordinate competing scroll writers through this callback while one resize branch ignores its veto. Reading a live ownership state must decide both resize branches synchronously, without waiting for a framework render. No dependency version is changed here. This branch is based on current upstream main, not the downstream release tag.

Validation

  • Current-main base: 11b48e4ab8b08d483c8fe29a31ef11261ffbda04.
  • Original current-main witnesses: 3/3 expected bad writes using the exact original TypeScript snapshot through normal Vitest transformation. This was not an original compiled ESM/CJS run.
  • Corrected current-main canonical production build: 70/70 focused regressions, 35 each against actual ESM and CJS outputs. Focused strict test types passed. Each configuration and the build/typecheck ran once, retries 0.
  • Loaded constructor paths/hashes and both declaration formats were verified. The 35-case test covers the observed stale-cache write, live lock transitions, growth/shrink, undefined defaults, false/true/absent decisions, smooth and zero-delta behavior, directions/fold cases and keyed prepend pixel anchoring.
  • Separate downstream release-pinned package proof: 6/6 original compiled ESM/CJS bad-write witnesses and 70/70 corrected compiled regressions. That package remains pinned to 3.17.8; this source transplant targets current main's 3.19.11.
  • A separate synthetic Linux application run using the pinned corrected package passed all 22 unchanged original long-conversation assertions in 16.438s. Actual browser-loaded corrected code was verified. Thirteen local API HTTP500 console errors were retained; that single run had zero page/ResizeObserver errors, not a universal elimination result.
  • Diagnostic BEFORE was observationally instrumented; AFTER was uninstrumented. This is not full native CI parity or proof of the unique historical whole-suite failure cause. Historical Windows intermittency and observer errors remain unresolved. Four additional unchanged application cases passed once with one worker, retries 0 and all 29 original assertions reached. They retained 29 local HTTP500 console errors and had zero page/ResizeObserver errors. The above-row case asserted settled 1200 after a native upward wheel and passed drift <2. The fourth upward-scrolling case anchored Workstream120 near the bottom (31784 to 31783, later 32183), not far-from-bottom retention. Supplemental native-input checks did not execute: a prior-artifact checksum guard stopped setup before Playwright, leaving all 61 proposed assertions unreached. A read-only host/container visibility probe subsequently matched, but the original discrepancy remains unexplained. No test retry was performed. Selected-history navigation remains source-only and unverified.
  • Downstream application draft: https://github.com/comp-work/monorepo/pull/4058. Both drafts now contain the two inspected synthetic screenshots below, with saved description and rendered-image verification. Downstream exact-head CI failed the extension self-update prerequisite before application Playwright started, so it provides no app long-case result. The relevant extension source is identical to its base; why Chromium retained the old disabled extension remains unproven. Both PRs remain draft and unmerged, not merge-ready.
  • Exact-head CI for metadata follow-up 096bbeb1dc7c956b8c69ac0cb4e6fd13118ed5d0, checked 2026-11-04T00:58:41.931Z: autofix.ci: action_required; PR: action_required; GitHub Actions Security Analysis: action_required. Third-party checks: Socket Security: Pull Request Alerts: success; CodeRabbit: skipped; Socket Security: Project Report: success. No workflow approval, rerun or bypass was performed. A workflow requiring maintainer approval is not passing CI.

✅ Checklist

  • The source, test, API documentation and reviewed release changeset are included. The changeset selects a core patch bugfix; maintainers retain discretion over release classification and version. No version, lockfile or runtime source was changed by the metadata follow-up.
  • I have tested this code locally with pnpm run test:pr. Only the focused checks above ran; broad validation is left to CI.

🚀 Release Impact

  • This change affects published code, and I have included .changeset/resize-ownership-veto.md for @tanstack/virtual-core: patch. Adding this file does not itself publish or release anything.
  • This change is docs/CI/dev-only (no release).

Lines of code

Category Added Deleted Net
Core callback contract 18 18 0
Focused regression coverage 219 0 219
Public API documentation 10 4 6
Release metadata 5 0 5
Total analyzed 252 22 230

No generated, vendored, lockfile or evidence files are included in this upstream diff.

Models used

Root source/artifact review and final handoff: openai/gpt-6.1-sol; reasoning effort is not exposed in verified turn metadata. Earlier implementation and independent-review model IDs and efforts are unavailable and are not inferred from configured defaults.

Selected synthetic screenshots

Public-safe synthetic app fixture. BEFORE includes observational diagnostic probes; AFTER does not. These are outcome screenshots, not motion or full native-CI proof.

before-labeled after-labeled

The independent end-anchor resize branch could compensate scroll position even when the consumer callback returned false. A caller using that callback to coordinate another scroll writer could therefore still lose ownership at the end of a list.

Let undefined delegate to the complete default policy and gate both synchronous correction branches on the callback decision. Preserve the current command-readback, smooth-scroll, batching, deferred iOS and structural machinery. Explicit false at end changes behavior intentionally; this is not a global scroll mutex.

Add the focused 35-case contract regression and document return-value semantics and boundaries. Current-main original witnesses reproduce three expected bad writes; corrected canonical ESM and CJS builds pass all 70 focused cases.
@changeset-bot

changeset-bot Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 096bbeb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@tanstack/virtual-core Patch
@tanstack/angular-virtual Patch
@tanstack/lit-virtual Patch
@tanstack/marko-virtual Patch
@tanstack/react-virtual Patch
@tanstack/solid-virtual Patch
@tanstack/svelte-virtual Patch
@tanstack/vue-virtual Patch
@tanstack/virtual-benchmarks Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 4, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant