[two_dimensional_scrollables] Fix crash when trailing pinned spans fall within the cache extent - #12719
[two_dimensional_scrollables] Fix crash when trailing pinned spans fall within the cache extent#12719icartsh wants to merge 1 commit into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request updates the two_dimensional_scrollables package to version 0.5.5. It fixes a crash occurring when trailing pinned rows or columns fall within the viewport's cache extent by excluding them from the calculation of the last non-pinned column and row indices in RenderTableViewport. This prevents the same columns or rows from being laid out in both the non-pinned and trailing pinned quadrants. Additionally, regression tests have been added to verify this behavior. There are no review comments to address.
|
CLA signed. |
…t twice
`RenderTableViewport._updateFirstAndLastVisibleCell` binary searches for
the last non-pinned span whose trailing offset reaches the target
trailing pixel. When the whole table fits inside the viewport plus the
cache extent, that search finds nothing and the code falls back to the
last index of the metrics map. With `trailingPinnedColumnCount` (or
`trailingPinnedRowCount`) greater than zero, that index is a pinned span.
`layoutChildSequence` then requests the same vicinity twice: once for the
non-pinned quadrant and once for the trailing pinned quadrant. The first
layout is hidden because `_needsDelegateRebuild` routes both calls
through `_buildChild`, but any later layout without a delegate rebuild
(a scroll, for example) takes the `_reuseChild` path and trips
`assert(elementToReuse != null)` on the second request:
'elementToReuse != null': Expected to re-use an element at
(row: 0, column: 2), but none was found.
Exclude the trailing pinned spans from the fallback, matching what
`_updateColumnMetrics`/`_updateRowMetrics` already do when they compute
the same value.
Fixes flutter/flutter#192152
|
Dropped the co-author trailer so the CLA check only sees the signed author. |
7ed38b1 to
343a066
Compare
RenderTableViewport._updateFirstAndLastVisibleCellbinary searches for the last non-pinned span whose trailing offset reaches the target trailing pixel. When the whole table fits inside the viewport plus the cache extent that search finds nothing, and the code falls back to the last index of the metrics map:With
trailingPinnedColumnCount(ortrailingPinnedRowCount) greater than zero, that index is a pinned span.layoutChildSequencethen asks for the same vicinity twice: once for the non-pinned quadrant and once for the trailing pinned quadrant.The first layout hides the problem, because
_needsDelegateRebuildroutes both calls through_buildChild. Any later layout without a delegate rebuild — a scroll, for instance — takes the_reuseChildpath, and the second request trips the assert intwo_dimensional_viewport.dart:This is easy to hit in practice: a table with a pinned trailing "actions" or "total" column whose columns happen to fit the viewport crashes on the first scroll.
The fix excludes the trailing pinned spans from the fallback, matching what
_updateColumnMetrics/_updateRowMetricsalready do when they compute the same value (delegate.columnCount! - delegate.trailingPinnedColumnCount - 1).trailingPinned*Countis required to be 0 when the corresponding count is null, so the subtraction is a no-op for infinite tables.Two regression tests are added, one for columns and one for rows. Both fail on
mainwith the assert above and pass with the fix.Fixes flutter/flutter#192152
Pre-Review Checklist
[shared_preferences]///).AI disclosure
Per the AI contribution guidelines: this change was written with the assistance of an AI coding agent (Claude Code). I have reviewed the diff, reproduced the crash against
main, and verified the tests fail without the fix and pass with it. I take responsibility for the contents of this PR.flutter testinpackages/two_dimensional_scrollables:+167: All tests passed!lib/reverted tomain: the two new tests fail with'elementToReuse != null': Expected to re-use an element at (row: 0, column: 2), but none was found.🤖 Generated with Claude Code
https://claude.ai/code/session_01MRZHkuG9nCwvNdMgxU8gQm
Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2