From 7c8bda2463a187c62f2a993fbb3ccf94117436d6 Mon Sep 17 00:00:00 2001 From: Jiaxu Li <138670014+Jiaxu-Li@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:31:39 +0800 Subject: [PATCH] [Observations] Prevent duplicate emissions on re-iterating Observations after cancellation Fix #85683: avoid duplicated values when re-iterating `Observations` after cancelling a prior iteration. This changes `Observations` to allocate its internal `_ManagedCriticalState` per iterator (in `makeAsyncIterator()`), rather than sharing a single state across all iterations. Sharing state allowed change notifications from a cancelled iteration to interfere with subsequent iterations, resulting in duplicated emissions. --- .../public/Observation/Sources/Observation/Observations.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stdlib/public/Observation/Sources/Observation/Observations.swift b/stdlib/public/Observation/Sources/Observation/Observations.swift index 3aa6d91ba56c6..ff82b96b81a8b 100644 --- a/stdlib/public/Observation/Sources/Observation/Observations.swift +++ b/stdlib/public/Observation/Sources/Observation/Observations.swift @@ -133,7 +133,6 @@ public struct Observations: AsyncSequence, Se // internal funnel method for initialziation internal init(emit: Emit) { self.emit = emit - self.state = _ManagedCriticalState(State()) } /// Constructs an asynchronous sequence for a given closure by tracking changes of `@Observable` types. @@ -167,7 +166,6 @@ public struct Observations: AsyncSequence, Se // the state ivar serves two purposes: // 1) to store a critical region of state of the mutations // 2) to idenitify the termination of _this_ sequence - var state: _ManagedCriticalState? let emit: Emit var started = false @@ -251,6 +249,6 @@ public struct Observations: AsyncSequence, Se } public func makeAsyncIterator() -> Iterator { - Iterator(state: state, emit: emit) + Iterator(state: _ManagedCriticalState(State()), emit: emit) } }