Skip to content

Commit 08faf84

Browse files
MainActor Store Isolation (#3277)
* `@preconcurrency @MainActor` isolation of `Store` * Remove unneeded `@MainActor`s * Remove thread checking code * Remove unneeded `@MainActor`s * Swift 5.10 compatibility fixes * wip * More 5.10 fixes * wip * fixes * wip * wip * up the timeout * wip * Fixes * Remove mainActorASAP in favor of mainActorNow. (#3288) * wip * Run swift-format * Update README.md * Fix integration tests. (#3294) * Fix integration tests. * wip * wip * Run swift-format * mainActorNow doesnt need escaping closure * wip * migration guide * wip * Update MigratingTo1.14.md --------- Co-authored-by: Brandon Williams <[email protected]> Co-authored-by: Brandon Williams <[email protected]> Co-authored-by: mbrandonw <[email protected]>
1 parent f02fab5 commit 08faf84

File tree

230 files changed

+719
-1368
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+719
-1368
lines changed

ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@
7777
"kind" : "remoteSourceControl",
7878
"location" : "https://github.com/pointfreeco/swift-dependencies",
7979
"state" : {
80-
"revision" : "d7472be6b3c89251ce4c0db07d32405b43426781",
81-
"version" : "1.3.7"
80+
"revision" : "21660b042cd8fd0bdd45cc39050cacd4e91a63a4",
81+
"version" : "1.3.8"
8282
}
8383
},
8484
{

Examples/CaseStudies/SwiftUICaseStudies/03-Effects-WebSocket.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,19 @@ extension WebSocketClient: DependencyKey {
241241
sendPing: { try await WebSocketActor.shared.sendPing(id: $0) }
242242
)
243243

244-
final actor WebSocketActor: GlobalActor {
245-
final class Delegate: NSObject, URLSessionWebSocketDelegate {
244+
@globalActor final actor WebSocketActor {
245+
private final class Delegate: NSObject, @unchecked Sendable, URLSessionWebSocketDelegate {
246246
var continuation: AsyncStream<Action>.Continuation?
247247

248-
func urlSession(
248+
nonisolated func urlSession(
249249
_: URLSession,
250250
webSocketTask _: URLSessionWebSocketTask,
251251
didOpenWithProtocol protocol: String?
252252
) {
253253
self.continuation?.yield(.didOpen(protocol: `protocol`))
254254
}
255255

256-
func urlSession(
256+
nonisolated func urlSession(
257257
_: URLSession,
258258
webSocketTask _: URLSessionWebSocketTask,
259259
didCloseWith closeCode: URLSessionWebSocketTask.CloseCode,

Examples/CaseStudies/SwiftUICaseStudiesTests/01-GettingStarted-AlertsAndConfirmationDialogsTests.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class AlertsAndConfirmationDialogsTests: XCTestCase {
7-
@MainActor
87
func testAlert() async {
9-
let store = TestStore(initialState: AlertAndConfirmationDialog.State()) {
8+
let store = await TestStore(initialState: AlertAndConfirmationDialog.State()) {
109
AlertAndConfirmationDialog()
1110
}
1211

@@ -33,9 +32,8 @@ final class AlertsAndConfirmationDialogsTests: XCTestCase {
3332
}
3433
}
3534

36-
@MainActor
3735
func testConfirmationDialog() async {
38-
let store = TestStore(initialState: AlertAndConfirmationDialog.State()) {
36+
let store = await TestStore(initialState: AlertAndConfirmationDialog.State()) {
3937
AlertAndConfirmationDialog()
4038
}
4139

Examples/CaseStudies/SwiftUICaseStudiesTests/01-GettingStarted-AnimationsTests.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ import XCTest
55
@testable import SwiftUICaseStudies
66

77
final class AnimationTests: XCTestCase {
8-
@MainActor
98
func testRainbow() async {
109
let clock = TestClock()
1110

12-
let store = TestStore(initialState: Animations.State()) {
11+
let store = await TestStore(initialState: Animations.State()) {
1312
Animations()
1413
} withDependencies: {
1514
$0.continuousClock = clock
@@ -58,11 +57,10 @@ final class AnimationTests: XCTestCase {
5857
await clock.run()
5958
}
6059

61-
@MainActor
6260
func testReset() async {
6361
let clock = TestClock()
6462

65-
let store = TestStore(initialState: Animations.State()) {
63+
let store = await TestStore(initialState: Animations.State()) {
6664
Animations()
6765
} withDependencies: {
6866
$0.continuousClock = clock

Examples/CaseStudies/SwiftUICaseStudiesTests/01-GettingStarted-BindingBasicsTests.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class BindingFormTests: XCTestCase {
7-
@MainActor
87
func testBasics() async {
9-
let store = TestStore(initialState: BindingForm.State()) {
8+
let store = await TestStore(initialState: BindingForm.State()) {
109
BindingForm()
1110
}
1211

Examples/CaseStudies/SwiftUICaseStudiesTests/02-GettingStarted-SharedStateFileStorageTests.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class SharedStateFileStorageTests: XCTestCase {
7-
@MainActor
87
func testTabSelection() async {
9-
let store = TestStore(initialState: SharedStateFileStorage.State()) {
8+
let store = await TestStore(initialState: SharedStateFileStorage.State()) {
109
SharedStateFileStorage()
1110
}
1211

@@ -18,9 +17,8 @@ final class SharedStateFileStorageTests: XCTestCase {
1817
}
1918
}
2019

21-
@MainActor
2220
func testSharedCounts() async {
23-
let store = TestStore(initialState: SharedStateFileStorage.State()) {
21+
let store = await TestStore(initialState: SharedStateFileStorage.State()) {
2422
SharedStateFileStorage()
2523
}
2624

@@ -37,9 +35,8 @@ final class SharedStateFileStorageTests: XCTestCase {
3735
}
3836
}
3937

40-
@MainActor
4138
func testAlert() async {
42-
let store = TestStore(initialState: SharedStateFileStorage.State()) {
39+
let store = await TestStore(initialState: SharedStateFileStorage.State()) {
4340
SharedStateFileStorage()
4441
}
4542

Examples/CaseStudies/SwiftUICaseStudiesTests/02-GettingStarted-SharedStateInMemoryTests.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class SharedStateInMemoryTests: XCTestCase {
7-
@MainActor
87
func testTabSelection() async {
9-
let store = TestStore(initialState: SharedStateInMemory.State()) {
8+
let store = await TestStore(initialState: SharedStateInMemory.State()) {
109
SharedStateInMemory()
1110
}
1211

@@ -18,9 +17,8 @@ final class SharedStateInMemoryTests: XCTestCase {
1817
}
1918
}
2019

21-
@MainActor
2220
func testSharedCounts() async {
23-
let store = TestStore(initialState: SharedStateInMemory.State()) {
21+
let store = await TestStore(initialState: SharedStateInMemory.State()) {
2422
SharedStateInMemory()
2523
}
2624

@@ -37,9 +35,8 @@ final class SharedStateInMemoryTests: XCTestCase {
3735
}
3836
}
3937

40-
@MainActor
4138
func testAlert() async {
42-
let store = TestStore(initialState: SharedStateInMemory.State()) {
39+
let store = await TestStore(initialState: SharedStateInMemory.State()) {
4340
SharedStateInMemory()
4441
}
4542

Examples/CaseStudies/SwiftUICaseStudiesTests/02-GettingStarted-SharedStateUserDefaultsTests.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class SharedStateUserDefaultsTests: XCTestCase {
7-
@MainActor
87
func testTabSelection() async {
9-
let store = TestStore(initialState: SharedStateUserDefaults.State()) {
8+
let store = await TestStore(initialState: SharedStateUserDefaults.State()) {
109
SharedStateUserDefaults()
1110
}
1211

@@ -18,9 +17,8 @@ final class SharedStateUserDefaultsTests: XCTestCase {
1817
}
1918
}
2019

21-
@MainActor
2220
func testSharedCounts() async {
23-
let store = TestStore(initialState: SharedStateUserDefaults.State()) {
21+
let store = await TestStore(initialState: SharedStateUserDefaults.State()) {
2422
SharedStateUserDefaults()
2523
}
2624

@@ -37,9 +35,8 @@ final class SharedStateUserDefaultsTests: XCTestCase {
3735
}
3836
}
3937

40-
@MainActor
4138
func testAlert() async {
42-
let store = TestStore(initialState: SharedStateUserDefaults.State()) {
39+
let store = await TestStore(initialState: SharedStateUserDefaults.State()) {
4340
SharedStateUserDefaults()
4441
}
4542

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-BasicsTests.swift

+4-8
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class EffectsBasicsTests: XCTestCase {
7-
@MainActor
87
func testCountDown() async {
9-
let store = TestStore(initialState: EffectsBasics.State()) {
8+
let store = await TestStore(initialState: EffectsBasics.State()) {
109
EffectsBasics()
1110
} withDependencies: {
1211
$0.continuousClock = ImmediateClock()
@@ -20,9 +19,8 @@ final class EffectsBasicsTests: XCTestCase {
2019
}
2120
}
2221

23-
@MainActor
2422
func testNumberFact() async {
25-
let store = TestStore(initialState: EffectsBasics.State()) {
23+
let store = await TestStore(initialState: EffectsBasics.State()) {
2624
EffectsBasics()
2725
} withDependencies: {
2826
$0.factClient.fetch = { "\($0) is a good number Brent" }
@@ -41,9 +39,8 @@ final class EffectsBasicsTests: XCTestCase {
4139
}
4240
}
4341

44-
@MainActor
4542
func testDecrement() async {
46-
let store = TestStore(initialState: EffectsBasics.State()) {
43+
let store = await TestStore(initialState: EffectsBasics.State()) {
4744
EffectsBasics()
4845
} withDependencies: {
4946
$0.continuousClock = ImmediateClock()
@@ -57,9 +54,8 @@ final class EffectsBasicsTests: XCTestCase {
5754
}
5855
}
5956

60-
@MainActor
6157
func testDecrementCancellation() async {
62-
let store = TestStore(initialState: EffectsBasics.State()) {
58+
let store = await TestStore(initialState: EffectsBasics.State()) {
6359
EffectsBasics()
6460
} withDependencies: {
6561
$0.continuousClock = TestClock()

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-CancellationTests.swift

+4-8
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class EffectsCancellationTests: XCTestCase {
7-
@MainActor
87
func testTrivia_SuccessfulRequest() async {
9-
let store = TestStore(initialState: EffectsCancellation.State()) {
8+
let store = await TestStore(initialState: EffectsCancellation.State()) {
109
EffectsCancellation()
1110
} withDependencies: {
1211
$0.factClient.fetch = { "\($0) is a good number Brent" }
@@ -27,10 +26,9 @@ final class EffectsCancellationTests: XCTestCase {
2726
}
2827
}
2928

30-
@MainActor
3129
func testTrivia_FailedRequest() async {
3230
struct FactError: Equatable, Error {}
33-
let store = TestStore(initialState: EffectsCancellation.State()) {
31+
let store = await TestStore(initialState: EffectsCancellation.State()) {
3432
EffectsCancellation()
3533
} withDependencies: {
3634
$0.factClient.fetch = { _ in throw FactError() }
@@ -50,9 +48,8 @@ final class EffectsCancellationTests: XCTestCase {
5048
// in the `.cancelButtonTapped` action of the `effectsCancellationReducer`. This will cause the
5149
// test to fail, showing that we are exhaustively asserting that the effect truly is canceled and
5250
// will never emit.
53-
@MainActor
5451
func testTrivia_CancelButtonCancelsRequest() async {
55-
let store = TestStore(initialState: EffectsCancellation.State()) {
52+
let store = await TestStore(initialState: EffectsCancellation.State()) {
5653
EffectsCancellation()
5754
} withDependencies: {
5855
$0.factClient.fetch = { _ in try await Task.never() }
@@ -66,9 +63,8 @@ final class EffectsCancellationTests: XCTestCase {
6663
}
6764
}
6865

69-
@MainActor
7066
func testTrivia_PlusMinusButtonsCancelsRequest() async {
71-
let store = TestStore(initialState: EffectsCancellation.State()) {
67+
let store = await TestStore(initialState: EffectsCancellation.State()) {
7268
EffectsCancellation()
7369
} withDependencies: {
7470
$0.factClient.fetch = { _ in try await Task.never() }

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-LongLivingTests.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class LongLivingEffectsTests: XCTestCase {
7-
@MainActor
87
func testReducer() async {
98
let (screenshots, takeScreenshot) = AsyncStream.makeStream(of: Void.self)
109

11-
let store = TestStore(initialState: LongLivingEffects.State()) {
10+
let store = await TestStore(initialState: LongLivingEffects.State()) {
1211
LongLivingEffects()
1312
} withDependencies: {
1413
$0.screenshots = { screenshots }

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-RefreshableTests.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class RefreshableTests: XCTestCase {
7-
@MainActor
87
func testHappyPath() async {
9-
let store = TestStore(initialState: Refreshable.State()) {
8+
let store = await TestStore(initialState: Refreshable.State()) {
109
Refreshable()
1110
} withDependencies: {
1211
$0.factClient.fetch = { "\($0) is a good number." }
@@ -22,11 +21,10 @@ final class RefreshableTests: XCTestCase {
2221
}
2322
}
2423

25-
@MainActor
2624
func testUnhappyPath() async {
2725
struct FactError: Equatable, Error {}
2826

29-
let store = TestStore(initialState: Refreshable.State()) {
27+
let store = await TestStore(initialState: Refreshable.State()) {
3028
Refreshable()
3129
} withDependencies: {
3230
$0.factClient.fetch = { _ in throw FactError() }
@@ -40,9 +38,8 @@ final class RefreshableTests: XCTestCase {
4038
await store.receive(\.factResponse.failure)
4139
}
4240

43-
@MainActor
4441
func testCancellation() async {
45-
let store = TestStore(initialState: Refreshable.State()) {
42+
let store = await TestStore(initialState: Refreshable.State()) {
4643
Refreshable()
4744
} withDependencies: {
4845
$0.factClient.fetch = {

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-TimersTests.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class TimersTests: XCTestCase {
7-
@MainActor
87
func testStart() async {
98
let clock = TestClock()
109

11-
let store = TestStore(initialState: Timers.State()) {
10+
let store = await TestStore(initialState: Timers.State()) {
1211
Timers()
1312
} withDependencies: {
1413
$0.continuousClock = clock

Examples/CaseStudies/SwiftUICaseStudiesTests/03-Effects-WebSocketTests.swift

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import XCTest
44
@testable import SwiftUICaseStudies
55

66
final class WebSocketTests: XCTestCase {
7-
@MainActor
87
func testWebSocketHappyPath() async {
98
let actions = AsyncStream.makeStream(of: WebSocketClient.Action.self)
109
let messages = AsyncStream.makeStream(of: Result<WebSocketClient.Message, Error>.self)
1110

12-
let store = TestStore(initialState: WebSocket.State()) {
11+
let store = await TestStore(initialState: WebSocket.State()) {
1312
WebSocket()
1413
} withDependencies: {
1514
$0.continuousClock = ImmediateClock()
@@ -56,12 +55,11 @@ final class WebSocketTests: XCTestCase {
5655
await store.finish()
5756
}
5857

59-
@MainActor
6058
func testWebSocketSendFailure() async {
6159
let actions = AsyncStream.makeStream(of: WebSocketClient.Action.self)
6260
let messages = AsyncStream.makeStream(of: Result<WebSocketClient.Message, Error>.self)
6361

64-
let store = TestStore(initialState: WebSocket.State()) {
62+
let store = await TestStore(initialState: WebSocket.State()) {
6563
WebSocket()
6664
} withDependencies: {
6765
$0.continuousClock = ImmediateClock()
@@ -138,11 +136,10 @@ final class WebSocketTests: XCTestCase {
138136
}
139137
}
140138

141-
@MainActor
142139
func testWebSocketConnectError() async {
143140
let actions = AsyncStream.makeStream(of: WebSocketClient.Action.self)
144141

145-
let store = TestStore(initialState: WebSocket.State()) {
142+
let store = await TestStore(initialState: WebSocket.State()) {
146143
WebSocket()
147144
} withDependencies: {
148145
$0.continuousClock = ImmediateClock()

0 commit comments

Comments
 (0)