On Fri, 10 Jul 2026 21:08:08 GMT, John Hendrikx <[email protected]> wrote:

>> modules/javafx.base/src/test/java/test/com/sun/javafx/binding/ListenerListBaseTest.java
>>  line 180:
>> 
>>> 178: 
>>> 179:     @Test
>>> 180:     void shouldNeverSilentlyRemoveWeakListeners() {
>> 
>> question: does this tests the public specification, or the implementation?
>
> Good one; this test is to make sure that dead weak listeners stubs don't 
> disappear at unexpected moments. Some code (see 
> `ObjectBinding#removeListener` for example) tracks whether the listener list 
> is empty through overrides of `addListener` and `removeListener`:
> 
> 
>     public void removeListener(ChangeListener<? super T> listener) {
>         observed = !LISTENER_MANAGER.removeListener(this, 
> (ChangeListener<Object>) listener);
>     }
> 
> Or the old code:
> 
>     public void removeListener(ChangeListener<? super T> listener) {
>         helper = ExpressionHelper.removeListener(helper, listener);
>         observed = helper != null;
>     }
> 
> To not break such tracking, we can only remove dead listeners when some other 
> list modification occurs; either an addition (in which case we know there is 
> at least one new listener, so we can remove any dead listeners), or a removal 
> (in which case if the list becomes empty, we return `true` or with the old 
> code, we check if `helper == null`.)
> 
> The `observed` flag is very important for the lazy binding code (that powers 
> `ObservableValue#map/flatMap/orElse`), but can also be very handy when you 
> want to remove or clean-up your own listeners if you yourself are not 
> observed anymore (if nobody observes you, then why would you bother updating 
> yourself :)).

I realize I didn't truly answer your question. This is not specified anywhere 
(the whole weak listener removal mechanism is basically internal stuff); there 
is only an indirect expectation that if you override add/remove listeners in 
order to track listeners (and by that I only mean empty or not empty, not a 
counter) that you would get the correct result.

So this tests the implementation I did, to ensure it is compatible with 
existing JavaFX code that tracks an `observed` flag.

I think improving this system somehow (more eagerly removing dead listeners) 
would require also a way to notify interested parties whether the list has 
become empty.

I believe an earlier iteration tried to do this by also returning a `boolean` 
from the notify call (ie. it would return true if all listeners were removed 
during notification), but I think that ran into a wall. I think the problem 
with that approach was that JavaFX code really doesn't like it when a simple 
notify (normally harmless) has a lot of consequences (like all kinds of 
listeners getting removed in a whole chain because something went from observed 
to unobserved state).

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1081#discussion_r3562238383

Reply via email to