Skip to content

Commit 697a534

Browse files
committed
8237868: java.lang.IndexOutOfBoundsException in FilteredList
Reviewed-by: angorya, mstrauss
1 parent 0dd5a94 commit 697a534

3 files changed

Lines changed: 56 additions & 5 deletions

File tree

modules/javafx.base/src/main/java/javafx/collections/ListChangeBuilder.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ public void nextRemove(int idx, E removed) {
207207

208208
if (last != null && last.to == idx) {
209209
last.removed.add(removed);
210-
} else if (last != null && last.from == idx + 1) {
211-
last.from--;
212-
last.to--;
213-
last.removed.add(0, removed);
214210
} else {
215211
insertRemoved(idx, removed);
216212
}

modules/javafx.base/src/test/java/test/javafx/collections/FilteredListTest.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
2626
package test.javafx.collections;
2727

2828
import com.sun.javafx.collections.ObservableListWrapper;
29+
2930
import java.util.Arrays;
3031
import java.util.Collections;
3132
import java.util.List;
@@ -36,6 +37,7 @@
3637
import javafx.collections.ObservableList;
3738
import javafx.collections.ObservableListWrapperShim;
3839
import javafx.collections.transformation.FilteredList;
40+
import org.junit.jupiter.api.AfterEach;
3941
import org.junit.jupiter.api.BeforeEach;
4042
import org.junit.jupiter.api.Test;
4143

@@ -55,6 +57,19 @@ public void setUp() {
5557
mlo = new MockListObserver<>();
5658
filteredList = new FilteredList<>(list, predicate);
5759
filteredList.addListener(mlo);
60+
61+
Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> {
62+
if (throwable instanceof RuntimeException) {
63+
throw (RuntimeException)throwable;
64+
} else {
65+
Thread.currentThread().getThreadGroup().uncaughtException(thread, throwable);
66+
}
67+
});
68+
}
69+
70+
@AfterEach
71+
void tearDown() {
72+
Thread.currentThread().setUncaughtExceptionHandler(null);
5873
}
5974

6075
@Test
@@ -321,4 +336,20 @@ public void testGetViewIndexOutOfBounds() {
321336
assertThrows(IndexOutOfBoundsException.class, () -> filteredList.getViewIndex(list.size()));
322337
assertDoesNotThrow(() -> filteredList.getViewIndex(filteredList.size()));
323338
}
339+
340+
@Test
341+
public void testSortedThenFilteredListDoesNotThrowIOOBE() {
342+
ObservableList<Long> numbers = FXCollections.observableArrayList();
343+
344+
ObservableList<Long> sortedList = numbers.sorted(Long::compare);
345+
ObservableList<Long> filteredList = sortedList.filtered(_ -> true);
346+
347+
numbers.add(0L);
348+
numbers.addAll(List.of(0L, 4L, 8L, 2L, 6L, 0L, 4L, 8L, 2L, 6L, 0L));
349+
350+
assertDoesNotThrow(() -> numbers.subList(0, numbers.size() - 1).clear());
351+
352+
assertEquals(List.of(0L), filteredList);
353+
assertEquals(List.of(0L), sortedList);
354+
}
324355
}

modules/javafx.base/src/test/java/test/javafx/collections/ListChangeBuilderTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,30 @@ public void testIndirectAddRemoveOnSameIndexWithAdded() {
720720
list.doEndChange();
721721
}
722722

723+
@Test
724+
public void testRemoveDisjointFirstThenGaps() {
725+
var list = new ExposedObservableList<>(new ArrayList<>(List.of("A", "B", "C", "D", "E", "F")));
726+
727+
list.addListener((ListChangeListener.Change<? extends String> change) -> {
728+
assertEquals(1, change.getList().size());
729+
change.next();
730+
731+
assertEquals(List.of("B", "C", "D", "E", "F"), change.getRemoved());
732+
733+
assertFalse(change.next());
734+
});
735+
736+
list.doBeginChange();
737+
738+
list.remove("D");
739+
list.remove("F");
740+
list.remove("B");
741+
list.remove("E");
742+
list.remove("C");
743+
744+
list.doEndChange();
745+
}
746+
723747
private static class ExposedObservableList<E> extends ObservableListWrapper<E> {
724748
ExposedObservableList(List<E> list) {
725749
super(list);

0 commit comments

Comments
 (0)