Skip to content

fix: harden virtualization scroll and resize lifecycle - #66

Merged
smiggleworth merged 4 commits into
mainfrom
fix/51-53-61-virtualization-contract
Aug 16, 2026
Merged

fix: harden virtualization scroll and resize lifecycle#66
smiggleworth merged 4 commits into
mainfrom
fix/51-53-61-virtualization-contract

Conversation

@smiggleworth

@smiggleworth smiggleworth commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Closes #51.
Closes #52.
Closes #53.
Closes #61.

Summary

  • give VirtualList explicit before/after spacers so native scrolling owns the full virtual extent
  • clamp deferred scroll writes against the current dataset both when data changes and when the write is consumed
  • make real user scroll events supersede stale programmatic commits in VirtualList and VirtualTable
  • move ResizeObserver-triggered state and DOM writes into a coalesced, teardown-safe animation-frame commit
  • enforce fixed-row visual containment in list and table layouts
  • release @askrjs/ui@0.0.32

TDD evidence

  • Red 12873b635ec27bc5118029114676516c36a43bb5: all three engines reported a 200px VirtualList.scrollHeight for 10,000 × 20px rows, browser-level ResizeObserver loop errors during resize churn, visible overflow in both row families, and a 96,024px table scroll state after replacement with a 408px-maximum dataset.
  • Red guard extension a333f95018463b3acf008860138b685096d0c0b2: the same deferred-write/data-replacement bug was reproduced in VirtualList at 80,000px against a new 300px maximum.
  • Green 3c466f9f93e001247914d422e31497247058ad43: 45 focused behavior tests pass across Chromium, Firefox, and WebKit, followed by all 57 virtualization behavior, accessibility, and determinism tests across those engines.
  • Full local gate at release head 75ca9a728bae57500c7e6e49678fb16ac790a079: build, lint, types, unit/check/jsdom suites, 309 browser files / 1,296 browser tests, publint, and isolated packed-consumer validation all pass.
  • All four benchmark tiers pass, including the VirtualList and VirtualTable hot paths; npm audit --omit=dev reports 0 vulnerabilities.

Root causes and permanent guardrails

  • VirtualList rendered only the live window. Semantically valid before/after spacer nodes now reserve exactly itemCount * rowHeight, including ul/ol composition. Normal browser CI asserts the real 200,000px scrollHeight, sets a native 20,000px scroll offset, dispatches the browser scroll event, and requires visible index 1,000.
  • Deferred scroll state was clamped only when no pending value existed. Both primitives now clamp the pending value whenever data changes and again immediately before committing it, while a real user scroll cancels the obsolete frame and becomes authoritative. Cross-engine regressions replace large datasets with unrelated small datasets before the frame lands and assert both immediate API state and final DOM state remain in range.
  • ResizeObserver callbacks synchronously wrote scroll and reactive state back into the observed layout. Observer delivery now only schedules one frame; the frame performs measurement-dependent writes outside the delivery cycle and is cancelled on ref transfer or teardown. Both primitives cycle seven extreme heights while listening to the browser error channel and forwarded console errors for the exact ResizeObserver-loop class.
  • Fixed-height rows allowed descendants to paint outside the geometry used by virtualization math. List rows clip directly. Table rows use collapsed zero-spacing geometry plus fixed, overflow-hidden cells whose content is isolated in a clipped positioned layer, so tall descendants cannot expand or bleed into the next logical row. Three-engine geometry tests assert configured row height and unchanged next-row position.

Acceptance audit

  • Reporter ownership and all four issue contracts were read back from GitHub.
  • Browser regressions were committed red before implementation, including both deferred-write primitives.
  • The same focused regressions pass green across Chromium, Firefox, and WebKit.
  • Permanent native-scroll, deferred-data, browser-error, teardown, and visual-geometry guardrails cover the bug classes.
  • Full local release, package, benchmark, and production-audit gates pass at the exact release head.
  • Exact-head hosted CI succeeds on macOS, Windows, and Ubuntu.
  • Every linked issue acceptance checkbox is checked with evidence before ready-for-review and squash merge.
  • v0.0.32 peels to the squash-merged main SHA, npm integrity is verified, and a clean consumer exercises the repaired virtualization surfaces with a zero-vulnerability production audit.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@smiggleworth
smiggleworth merged commit d5c0766 into main Aug 16, 2026
5 of 6 checks passed
@smiggleworth
smiggleworth deleted the fix/51-53-61-virtualization-contract branch August 16, 2026 00:25
@smiggleworth

Copy link
Copy Markdown
Contributor Author

Release closure: publish run https://github.com/askrjs/askr-ui/actions/runs/31917207792 succeeded at squash-merged main d5c076687d5c18a2b762f422f9c7a6dbb32e0689; annotated v0.0.32 peels to that exact commit. npm reports integrity sha512-GWC/vjmjzk9QODCoPTYtF6VBqbRCfxrzBGLD4Wb/t5AJxaTqIgCNt+iOZFKpT0nJrQ9tLNc8ZIDhOttT3D8YQQ==. A clean consumer installed @askrjs/ui@0.0.32, loaded the public VirtualList and VirtualTable subpaths as callable exports, and completed npm audit --omit=dev with 0 vulnerabilities.

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

Labels

None yet

Projects

None yet

2 participants