diff --git a/modules/javafx.base/src/main/java/javafx/beans/binding/ObjectBinding.java b/modules/javafx.base/src/main/java/javafx/beans/binding/ObjectBinding.java index 84f62a8416c..131aa4177ee 100644 --- a/modules/javafx.base/src/main/java/javafx/beans/binding/ObjectBinding.java +++ b/modules/javafx.base/src/main/java/javafx/beans/binding/ObjectBinding.java @@ -180,7 +180,15 @@ public final void invalidate() { valid = false; onInvalidating(); ExpressionHelper.fireValueChangedEvent(helper); - value = null; // clear cached value to avoid hard reference to stale data + + /* + * Cached value should be cleared to avoid a strong reference to stale data, + * but only if this binding didn't become valid after firing the event: + */ + + if (!valid) { + value = null; + } } } diff --git a/modules/javafx.base/src/test/java/test/javafx/beans/value/LazyObjectBindingTest.java b/modules/javafx.base/src/test/java/test/javafx/beans/value/LazyObjectBindingTest.java index 72da81b3c26..23a630c0673 100644 --- a/modules/javafx.base/src/test/java/test/javafx/beans/value/LazyObjectBindingTest.java +++ b/modules/javafx.base/src/test/java/test/javafx/beans/value/LazyObjectBindingTest.java @@ -52,6 +52,24 @@ void shouldBeInvalidInitially() { assertFalse(binding.isValid()); } + @Test + void invalidationWhichBecomesValidDuringCallbacksShouldReturnCorrectValue() { + LazyObjectBindingStub binding = new LazyObjectBindingStub<>() { + @Override + protected String computeValue() { + return "A"; + } + }; + + binding.addListener(obs -> { + assertEquals("A", binding.get()); + }); + + binding.invalidate(); // becomes valid again immediately + + assertEquals("A", binding.get()); + } + @Nested class WhenObservedWithInvalidationListener { private InvalidationListener invalidationListener = obs -> {};