@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.
- package/Package.swift +200 -9
- package/README.md +7 -9
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +0 -4
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +6 -1
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +55 -6
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +1 -1
- package/Sources/SwiftUI/API/AlignmentGuides.swift +68 -0
- package/Sources/SwiftUI/API/Animation.swift +37 -5
- package/Sources/SwiftUI/API/App.swift +31 -1
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +104 -28
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +59 -27
- package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +1 -1
- package/Sources/SwiftUI/API/EditMode.swift +25 -82
- package/Sources/SwiftUI/API/Effects.swift +125 -10
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +100 -9
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +11 -3
- package/Sources/SwiftUI/API/Gauge.swift +26 -10
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +1 -1
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +1 -1
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
- package/Sources/SwiftUI/API/Layout.swift +71 -12
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +61 -6
- package/Sources/SwiftUI/API/Menu.swift +8 -1
- package/Sources/SwiftUI/API/Modifiers.swift +88 -12
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +24 -9
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +14 -4
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +17 -4
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +168 -39
- package/Sources/SwiftUI/API/Publishers.swift +4 -4
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +3 -2
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +86 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +187 -8
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +18 -1
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +148 -4
- package/Sources/SwiftUI/API/Tasks.swift +2 -2
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Toolbar.swift +52 -16
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +46 -2
- package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
- package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +7 -1
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +17 -3
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Localization/Localization.swift +524 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
- package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +1 -1
- package/index.mjs +2 -2
- package/manifest.d.mts +2 -0
- package/manifest.mjs +41 -0
- package/package.json +5 -3
- package/sync-sources.mjs +21 -7
- package/Sources/FoundationLite/Common.swift +0 -3
- package/Sources/FoundationLite/FoundationLite.swift +0 -171
- package/Sources/FoundationLite/Interaction.swift +0 -146
- package/Sources/FoundationLite/Timer.swift +0 -48
- package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
// `DispatchQueue` for the browser. The WASI SDK ships no Dispatch, yet
|
|
2
|
+
// `DispatchQueue.main.async { … }` and `asyncAfter(deadline: .now() + 0.5)`
|
|
3
|
+
// are how much SwiftUI code (and many packages) defer work to the next turn
|
|
4
|
+
// or a moment later. The page has one thread, so every queue is the main
|
|
5
|
+
// queue: work runs on the main actor, in order, from the runtime's executor,
|
|
6
|
+
// and a deadline is a `Task.sleep` (so headless runs stay deterministic, like
|
|
7
|
+
// `Timer` in Timer.swift).
|
|
8
|
+
//
|
|
9
|
+
// The CLI's staging gives the app (and each package built against the shim)
|
|
10
|
+
// typealiases for these names, so a host `check`, where Foundation re-exports
|
|
11
|
+
// Dispatch, type-checks against the same API the browser build has. Work
|
|
12
|
+
// items and groups are here (a group's `notify` runs once everything that
|
|
13
|
+
// entered has left), and memory-pressure sources, which never fire;
|
|
14
|
+
// semaphores and other sources are not (waiting would block the only
|
|
15
|
+
// thread): code that needs them is a compile error in the browser build.
|
|
16
|
+
|
|
17
|
+
import Foundation
|
|
18
|
+
|
|
19
|
+
/// A point in time for `asyncAfter`, on the clock `Task.sleep` uses.
|
|
20
|
+
public struct DispatchTime: Comparable, Hashable, Sendable {
|
|
21
|
+
/// Nanoseconds since the first `now()` of the process.
|
|
22
|
+
public let uptimeNanoseconds: UInt64
|
|
23
|
+
|
|
24
|
+
public init(uptimeNanoseconds: UInt64) {
|
|
25
|
+
self.uptimeNanoseconds = uptimeNanoseconds
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
nonisolated(unsafe) private static let origin = ContinuousClock.now
|
|
29
|
+
|
|
30
|
+
public static func now() -> DispatchTime {
|
|
31
|
+
let elapsed = ContinuousClock.now - origin
|
|
32
|
+
let (seconds, attoseconds) = elapsed.components
|
|
33
|
+
return DispatchTime(uptimeNanoseconds: UInt64(max(0, seconds)) * 1_000_000_000 + UInt64(max(0, attoseconds) / 1_000_000_000))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public static let distantFuture = DispatchTime(uptimeNanoseconds: .max)
|
|
37
|
+
|
|
38
|
+
public static func < (lhs: DispatchTime, rhs: DispatchTime) -> Bool {
|
|
39
|
+
lhs.uptimeNanoseconds < rhs.uptimeNanoseconds
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// The time from this one to `other` (negative when `other` is earlier).
|
|
43
|
+
public func distance(to other: DispatchTime) -> DispatchTimeInterval {
|
|
44
|
+
.nanoseconds(Int(truncatingIfNeeded: Int64(bitPattern: other.uptimeNanoseconds &- uptimeNanoseconds)))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// The time `nanoseconds` later (or earlier), clamped. Public for the CLI's generated operators.
|
|
48
|
+
public func _adding(nanoseconds: Double) -> DispatchTime {
|
|
49
|
+
let sum = Double(uptimeNanoseconds) + nanoseconds
|
|
50
|
+
if sum <= 0 { return DispatchTime(uptimeNanoseconds: 0) }
|
|
51
|
+
if sum >= Double(UInt64.max) { return .distantFuture }
|
|
52
|
+
return DispatchTime(uptimeNanoseconds: UInt64(sum))
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Global, as Dispatch declares them, so that `.now() + 0.5` finds them: the
|
|
57
|
+
// left operand's type comes from the context, too late for a static operator.
|
|
58
|
+
|
|
59
|
+
public func + (time: DispatchTime, seconds: Double) -> DispatchTime {
|
|
60
|
+
time._adding(nanoseconds: seconds * 1_000_000_000)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public func - (time: DispatchTime, seconds: Double) -> DispatchTime {
|
|
64
|
+
time._adding(nanoseconds: -seconds * 1_000_000_000)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public func + (time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime { DispatchTime._plus(time, interval) }
|
|
68
|
+
public func - (time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime { DispatchTime._minus(time, interval) }
|
|
69
|
+
|
|
70
|
+
extension DispatchTime {
|
|
71
|
+
public static func _plus(_ time: DispatchTime, _ interval: DispatchTimeInterval) -> DispatchTime {
|
|
72
|
+
guard let nanoseconds = interval.nanoseconds else { return .distantFuture }
|
|
73
|
+
return time._adding(nanoseconds: nanoseconds)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public static func _minus(_ time: DispatchTime, _ interval: DispatchTimeInterval) -> DispatchTime {
|
|
77
|
+
guard let nanoseconds = interval.nanoseconds else { return DispatchTime(uptimeNanoseconds: 0) }
|
|
78
|
+
return time._adding(nanoseconds: -nanoseconds)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// A duration for `DispatchTime` arithmetic.
|
|
83
|
+
public enum DispatchTimeInterval: Equatable, Sendable {
|
|
84
|
+
case seconds(Int)
|
|
85
|
+
case milliseconds(Int)
|
|
86
|
+
case microseconds(Int)
|
|
87
|
+
case nanoseconds(Int)
|
|
88
|
+
case never
|
|
89
|
+
|
|
90
|
+
var nanoseconds: Double? {
|
|
91
|
+
switch self {
|
|
92
|
+
case .seconds(let n): Double(n) * 1_000_000_000
|
|
93
|
+
case .milliseconds(let n): Double(n) * 1_000_000
|
|
94
|
+
case .microseconds(let n): Double(n) * 1_000
|
|
95
|
+
case .nanoseconds(let n): Double(n)
|
|
96
|
+
case .never: nil
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// A quality of service, accepted and ignored: the page runs everything on one thread.
|
|
102
|
+
public struct DispatchQoS: Equatable, Sendable {
|
|
103
|
+
public enum QoSClass: Equatable, Sendable {
|
|
104
|
+
case background, utility, `default`, userInitiated, userInteractive, unspecified
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public let qosClass: QoSClass
|
|
108
|
+
|
|
109
|
+
public init(qosClass: QoSClass, relativePriority: Int) {
|
|
110
|
+
self.qosClass = qosClass
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public static let background = DispatchQoS(qosClass: .background, relativePriority: 0)
|
|
114
|
+
public static let utility = DispatchQoS(qosClass: .utility, relativePriority: 0)
|
|
115
|
+
public static let `default` = DispatchQoS(qosClass: .default, relativePriority: 0)
|
|
116
|
+
public static let userInitiated = DispatchQoS(qosClass: .userInitiated, relativePriority: 0)
|
|
117
|
+
public static let userInteractive = DispatchQoS(qosClass: .userInteractive, relativePriority: 0)
|
|
118
|
+
public static let unspecified = DispatchQoS(qosClass: .unspecified, relativePriority: 0)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// A queue of work. Every queue runs its work on the main actor, in order.
|
|
122
|
+
public final class DispatchQueue: Sendable {
|
|
123
|
+
public struct Attributes: OptionSet, Sendable {
|
|
124
|
+
public let rawValue: UInt64
|
|
125
|
+
public init(rawValue: UInt64) { self.rawValue = rawValue }
|
|
126
|
+
public static let concurrent = Attributes(rawValue: 1 << 1)
|
|
127
|
+
public static let initiallyInactive = Attributes(rawValue: 1 << 2)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public let label: String
|
|
131
|
+
/// `setSpecific` values, by key.
|
|
132
|
+
private let specifics = _QueueSpecifics()
|
|
133
|
+
|
|
134
|
+
public init(label: String, qos: DispatchQoS = .unspecified, attributes: Attributes = []) {
|
|
135
|
+
self.label = label
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// The queues whose work is running, innermost last: what
|
|
139
|
+
/// `DispatchQueue.getSpecific(key:)` reads. Code outside any queue's work
|
|
140
|
+
/// runs on the main queue.
|
|
141
|
+
nonisolated(unsafe) private static var running: [DispatchQueue] = []
|
|
142
|
+
|
|
143
|
+
/// Runs `work` as this queue's: `getSpecific(key:)` reads this queue's values meanwhile.
|
|
144
|
+
private func running<T>(_ work: () throws -> T) rethrows -> T {
|
|
145
|
+
Self.running.append(self)
|
|
146
|
+
defer { Self.running.removeLast() }
|
|
147
|
+
return try work()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// Stores `value` under `key` on this queue (nil removes it).
|
|
151
|
+
public func setSpecific<T>(key: DispatchSpecificKey<T>, value: T?) {
|
|
152
|
+
specifics.values[ObjectIdentifier(key)] = value.map { $0 as Any }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// The value stored under `key` on this queue.
|
|
156
|
+
public func getSpecific<T>(key: DispatchSpecificKey<T>) -> T? {
|
|
157
|
+
specifics.values[ObjectIdentifier(key)] as? T
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// The value stored under `key` on the queue whose work is running (the
|
|
161
|
+
/// main queue's outside any): how code tells it is already on a queue
|
|
162
|
+
/// (SQLite.swift's connections do before `sync`).
|
|
163
|
+
public static func getSpecific<T>(key: DispatchSpecificKey<T>) -> T? {
|
|
164
|
+
(running.last ?? main).getSpecific(key: key)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public static let main = DispatchQueue(label: "com.apple.main-thread")
|
|
168
|
+
|
|
169
|
+
public static func global(qos: DispatchQoS.QoSClass = .default) -> DispatchQueue {
|
|
170
|
+
main
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// Runs `work` on the next turn of the main actor.
|
|
174
|
+
public func async(execute work: @escaping () -> Void) {
|
|
175
|
+
nonisolated(unsafe) let work = work
|
|
176
|
+
Task { @MainActor in self.running(work) }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// `async(group:qos:flags:execute:)`: the group, QoS and flags are accepted.
|
|
180
|
+
public func async(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping () -> Void) {
|
|
181
|
+
group?.enter()
|
|
182
|
+
nonisolated(unsafe) let work = work
|
|
183
|
+
Task { @MainActor in
|
|
184
|
+
self.running(work)
|
|
185
|
+
group?.leave()
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public func async(execute item: DispatchWorkItem) {
|
|
190
|
+
Task { @MainActor in self.running { item.perform() } }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/// Runs `work` once `deadline` has passed.
|
|
194
|
+
public func asyncAfter(deadline: DispatchTime, execute work: @escaping () -> Void) {
|
|
195
|
+
nonisolated(unsafe) let work = work
|
|
196
|
+
asyncAfter(deadline: deadline, qos: .unspecified, flags: [], execute: { work() })
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public func asyncAfter(deadline: DispatchTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping () -> Void) {
|
|
200
|
+
nonisolated(unsafe) let work = work
|
|
201
|
+
let delay = Self.delay(until: deadline)
|
|
202
|
+
Task { @MainActor in
|
|
203
|
+
if delay > 0 { try? await Task.sleep(for: .seconds(delay)) }
|
|
204
|
+
self.running(work)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
public func asyncAfter(deadline: DispatchTime, execute item: DispatchWorkItem) {
|
|
209
|
+
let delay = Self.delay(until: deadline)
|
|
210
|
+
Task { @MainActor in
|
|
211
|
+
if delay > 0 { try? await Task.sleep(for: .seconds(delay)) }
|
|
212
|
+
self.running { item.perform() }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static func delay(until deadline: DispatchTime) -> Double {
|
|
217
|
+
let now = DispatchTime.now()
|
|
218
|
+
return deadline > now ? Double(deadline.uptimeNanoseconds - now.uptimeNanoseconds) / 1_000_000_000 : 0
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public func sync(execute item: DispatchWorkItem) { running { item.perform() } }
|
|
222
|
+
|
|
223
|
+
public func sync<T>(flags: DispatchWorkItemFlags, execute work: () throws -> T) rethrows -> T {
|
|
224
|
+
try running(work)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// Runs `work` now and returns its result: with one thread, nothing else can be running.
|
|
228
|
+
public func sync<T>(execute work: () throws -> T) rethrows -> T {
|
|
229
|
+
try running(work)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/// A key for `DispatchQueue.setSpecific(key:value:)`; keys compare by identity.
|
|
234
|
+
public final class DispatchSpecificKey<T>: @unchecked Sendable {
|
|
235
|
+
public init() {}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
final class _QueueSpecifics: @unchecked Sendable {
|
|
239
|
+
var values: [ObjectIdentifier: Any] = [:]
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// MARK: - Sources
|
|
243
|
+
|
|
244
|
+
/// A dispatch source. The browser raises no events for the kinds here: a
|
|
245
|
+
/// memory-pressure source never fires (the page cannot tell), and handlers
|
|
246
|
+
/// are kept until the source is cancelled.
|
|
247
|
+
public protocol DispatchSourceProtocol: AnyObject, Sendable {
|
|
248
|
+
func setEventHandler(handler: (@Sendable () -> Void)?)
|
|
249
|
+
func setCancelHandler(handler: (@Sendable () -> Void)?)
|
|
250
|
+
func setRegistrationHandler(handler: (@Sendable () -> Void)?)
|
|
251
|
+
func activate()
|
|
252
|
+
func resume()
|
|
253
|
+
func suspend()
|
|
254
|
+
func cancel()
|
|
255
|
+
var isCancelled: Bool { get }
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
public protocol DispatchSourceMemoryPressure: DispatchSourceProtocol {
|
|
259
|
+
var data: DispatchSource.MemoryPressureEvent { get }
|
|
260
|
+
var mask: DispatchSource.MemoryPressureEvent { get }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public enum DispatchSource {
|
|
264
|
+
public struct MemoryPressureEvent: OptionSet, Sendable {
|
|
265
|
+
public let rawValue: UInt
|
|
266
|
+
public init(rawValue: UInt) { self.rawValue = rawValue }
|
|
267
|
+
public static let normal = MemoryPressureEvent(rawValue: 1 << 0)
|
|
268
|
+
public static let warning = MemoryPressureEvent(rawValue: 1 << 1)
|
|
269
|
+
public static let critical = MemoryPressureEvent(rawValue: 1 << 2)
|
|
270
|
+
public static let all: MemoryPressureEvent = [.normal, .warning, .critical]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
public static func makeMemoryPressureSource(eventMask: MemoryPressureEvent, queue: DispatchQueue? = nil) -> any DispatchSourceMemoryPressure {
|
|
274
|
+
_MemoryPressureSource(mask: eventMask)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// A timer source: once scheduled and resumed, it calls its handler at the
|
|
279
|
+
/// deadline, and every `repeating` interval after that, on the main actor's
|
|
280
|
+
/// clock, the executor's (asyncAfter's).
|
|
281
|
+
public protocol DispatchSourceTimer: DispatchSourceProtocol {
|
|
282
|
+
/// Fires at `deadline`, then every `nanoseconds` (nil: once).
|
|
283
|
+
func _schedule(deadline: DispatchTime, repeatingNanoseconds nanoseconds: Double?)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
extension DispatchSourceTimer {
|
|
287
|
+
public func schedule(deadline: DispatchTime, repeating interval: DispatchTimeInterval = .never, leeway: DispatchTimeInterval = .nanoseconds(0)) {
|
|
288
|
+
_schedule(deadline: deadline, repeatingNanoseconds: interval.nanoseconds.flatMap { $0 > 0 ? $0 : nil })
|
|
289
|
+
}
|
|
290
|
+
public func schedule(deadline: DispatchTime, repeating interval: Double, leeway: DispatchTimeInterval = .nanoseconds(0)) {
|
|
291
|
+
_schedule(deadline: deadline, repeatingNanoseconds: interval > 0 && interval.isFinite ? interval * 1_000_000_000 : nil)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
extension DispatchSource {
|
|
296
|
+
public struct TimerFlags: OptionSet, Sendable {
|
|
297
|
+
public let rawValue: UInt
|
|
298
|
+
public init(rawValue: UInt) { self.rawValue = rawValue }
|
|
299
|
+
public static let strict = TimerFlags(rawValue: 1)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
public static func makeTimerSource(flags: TimerFlags = [], queue: DispatchQueue? = nil) -> any DispatchSourceTimer {
|
|
303
|
+
_TimerSource()
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
final class _TimerSource: DispatchSourceTimer, @unchecked Sendable {
|
|
308
|
+
private var handler: (@Sendable () -> Void)?
|
|
309
|
+
private var cancelHandler: (@Sendable () -> Void)?
|
|
310
|
+
private var deadline: DispatchTime?
|
|
311
|
+
/// Nanoseconds between firings; nil for once.
|
|
312
|
+
private var interval: Double?
|
|
313
|
+
private var task: Task<Void, Never>?
|
|
314
|
+
private var running = false
|
|
315
|
+
private(set) var isCancelled = false
|
|
316
|
+
|
|
317
|
+
func setEventHandler(handler: (@Sendable () -> Void)?) { self.handler = handler }
|
|
318
|
+
func setCancelHandler(handler: (@Sendable () -> Void)?) { cancelHandler = handler }
|
|
319
|
+
func setRegistrationHandler(handler: (@Sendable () -> Void)?) { handler?() }
|
|
320
|
+
|
|
321
|
+
func _schedule(deadline: DispatchTime, repeatingNanoseconds nanoseconds: Double?) {
|
|
322
|
+
self.deadline = deadline
|
|
323
|
+
interval = nanoseconds
|
|
324
|
+
if running { start() }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
func activate() { resume() }
|
|
328
|
+
|
|
329
|
+
func resume() {
|
|
330
|
+
guard !running, !isCancelled else { return }
|
|
331
|
+
running = true
|
|
332
|
+
start()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
func suspend() {
|
|
336
|
+
running = false
|
|
337
|
+
task?.cancel()
|
|
338
|
+
task = nil
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
func cancel() {
|
|
342
|
+
guard !isCancelled else { return }
|
|
343
|
+
isCancelled = true
|
|
344
|
+
suspend()
|
|
345
|
+
handler = nil
|
|
346
|
+
let cancelHandler = self.cancelHandler
|
|
347
|
+
self.cancelHandler = nil
|
|
348
|
+
if let cancelHandler { DispatchQueue.main.async { cancelHandler() } }
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private func start() {
|
|
352
|
+
task?.cancel()
|
|
353
|
+
guard let deadline, deadline != .distantFuture else { return }
|
|
354
|
+
nonisolated(unsafe) let source = self
|
|
355
|
+
task = Task { @MainActor in
|
|
356
|
+
let wait = Double(deadline.uptimeNanoseconds) - Double(DispatchTime.now().uptimeNanoseconds)
|
|
357
|
+
if wait > 0 { try? await Task.sleep(nanoseconds: UInt64(wait)) }
|
|
358
|
+
while !Task.isCancelled {
|
|
359
|
+
source.handler?()
|
|
360
|
+
guard let interval = source.interval else { break }
|
|
361
|
+
try? await Task.sleep(nanoseconds: UInt64(interval))
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
final class _MemoryPressureSource: DispatchSourceMemoryPressure, @unchecked Sendable {
|
|
368
|
+
let mask: DispatchSource.MemoryPressureEvent
|
|
369
|
+
private var handlers: [@Sendable () -> Void] = []
|
|
370
|
+
private(set) var isCancelled = false
|
|
371
|
+
|
|
372
|
+
init(mask: DispatchSource.MemoryPressureEvent) { self.mask = mask }
|
|
373
|
+
|
|
374
|
+
var data: DispatchSource.MemoryPressureEvent { [] }
|
|
375
|
+
func setEventHandler(handler: (@Sendable () -> Void)?) { handlers = handler.map { [$0] } ?? [] }
|
|
376
|
+
func setCancelHandler(handler: (@Sendable () -> Void)?) {}
|
|
377
|
+
func setRegistrationHandler(handler: (@Sendable () -> Void)?) {}
|
|
378
|
+
func activate() {}
|
|
379
|
+
func resume() {}
|
|
380
|
+
func suspend() {}
|
|
381
|
+
func cancel() {
|
|
382
|
+
isCancelled = true
|
|
383
|
+
handlers = []
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// MARK: - Work items and groups
|
|
388
|
+
|
|
389
|
+
public struct DispatchWorkItemFlags: OptionSet, Sendable {
|
|
390
|
+
public let rawValue: UInt
|
|
391
|
+
public init(rawValue: UInt) { self.rawValue = rawValue }
|
|
392
|
+
public static let barrier = DispatchWorkItemFlags(rawValue: 1 << 0)
|
|
393
|
+
public static let detached = DispatchWorkItemFlags(rawValue: 1 << 1)
|
|
394
|
+
public static let assignCurrentContext = DispatchWorkItemFlags(rawValue: 1 << 2)
|
|
395
|
+
public static let noQoS = DispatchWorkItemFlags(rawValue: 1 << 3)
|
|
396
|
+
public static let inheritQoS = DispatchWorkItemFlags(rawValue: 1 << 4)
|
|
397
|
+
public static let enforceQoS = DispatchWorkItemFlags(rawValue: 1 << 5)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/// Work that can be cancelled before it runs.
|
|
401
|
+
public final class DispatchWorkItem: @unchecked Sendable {
|
|
402
|
+
private var block: (() -> Void)?
|
|
403
|
+
public private(set) var isCancelled = false
|
|
404
|
+
|
|
405
|
+
public init(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @escaping @convention(block) () -> Void) {
|
|
406
|
+
self.block = block
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
public func perform() {
|
|
410
|
+
guard !isCancelled else { return }
|
|
411
|
+
block?()
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
public func cancel() {
|
|
415
|
+
isCancelled = true
|
|
416
|
+
block = nil
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/// Returns at once: with one thread, the work ran already or cannot run while this waits.
|
|
420
|
+
public func wait() {}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/// A group of work. `notify` runs once everything entered has left.
|
|
424
|
+
public final class DispatchGroup: @unchecked Sendable {
|
|
425
|
+
private var count = 0
|
|
426
|
+
private var waiting: [() -> Void] = []
|
|
427
|
+
|
|
428
|
+
public init() {}
|
|
429
|
+
|
|
430
|
+
public func enter() { count += 1 }
|
|
431
|
+
|
|
432
|
+
public func leave() {
|
|
433
|
+
count = max(0, count - 1)
|
|
434
|
+
guard count == 0 else { return }
|
|
435
|
+
let ready = waiting
|
|
436
|
+
waiting = []
|
|
437
|
+
for work in ready { work() }
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute work: @escaping () -> Void) {
|
|
441
|
+
nonisolated(unsafe) let work = work
|
|
442
|
+
if count == 0 {
|
|
443
|
+
queue.async(execute: { work() })
|
|
444
|
+
} else {
|
|
445
|
+
waiting.append { queue.async(execute: { work() }) }
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// MARK: - Time constants
|
|
451
|
+
|
|
452
|
+
// Dispatch's (C) time constants, which code multiplies `Task.sleep`
|
|
453
|
+
// durations with (`Task.sleep(nanoseconds: NSEC_PER_SEC / 2)`).
|
|
454
|
+
public let NSEC_PER_SEC: UInt64 = 1_000_000_000
|
|
455
|
+
public let NSEC_PER_MSEC: UInt64 = 1_000_000
|
|
456
|
+
public let NSEC_PER_USEC: UInt64 = 1_000
|
|
457
|
+
public let USEC_PER_SEC: UInt64 = 1_000_000
|
|
458
|
+
public let MSEC_PER_SEC: UInt64 = 1_000
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// SwiftUI's environment values of Foundation types: `locale`, `calendar` and
|
|
2
|
+
// `timeZone`. The SwiftUI shim does not import Foundation, so they are
|
|
3
|
+
// declared here. Each defaults to the current one (the viewer's locale,
|
|
4
|
+
// FoundationBridge/Locale.swift); a view may set them for the views it
|
|
5
|
+
// contains, which read them back. The shim's own texts and formatters do
|
|
6
|
+
// not consult them.
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
private struct LocaleKey: EnvironmentKey {
|
|
12
|
+
static var defaultValue: Locale? { nil }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private struct CalendarKey: EnvironmentKey {
|
|
16
|
+
static var defaultValue: Calendar? { nil }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private struct TimeZoneKey: EnvironmentKey {
|
|
20
|
+
static var defaultValue: TimeZone? { nil }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
extension EnvironmentValues {
|
|
24
|
+
/// The locale views format for: the viewer's unless a view sets one.
|
|
25
|
+
public var locale: Locale {
|
|
26
|
+
get { self[LocaleKey.self] ?? .current }
|
|
27
|
+
set { self[LocaleKey.self] = newValue }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// The calendar views use: the current one unless a view sets one.
|
|
31
|
+
public var calendar: Calendar {
|
|
32
|
+
get { self[CalendarKey.self] ?? .current }
|
|
33
|
+
set { self[CalendarKey.self] = newValue }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// The time zone views use: the current one unless a view sets one.
|
|
37
|
+
public var timeZone: TimeZone {
|
|
38
|
+
get { self[TimeZoneKey.self] ?? .current }
|
|
39
|
+
set { self[TimeZoneKey.self] = newValue }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// `.fileImporter`: the page's file chooser in place of the Files app. It is
|
|
2
|
+
// the photo picker's `pickFiles` host request (docs/ops-protocol.md, "Photos
|
|
3
|
+
// picker"), with an `accept` made from the allowed content types. The
|
|
4
|
+
// chosen files are written to a folder of their own in the app's temporary
|
|
5
|
+
// directory, and `onCompletion` gets their file URLs, which the app reads
|
|
6
|
+
// like any file (no security scope to start: `startAccessingSecurityScopedResource`
|
|
7
|
+
// answers true). A dismissed chooser calls `onCancellation`, if given, and
|
|
8
|
+
// not `onCompletion`, as on iOS. Opening a chooser needs a tap, so set
|
|
9
|
+
// `isPresented` from a button's action.
|
|
10
|
+
|
|
11
|
+
import Foundation
|
|
12
|
+
import SwiftUI
|
|
13
|
+
import UniformTypeIdentifiers
|
|
14
|
+
|
|
15
|
+
/// One file import: what to offer and what to do with the files.
|
|
16
|
+
struct _FileImport {
|
|
17
|
+
let types: [UTType]
|
|
18
|
+
let multiple: Bool
|
|
19
|
+
let completion: @MainActor (Result<[URL], any Error>) -> Void
|
|
20
|
+
let cancellation: (@MainActor () -> Void)?
|
|
21
|
+
|
|
22
|
+
/// The chooser's `accept`: a MIME pattern or an extension per type;
|
|
23
|
+
/// empty (any file) when a type covers all data.
|
|
24
|
+
var accept: String {
|
|
25
|
+
var parts: [String] = []
|
|
26
|
+
for type in types {
|
|
27
|
+
if [UTType.item, .data, .content].contains(type) { return "" }
|
|
28
|
+
if type == .image { parts.append("image/*") }
|
|
29
|
+
else if type == .movie || type == .video || type == .audiovisualContent { parts.append("video/*") }
|
|
30
|
+
else if type == .audio { parts.append("audio/*") }
|
|
31
|
+
else if type == .text || type == .plainText { parts.append("text/*") }
|
|
32
|
+
else if let mime = type.preferredMIMEType { parts.append(mime) }
|
|
33
|
+
else if let ext = type.preferredFilenameExtension { parts.append(".\(ext)") }
|
|
34
|
+
}
|
|
35
|
+
return parts.joined(separator: ",")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@MainActor func run() async {
|
|
39
|
+
let params: _JSON = .object(["accept": .string(accept), "multiple": .bool(multiple)])
|
|
40
|
+
let value: _JSON
|
|
41
|
+
do {
|
|
42
|
+
value = try await _Runtime.shared._hostRequest(kind: "pickFiles", params: params)
|
|
43
|
+
} catch {
|
|
44
|
+
completion(.failure(error))
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
guard case .object(let fields) = value, case .array(let entries)? = fields["items"], !entries.isEmpty else {
|
|
48
|
+
cancellation?()
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
do {
|
|
52
|
+
completion(.success(try entries.map(Self.write)))
|
|
53
|
+
} catch {
|
|
54
|
+
completion(.failure(error))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Writes one chosen file (`{name, data}`) to a new folder in the temporary directory.
|
|
59
|
+
static func write(_ entry: _JSON) throws -> URL {
|
|
60
|
+
guard case .object(let fields) = entry, case .string(let base64)? = fields["data"],
|
|
61
|
+
let data = Data(base64Encoded: base64) else {
|
|
62
|
+
throw CocoaError(.fileReadCorruptFile)
|
|
63
|
+
}
|
|
64
|
+
var name = "file"
|
|
65
|
+
if case .string(let given)? = fields["name"], !given.isEmpty, !given.contains("/") { name = given }
|
|
66
|
+
let folder = FileManager.default.temporaryDirectory.appendingPathComponent("Imports/\(UUID().uuidString)", isDirectory: true)
|
|
67
|
+
try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
|
|
68
|
+
let url = folder.appendingPathComponent(name)
|
|
69
|
+
try data.write(to: url)
|
|
70
|
+
return url
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Opens the chooser when `isPresented` becomes true and sets it back to false once the viewer is done.
|
|
75
|
+
struct _FileImporterPresenter<Content: View>: View {
|
|
76
|
+
let content: Content
|
|
77
|
+
let isPresented: Binding<Bool>
|
|
78
|
+
let fileImport: _FileImport
|
|
79
|
+
|
|
80
|
+
var body: some View {
|
|
81
|
+
let isPresented = isPresented
|
|
82
|
+
nonisolated(unsafe) let fileImport = fileImport
|
|
83
|
+
return content.onChange(of: isPresented.wrappedValue, initial: true) { _, presented in
|
|
84
|
+
guard presented else { return }
|
|
85
|
+
MainActor.assumeIsolated {
|
|
86
|
+
Task { @MainActor in
|
|
87
|
+
await fileImport.run()
|
|
88
|
+
isPresented.wrappedValue = false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
extension View {
|
|
96
|
+
/// Lets the viewer pick one file of `allowedContentTypes`.
|
|
97
|
+
public func fileImporter(isPresented: Binding<Bool>, allowedContentTypes: [UTType],
|
|
98
|
+
onCompletion: @escaping (Result<URL, any Error>) -> Void) -> some View {
|
|
99
|
+
_FileImporterPresenter(content: self, isPresented: isPresented,
|
|
100
|
+
fileImport: _FileImport(types: allowedContentTypes, multiple: false,
|
|
101
|
+
completion: { onCompletion($0.flatMap { urls in .success(urls[0]) }) },
|
|
102
|
+
cancellation: nil))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Lets the viewer pick files of `allowedContentTypes`, several when `allowsMultipleSelection`.
|
|
106
|
+
public func fileImporter(isPresented: Binding<Bool>, allowedContentTypes: [UTType], allowsMultipleSelection: Bool,
|
|
107
|
+
onCompletion: @escaping (Result<[URL], any Error>) -> Void) -> some View {
|
|
108
|
+
_FileImporterPresenter(content: self, isPresented: isPresented,
|
|
109
|
+
fileImport: _FileImport(types: allowedContentTypes, multiple: allowsMultipleSelection,
|
|
110
|
+
completion: { onCompletion($0) }, cancellation: nil))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// As above, with `onCancellation` called when the viewer dismisses the chooser.
|
|
114
|
+
public func fileImporter(isPresented: Binding<Bool>, allowedContentTypes: [UTType], allowsMultipleSelection: Bool,
|
|
115
|
+
onCompletion: @escaping (Result<[URL], any Error>) -> Void,
|
|
116
|
+
onCancellation: @escaping () -> Void) -> some View {
|
|
117
|
+
_FileImporterPresenter(content: self, isPresented: isPresented,
|
|
118
|
+
fileImport: _FileImport(types: allowedContentTypes, multiple: allowsMultipleSelection,
|
|
119
|
+
completion: { onCompletion($0) }, cancellation: { onCancellation() }))
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
extension URL {
|
|
124
|
+
/// True: picked files are plain files of the app's.
|
|
125
|
+
public func startAccessingSecurityScopedResource() -> Bool { true }
|
|
126
|
+
/// Nothing to stop.
|
|
127
|
+
public func stopAccessingSecurityScopedResource() {}
|
|
128
|
+
}
|