Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@ class MockAPIClient: APIClientProtocol {
var response: Book?

func fetchBook(isbn: String) async throws -> Book {
guard let response = response else {
guard let response else {
throw URLError(.unknown)
}
return response
Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Context/AtomContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public protocol AtomContext {
/// ```
///
/// - Parameter atom: An atom that associates the value.
func reset<Node: Atom>(_ atom: Node)
func reset(_ atom: some Atom)
}

public extension AtomContext {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Context/AtomTestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public struct AtomTestContext: AtomWatchableContext {
/// ```
///
/// - Parameter atom: An atom that associates the value.
public func reset<Node: Atom>(_ atom: Node) {
public func reset(_ atom: some Atom) {
state.store.reset(atom)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Context/AtomTransactionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public struct AtomTransactionContext<Coordinator>: AtomWatchableContext {
///
/// - Parameter atom: An atom that associates the value.
@inlinable
public func reset<Node: Atom>(_ atom: Node) {
public func reset(_ atom: some Atom) {
_store.reset(atom)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Context/AtomViewContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public struct AtomViewContext: AtomWatchableContext {
///
/// - Parameter atom: An atom that associates the value.
@inlinable
public func reset<Node: Atom>(_ atom: Node) {
public func reset(_ atom: some Atom) {
_store.reset(atom)
}

Expand Down
18 changes: 12 additions & 6 deletions Sources/Atoms/Core/AtomCache.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
@MainActor
internal protocol AtomCacheBase {
internal protocol AtomCacheProtocol: CustomStringConvertible {
associatedtype Node: Atom

var atom: Node { get set }
var value: Node.Loader.Value? { get set }
var shouldKeepAlive: Bool { get }

func reset(with store: StoreContext)
}

internal struct AtomCache<Node: Atom>: AtomCacheBase, CustomStringConvertible {
internal extension AtomCacheProtocol {
var description: String {
value.map { "\($0)" } ?? "nil"
}
}

internal struct AtomCache<Node: Atom>: AtomCacheProtocol {
var atom: Node
var value: Node.Loader.Value?

var shouldKeepAlive: Bool {
Node.shouldKeepAlive
}

var description: String {
value.map { "\($0)" } ?? "nil"
}

func reset(with store: StoreContext) {
store.reset(atom)
}
Expand Down
9 changes: 6 additions & 3 deletions Sources/Atoms/Core/AtomState.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
@MainActor
internal protocol AtomStateBase {
var transaction: Transaction? { get nonmutating set }
internal protocol AtomStateProtocol: AnyObject {
associatedtype Coordinator

var coordinator: Coordinator { get }
var transaction: Transaction? { get set }
}

internal final class AtomState<Coordinator>: AtomStateBase {
internal final class AtomState<Coordinator>: AtomStateProtocol {
let coordinator: Coordinator
var transaction: Transaction?

Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Core/Loader/AsyncSequenceAtomLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public struct AsyncSequenceAtomLoader<Node: AsyncSequenceAtom>: RefreshableAtomL
/// and returns a final value.
public func refresh(context: Context) async -> Value {
let sequence = context.transaction(atom.sequence)
let task = Task { () -> Value in
let task = Task {
var phase = Value.suspending

do {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Core/Loader/ObservableObjectAtomLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public struct ObservableObjectAtomLoader<Node: ObservableObjectAtom>: AtomLoader
/// Handles updates or cancellation of the passed value.
public func handle(context: Context, with object: Value) -> Value {
let cancellable = object.objectWillChange.sink { [weak object] _ in
guard let object = object else {
guard let object else {
return
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Core/Loader/PublisherAtomLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public struct PublisherAtomLoader<Node: PublisherAtom>: RefreshableAtomLoader {
/// Refreshes and awaits until the asynchronous is finished and returns a final value.
public func refresh(context: Context) async -> Value {
let results = context.transaction(atom.publisher).results
let task = Task { () -> Value in
let task = Task {
var phase = Value.suspending

for await result in results {
Expand Down
14 changes: 9 additions & 5 deletions Sources/Atoms/Core/Overrides.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@MainActor
internal struct Overrides {
private var _entriesForNode = [AtomKey: AtomOverrideBase]()
private var _entriesForType = [AtomTypeKey: AtomOverrideBase]()
private var _entriesForNode = [AtomKey: any AtomOverrideProtocol]()
private var _entriesForType = [AtomTypeKey: any AtomOverrideProtocol]()

nonisolated init() {}

Expand All @@ -25,7 +25,7 @@ internal struct Overrides {
let key = AtomKey(atom)
let baseOverride = _entriesForNode[key] ?? _entriesForType[key.typeKey]

guard let baseOverride = baseOverride else {
guard let baseOverride else {
return nil
}

Expand All @@ -48,8 +48,12 @@ internal struct Overrides {
}

@MainActor
internal protocol AtomOverrideBase {}
internal protocol AtomOverrideProtocol {
associatedtype Node: Atom

internal struct AtomOverride<Node: Atom>: AtomOverrideBase {
var value: (Node) -> Node.Loader.Value { get }
}

internal struct AtomOverride<Node: Atom>: AtomOverrideProtocol {
let value: (Node) -> Node.Loader.Value
}
8 changes: 4 additions & 4 deletions Sources/Atoms/Core/StoreContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ internal struct StoreContext {
let store = getStore()
let key = AtomKey(atom)
let subscription = Subscription(notifyUpdate: notifyUpdate) { [weak store] in
guard let store = store else {
guard let store else {
return
}

Expand Down Expand Up @@ -116,7 +116,7 @@ internal struct StoreContext {
}

@usableFromInline
func reset<Node: Atom>(_ atom: Node) {
func reset(_ atom: some Atom) {
let key = AtomKey(atom)
let value = getNewValue(of: atom, for: key)

Expand Down Expand Up @@ -369,7 +369,7 @@ private extension StoreContext {
store.state.caches[key] = cache

// Do not notify update if the new value and the old value are equivalent.
if let oldValue = oldValue, !atom._loader.shouldNotifyUpdate(newValue: value, oldValue: oldValue) {
if let oldValue, !atom._loader.shouldNotifyUpdate(newValue: value, oldValue: oldValue) {
return
}

Expand All @@ -379,7 +379,7 @@ private extension StoreContext {
// Notify value update.
notifyUpdateToObservers()

guard let oldValue = oldValue else {
guard let oldValue else {
return
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/Atoms/Core/StoreState.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
internal struct StoreState {
var caches = [AtomKey: AtomCacheBase]()
var states = [AtomKey: AtomStateBase]()
var caches = [AtomKey: any AtomCacheProtocol]()
var states = [AtomKey: any AtomStateProtocol]()
var subscriptions = [AtomKey: [SubscriptionKey: Subscription]]()
}
4 changes: 2 additions & 2 deletions Sources/Atoms/Snapshot.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/// A snapshot structure that captures specific set of values of atoms and their dependency graph.
public struct Snapshot: CustomStringConvertible {
internal let graph: Graph
internal let caches: [AtomKey: AtomCacheBase]
internal let caches: [AtomKey: any AtomCacheProtocol]
internal let subscriptions: [AtomKey: [SubscriptionKey: Subscription]]
private let _restore: @MainActor () -> Void

internal init(
graph: Graph,
caches: [AtomKey: AtomCacheBase],
caches: [AtomKey: any AtomCacheProtocol],
subscriptions: [AtomKey: [SubscriptionKey: Subscription]],
restore: @MainActor @escaping () -> Void
) {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Atoms/Suspense.swift
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private extension Suspense {
return
}

guard let task = task else {
guard let task else {
phase = .suspending
return suspensionTask = nil
}
Expand Down
10 changes: 5 additions & 5 deletions Tests/AtomsTests/AsyncPhaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ final class AsyncPhaseTests: XCTestCase {
func testFlatMap() {
XCTContext.runActivity(named: "To suspending") { _ in
let transformed = phases.map { phase in
phase.flatMap { _ -> AsyncPhase<Int, TestError> in
phase.flatMap { _ -> AsyncPhase<Int, _> in
.suspending
}
}
Expand Down Expand Up @@ -132,7 +132,7 @@ final class AsyncPhaseTests: XCTestCase {

XCTContext.runActivity(named: "To failure") { _ in
let transformed = phases.map { phase in
phase.flatMap { _ -> AsyncPhase<Int, TestError> in
phase.flatMap { _ -> AsyncPhase<Int, _> in
.failure(TestError(value: 1))
}
}
Expand All @@ -150,7 +150,7 @@ final class AsyncPhaseTests: XCTestCase {
func testFlatMapError() {
XCTContext.runActivity(named: "To suspending") { _ in
let transformed = phases.map { phase in
phase.flatMapError { _ -> AsyncPhase<Int, TestError> in
phase.flatMapError { _ -> AsyncPhase<_, TestError> in
.suspending
}
}
Expand All @@ -166,7 +166,7 @@ final class AsyncPhaseTests: XCTestCase {

XCTContext.runActivity(named: "To success") { _ in
let transformed = phases.map { phase in
phase.flatMapError { _ -> AsyncPhase<Int, TestError> in
phase.flatMapError { _ -> AsyncPhase<_, TestError> in
.success(1)
}
}
Expand All @@ -182,7 +182,7 @@ final class AsyncPhaseTests: XCTestCase {

XCTContext.runActivity(named: "To failure") { _ in
let transformed = phases.map { phase in
phase.flatMapError { _ -> AsyncPhase<Int, URLError> in
phase.flatMapError { _ -> AsyncPhase<_, URLError> in
.failure(URLError(.badURL))
}
}
Expand Down