Skip to content

Commit f1da067

Browse files
vaadin-botLegioth
andauthored
fix: Allow observing other nodes from an observer (#21653) (#21657)
Fixes #21603 Co-authored-by: Leif Åstrand <leif@vaadin.com>
1 parent bbc92a5 commit f1da067

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

signals/src/main/java/com/vaadin/signals/impl/SignalTree.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ protected void notifyObservers(Snapshot oldSnapshot, Snapshot newSnapshot) {
234234
}
235235

236236
runWithLock(() -> {
237-
observers.forEach((nodeId, list) -> {
237+
Map.copyOf(observers).forEach((nodeId, list) -> {
238238
Data oldNode = oldSnapshot.data(nodeId).orElse(Node.EMPTY);
239239
Data newNode = newSnapshot.data(nodeId).orElse(Node.EMPTY);
240240

signals/src/test/java/com/vaadin/signals/impl/EffectTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,27 @@ void changeTracking_noOpChange_effectNotRunButRemainsActive() {
267267
assertEquals(List.of("value", "update"), invocations);
268268
}
269269

270+
@Test
271+
void changeTracking_readChildNodes_coveredByNextEffectInvocation() {
272+
ListSignal<String> signal = new ListSignal<>(String.class);
273+
ArrayList<List<String>> invocations = new ArrayList<>();
274+
275+
Signal.effect(() -> {
276+
List<String> values = signal.value().stream().map(Signal::value)
277+
.toList();
278+
invocations.add(values);
279+
});
280+
281+
assertEquals(List.of(List.of()), invocations);
282+
283+
signal.insertLast("One");
284+
assertEquals(List.of(List.of(), List.of("One")), invocations);
285+
286+
signal.insertLast("Two");
287+
assertEquals(List.of(List.of(), List.of("One"), List.of("One", "Two")),
288+
invocations);
289+
}
290+
270291
@Test
271292
void callback_updateSignal_throws() {
272293
ValueSignal<String> signal = new ValueSignal<>("value");

signals/src/test/java/com/vaadin/signals/impl/SynchronousSignalTreeTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,37 @@ void observe_observeInCallback_registeredAgain() {
350350
assertEquals(1, count.get());
351351
}
352352

353+
@Test
354+
void observe_observeAnotherNodeInCallback_observerAdded() {
355+
SynchronousSignalTree tree = new SynchronousSignalTree(false);
356+
357+
Id childId = Id.random();
358+
AtomicInteger count = new AtomicInteger();
359+
tree.observeNextChange(Id.ZERO, () -> {
360+
tree.observeNextChange(childId, () -> {
361+
count.incrementAndGet();
362+
return false;
363+
});
364+
return false;
365+
});
366+
367+
tree.commitSingleCommand(new SignalCommand.InsertCommand(childId,
368+
Id.ZERO, null, new DoubleNode(2), ListPosition.last()));
369+
370+
// Nothing yet since root observer not invoked
371+
assertEquals(0, count.get());
372+
373+
tree.commitSingleCommand(TestUtil.writeRootValueCommand());
374+
375+
// Nothing yet since child observer not invoked
376+
assertEquals(0, count.get());
377+
378+
tree.commitSingleCommand(new SignalCommand.SetCommand(Id.random(),
379+
childId, new DoubleNode(3)));
380+
381+
assertEquals(1, count.get());
382+
}
383+
353384
@Test
354385
void subscribeToProcessed_noChanges_doesNotReceive() {
355386
SynchronousSignalTree tree = new SynchronousSignalTree(false);

0 commit comments

Comments
 (0)