Skip to content

Fix Sendable unsoundness, CancelBag TOCTOU, locker naming, default animation, and add async dispatch API#17

Open
nashysolutions wants to merge 2 commits intoanthony1810:mainfrom
nashysolutions:fix/screenstatekit-library
Open

Fix Sendable unsoundness, CancelBag TOCTOU, locker naming, default animation, and add async dispatch API#17
nashysolutions wants to merge 2 commits intoanthony1810:mainfrom
nashysolutions:fix/screenstatekit-library

Conversation

@nashysolutions
Copy link

@nashysolutions nashysolutions commented Feb 24, 2026

Summary

Test plan

  • Build ScreenStateKit — no new warnings or errors
  • CancelBag: confirm cancelAll() called immediately after store() cancels the stored task
  • StateUpdatable: confirm list updates are no longer animated by default; callers needing animation pass withAnimation: .smooth explicitly
  • Conforming types implementing send(action:) compile correctly; existing receive(action:) implementations are unaffected

🤖 Generated with Claude Code

…t animation

- ScreenState: change open class Sendable to @unchecked Sendable with a doc
  comment stating the invariant all subclasses must maintain (fixes anthony1810#19)
- CancelBag: add async-safe store(task:identifier:) that inserts synchronously
  within actor isolation, eliminating the TOCTOU window between registration
  and storage (fixes anthony1810#20)
- NonIsolatedActionLocker: add doc comment explicitly marking it not thread-safe
  and directing users to IsolatedActionLocker for concurrent use (fixes anthony1810#21)
- StateUpdatable.updateState: change default animation from .smooth to .none
  so state mutations from network responses are no longer animated by default;
  callers can opt in at the call site where animation is intentional (fixes #22)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The protocol previously only exposed nonisolated receive(action:), which
spawns an unstructured fire-and-forget task with no cancellation support.
Callers in async contexts (SwiftUI .task, .refreshable) had to reach into
conforming types' internal isolatedReceive method to get awaitable dispatch.

Adding func send(action: Action) async makes the safe, structured path part
of the public contract. receive(action:) is retained for sync contexts
(button callbacks, onAppear) where awaiting is not possible (fixes anthony1810#15).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nashysolutions nashysolutions changed the title Fix Sendable unsoundness, CancelBag TOCTOU, locker naming, and default animation Fix Sendable unsoundness, CancelBag TOCTOU, locker naming, default animation, and add async dispatch API Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant