fix concurrent-modification in BufferLine anchor iteration
`removeCells`, `insertCells`, and `dispose` each iterate over `_anchors` while invoking `anchor.dispose()` on entries inside the loop — but `dispose()` removes the anchor from the same list, which shifts later indexes left and causes the for-loop to skip them. Symptoms (no user-facing report yet, but real correctness bug): - After `removeCells` with multiple anchors past the start, anchors that should be repositioned were silently left at their old `x`. - After `insertCells` with anchors getting pushed past `_length`, ones meant to be disposed could survive. - `BufferLine.dispose` would throw `ConcurrentModificationError` as soon as more than one anchor was attached. Fix: iterate `_anchors.toList()` (a snapshot) in all three sites. Cheap, safe, and matches the expected anchor-management semantics. Surfaced by the unit tests added under T-91; that commit covers the fix with regression tests. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -179,8 +179,9 @@ class BufferLine with IndexedItem {
|
||||
}
|
||||
|
||||
// Update anchors, remove anchors that are inside the removed range.
|
||||
for (var i = 0; i < _anchors.length; i++) {
|
||||
final anchor = _anchors[i];
|
||||
// Iterate over a snapshot — anchor.dispose() removes itself from
|
||||
// _anchors, so a live for-loop would skip later entries.
|
||||
for (final anchor in _anchors.toList()) {
|
||||
if (anchor.x >= start) {
|
||||
if (anchor.x < start + count) {
|
||||
anchor.dispose();
|
||||
@@ -218,8 +219,9 @@ class BufferLine with IndexedItem {
|
||||
}
|
||||
|
||||
// Update anchors, move anchors that are after the inserted range.
|
||||
for (var i = 0; i < _anchors.length; i++) {
|
||||
final anchor = _anchors[i];
|
||||
// Iterate over a snapshot — anchor.dispose() removes itself from
|
||||
// _anchors, so a live for-loop would skip later entries.
|
||||
for (final anchor in _anchors.toList()) {
|
||||
if (anchor.x >= start + count) {
|
||||
anchor.reposition(anchor.x + count);
|
||||
|
||||
@@ -352,7 +354,8 @@ class BufferLine with IndexedItem {
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
for (final anchor in _anchors) {
|
||||
// Snapshot — anchor.dispose() removes itself from _anchors.
|
||||
for (final anchor in _anchors.toList()) {
|
||||
anchor.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user