1- import Foundation
2-
31@usableFromInline
42@MainActor
53internal struct StoreContext {
@@ -90,7 +88,7 @@ internal struct StoreContext {
9088 let key = AtomKey ( atom, scopeKey: scopeKey)
9189
9290 if let cache = lookupCache ( of: atom, for: key) {
93- update ( atom: atom, for: key, value : value, cache: cache, order : . newValue )
91+ update ( atom: atom, for: key, newValue : value, cache: cache)
9492 }
9593 }
9694
@@ -101,9 +99,8 @@ internal struct StoreContext {
10199 let key = AtomKey ( atom, scopeKey: scopeKey)
102100
103101 if let cache = lookupCache ( of: atom, for: key) {
104- var value = cache. value
105- body ( & value)
106- update ( atom: atom, for: key, value: value, cache: cache, order: . newValue)
102+ let newValue = mutating ( cache. value, body)
103+ update ( atom: atom, for: key, newValue: newValue, cache: cache)
107104 }
108105 }
109106
@@ -129,18 +126,12 @@ internal struct StoreContext {
129126 func watch< Node: Atom > (
130127 _ atom: Node ,
131128 subscriber: Subscriber ,
132- requiresObjectUpdate: Bool ,
133- notifyUpdate: @escaping ( ) -> Void
129+ subscription: Subscription
134130 ) -> Node . Loader . Value {
135131 let override = lookupOverride ( of: atom)
136132 let scopeKey = lookupScopeKey ( of: atom, isScopedOverriden: override? . isScoped ?? false )
137133 let key = AtomKey ( atom, scopeKey: scopeKey)
138134 let cache = getCache ( of: atom, for: key, override: override)
139- let subscription = Subscription (
140- location: subscriber. location,
141- requiresObjectUpdate: requiresObjectUpdate,
142- notifyUpdate: notifyUpdate
143- )
144135 let isNewSubscription = subscriber. subscribingKeys. insert ( key) . inserted
145136
146137 store. state. subscriptions [ key, default: [ : ] ] . updateValue ( subscription, forKey: subscriber. key)
@@ -177,8 +168,8 @@ internal struct StoreContext {
177168 }
178169
179170 // Notify update unless it's cancelled or terminated by other operations.
180- if !Task. isCancelled && !context. transaction . isTerminated {
181- update ( atom: atom, for: key, value : value, cache: cache, order : . newValue )
171+ if !Task. isCancelled && !context. isTerminated {
172+ update ( atom: atom, for: key, newValue : value, cache: cache)
182173 }
183174
184175 return value
@@ -199,7 +190,7 @@ internal struct StoreContext {
199190
200191 // Notify update unless it's cancelled or terminated by other operations.
201192 if !Task. isCancelled && !transaction. isTerminated {
202- update ( atom: atom, for: key, value : value, cache: cache, order : . newValue )
193+ update ( atom: atom, for: key, newValue : value, cache: cache)
203194 }
204195
205196 return value
@@ -214,7 +205,7 @@ internal struct StoreContext {
214205
215206 if let cache = lookupCache ( of: atom, for: key) {
216207 let newCache = makeCache ( of: atom, for: key, override: override)
217- update ( atom: atom, for: key, value : newCache. value, cache: cache, order : . newValue )
208+ update ( atom: atom, for: key, newValue : newCache. value, cache: cache)
218209 }
219210 }
220211
@@ -289,7 +280,7 @@ internal struct StoreContext {
289280 // Notify updates only for the subscriptions of restored atoms.
290281 if let subscriptions = store. state. subscriptions [ key] {
291282 for subscription in ContiguousArray ( subscriptions. values) {
292- subscription. notifyUpdate ( )
283+ subscription. update ( )
293284 }
294285 }
295286 }
@@ -336,54 +327,38 @@ private extension StoreContext {
336327 store: self ,
337328 transaction: transaction,
338329 coordinator: state. coordinator
339- ) { value , order in
340- guard let cache = lookupCache ( of: atom, for: key) else {
341- return
330+ ) { newValue in
331+ if let cache = lookupCache ( of: atom, for: key) {
332+ update ( atom : atom , for : key , newValue : newValue , cache : cache )
342333 }
343-
344- update (
345- atom: atom,
346- for: key,
347- value: value,
348- cache: cache,
349- order: order
350- )
351334 }
352335 }
353336
354337 func update< Node: Atom > (
355338 atom: Node ,
356339 for key: AtomKey ,
357- value: Node . Loader . Value ,
358- cache: AtomCache < Node > ,
359- order: UpdateOrder
340+ newValue: Node . Loader . Value ,
341+ cache: AtomCache < Node >
360342 ) {
361343 let oldValue = cache. value
362344
363- if case . newValue = order {
364- var cache = cache
365- cache. value = value
366- store. state. caches [ key] = cache
345+ store. state. caches [ key] = mutating ( cache) {
346+ $0. value = newValue
367347 }
368348
369- // Do not notify update if the new value and the old value are equivalent.
370- if !atom. _loader. shouldUpdate ( newValue: value, oldValue: oldValue) {
349+ guard atom. _loader. shouldUpdate ( newValue: newValue, oldValue: oldValue) else {
371350 return
372351 }
373352
374- // Notifying update to view subscriptions first.
375- if let subscriptions = store. state. subscriptions [ key] {
376- for subscription in ContiguousArray ( subscriptions. values) {
377- if case . objectWillChange = order, subscription. requiresObjectUpdate {
378- RunLoop . current. perform ( subscription. notifyUpdate)
379- }
380- else {
381- subscription. notifyUpdate ( )
353+ atom. _loader. performUpdate {
354+ // Notifies update to view subscriptions first.
355+ if let subscriptions = store. state. subscriptions [ key] {
356+ for subscription in ContiguousArray ( subscriptions. values) {
357+ subscription. update ( )
382358 }
383359 }
384- }
385360
386- func notifyUpdate ( ) {
361+ // Notifies update to downstream atoms.
387362 if let children = store. graph. children [ key] {
388363 for child in ContiguousArray ( children) {
389364 // Reset the atom value and then notifies downstream atoms.
@@ -398,21 +373,7 @@ private extension StoreContext {
398373
399374 let state = getState ( of: atom, for: key)
400375 let context = AtomCurrentContext ( store: self , coordinator: state. coordinator)
401- atom. updated ( newValue: value, oldValue: oldValue, context: context)
402- }
403-
404- switch order {
405- case . newValue:
406- notifyUpdate ( )
407-
408- case . objectWillChange:
409- // At the timing when `ObservableObject/objectWillChange` emits, its properties
410- // have not yet been updated and are still old when dependent atoms read it.
411- // As a workaround, the update is executed in the next run loop
412- // so that the downstream atoms can receive the object that's already updated.
413- RunLoop . current. perform {
414- notifyUpdate ( )
415- }
376+ atom. updated ( newValue: newValue, oldValue: oldValue, context: context)
416377 }
417378 }
418379
0 commit comments