On Mon, 13 Jul 2026 16:03:46 GMT, Andy Goryachev <[email protected]> wrote:
> Re: replacing listeners inside the callback.
>
> Here is the scenario I was talking about:
>
> ```
> @Test
> void replaceInsideCallback() {
> SimpleObjectProperty<String> p = new SimpleObjectProperty<>("A");
> ArrayList<String> changes = new ArrayList<>();
>
> ChangeListener<String> li1 = (_, old, val) -> {
> String s = "1 " + old + "→" + val;
> IO.println(s);
> changes.add(s);
> };
>
> ChangeListener<String> li2 = (_, old, val) -> {
> String s = "2 " + old + "→" + val;
> IO.println(s);
> changes.add(s);
> };
>
> AtomicBoolean replace = new AtomicBoolean(true);
>
> p.addListener(_ -> {
> if (replace.getAndSet(false)) {
> p.removeListener(li1);
> p.addListener(li2);
> }
> });
>
> p.addListener(li1);
> p.set("B");
> changes.clear();
> p.set("C");
>
> assertEquals(List.of("2 B→C"), changes);
> }
> ```
>
> This test passes in master but fails in this PR.
This should have worked as expected, but you managed to find a very interesting
edge case here, which I will fix.
The edge case:
- There is only an invalidation listener initially
- Property p is currently valid
- You change the value of p, invalidation listener fires as p is valid
- The invalidation listener removes a change listener (which will NOT be
notified now, it would normally run after the invalidation listener); you also
add a new change listener that will also NOT be notified as it only will
participate in new notifications, not ongoing ones
- BUG: the property p is NOT made valid, and remains invalid, as there is no
more change listener to notify, and the new one won't participate...
- Next change (`p.set("C")`) considers property invalid, and so fires no change
events, despite a change listener being present
-------------
PR Comment: https://git.openjdk.org/jfx/pull/1081#issuecomment-4963121455