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