Fix Stream.close() exception suppression logic.
Change-Id: Id68c0cb05beab1f6059bcfd9cb51f9db87a8ddd0
diff --git a/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
index 018331f..b78b41f 100644
--- a/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
+++ b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
@@ -17,8 +17,6 @@
package java.util.stream;
import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
// package protected, as not part of jre
@@ -70,33 +68,39 @@
public void close() {
if (root == null) {
terminated = true;
-
- // TODO this might not be quite right, make sure that it behaves the same way when throwing
- // the same exception multiple times as JDK does.
- LinkedHashSet<Throwable> throwables = new LinkedHashSet<>();
- onClose.forEach((runnable) -> {
- try {
- runnable.run();
- } catch (Throwable e) {
- throwables.add(e);
- }
- });
- onClose.clear();
- if (!throwables.isEmpty()) {
- Iterator<Throwable> iterator = throwables.iterator();
- Throwable outer = iterator.next();
- iterator.forEachRemaining(outer::addSuppressed);
-
- if (outer instanceof RuntimeException) {
- throw (RuntimeException) outer;
- }
- if (outer instanceof Error) {
- throw (Error) outer;
- }
- assert false : "Couldn't have caught this exception from a Runnable! " + outer;
- }
+ runClosers();
} else {
root.close();
}
}
+
+ private void runClosers() {
+ ArrayList<Throwable> throwables = new ArrayList<>();
+ onClose.forEach(runnable -> {
+ try {
+ runnable.run();
+ } catch (Throwable e) {
+ throwables.add(e);
+ }
+ });
+ onClose.clear();
+
+ if (!throwables.isEmpty()) {
+ Throwable e = throwables.get(0);
+ for (int i = 1, size = throwables.size(); i < size; ++i) {
+ Throwable suppressed = throwables.get(i);
+ if (suppressed != e) {
+ e.addSuppressed(suppressed);
+ }
+ }
+
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ if (e instanceof Error) {
+ throw (Error) e;
+ }
+ assert false : "Couldn't have caught this exception from a Runnable! " + e;
+ }
+ }
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
index d46bfaf..7835e05 100644
--- a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
@@ -591,6 +591,12 @@
.onClose(() -> {
throw b;
})
+ .onClose(() -> {
+ throw a2;
+ })
+ .onClose(() -> {
+ throw b;
+ })
.onClose(() -> calledCount[0]++);
try {
@@ -598,9 +604,7 @@
fail("RuntimeException expected");
} catch (RuntimeException expected) {
assertSame(a2, expected);
- assertEquals(1, expected.getSuppressed().length);
- Throwable firstSuppressed = expected.getSuppressed()[0];
- assertSame(b, firstSuppressed);
+ assertEquals(new Throwable[] {b, b}, expected.getSuppressed());
}
assertEquals(1, calledCount[0]);