@swiftbrowser/swift 0.0.0-stage → 0.2.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 +214 -0
- package/README.md +10 -2
- 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 +61 -0
- 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/FoundationBridge/Bundle.swift +119 -0
- 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 +29 -0
- 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/Locale.swift +86 -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 +53 -0
- package/Sources/FoundationBridge/UITextChecker.swift +30 -0
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/FoundationBridge/UserDefaults.swift +183 -0
- 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 +181 -0
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +221 -0
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +285 -0
- package/Sources/SwiftUI/API/App.swift +87 -0
- 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 +237 -0
- 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 +300 -0
- package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +92 -0
- package/Sources/SwiftUI/API/EditMode.swift +212 -0
- package/Sources/SwiftUI/API/Effects.swift +388 -0
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +439 -0
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +137 -0
- package/Sources/SwiftUI/API/Font.swift +131 -0
- package/Sources/SwiftUI/API/Gauge.swift +290 -0
- package/Sources/SwiftUI/API/Geometry.swift +89 -0
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +342 -0
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +188 -0
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
- package/Sources/SwiftUI/API/Layout.swift +220 -0
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +331 -0
- package/Sources/SwiftUI/API/Menu.swift +58 -0
- package/Sources/SwiftUI/API/Modifiers.swift +313 -0
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +386 -0
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
- package/Sources/SwiftUI/API/OnChange.swift +48 -0
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +185 -0
- 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 +122 -0
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +517 -0
- package/Sources/SwiftUI/API/Publishers.swift +107 -0
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +84 -0
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
- 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 +144 -0
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/StrokeStyle.swift +30 -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 +263 -0
- package/Sources/SwiftUI/API/Tasks.swift +35 -0
- 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/Timeline.swift +212 -0
- package/Sources/SwiftUI/API/Toolbar.swift +251 -0
- 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 +215 -0
- package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
- package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +325 -0
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +660 -0
- package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Charts/Marks.swift +204 -0
- package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
- package/Sources/SwiftUI/Charts/Scales.swift +326 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
- package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
- package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
- 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 +2 -0
- package/index.mjs +16 -0
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +30 -4
- package/sync-sources.mjs +33 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/// RFC 8259 parser for `_JSON`. Like the serializer in JSON.swift it uses no
|
|
2
|
+
/// Foundation (see Geometry.swift): it walks the UTF-8 bytes of the input with
|
|
3
|
+
/// an index and builds numbers by hand.
|
|
4
|
+
///
|
|
5
|
+
/// Rejected on purpose: trailing garbage, trailing commas, leading zeros
|
|
6
|
+
/// (`01`), control characters inside strings, unknown escapes, lone UTF-16
|
|
7
|
+
/// surrogates, unterminated input, and nesting deeper than 512 levels (a
|
|
8
|
+
/// recursive parser would otherwise overflow the stack on hostile input).
|
|
9
|
+
|
|
10
|
+
/// Error thrown by `_JSON.parse`. `offset` is the UTF-8 byte offset into the
|
|
11
|
+
/// input at which the problem was detected.
|
|
12
|
+
public struct _JSONParseError: Error, CustomStringConvertible, Sendable {
|
|
13
|
+
public let message: String
|
|
14
|
+
public let offset: Int
|
|
15
|
+
|
|
16
|
+
public init(message: String, offset: Int) {
|
|
17
|
+
self.message = message
|
|
18
|
+
self.offset = offset
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public var description: String { "\(message) at byte offset \(offset)" }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
extension _JSON {
|
|
25
|
+
/// Parses one JSON text. Any number of whitespace characters may surround
|
|
26
|
+
/// the value; anything else before or after it is an error.
|
|
27
|
+
public static func parse(_ text: String) throws(_JSONParseError) -> _JSON {
|
|
28
|
+
var parser = _JSONParser(bytes: Array(text.utf8))
|
|
29
|
+
parser.skipWhitespace()
|
|
30
|
+
let value = try parser.parseValue()
|
|
31
|
+
parser.skipWhitespace()
|
|
32
|
+
if parser.index < parser.bytes.count {
|
|
33
|
+
throw parser.error("unexpected characters after the JSON value")
|
|
34
|
+
}
|
|
35
|
+
return value
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private struct _JSONParser {
|
|
40
|
+
/// Nesting limit for arrays and objects.
|
|
41
|
+
static let maxDepth = 512
|
|
42
|
+
|
|
43
|
+
let bytes: [UInt8]
|
|
44
|
+
var index = 0
|
|
45
|
+
private var depth = 0
|
|
46
|
+
|
|
47
|
+
init(bytes: [UInt8]) {
|
|
48
|
+
self.bytes = bytes
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// MARK: Helpers
|
|
52
|
+
|
|
53
|
+
private var peek: UInt8? { index < bytes.count ? bytes[index] : nil }
|
|
54
|
+
|
|
55
|
+
func error(_ message: String) -> _JSONParseError {
|
|
56
|
+
error(message, at: index)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func error(_ message: String, at offset: Int) -> _JSONParseError {
|
|
60
|
+
_JSONParseError(message: message, offset: offset)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private func endOfInput() -> _JSONParseError {
|
|
64
|
+
error("unexpected end of input", at: bytes.count)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
mutating func skipWhitespace() {
|
|
68
|
+
while index < bytes.count {
|
|
69
|
+
switch bytes[index] {
|
|
70
|
+
case 0x20, 0x09, 0x0A, 0x0D: index += 1 // space, tab, LF, CR
|
|
71
|
+
default: return
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private static func isDigit(_ byte: UInt8) -> Bool {
|
|
77
|
+
byte >= 0x30 && byte <= 0x39 // '0'...'9'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// MARK: Values
|
|
81
|
+
|
|
82
|
+
mutating func parseValue() throws(_JSONParseError) -> _JSON {
|
|
83
|
+
guard let byte = peek else { throw endOfInput() }
|
|
84
|
+
switch byte {
|
|
85
|
+
case 0x7B: // {
|
|
86
|
+
return try parseObject()
|
|
87
|
+
case 0x5B: // [
|
|
88
|
+
return try parseArray()
|
|
89
|
+
case 0x22: // "
|
|
90
|
+
return .string(try parseString())
|
|
91
|
+
case 0x74: // t
|
|
92
|
+
try expectLiteral("true")
|
|
93
|
+
return .bool(true)
|
|
94
|
+
case 0x66: // f
|
|
95
|
+
try expectLiteral("false")
|
|
96
|
+
return .bool(false)
|
|
97
|
+
case 0x6E: // n
|
|
98
|
+
try expectLiteral("null")
|
|
99
|
+
return .null
|
|
100
|
+
case 0x2D, 0x30...0x39: // - or digit
|
|
101
|
+
return .number(try parseNumber())
|
|
102
|
+
default:
|
|
103
|
+
throw error("unexpected character")
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private mutating func expectLiteral(_ literal: StaticString) throws(_JSONParseError) {
|
|
108
|
+
let start = index
|
|
109
|
+
var matched = true
|
|
110
|
+
literal.withUTF8Buffer { expected in
|
|
111
|
+
if index + expected.count > bytes.count {
|
|
112
|
+
matched = false
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
for (offset, byte) in expected.enumerated() where bytes[index + offset] != byte {
|
|
116
|
+
matched = false
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
index += expected.count
|
|
120
|
+
}
|
|
121
|
+
if !matched {
|
|
122
|
+
throw error("invalid literal; expected '\(literal)'", at: start)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// MARK: Containers
|
|
127
|
+
|
|
128
|
+
private mutating func enterContainer() throws(_JSONParseError) {
|
|
129
|
+
depth += 1
|
|
130
|
+
if depth > Self.maxDepth {
|
|
131
|
+
throw error("nesting deeper than \(Self.maxDepth) levels")
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private mutating func parseArray() throws(_JSONParseError) -> _JSON {
|
|
136
|
+
try enterContainer()
|
|
137
|
+
defer { depth -= 1 }
|
|
138
|
+
index += 1 // [
|
|
139
|
+
var items: [_JSON] = []
|
|
140
|
+
skipWhitespace()
|
|
141
|
+
if peek == 0x5D { // ]
|
|
142
|
+
index += 1
|
|
143
|
+
return .array(items)
|
|
144
|
+
}
|
|
145
|
+
while true {
|
|
146
|
+
skipWhitespace()
|
|
147
|
+
items.append(try parseValue())
|
|
148
|
+
skipWhitespace()
|
|
149
|
+
guard let byte = peek else { throw endOfInput() }
|
|
150
|
+
switch byte {
|
|
151
|
+
case 0x2C: // ,
|
|
152
|
+
index += 1
|
|
153
|
+
skipWhitespace()
|
|
154
|
+
if peek == 0x5D { throw error("trailing comma in array") }
|
|
155
|
+
case 0x5D: // ]
|
|
156
|
+
index += 1
|
|
157
|
+
return .array(items)
|
|
158
|
+
default:
|
|
159
|
+
throw error("expected ',' or ']' in array")
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private mutating func parseObject() throws(_JSONParseError) -> _JSON {
|
|
165
|
+
try enterContainer()
|
|
166
|
+
defer { depth -= 1 }
|
|
167
|
+
index += 1 // {
|
|
168
|
+
var members: [String: _JSON] = [:]
|
|
169
|
+
skipWhitespace()
|
|
170
|
+
if peek == 0x7D { // }
|
|
171
|
+
index += 1
|
|
172
|
+
return .object(members)
|
|
173
|
+
}
|
|
174
|
+
while true {
|
|
175
|
+
skipWhitespace()
|
|
176
|
+
guard let byte = peek else { throw endOfInput() }
|
|
177
|
+
guard byte == 0x22 else {
|
|
178
|
+
throw error(peek == 0x7D ? "trailing comma in object" : "expected string key in object")
|
|
179
|
+
}
|
|
180
|
+
let key = try parseString()
|
|
181
|
+
skipWhitespace()
|
|
182
|
+
guard let separator = peek else { throw endOfInput() }
|
|
183
|
+
guard separator == 0x3A else { throw error("expected ':' after object key") } // :
|
|
184
|
+
index += 1
|
|
185
|
+
skipWhitespace()
|
|
186
|
+
members[key] = try parseValue()
|
|
187
|
+
skipWhitespace()
|
|
188
|
+
guard let next = peek else { throw endOfInput() }
|
|
189
|
+
switch next {
|
|
190
|
+
case 0x2C: // ,
|
|
191
|
+
index += 1
|
|
192
|
+
case 0x7D: // }
|
|
193
|
+
index += 1
|
|
194
|
+
return .object(members)
|
|
195
|
+
default:
|
|
196
|
+
throw error("expected ',' or '}' in object")
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// MARK: Strings
|
|
202
|
+
|
|
203
|
+
/// Parses a string starting at the opening quote and returns its contents.
|
|
204
|
+
private mutating func parseString() throws(_JSONParseError) -> String {
|
|
205
|
+
let start = index
|
|
206
|
+
index += 1 // opening quote
|
|
207
|
+
var buffer: [UInt8] = []
|
|
208
|
+
while true {
|
|
209
|
+
// Copy a run of ordinary bytes in one go.
|
|
210
|
+
let runStart = index
|
|
211
|
+
while index < bytes.count {
|
|
212
|
+
let byte = bytes[index]
|
|
213
|
+
if byte == 0x22 || byte == 0x5C || byte < 0x20 { break }
|
|
214
|
+
index += 1
|
|
215
|
+
}
|
|
216
|
+
guard index < bytes.count else {
|
|
217
|
+
throw error("unterminated string", at: start)
|
|
218
|
+
}
|
|
219
|
+
let byte = bytes[index]
|
|
220
|
+
if byte == 0x22 { // closing quote
|
|
221
|
+
index += 1
|
|
222
|
+
if buffer.isEmpty {
|
|
223
|
+
return String(decoding: bytes[runStart..<(index - 1)], as: UTF8.self)
|
|
224
|
+
}
|
|
225
|
+
buffer.append(contentsOf: bytes[runStart..<(index - 1)])
|
|
226
|
+
return String(decoding: buffer, as: UTF8.self)
|
|
227
|
+
}
|
|
228
|
+
buffer.append(contentsOf: bytes[runStart..<index])
|
|
229
|
+
if byte == 0x5C { // backslash
|
|
230
|
+
try parseEscape(into: &buffer)
|
|
231
|
+
} else {
|
|
232
|
+
throw error("control character in string must be escaped")
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/// Parses one escape sequence starting at the backslash.
|
|
238
|
+
private mutating func parseEscape(into buffer: inout [UInt8]) throws(_JSONParseError) {
|
|
239
|
+
let start = index
|
|
240
|
+
index += 1 // backslash
|
|
241
|
+
guard let byte = peek else { throw endOfInput() }
|
|
242
|
+
index += 1
|
|
243
|
+
switch byte {
|
|
244
|
+
case 0x22: buffer.append(0x22) // \"
|
|
245
|
+
case 0x5C: buffer.append(0x5C) // \\
|
|
246
|
+
case 0x2F: buffer.append(0x2F) // \/
|
|
247
|
+
case 0x62: buffer.append(0x08) // \b
|
|
248
|
+
case 0x66: buffer.append(0x0C) // \f
|
|
249
|
+
case 0x6E: buffer.append(0x0A) // \n
|
|
250
|
+
case 0x72: buffer.append(0x0D) // \r
|
|
251
|
+
case 0x74: buffer.append(0x09) // \t
|
|
252
|
+
case 0x75: // \u
|
|
253
|
+
var scalar = try parseHex4()
|
|
254
|
+
if scalar >= 0xD800 && scalar <= 0xDBFF {
|
|
255
|
+
// High surrogate: a low surrogate escape must follow.
|
|
256
|
+
guard index + 1 < bytes.count, bytes[index] == 0x5C, bytes[index + 1] == 0x75 else {
|
|
257
|
+
throw error("high surrogate without a following low surrogate", at: start)
|
|
258
|
+
}
|
|
259
|
+
index += 2
|
|
260
|
+
let low = try parseHex4()
|
|
261
|
+
guard low >= 0xDC00 && low <= 0xDFFF else {
|
|
262
|
+
throw error("invalid low surrogate in escape", at: start)
|
|
263
|
+
}
|
|
264
|
+
scalar = 0x10000 + ((scalar - 0xD800) << 10) + (low - 0xDC00)
|
|
265
|
+
} else if scalar >= 0xDC00 && scalar <= 0xDFFF {
|
|
266
|
+
throw error("lone low surrogate in escape", at: start)
|
|
267
|
+
}
|
|
268
|
+
Self.appendUTF8(scalar, to: &buffer)
|
|
269
|
+
default:
|
|
270
|
+
throw error("invalid escape sequence", at: start)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/// Reads exactly four hex digits.
|
|
275
|
+
private mutating func parseHex4() throws(_JSONParseError) -> UInt32 {
|
|
276
|
+
guard index + 4 <= bytes.count else { throw endOfInput() }
|
|
277
|
+
var value: UInt32 = 0
|
|
278
|
+
for _ in 0..<4 {
|
|
279
|
+
let byte = bytes[index]
|
|
280
|
+
let digit: UInt32
|
|
281
|
+
switch byte {
|
|
282
|
+
case 0x30...0x39: digit = UInt32(byte - 0x30)
|
|
283
|
+
case 0x41...0x46: digit = UInt32(byte - 0x41 + 10)
|
|
284
|
+
case 0x61...0x66: digit = UInt32(byte - 0x61 + 10)
|
|
285
|
+
default: throw error("invalid hex digit in \\u escape")
|
|
286
|
+
}
|
|
287
|
+
value = value << 4 | digit
|
|
288
|
+
index += 1
|
|
289
|
+
}
|
|
290
|
+
return value
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private static func appendUTF8(_ scalar: UInt32, to buffer: inout [UInt8]) {
|
|
294
|
+
if scalar < 0x80 {
|
|
295
|
+
buffer.append(UInt8(scalar))
|
|
296
|
+
} else if scalar < 0x800 {
|
|
297
|
+
buffer.append(0xC0 | UInt8(scalar >> 6))
|
|
298
|
+
buffer.append(0x80 | UInt8(scalar & 0x3F))
|
|
299
|
+
} else if scalar < 0x10000 {
|
|
300
|
+
buffer.append(0xE0 | UInt8(scalar >> 12))
|
|
301
|
+
buffer.append(0x80 | UInt8((scalar >> 6) & 0x3F))
|
|
302
|
+
buffer.append(0x80 | UInt8(scalar & 0x3F))
|
|
303
|
+
} else {
|
|
304
|
+
buffer.append(0xF0 | UInt8(scalar >> 18))
|
|
305
|
+
buffer.append(0x80 | UInt8((scalar >> 12) & 0x3F))
|
|
306
|
+
buffer.append(0x80 | UInt8((scalar >> 6) & 0x3F))
|
|
307
|
+
buffer.append(0x80 | UInt8(scalar & 0x3F))
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// MARK: Numbers
|
|
312
|
+
|
|
313
|
+
/// Powers of ten as correctly rounded literals. Entries 1e0...1e22 are
|
|
314
|
+
/// exactly representable, so for every realistic number (at most 15-16
|
|
315
|
+
/// significant digits, a modest exponent) the single multiplication or
|
|
316
|
+
/// division below yields the correctly rounded Double. Beyond that the
|
|
317
|
+
/// result is within an ulp, which is accurate enough for this use.
|
|
318
|
+
private static let powersOfTen: [Double] = [
|
|
319
|
+
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
|
|
320
|
+
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21,
|
|
321
|
+
1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32,
|
|
322
|
+
1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43,
|
|
323
|
+
1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54,
|
|
324
|
+
1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65,
|
|
325
|
+
1e66, 1e67, 1e68, 1e69, 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76,
|
|
326
|
+
1e77, 1e78, 1e79, 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87,
|
|
327
|
+
1e88, 1e89, 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98,
|
|
328
|
+
1e99, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
|
|
329
|
+
1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 1e120,
|
|
330
|
+
1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131,
|
|
331
|
+
1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142,
|
|
332
|
+
1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151, 1e152, 1e153,
|
|
333
|
+
1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160, 1e161, 1e162, 1e163, 1e164,
|
|
334
|
+
1e165, 1e166, 1e167, 1e168, 1e169, 1e170, 1e171, 1e172, 1e173, 1e174, 1e175,
|
|
335
|
+
1e176, 1e177, 1e178, 1e179, 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186,
|
|
336
|
+
1e187, 1e188, 1e189, 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197,
|
|
337
|
+
1e198, 1e199, 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208,
|
|
338
|
+
1e209, 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
|
|
339
|
+
1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, 1e230,
|
|
340
|
+
1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, 1e240, 1e241,
|
|
341
|
+
1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, 1e250, 1e251, 1e252,
|
|
342
|
+
1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, 1e260, 1e261, 1e262, 1e263,
|
|
343
|
+
1e264, 1e265, 1e266, 1e267, 1e268, 1e269, 1e270, 1e271, 1e272, 1e273, 1e274,
|
|
344
|
+
1e275, 1e276, 1e277, 1e278, 1e279, 1e280, 1e281, 1e282, 1e283, 1e284, 1e285,
|
|
345
|
+
1e286, 1e287, 1e288, 1e289, 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296,
|
|
346
|
+
1e297, 1e298, 1e299, 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307,
|
|
347
|
+
1e308,
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
/// Parses `-?int frac? exp?` into a Double. Up to 19 significant digits
|
|
351
|
+
/// are accumulated exactly in a UInt64; further digits only shift the
|
|
352
|
+
/// decimal exponent. The exponent is then applied with a single
|
|
353
|
+
/// multiplication or division by a power of ten from the table above.
|
|
354
|
+
private mutating func parseNumber() throws(_JSONParseError) -> Double {
|
|
355
|
+
let start = index
|
|
356
|
+
var negative = false
|
|
357
|
+
if peek == 0x2D { // -
|
|
358
|
+
negative = true
|
|
359
|
+
index += 1
|
|
360
|
+
}
|
|
361
|
+
guard let first = peek else { throw endOfInput() }
|
|
362
|
+
guard Self.isDigit(first) else { throw error("expected a digit") }
|
|
363
|
+
|
|
364
|
+
var mantissa: UInt64 = 0
|
|
365
|
+
var exponent = 0 // decimal exponent to apply to the mantissa
|
|
366
|
+
let mantissaLimit: UInt64 = 1_000_000_000_000_000_000 // 1e18; below it, *10+9 fits
|
|
367
|
+
|
|
368
|
+
// Integer part.
|
|
369
|
+
if first == 0x30 {
|
|
370
|
+
index += 1
|
|
371
|
+
if let next = peek, Self.isDigit(next) {
|
|
372
|
+
throw error("leading zeros are not allowed", at: start)
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
while let byte = peek, Self.isDigit(byte) {
|
|
376
|
+
if mantissa < mantissaLimit {
|
|
377
|
+
mantissa = mantissa * 10 + UInt64(byte - 0x30)
|
|
378
|
+
} else {
|
|
379
|
+
exponent += 1
|
|
380
|
+
}
|
|
381
|
+
index += 1
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Fraction.
|
|
386
|
+
if peek == 0x2E { // .
|
|
387
|
+
index += 1
|
|
388
|
+
guard let byte = peek, Self.isDigit(byte) else {
|
|
389
|
+
throw error("expected a digit after the decimal point")
|
|
390
|
+
}
|
|
391
|
+
while let byte = peek, Self.isDigit(byte) {
|
|
392
|
+
if mantissa < mantissaLimit {
|
|
393
|
+
mantissa = mantissa * 10 + UInt64(byte - 0x30)
|
|
394
|
+
exponent -= 1
|
|
395
|
+
}
|
|
396
|
+
index += 1
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Exponent.
|
|
401
|
+
if let byte = peek, byte == 0x65 || byte == 0x45 { // e or E
|
|
402
|
+
index += 1
|
|
403
|
+
var exponentNegative = false
|
|
404
|
+
if peek == 0x2B { // +
|
|
405
|
+
index += 1
|
|
406
|
+
} else if peek == 0x2D { // -
|
|
407
|
+
exponentNegative = true
|
|
408
|
+
index += 1
|
|
409
|
+
}
|
|
410
|
+
guard let digit = peek, Self.isDigit(digit) else {
|
|
411
|
+
throw error("expected a digit in the exponent")
|
|
412
|
+
}
|
|
413
|
+
var explicitExponent = 0
|
|
414
|
+
while let byte = peek, Self.isDigit(byte) {
|
|
415
|
+
// Clamp so absurd exponents cannot overflow Int; the value
|
|
416
|
+
// saturates to infinity or zero below anyway.
|
|
417
|
+
if explicitExponent < 100_000 {
|
|
418
|
+
explicitExponent = explicitExponent * 10 + Int(byte - 0x30)
|
|
419
|
+
}
|
|
420
|
+
index += 1
|
|
421
|
+
}
|
|
422
|
+
exponent += exponentNegative ? -explicitExponent : explicitExponent
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
var value = Double(mantissa)
|
|
426
|
+
if mantissa != 0 {
|
|
427
|
+
if exponent > 308 {
|
|
428
|
+
// Even a mantissa of 1 exceeds Double.greatestFiniteMagnitude.
|
|
429
|
+
value = .infinity
|
|
430
|
+
} else if exponent > 0 {
|
|
431
|
+
value *= Self.powersOfTen[exponent] // may overflow to +infinity
|
|
432
|
+
} else if exponent < -308 {
|
|
433
|
+
// Step down in two divisions; the mantissa has at most 19
|
|
434
|
+
// digits, so anything below 1e-330 underflows to zero.
|
|
435
|
+
let remaining = -exponent - 308
|
|
436
|
+
value = remaining > 22 ? 0 : value / Self.powersOfTen[308] / Self.powersOfTen[remaining]
|
|
437
|
+
} else if exponent < 0 {
|
|
438
|
+
value /= Self.powersOfTen[-exponent]
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return negative ? -value : value
|
|
442
|
+
}
|
|
443
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Lazy rows. SwiftUI builds the rows of a `List` (or `Form`), and of a `LazyVStack` or
|
|
2
|
+
// `LazyHStack`, as they scroll into view: a timeline of a thousand posts
|
|
3
|
+
// mounts the few on screen. Building every row up front made long lists
|
|
4
|
+
// expensive in the browser, in time (each row's body, its elements, the
|
|
5
|
+
// page's layout of them) and in memory, which a phone's browser runs out of.
|
|
6
|
+
//
|
|
7
|
+
// Here a keyed group (`ForEach`, or a modifier spread over one) whose rows
|
|
8
|
+
// are a lazy container's rows mounts its first rows only, followed by a
|
|
9
|
+
// `lazyspacer` element standing for the rest. When the page sees the spacer
|
|
10
|
+
// come near its scroll view's visible area it sends a `lazy` event, and the
|
|
11
|
+
// group mounts the next rows (docs/ops-protocol.md, "Lazy rows"). Rows that
|
|
12
|
+
// were built stay built, as on iOS a row's state survives scrolling away.
|
|
13
|
+
//
|
|
14
|
+
// The rows of a lazy container are its content seen through groups,
|
|
15
|
+
// sections and views with a body of their own: `List { Section {
|
|
16
|
+
// ForEach(...) } }` and `List { TimelineRows() }` are lazy, while a
|
|
17
|
+
// `ForEach` inside a row's own `VStack` is part of that row and is built
|
|
18
|
+
// with it.
|
|
19
|
+
|
|
20
|
+
/// `List`, `Form`, `LazyVStack` and `LazyHStack`: their rows are built lazily.
|
|
21
|
+
protocol _LazyRowsContainer: _TraitBearing {
|
|
22
|
+
var _lazyAxis: Axis { get }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
enum _LazyRows {
|
|
26
|
+
/// Rows a group mounts before its spacer, and the rows each `lazy` event adds.
|
|
27
|
+
static let batch = 12
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// The key of a group's spacer among its rows' keys. Each batch's spacer is a
|
|
31
|
+
/// new element (keyed by the rows before it), so the page watches it afresh:
|
|
32
|
+
/// one still in view after a batch was built asks for the next.
|
|
33
|
+
struct _LazySpacerKey: Hashable {
|
|
34
|
+
let built: Int
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// The rows of a lazy group that are not built yet (`lazyspacer` element).
|
|
38
|
+
struct _LazyRowsSpacer {
|
|
39
|
+
let axis: Axis
|
|
40
|
+
let remaining: Int
|
|
41
|
+
let extend: @MainActor () -> Void
|
|
42
|
+
}
|
|
43
|
+
extension _LazyRowsSpacer: _PrimitiveView {}
|
|
44
|
+
|
|
45
|
+
extension _LazyRowsSpacer: _HostView {
|
|
46
|
+
var _kind: String { "lazyspacer" }
|
|
47
|
+
func _props(in environment: EnvironmentValues) -> _JSON {
|
|
48
|
+
.object([
|
|
49
|
+
"axis": .string(axis == .horizontal ? "horizontal" : "vertical"),
|
|
50
|
+
"remaining": .number(Double(remaining)),
|
|
51
|
+
])
|
|
52
|
+
}
|
|
53
|
+
var _handler: ((_JSON) -> Void)? {
|
|
54
|
+
let extend = extend
|
|
55
|
+
return { _ in MainActor.assumeIsolated { extend() } }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
extension List: _LazyRowsContainer {
|
|
60
|
+
var _lazyAxis: Axis { .vertical }
|
|
61
|
+
}
|
|
62
|
+
/// A `Form` is a grouped list, on iOS as here.
|
|
63
|
+
extension Form: _LazyRowsContainer {
|
|
64
|
+
var _lazyAxis: Axis { .vertical }
|
|
65
|
+
}
|
|
66
|
+
extension LazyVStack: _LazyRowsContainer {
|
|
67
|
+
var _lazyAxis: Axis { .vertical }
|
|
68
|
+
}
|
|
69
|
+
extension LazyHStack: _LazyRowsContainer {
|
|
70
|
+
var _lazyAxis: Axis { .horizontal }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// MARK: - Lazy menus
|
|
74
|
+
|
|
75
|
+
// A `Menu`'s items and a `.contextMenu`'s are built when the menu opens, as
|
|
76
|
+
// on iOS, and dropped when it closes. Until then the `menu` / `contextmenu`
|
|
77
|
+
// element has its label (or content) only and `"deferred": true`; the page
|
|
78
|
+
// sends `{"type": "menu", "id": n, "open": true}` when the viewer opens it,
|
|
79
|
+
// shows the popover once the items arrive, and sends `"open": false` when it
|
|
80
|
+
// closes (docs/ops-protocol.md, "Lazy menus"). A timeline's rows each carry
|
|
81
|
+
// a menu or two: built eagerly they were half of Ice Cubes' page. Headless
|
|
82
|
+
// runs, whose event scripts tap menu items directly, build them eagerly.
|
|
83
|
+
|
|
84
|
+
/// `Menu` and `.contextMenu`: hosts whose items are built only while open.
|
|
85
|
+
protocol _LazyMenuHost: _TraitBearing {
|
|
86
|
+
/// The label (a `Menu`'s, in its `ZStack`) or the content (a context menu's).
|
|
87
|
+
var _menuBase: any View { get }
|
|
88
|
+
var _menuItems: any View { get }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
extension Menu: _LazyMenuHost {
|
|
92
|
+
var _menuBase: any View { ZStack { label } }
|
|
93
|
+
var _menuItems: any View { content }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
extension _ContextMenuView: _LazyMenuHost {
|
|
97
|
+
var _menuBase: any View { content }
|
|
98
|
+
var _menuItems: any View { items }
|
|
99
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Views measured by the page for code that asks for a view's size
|
|
2
|
+
// synchronously: `UIHostingController.sizeThatFits(in:)` (UIKit), which
|
|
3
|
+
// packages call to size SwiftUI views before laying them out themselves
|
|
4
|
+
// (WrappingHStack measures each item this way to break its lines). Swift has
|
|
5
|
+
// no text metrics, so the answer comes from the page, one render late:
|
|
6
|
+
//
|
|
7
|
+
// 1. The first ask for a view finds no measurement: the answer is nil (the
|
|
8
|
+
// hosting controller reports a zero size) and the view joins the pending
|
|
9
|
+
// list.
|
|
10
|
+
// 2. The render that asked also renders the pending views, off screen: as
|
|
11
|
+
// the children of a `layout` element of their own at the root, transparent
|
|
12
|
+
// and not hit-testable. The page measures a `layout` element's children
|
|
13
|
+
// (minimum, ideal and maximum size) and sends them in a `layout` event,
|
|
14
|
+
// as it does for a custom `Layout` (CustomLayout.swift).
|
|
15
|
+
// 3. The event fills the cache and asks for a render in which no body is
|
|
16
|
+
// skipped as unchanged, so the code that measured runs again and finds
|
|
17
|
+
// the sizes (the library keeps them in objects of its own, which only a
|
|
18
|
+
// body that re-runs makes again).
|
|
19
|
+
//
|
|
20
|
+
// A view is known by its reflected description (`String(reflecting:)`): its
|
|
21
|
+
// type and stored values, as SwiftUI's own diffing sees them. Content a body
|
|
22
|
+
// reads from elsewhere (an observable object) is not part of it, so such a
|
|
23
|
+
// view keeps its first measurement. Views are measured in the root's
|
|
24
|
+
// environment, as Apple's hosting controller measures them in its own,
|
|
25
|
+
// without the environment of the view that asks. A view whose description
|
|
26
|
+
// changes on every render (one that stores a new UUID each time) would be
|
|
27
|
+
// measured forever: after a few rounds in a row that only found new views,
|
|
28
|
+
// measurements are still taken but no longer re-render.
|
|
29
|
+
|
|
30
|
+
/// A view's sizes as the page measured them: for a zero, unspecified and infinite proposal.
|
|
31
|
+
struct _MeasuredSizes: Equatable {
|
|
32
|
+
var min: CGSize
|
|
33
|
+
var ideal: CGSize
|
|
34
|
+
var max: CGSize
|
|
35
|
+
|
|
36
|
+
/// The size for `proposal`, as `LayoutSubview.sizeThatFits` answers it.
|
|
37
|
+
func fitting(_ proposal: ProposedViewSize) -> CGSize {
|
|
38
|
+
CGSize(
|
|
39
|
+
width: LayoutSubview.fit(proposal.width, min: min.width, ideal: ideal.width, max: max.width),
|
|
40
|
+
height: LayoutSubview.fit(proposal.height, min: min.height, ideal: ideal.height, max: max.height)
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// The page's measurements of views, by description, and the views waiting for one.
|
|
46
|
+
@MainActor
|
|
47
|
+
public final class _ViewMeasurements {
|
|
48
|
+
public static let shared = _ViewMeasurements()
|
|
49
|
+
|
|
50
|
+
private var sizes: [String: _MeasuredSizes] = [:]
|
|
51
|
+
/// Waiting views, in the order the measuring element renders them.
|
|
52
|
+
private(set) var pending: [(key: String, view: AnyView)] = []
|
|
53
|
+
private var pendingKeys: Set<String> = []
|
|
54
|
+
/// Rounds in a row in which measurements arrived and the render that
|
|
55
|
+
/// followed asked for new views again.
|
|
56
|
+
private var rounds = 0
|
|
57
|
+
static let maxRounds = 4
|
|
58
|
+
/// The runtime that rendered last: the one to render again.
|
|
59
|
+
weak var runtime: _Runtime?
|
|
60
|
+
|
|
61
|
+
init() {}
|
|
62
|
+
|
|
63
|
+
/// The size `view` takes for `proposal`, from the page's measurement;
|
|
64
|
+
/// nil until the page has measured it, and the view is then queued.
|
|
65
|
+
public func size<V: View>(of view: V, fitting proposal: ProposedViewSize) -> CGSize? {
|
|
66
|
+
let key = String(reflecting: view)
|
|
67
|
+
if let measured = sizes[key] { return measured.fitting(proposal) }
|
|
68
|
+
if pendingKeys.insert(key).inserted {
|
|
69
|
+
pending.append((key, AnyView(view)))
|
|
70
|
+
runtime?._scheduleRender()
|
|
71
|
+
}
|
|
72
|
+
return nil
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Records the sizes of the pending views the page measured (`keys`, in order).
|
|
76
|
+
func record(_ measured: [(key: String, sizes: _MeasuredSizes)]) {
|
|
77
|
+
var added = false
|
|
78
|
+
for (key, value) in measured where pendingKeys.contains(key) {
|
|
79
|
+
sizes[key] = value
|
|
80
|
+
pendingKeys.remove(key)
|
|
81
|
+
added = true
|
|
82
|
+
}
|
|
83
|
+
guard added else { return }
|
|
84
|
+
pending.removeAll { sizes[$0.key] != nil }
|
|
85
|
+
rounds += 1
|
|
86
|
+
if rounds <= Self.maxRounds { runtime?._renderEverything() }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Called after a render: a render that asked for nothing new ends the rounds.
|
|
90
|
+
func renderFinished() {
|
|
91
|
+
if pending.isEmpty { rounds = 0 }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// Forgets everything (tests).
|
|
95
|
+
func reset() {
|
|
96
|
+
sizes = [:]
|
|
97
|
+
pending = []
|
|
98
|
+
pendingKeys = []
|
|
99
|
+
rounds = 0
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// The off-screen element that has the pending views measured: a `layout`
|
|
104
|
+
/// element whose children are the views, transparent and not hit-testable.
|
|
105
|
+
struct _MeasuringView: View {
|
|
106
|
+
let entries: [(key: String, view: AnyView)]
|
|
107
|
+
|
|
108
|
+
var body: some View {
|
|
109
|
+
_MeasuringLayout(entries: entries)
|
|
110
|
+
.opacity(0)
|
|
111
|
+
.allowsHitTesting(false)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
struct _MeasuringLayout {
|
|
116
|
+
let entries: [(key: String, view: AnyView)]
|
|
117
|
+
}
|
|
118
|
+
extension _MeasuringLayout: _PrimitiveView {}
|
|
119
|
+
extension _MeasuringLayout: _HostView {
|
|
120
|
+
var _kind: String { "layout" }
|
|
121
|
+
|
|
122
|
+
func _props(in environment: EnvironmentValues) -> _JSON {
|
|
123
|
+
.object(["proposal": .null, "size": .null, "frames": .null])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var _content: [any View] { entries.map(\.view) }
|
|
127
|
+
|
|
128
|
+
var _handler: ((_JSON) -> Void)? {
|
|
129
|
+
let keys = entries.map(\.key)
|
|
130
|
+
return { event in
|
|
131
|
+
// An event for another set of children (a render added views
|
|
132
|
+
// since) is left for the event about the current ones.
|
|
133
|
+
guard let (_, subviews) = _parseLayoutEvent(event), subviews.count == keys.count else { return }
|
|
134
|
+
let measured = zip(keys, subviews).map { key, subview in
|
|
135
|
+
(key: key, sizes: _MeasuredSizes(min: subview.min, ideal: subview.ideal, max: subview.max))
|
|
136
|
+
}
|
|
137
|
+
MainActor.assumeIsolated { _ViewMeasurements.shared.record(measured) }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|