@swiftbrowser/swift 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/Package.swift +200 -9
  2. package/README.md +7 -9
  3. package/Sources/AVFoundation/AVFoundation.swift +131 -0
  4. package/Sources/AVFoundation/Asset.swift +487 -0
  5. package/Sources/AVFoundation/AudioSession.swift +144 -0
  6. package/Sources/AVFoundation/CMTime.swift +303 -0
  7. package/Sources/AVFoundation/Capture.swift +688 -0
  8. package/Sources/AVFoundation/Player.swift +749 -0
  9. package/Sources/AVFoundation/PlayerView.swift +117 -0
  10. package/Sources/AVKit/AVKit.swift +132 -0
  11. package/Sources/Accelerate/Accelerate.swift +122 -0
  12. package/Sources/AppIntents/AppIntents.swift +144 -0
  13. package/Sources/AppIntents/Parameters.swift +220 -0
  14. package/Sources/AppIntents/Shortcuts.swift +159 -0
  15. package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
  16. package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
  17. package/Sources/AuthenticationServices/Authorization.swift +251 -0
  18. package/Sources/Charts/Charts.swift +0 -4
  19. package/Sources/Combine/AnyCancellable.swift +65 -0
  20. package/Sources/Combine/AnyPublisher.swift +148 -0
  21. package/Sources/Combine/AnySubscriber.swift +230 -0
  22. package/Sources/Combine/Cancellable.swift +35 -0
  23. package/Sources/Combine/Codable.swift +29 -0
  24. package/Sources/Combine/CombineIdentifier.swift +45 -0
  25. package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
  26. package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
  27. package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
  28. package/Sources/Combine/CurrentValueSubject.swift +252 -0
  29. package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
  30. package/Sources/Combine/Future.swift +228 -0
  31. package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
  32. package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
  33. package/Sources/Combine/Helpers/ConduitList.swift +59 -0
  34. package/Sources/Combine/Helpers/DebugHook.swift +177 -0
  35. package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
  36. package/Sources/Combine/Helpers/Locking.swift +30 -0
  37. package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
  38. package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
  39. package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
  40. package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
  41. package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
  42. package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
  43. package/Sources/Combine/Helpers/Utils.swift +30 -0
  44. package/Sources/Combine/Helpers/Violations.swift +33 -0
  45. package/Sources/Combine/ImmediateScheduler.swift +178 -0
  46. package/Sources/Combine/LICENSE +21 -0
  47. package/Sources/Combine/NotificationPublisher.swift +48 -0
  48. package/Sources/Combine/ObjectWillChange.swift +46 -0
  49. package/Sources/Combine/PassthroughSubject.swift +222 -0
  50. package/Sources/Combine/Publisher+Subscribe.swift +53 -0
  51. package/Sources/Combine/Publishers/Deferred.swift +48 -0
  52. package/Sources/Combine/Publishers/Empty.swift +54 -0
  53. package/Sources/Combine/Publishers/Fail.swift +42 -0
  54. package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
  55. package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
  56. package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
  57. package/Sources/Combine/Publishers/Just.swift +313 -0
  58. package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
  59. package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
  60. package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
  61. package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
  62. package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
  63. package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
  64. package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
  65. package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
  66. package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
  67. package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
  68. package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
  69. package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
  70. package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
  71. package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
  72. package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
  73. package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
  74. package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
  75. package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
  76. package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
  77. package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
  78. package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
  79. package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
  80. package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
  81. package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
  82. package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
  83. package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
  84. package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
  85. package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
  86. package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
  87. package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
  88. package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
  89. package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
  90. package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
  91. package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
  92. package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
  93. package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
  94. package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
  95. package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
  96. package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
  97. package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
  98. package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
  99. package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
  100. package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
  101. package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
  102. package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
  103. package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
  104. package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
  105. package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
  106. package/Sources/Combine/Publishers/Publishers.swift +13 -0
  107. package/Sources/Combine/Publishers/Record.swift +237 -0
  108. package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
  109. package/Sources/Combine/Result.swift +46 -0
  110. package/Sources/Combine/Scheduler.swift +89 -0
  111. package/Sources/Combine/Schedulers.swift +211 -0
  112. package/Sources/Combine/Subject+Void.swift +17 -0
  113. package/Sources/Combine/Subscriber+Void.swift +20 -0
  114. package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
  115. package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
  116. package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
  117. package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
  118. package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
  119. package/Sources/Combine/Subscription.swift +22 -0
  120. package/Sources/Combine/Subscriptions.swift +42 -0
  121. package/Sources/Combine/SwiftUIObservation.swift +10 -0
  122. package/Sources/Combine/_Introspection.swift +107 -0
  123. package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
  124. package/Sources/Compression/Compression.swift +365 -0
  125. package/Sources/Compression/Deflate.swift +407 -0
  126. package/Sources/Compression/Zlib.swift +179 -0
  127. package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
  128. package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
  129. package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
  130. package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
  131. package/Sources/CoreImage/CIColor.swift +41 -0
  132. package/Sources/CoreImage/CIContext.swift +31 -0
  133. package/Sources/CoreImage/CIDetector.swift +57 -0
  134. package/Sources/CoreImage/CIFilter.swift +243 -0
  135. package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
  136. package/Sources/CoreImage/CIImage.swift +162 -0
  137. package/Sources/CoreImage/QRCode.swift +393 -0
  138. package/Sources/CoreLocation/Coordinate.swift +30 -0
  139. package/Sources/CoreLocation/Location.swift +65 -0
  140. package/Sources/CoreML/Evaluation.swift +414 -0
  141. package/Sources/CoreML/FeatureValue.swift +266 -0
  142. package/Sources/CoreML/Model.swift +269 -0
  143. package/Sources/CoreML/MultiArray.swift +92 -0
  144. package/Sources/CoreML/Specification.swift +233 -0
  145. package/Sources/CoreText/CoreText.swift +64 -0
  146. package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
  147. package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
  148. package/Sources/CryptoKit/CryptoKit.swift +375 -0
  149. package/Sources/CryptoKit/Curve25519.swift +317 -0
  150. package/Sources/CryptoKit/P256.swift +321 -0
  151. package/Sources/FoundationBridge/AppStorage.swift +165 -0
  152. package/Sources/FoundationBridge/AssetResources.swift +90 -0
  153. package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
  154. package/Sources/FoundationBridge/AsyncImage.swift +116 -0
  155. package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
  156. package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
  157. package/Sources/FoundationBridge/CombineExports.swift +8 -0
  158. package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
  159. package/Sources/FoundationBridge/Dispatch.swift +458 -0
  160. package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
  161. package/Sources/FoundationBridge/FileImporter.swift +128 -0
  162. package/Sources/FoundationBridge/FileSystem.swift +68 -0
  163. package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
  164. package/Sources/FoundationBridge/HostResolution.swift +31 -0
  165. package/Sources/FoundationBridge/ItemProvider.swift +655 -0
  166. package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
  167. package/Sources/FoundationBridge/Links.swift +127 -0
  168. package/Sources/FoundationBridge/ListFormatter.swift +32 -0
  169. package/Sources/FoundationBridge/Localization.swift +149 -0
  170. package/Sources/FoundationBridge/Locks.swift +50 -0
  171. package/Sources/FoundationBridge/Markdown.swift +527 -0
  172. package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
  173. package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
  174. package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
  175. package/Sources/FoundationBridge/Operation.swift +195 -0
  176. package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
  177. package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
  178. package/Sources/FoundationBridge/SceneStorage.swift +78 -0
  179. package/Sources/FoundationBridge/SecurityExports.swift +8 -0
  180. package/Sources/FoundationBridge/Selector.swift +226 -0
  181. package/Sources/FoundationBridge/StringComparators.swift +17 -0
  182. package/Sources/FoundationBridge/Table.swift +211 -0
  183. package/Sources/FoundationBridge/TextAttributes.swift +42 -0
  184. package/Sources/FoundationBridge/Timer.swift +6 -1
  185. package/Sources/FoundationBridge/URLSession.swift +718 -0
  186. package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
  187. package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
  188. package/Sources/FoundationBridge/WebSocket.swift +187 -0
  189. package/Sources/FoundationModels/FoundationModels.swift +1098 -0
  190. package/Sources/ImageIO/GIF.swift +72 -0
  191. package/Sources/ImageIO/ImageIO.swift +248 -0
  192. package/Sources/ImageIO/ImageTypes.swift +28 -0
  193. package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
  194. package/Sources/LocalAuthentication/LAContext.swift +86 -0
  195. package/Sources/MapKit/Geometry.swift +223 -0
  196. package/Sources/MapKit/Map.swift +638 -0
  197. package/Sources/MapKit/MapView.swift +229 -0
  198. package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
  199. package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
  200. package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
  201. package/Sources/OSLog/OSLog.swift +6 -0
  202. package/Sources/Photos/Photos.swift +572 -0
  203. package/Sources/PhotosUI/PhotosPicker.swift +248 -0
  204. package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
  205. package/Sources/QuickLook/QuickLook.swift +168 -0
  206. package/Sources/SafariServices/SafariServices.swift +106 -0
  207. package/Sources/Security/Security.swift +332 -0
  208. package/Sources/StoreKit/AppStore.swift +207 -0
  209. package/Sources/StoreKit/Products.swift +280 -0
  210. package/Sources/StoreKit/RequestReview.swift +28 -0
  211. package/Sources/StoreKit/StoreKit1.swift +486 -0
  212. package/Sources/StoreKit/StoreViews.swift +428 -0
  213. package/Sources/StoreKit/Transactions.swift +197 -0
  214. package/Sources/SwiftData/Macros.swift +58 -0
  215. package/Sources/SwiftData/ModelActor.swift +38 -0
  216. package/Sources/SwiftData/ModelContainer.swift +129 -0
  217. package/Sources/SwiftData/ModelContext.swift +451 -0
  218. package/Sources/SwiftData/PersistentModel.swift +238 -0
  219. package/Sources/SwiftData/Properties.swift +261 -0
  220. package/Sources/SwiftData/Query.swift +256 -0
  221. package/Sources/SwiftData/Schema.swift +192 -0
  222. package/Sources/SwiftData/Store.swift +146 -0
  223. package/Sources/SwiftData/StringPredicates.swift +125 -0
  224. package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
  225. package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
  226. package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
  227. package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
  228. package/Sources/SwiftDataMacros/Plugin.swift +18 -0
  229. package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
  230. package/Sources/SwiftUI/API/Accessibility.swift +55 -6
  231. package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
  232. package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
  233. package/Sources/SwiftUI/API/Alert.swift +1 -1
  234. package/Sources/SwiftUI/API/AlignmentGuides.swift +68 -0
  235. package/Sources/SwiftUI/API/Animation.swift +37 -5
  236. package/Sources/SwiftUI/API/App.swift +31 -1
  237. package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
  238. package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
  239. package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
  240. package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
  241. package/Sources/SwiftUI/API/Canvas.swift +337 -0
  242. package/Sources/SwiftUI/API/Color.swift +104 -28
  243. package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
  244. package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
  245. package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
  246. package/Sources/SwiftUI/API/Commands.swift +106 -0
  247. package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
  248. package/Sources/SwiftUI/API/ContentShape.swift +33 -0
  249. package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
  250. package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
  251. package/Sources/SwiftUI/API/Controls.swift +59 -27
  252. package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
  253. package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
  254. package/Sources/SwiftUI/API/Decorations.swift +1 -1
  255. package/Sources/SwiftUI/API/EditMode.swift +25 -82
  256. package/Sources/SwiftUI/API/Effects.swift +125 -10
  257. package/Sources/SwiftUI/API/Entry.swift +8 -0
  258. package/Sources/SwiftUI/API/Environment.swift +100 -9
  259. package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
  260. package/Sources/SwiftUI/API/Focus.swift +11 -3
  261. package/Sources/SwiftUI/API/Gauge.swift +26 -10
  262. package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
  263. package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
  264. package/Sources/SwiftUI/API/GestureState.swift +65 -0
  265. package/Sources/SwiftUI/API/Gestures.swift +1 -1
  266. package/Sources/SwiftUI/API/Glass.swift +127 -0
  267. package/Sources/SwiftUI/API/Grid.swift +1 -1
  268. package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
  269. package/Sources/SwiftUI/API/KeyPress.swift +54 -0
  270. package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
  271. package/Sources/SwiftUI/API/Layout.swift +71 -12
  272. package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
  273. package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
  274. package/Sources/SwiftUI/API/Lists.swift +61 -6
  275. package/Sources/SwiftUI/API/Menu.swift +8 -1
  276. package/Sources/SwiftUI/API/Modifiers.swift +88 -12
  277. package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
  278. package/Sources/SwiftUI/API/Namespace.swift +44 -0
  279. package/Sources/SwiftUI/API/Navigation.swift +24 -9
  280. package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
  281. package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
  282. package/Sources/SwiftUI/API/Path.swift +543 -0
  283. package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
  284. package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
  285. package/Sources/SwiftUI/API/Picker.swift +14 -4
  286. package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
  287. package/Sources/SwiftUI/API/Popover.swift +41 -0
  288. package/Sources/SwiftUI/API/Preferences.swift +262 -0
  289. package/Sources/SwiftUI/API/Presentation.swift +17 -4
  290. package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
  291. package/Sources/SwiftUI/API/Primitives.swift +168 -39
  292. package/Sources/SwiftUI/API/Publishers.swift +4 -4
  293. package/Sources/SwiftUI/API/Redaction.swift +75 -0
  294. package/Sources/SwiftUI/API/RowActions.swift +3 -2
  295. package/Sources/SwiftUI/API/Scenes.swift +131 -0
  296. package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
  297. package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
  298. package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
  299. package/Sources/SwiftUI/API/SectionSupplements.swift +86 -0
  300. package/Sources/SwiftUI/API/Shape.swift +214 -0
  301. package/Sources/SwiftUI/API/ShapeStyle.swift +187 -8
  302. package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
  303. package/Sources/SwiftUI/API/Sharing.swift +193 -0
  304. package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
  305. package/Sources/SwiftUI/API/State.swift +18 -1
  306. package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
  307. package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
  308. package/Sources/SwiftUI/API/TabContent.swift +841 -0
  309. package/Sources/SwiftUI/API/Table.swift +382 -0
  310. package/Sources/SwiftUI/API/Tabs.swift +148 -4
  311. package/Sources/SwiftUI/API/Tasks.swift +2 -2
  312. package/Sources/SwiftUI/API/Text.swift +386 -0
  313. package/Sources/SwiftUI/API/TextDates.swift +61 -0
  314. package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
  315. package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
  316. package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
  317. package/Sources/SwiftUI/API/Toolbar.swift +52 -16
  318. package/Sources/SwiftUI/API/Transfer.swift +145 -0
  319. package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
  320. package/Sources/SwiftUI/API/Video.swift +64 -0
  321. package/Sources/SwiftUI/API/View.swift +46 -2
  322. package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
  323. package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
  324. package/Sources/SwiftUI/API/Windows.swift +25 -0
  325. package/Sources/SwiftUI/Charts/Axis.swift +7 -1
  326. package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
  327. package/Sources/SwiftUI/Charts/Chart.swift +17 -3
  328. package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
  329. package/Sources/SwiftUI/Localization/Localization.swift +524 -0
  330. package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
  331. package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
  332. package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
  333. package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
  334. package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
  335. package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
  336. package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
  337. package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
  338. package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
  339. package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
  340. package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
  341. package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
  342. package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
  343. package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
  344. package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
  345. package/Sources/Symbols/Symbols.swift +25 -0
  346. package/Sources/Translation/Translation.swift +423 -0
  347. package/Sources/UIKit/Activity.swift +213 -0
  348. package/Sources/UIKit/Alerts.swift +69 -0
  349. package/Sources/UIKit/AppDelegate.swift +222 -0
  350. package/Sources/UIKit/Appearance.swift +84 -0
  351. package/Sources/UIKit/ColorConversions.swift +70 -0
  352. package/Sources/UIKit/Controls.swift +225 -0
  353. package/Sources/UIKit/Device.swift +200 -0
  354. package/Sources/UIKit/Feedback.swift +65 -0
  355. package/Sources/UIKit/Font.swift +307 -0
  356. package/Sources/UIKit/Graphics.swift +204 -0
  357. package/Sources/UIKit/HostingController.swift +185 -0
  358. package/Sources/UIKit/Identity.swift +24 -0
  359. package/Sources/UIKit/Introspectable.swift +510 -0
  360. package/Sources/UIKit/Pasteboard.swift +363 -0
  361. package/Sources/UIKit/PhotoAlbum.swift +81 -0
  362. package/Sources/UIKit/RemoteNotifications.swift +15 -0
  363. package/Sources/UIKit/Representable.swift +288 -0
  364. package/Sources/UIKit/SafeArea.swift +12 -0
  365. package/Sources/UIKit/SceneDelegates.swift +132 -0
  366. package/Sources/UIKit/Scenes.swift +40 -0
  367. package/Sources/UIKit/ScrollView.swift +157 -0
  368. package/Sources/UIKit/ShortcutItems.swift +67 -0
  369. package/Sources/UIKit/SymbolConfiguration.swift +124 -0
  370. package/Sources/UIKit/TargetAction.swift +123 -0
  371. package/Sources/UIKit/TextPaste.swift +161 -0
  372. package/Sources/UIKit/TextView.swift +538 -0
  373. package/Sources/UIKit/UIKit.swift +292 -0
  374. package/Sources/UIKit/UIView.swift +855 -0
  375. package/Sources/UIKit/ViewTranslation.swift +311 -0
  376. package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
  377. package/Sources/UserNotifications/Content.swift +370 -0
  378. package/Sources/UserNotifications/NotificationCenter.swift +309 -0
  379. package/Sources/WeatherKit/WeatherKit.swift +228 -0
  380. package/Sources/WebKit/WebKit.swift +245 -0
  381. package/Sources/os/os.swift +376 -0
  382. package/Sources/zlib/zlib.swift +6 -0
  383. package/index.d.ts +1 -1
  384. package/index.mjs +2 -2
  385. package/manifest.d.mts +2 -0
  386. package/manifest.mjs +41 -0
  387. package/package.json +5 -3
  388. package/sync-sources.mjs +21 -7
  389. package/Sources/FoundationLite/Common.swift +0 -3
  390. package/Sources/FoundationLite/FoundationLite.swift +0 -171
  391. package/Sources/FoundationLite/Interaction.swift +0 -146
  392. package/Sources/FoundationLite/Timer.swift +0 -48
  393. package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
@@ -0,0 +1,38 @@
1
+ // Model actors (`@ModelActor`, Macros.swift): an actor that works with a
2
+ // context of its own. Apple's runs on its model executor; here it runs on the
3
+ // main actor's executor, as everything in the browser runs on one thread, so
4
+ // the context (which, like the runtime, lives on the main actor) is used
5
+ // where it expects to be.
6
+
7
+ /// What runs a model actor's work: here, the holder of its context.
8
+ public protocol ModelExecutor: AnyObject, Sendable {
9
+ var modelContext: ModelContext { get }
10
+ }
11
+
12
+ /// The executor `@ModelActor` makes, holding the actor's context.
13
+ public final class DefaultSerialModelExecutor: ModelExecutor, @unchecked Sendable {
14
+ public let modelContext: ModelContext
15
+
16
+ public init(modelContext: ModelContext) {
17
+ self.modelContext = modelContext
18
+ }
19
+ }
20
+
21
+ /// An actor with a model container and a context of its own.
22
+ public protocol ModelActor: Actor {
23
+ nonisolated var modelContainer: ModelContainer { get }
24
+ nonisolated var modelExecutor: any ModelExecutor { get }
25
+ }
26
+
27
+ extension ModelActor {
28
+ /// The main actor's executor (see the file comment).
29
+ public nonisolated var unownedExecutor: UnownedSerialExecutor { MainActor.sharedUnownedExecutor }
30
+
31
+ /// The actor's context, which its executor holds.
32
+ public var modelContext: ModelContext { modelExecutor.modelContext }
33
+
34
+ /// The model with `id` in the actor's context, if it is there.
35
+ public subscript<T: PersistentModel>(id: PersistentIdentifier, as type: T.Type) -> T? {
36
+ modelContext.registeredModel(for: id)
37
+ }
38
+ }
@@ -0,0 +1,129 @@
1
+ // Containers and their configurations. A configuration names a store; a
2
+ // persistent store is saved to the page's IndexedDB (one database per app,
3
+ // docs/ops-protocol.md, "Phase 18"), an in-memory one keeps nothing.
4
+
5
+ import Foundation
6
+ import SwiftUI
7
+
8
+ /// Where and how a container stores its models.
9
+ public struct ModelConfiguration: Hashable, Identifiable, @unchecked Sendable {
10
+ public enum CloudKitDatabase: Hashable, Sendable {
11
+ case automatic
12
+ case none
13
+ case `private`(String)
14
+ }
15
+
16
+ public enum GroupContainer: Hashable, Sendable {
17
+ case automatic
18
+ case none
19
+ case identifier(String)
20
+ }
21
+
22
+ public var name: String
23
+ public var url: URL
24
+ public var isStoredInMemoryOnly: Bool
25
+ public var allowsSave: Bool
26
+ public var schema: Schema?
27
+ public var cloudKitDatabase: CloudKitDatabase
28
+ public var groupContainer: GroupContainer
29
+
30
+ public var id: String { name }
31
+
32
+ public init(
33
+ _ name: String? = nil,
34
+ schema: Schema? = nil,
35
+ isStoredInMemoryOnly: Bool = false,
36
+ allowsSave: Bool = true,
37
+ groupContainer: GroupContainer = .automatic,
38
+ cloudKitDatabase: CloudKitDatabase = .automatic
39
+ ) {
40
+ let name = name ?? "default"
41
+ self.name = name
42
+ url = URL(fileURLWithPath: "/swiftdata/\(name).store")
43
+ self.isStoredInMemoryOnly = isStoredInMemoryOnly
44
+ self.allowsSave = allowsSave
45
+ self.schema = schema
46
+ self.cloudKitDatabase = cloudKitDatabase
47
+ self.groupContainer = groupContainer
48
+ }
49
+
50
+ public init(
51
+ _ name: String? = nil,
52
+ schema: Schema? = nil,
53
+ url: URL,
54
+ allowsSave: Bool = true,
55
+ cloudKitDatabase: CloudKitDatabase = .automatic
56
+ ) {
57
+ self.name = name ?? url.deletingPathExtension().lastPathComponent
58
+ self.url = url
59
+ isStoredInMemoryOnly = false
60
+ self.allowsSave = allowsSave
61
+ self.schema = schema
62
+ self.cloudKitDatabase = cloudKitDatabase
63
+ groupContainer = .automatic
64
+ }
65
+
66
+ public init(for forTypes: any PersistentModel.Type..., isStoredInMemoryOnly: Bool = false) {
67
+ self.init(schema: Schema(forTypes), isStoredInMemoryOnly: isStoredInMemoryOnly)
68
+ }
69
+
70
+ public init(isStoredInMemoryOnly: Bool) {
71
+ self.init(nil, isStoredInMemoryOnly: isStoredInMemoryOnly)
72
+ }
73
+
74
+ /// The name the store goes by in IndexedDB and in `swiftdata` ops.
75
+ var storeIdentifier: String { url.lastPathComponent }
76
+
77
+ public static func == (lhs: ModelConfiguration, rhs: ModelConfiguration) -> Bool {
78
+ lhs.name == rhs.name && lhs.url == rhs.url && lhs.isStoredInMemoryOnly == rhs.isStoredInMemoryOnly
79
+ && lhs.allowsSave == rhs.allowsSave
80
+ }
81
+
82
+ public func hash(into hasher: inout Hasher) {
83
+ hasher.combine(name)
84
+ hasher.combine(url)
85
+ hasher.combine(isStoredInMemoryOnly)
86
+ }
87
+ }
88
+
89
+ /// The models of a schema and the store that keeps them.
90
+ public final class ModelContainer: @unchecked Sendable {
91
+ public let schema: Schema
92
+ public let configurations: [ModelConfiguration]
93
+ let store: _Store
94
+ private var _mainContext: ModelContext?
95
+
96
+ public init(for schema: Schema, migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: [ModelConfiguration] = []) throws {
97
+ let configuration = configurations.first ?? ModelConfiguration(schema: schema)
98
+ self.schema = schema
99
+ self.configurations = configurations.isEmpty ? [configuration] : configurations
100
+ store = _Store.open(identifier: configuration.storeIdentifier, inMemory: configuration.isStoredInMemoryOnly)
101
+ }
102
+
103
+ public convenience init(for schema: Schema, migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: ModelConfiguration...) throws {
104
+ try self.init(for: schema, migrationPlan: migrationPlan, configurations: configurations)
105
+ }
106
+
107
+ public convenience init(for forTypes: any PersistentModel.Type..., migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: ModelConfiguration...) throws {
108
+ try self.init(for: Schema(forTypes), migrationPlan: migrationPlan, configurations: configurations)
109
+ }
110
+
111
+ public convenience init(for forTypes: any PersistentModel.Type..., migrationPlan: (any SchemaMigrationPlan.Type)? = nil, configurations: [ModelConfiguration]) throws {
112
+ try self.init(for: Schema(forTypes), migrationPlan: migrationPlan, configurations: configurations)
113
+ }
114
+
115
+ /// The context bound to the main actor, which saves on its own after
116
+ /// every event that changed it (`autosaveEnabled`).
117
+ @MainActor public var mainContext: ModelContext {
118
+ if let context = _mainContext { return context }
119
+ let context = ModelContext(self)
120
+ context.autosaveEnabled = true
121
+ _mainContext = context
122
+ return context
123
+ }
124
+
125
+ /// Deletes every model of the container's store.
126
+ public func deleteAllData() {
127
+ store.commit(put: [], delete: [], clear: true, from: nil)
128
+ }
129
+ }
@@ -0,0 +1,451 @@
1
+ // A context: the live models of a store, and the changes not yet saved.
2
+ //
3
+ // It keeps one object per record (fetching twice returns the same model),
4
+ // tracks inserted, changed and deleted models, keeps the two sides of a
5
+ // relationship in step, and saves into its store. The main context saves on
6
+ // its own at the end of every event that changed it, like SwiftData's
7
+ // autosave; `@Query` re-runs when the context changes.
8
+
9
+ import Foundation
10
+ import Observation
11
+ import SwiftUI
12
+
13
+ public struct SwiftDataError: Error, Equatable, CustomStringConvertible, Sendable {
14
+ public struct Code: Hashable, Sendable {
15
+ let name: String
16
+ public static let unsupportedPredicate = Code(name: "unsupportedPredicate")
17
+ public static let unsupportedSortDescriptor = Code(name: "unsupportedSortDescriptor")
18
+ public static let modelValidationFailure = Code(name: "modelValidationFailure")
19
+ public static let loadIssueModelContainer = Code(name: "loadIssueModelContainer")
20
+ static let _decodeFailed = Code(name: "decodeFailed")
21
+ }
22
+
23
+ public let code: Code
24
+ let message: String
25
+
26
+ init(_ code: Code, _ message: String) {
27
+ self.code = code
28
+ self.message = message
29
+ }
30
+
31
+ public static let unsupportedPredicate = SwiftDataError(.unsupportedPredicate, "the predicate is not supported")
32
+ public static let modelValidationFailure = SwiftDataError(.modelValidationFailure, "a model failed validation")
33
+ public static let loadIssueModelContainer = SwiftDataError(.loadIssueModelContainer, "the container could not be loaded")
34
+
35
+ public static func == (lhs: SwiftDataError, rhs: SwiftDataError) -> Bool { lhs.code == rhs.code }
36
+
37
+ public var description: String { "SwiftDataError(\(code.name)): \(message)" }
38
+ }
39
+
40
+ /// Bumped on every change to a context's models; `@Query` reads it so that
41
+ /// the views showing a query re-run when the context changes.
42
+ @Observable
43
+ final class _ChangeSignal {
44
+ var generation = 0
45
+ }
46
+
47
+ public final class ModelContext: Equatable, Hashable {
48
+ public let container: ModelContainer
49
+ let store: _Store
50
+ /// Whether the context saves on its own after each event that changed
51
+ /// it. On for a container's `mainContext`, off for contexts an app makes.
52
+ public var autosaveEnabled = false
53
+
54
+ /// The context's live models, by identity.
55
+ private var registered: [PersistentIdentifier: any PersistentModel] = [:]
56
+ /// Inserted, not yet saved, in order.
57
+ private var inserted: [PersistentIdentifier] = []
58
+ private var insertedSet: Set<PersistentIdentifier> = []
59
+ private var changed: Set<PersistentIdentifier> = []
60
+ private var deleted: [PersistentIdentifier: any PersistentModel] = [:]
61
+ private var autosaveScheduled = false
62
+ let signal = _ChangeSignal()
63
+
64
+ public init(_ container: ModelContainer) {
65
+ self.container = container
66
+ store = container.store
67
+ store.register(self)
68
+ }
69
+
70
+ public static func == (lhs: ModelContext, rhs: ModelContext) -> Bool { lhs === rhs }
71
+ public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
72
+
73
+ public static let willSave = Notification.Name("SwiftData.ModelContext.willSave")
74
+ public static let didSave = Notification.Name("SwiftData.ModelContext.didSave")
75
+
76
+ // MARK: State
77
+
78
+ public var hasChanges: Bool { !inserted.isEmpty || !changed.isEmpty || !deleted.isEmpty }
79
+
80
+ public var insertedModelsArray: [any PersistentModel] { inserted.compactMap { registered[$0] } }
81
+ public var changedModelsArray: [any PersistentModel] { changed.sorted().compactMap { registered[$0] } }
82
+ public var deletedModelsArray: [any PersistentModel] { deleted.keys.sorted().compactMap { deleted[$0] } }
83
+
84
+ func _hasChanges(_ id: PersistentIdentifier) -> Bool {
85
+ insertedSet.contains(id) || changed.contains(id) || deleted[id] != nil
86
+ }
87
+
88
+ /// Nothing is deferred: changes apply as they are made.
89
+ public func processPendingChanges() {}
90
+
91
+ // MARK: Inserting
92
+
93
+ /// Adds a model to the context, with the models its relationships hold.
94
+ /// It is saved at the next `save()` (or autosave).
95
+ public func insert<T: PersistentModel>(_ model: T) {
96
+ _insert(model)
97
+ }
98
+
99
+ private func _insert(_ model: any PersistentModel) {
100
+ let backing = model.persistentBackingData
101
+ if backing.context === self {
102
+ // A deleted model inserted again is no longer deleted.
103
+ if backing.isDeleted, deleted.removeValue(forKey: backing.identifier) != nil {
104
+ backing.isDeleted = false
105
+ registered[backing.identifier] = model
106
+ noteChange()
107
+ }
108
+ return
109
+ }
110
+ if backing.context != nil {
111
+ print("[SwiftData] a \(backing.entity.name) from another context was inserted; it now belongs to this one")
112
+ }
113
+ backing.context = self
114
+ backing.storeIdentifier = store.identifier
115
+ backing.isDeleted = false
116
+ if let key = backing.primaryKey, store.record(key) != nil {
117
+ // The model was identified before its store opened and took a key
118
+ // a stored record already has.
119
+ backing.primaryKey = _Store.allocatePrimaryKey()
120
+ }
121
+ let id = backing.identifier
122
+ registered[id] = model
123
+ if insertedSet.insert(id).inserted { inserted.append(id) }
124
+ for property in backing.entity.relationships {
125
+ for target in backing.relatedModels(property) {
126
+ _insert(target)
127
+ if let inverse = backing.entity.inverse(of: property) {
128
+ link(target, inverse, to: model)
129
+ }
130
+ }
131
+ }
132
+ noteChange()
133
+ }
134
+
135
+ // MARK: Deleting
136
+
137
+ /// Removes a model from the store at the next save, applying its
138
+ /// relationships' delete rules.
139
+ public func delete<T: PersistentModel>(_ model: T) {
140
+ _delete(model)
141
+ }
142
+
143
+ private func _delete(_ model: any PersistentModel) {
144
+ let backing = model.persistentBackingData
145
+ guard backing.context === self, !backing.isDeleted else { return }
146
+ let id = backing.identifier
147
+ let related = backing.entity.relationships.map { ($0, backing.relatedModels($0)) }
148
+ backing.isDeleted = true
149
+ if insertedSet.remove(id) != nil {
150
+ inserted.removeAll { $0 == id }
151
+ registered[id] = nil
152
+ } else {
153
+ deleted[id] = model
154
+ changed.remove(id)
155
+ registered[id] = nil
156
+ }
157
+ for (property, targets) in related {
158
+ switch property.deleteRule {
159
+ case .cascade:
160
+ for target in targets { _delete(target) }
161
+ case .nullify, .deny:
162
+ guard let inverse = backing.entity.inverse(of: property) else { continue }
163
+ for target in targets where !target.persistentBackingData.isDeleted {
164
+ unlink(target, inverse, from: model)
165
+ }
166
+ case .noAction:
167
+ break
168
+ }
169
+ }
170
+ noteChange()
171
+ }
172
+
173
+ /// Deletes every model of a type that matches the predicate.
174
+ public func delete<T: PersistentModel>(model: T.Type, where predicate: Predicate<T>? = nil, includeSubclasses: Bool = true) throws {
175
+ for item in try fetch(FetchDescriptor<T>(predicate: predicate)) { delete(item) }
176
+ }
177
+
178
+ // MARK: Fetching
179
+
180
+ public func fetch<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [T] {
181
+ var results = try matches(descriptor)
182
+ if !descriptor.sortBy.isEmpty { results.sort(using: descriptor.sortBy) }
183
+ let offset = max(0, descriptor.fetchOffset ?? 0)
184
+ if offset > 0 { results = Array(results.dropFirst(offset)) }
185
+ if let limit = descriptor.fetchLimit, limit >= 0, results.count > limit { results = Array(results.prefix(limit)) }
186
+ return results
187
+ }
188
+
189
+ public func fetch<T: PersistentModel>(_ descriptor: FetchDescriptor<T>, batchSize: Int) throws -> FetchResultsCollection<T> {
190
+ FetchResultsCollection(models: try fetch(descriptor))
191
+ }
192
+
193
+ public func fetchCount<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> Int {
194
+ var count = try matches(descriptor).count
195
+ count = max(0, count - max(0, descriptor.fetchOffset ?? 0))
196
+ if let limit = descriptor.fetchLimit, limit >= 0 { count = min(count, limit) }
197
+ return count
198
+ }
199
+
200
+ public func fetchIdentifiers<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [PersistentIdentifier] {
201
+ try fetch(descriptor).map(\.persistentModelID)
202
+ }
203
+
204
+ public func enumerate<T: PersistentModel>(_ descriptor: FetchDescriptor<T>, batchSize: Int = 5000, allowEscapingMutations: Bool = false, block: (T) throws -> Void) throws {
205
+ for model in try fetch(descriptor) { try block(model) }
206
+ }
207
+
208
+ /// The models of `T` the context can see (saved and, unless the
209
+ /// descriptor says otherwise, inserted), filtered by its predicate.
210
+ private func matches<T: PersistentModel>(_ descriptor: FetchDescriptor<T>) throws -> [T] {
211
+ let entity = _Entity.of(T.self)
212
+ var candidates: [T] = []
213
+ for key in store.keys(of: entity.name) {
214
+ if let model = _model(primaryKey: key, type: T.self) as? T { candidates.append(model) }
215
+ }
216
+ if descriptor.includePendingChanges {
217
+ for id in inserted where id.entityName == entity.name {
218
+ if let model = registered[id] as? T, store.record(id.primaryKey) == nil { candidates.append(model) }
219
+ }
220
+ }
221
+ guard let predicate = descriptor.predicate else { return candidates }
222
+ return try candidates.filter { try predicate.evaluate($0) }
223
+ }
224
+
225
+ /// The live model for a stored record (materialized on first use), or
226
+ /// nil when the record is gone or deleted in this context.
227
+ func _model(primaryKey: Int64, type: any PersistentModel.Type) -> (any PersistentModel)? {
228
+ let entity = _Entity.of(type)
229
+ let id = PersistentIdentifier(entityName: entity.name, storeIdentifier: store.identifier, primaryKey: primaryKey)
230
+ if let model = registered[id] { return model }
231
+ guard deleted[id] == nil, let record = store.record(primaryKey), record.entity == entity.name else { return nil }
232
+ let backing = _ModelBacking(type: type, primaryKey: primaryKey, storeIdentifier: store.identifier, stored: record.values)
233
+ backing.context = self
234
+ let model = type.init(backingData: backing)
235
+ registered[id] = model
236
+ return model
237
+ }
238
+
239
+ /// The model with this identifier, if the context has it or its store
240
+ /// has its record.
241
+ public func registeredModel<T: PersistentModel>(for id: PersistentIdentifier) -> T? {
242
+ registered[id] as? T
243
+ }
244
+
245
+ public func model(for id: PersistentIdentifier) -> any PersistentModel {
246
+ if let model = registered[id] { return model }
247
+ guard let entity = _Entity.byEntityName[id.entityName], let model = _model(primaryKey: id.primaryKey, type: entity.type) else {
248
+ fatalError("SwiftData: no \(id.entityName) with identifier \(id) in this context")
249
+ }
250
+ return model
251
+ }
252
+
253
+ // MARK: Saving
254
+
255
+ /// Writes the context's changes to its store; a persistent store sends
256
+ /// them to the page, which keeps them in IndexedDB.
257
+ public func save() throws {
258
+ guard hasChanges else { return }
259
+ guard container.configurations.first?.allowsSave ?? true else { return }
260
+ var put: [(Int64, _Record)] = []
261
+ var removed: [Int64] = deleted.keys.map(\.primaryKey).sorted()
262
+ var replaced: [any PersistentModel] = []
263
+ let ids = inserted + changed.sorted().filter { !insertedSet.contains($0) }
264
+ for id in ids {
265
+ guard let model = registered[id] else { continue }
266
+ let backing = model.persistentBackingData
267
+ var values: [String: _JSON] = [:]
268
+ for metadata in backing.entity.properties {
269
+ values[metadata.name] = backing.json(of: metadata.property)
270
+ }
271
+ // `@Attribute(.unique)`: a new model whose value a stored record
272
+ // already has replaces that record.
273
+ if insertedSet.contains(id) {
274
+ for unique in backing.entity.uniqueAttributes {
275
+ guard let value = values[unique.name] else { continue }
276
+ for key in store.keys(of: backing.entity.name) where key != id.primaryKey && store.record(key)?.values[unique.name] == value {
277
+ removed.append(key)
278
+ let otherID = PersistentIdentifier(entityName: backing.entity.name, storeIdentifier: store.identifier, primaryKey: key)
279
+ if let other = registered[otherID] { replaced.append(other) }
280
+ }
281
+ }
282
+ }
283
+ put.append((id.primaryKey, _Record(entity: backing.entity.name, values: values)))
284
+ }
285
+ for model in deleted.values { model.persistentBackingData.context = nil }
286
+ for model in replaced {
287
+ let backing = model.persistentBackingData
288
+ backing.isDeleted = true
289
+ registered[backing.identifier] = nil
290
+ backing.context = nil
291
+ }
292
+ // Saved records are read back from the store: a model keeps its live
293
+ // values, and the store's JSON is what a later fetch decodes.
294
+ inserted.removeAll()
295
+ insertedSet.removeAll()
296
+ changed.removeAll()
297
+ deleted.removeAll()
298
+ store.commit(put: put, delete: removed, from: self)
299
+ noteChange(autosave: false)
300
+ }
301
+
302
+ /// Discards unsaved changes: inserted models leave the context, deleted
303
+ /// ones return, and changed ones read their saved values again.
304
+ public func rollback() {
305
+ for id in inserted {
306
+ guard let model = registered.removeValue(forKey: id) else { continue }
307
+ model.persistentBackingData.context = nil
308
+ }
309
+ for (id, model) in deleted where store.record(id.primaryKey) != nil {
310
+ model.persistentBackingData.isDeleted = false
311
+ registered[id] = model
312
+ }
313
+ for id in changed { reload(id) }
314
+ for (id, _) in deleted { reload(id) }
315
+ inserted.removeAll()
316
+ insertedSet.removeAll()
317
+ changed.removeAll()
318
+ deleted.removeAll()
319
+ noteChange(autosave: false)
320
+ }
321
+
322
+ /// Runs `block` and saves.
323
+ public func transaction(block: () throws -> Void) throws {
324
+ try block()
325
+ try save()
326
+ }
327
+
328
+ /// Resets a registered model to its stored record.
329
+ private func reload(_ id: PersistentIdentifier) {
330
+ guard let model = registered[id], let record = store.record(id.primaryKey) else { return }
331
+ let backing = model.persistentBackingData
332
+ backing.slots = record.values.mapValues { .stored($0) }
333
+ for metadata in backing.entity.properties { metadata.property.notify(model) }
334
+ }
335
+
336
+ /// Another context saved to the store: models this context has not
337
+ /// changed take the saved values, deleted records' models leave.
338
+ func _storeDidChange(changed saved: Set<Int64>, deleted removed: Set<Int64>, cleared: Bool) {
339
+ for (id, model) in registered where !insertedSet.contains(id) {
340
+ if cleared || removed.contains(id.primaryKey) {
341
+ registered[id] = nil
342
+ model.persistentBackingData.isDeleted = true
343
+ model.persistentBackingData.context = nil
344
+ changed.remove(id)
345
+ } else if saved.contains(id.primaryKey), !changed.contains(id) {
346
+ reload(id)
347
+ }
348
+ }
349
+ if cleared {
350
+ for (_, model) in deleted { model.persistentBackingData.context = nil }
351
+ deleted.removeAll()
352
+ }
353
+ noteChange(autosave: false)
354
+ }
355
+
356
+ // MARK: Changes
357
+
358
+ /// A persisted attribute of a registered model was set.
359
+ func _modelDidChange(_ model: any PersistentModel) {
360
+ let id = model.persistentModelID
361
+ if !insertedSet.contains(id) { changed.insert(id) }
362
+ noteChange()
363
+ }
364
+
365
+ /// A relationship of `model` changed from `old` to `new`: models it now
366
+ /// holds join the context, and the inverse follows on both sides.
367
+ func _relationship(_ property: _Property, of model: any PersistentModel, changedFrom old: [any PersistentModel], to new: [any PersistentModel]) {
368
+ let inverse = model.persistentBackingData.entity.inverse(of: property)
369
+ for target in new where !old.contains(where: { $0 === target }) {
370
+ _insert(target)
371
+ if let inverse { link(target, inverse, to: model) }
372
+ }
373
+ guard let inverse else { return }
374
+ for target in old where !new.contains(where: { $0 === target }) {
375
+ unlink(target, inverse, from: model)
376
+ }
377
+ }
378
+
379
+ /// Makes `target`'s `inverse` hold `model`.
380
+ private func link(_ target: any PersistentModel, _ inverse: _Property, to model: any PersistentModel) {
381
+ let backing = target.persistentBackingData
382
+ let current = backing.relatedModels(inverse)
383
+ if current.contains(where: { $0 === model }) { return }
384
+ if inverse.kind == .toMany {
385
+ setRaw(target, inverse, inverse.make(current + [model]))
386
+ } else {
387
+ setRaw(target, inverse, inverse.make([model]))
388
+ // A to-one inverse that held another model: that model's side
389
+ // of the relationship lets go of `target`.
390
+ if let previous = current.first, let forward = backing.entity.inverse(of: inverse) {
391
+ unlink(previous, forward, from: target)
392
+ }
393
+ }
394
+ }
395
+
396
+ /// Makes `target`'s `inverse` stop holding `model`.
397
+ private func unlink(_ target: any PersistentModel, _ inverse: _Property, from model: any PersistentModel) {
398
+ let backing = target.persistentBackingData
399
+ let current = backing.relatedModels(inverse)
400
+ guard current.contains(where: { $0 === model }) else { return }
401
+ let remaining = current.filter { $0 !== model }
402
+ if inverse.kind == .toOne, remaining.isEmpty, !inverse.isOptional { return }
403
+ setRaw(target, inverse, inverse.make(remaining))
404
+ }
405
+
406
+ /// Sets a relationship without running its own inverse bookkeeping, and
407
+ /// tells its observers.
408
+ private func setRaw(_ target: any PersistentModel, _ property: _Property, _ value: Any) {
409
+ let backing = target.persistentBackingData
410
+ backing.slots[property.name] = .live(value)
411
+ property.notify(target)
412
+ if backing.context === self, !backing.isDeleted { _modelDidChange(target) }
413
+ }
414
+
415
+ private func noteChange(autosave: Bool = true) {
416
+ signal.generation += 1
417
+ if autosave { scheduleAutosave() }
418
+ }
419
+
420
+ private func scheduleAutosave() {
421
+ guard autosaveEnabled, !autosaveScheduled else { return }
422
+ autosaveScheduled = true
423
+ // Models and contexts belong to the main actor in practice (there is
424
+ // one thread on wasm); the box only carries the context across.
425
+ let box = _UncheckedWeakContext(context: self)
426
+ MainActor.assumeIsolated {
427
+ _Runtime.shared._afterUpdate { box.context?.autosave() }
428
+ }
429
+ }
430
+
431
+ private func autosave() {
432
+ autosaveScheduled = false
433
+ do {
434
+ try save()
435
+ } catch {
436
+ print("[SwiftData] autosave failed: \(error)")
437
+ }
438
+ }
439
+ }
440
+
441
+ private struct _UncheckedWeakContext: @unchecked Sendable {
442
+ weak var context: ModelContext?
443
+ }
444
+
445
+ /// The results of a batched fetch (all of them: the store is in memory).
446
+ public struct FetchResultsCollection<Element: PersistentModel>: RandomAccessCollection {
447
+ let models: [Element]
448
+ public var startIndex: Int { models.startIndex }
449
+ public var endIndex: Int { models.endIndex }
450
+ public subscript(position: Int) -> Element { models[position] }
451
+ }