@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,718 @@
|
|
|
1
|
+
// `URLSession` for the browser. swift-corelibs Foundation marks `URLSession`,
|
|
2
|
+
// `URLResponse`, `HTTPURLResponse` and friends unavailable on WASI (they moved
|
|
3
|
+
// to FoundationNetworking, which needs libcurl). These types have the same
|
|
4
|
+
// names and the API apps use; a request becomes a `fetch` request op the page
|
|
5
|
+
// performs with the browser's `fetch`, and the answer comes back as a
|
|
6
|
+
// `response` event (see docs/ops-protocol.md, "Phase 13").
|
|
7
|
+
//
|
|
8
|
+
// What the browser's fetch implies: cross-origin servers must allow the page
|
|
9
|
+
// (CORS), cookies follow the browser's rules, and HTTP errors are responses,
|
|
10
|
+
// not thrown errors, as with Foundation's URLSession. Headless runs answer
|
|
11
|
+
// from `SB_RESPONSES` fixtures (see `_Runtime._hostRequest`).
|
|
12
|
+
|
|
13
|
+
import Foundation
|
|
14
|
+
import SwiftUI
|
|
15
|
+
|
|
16
|
+
// MARK: - URLRequest
|
|
17
|
+
|
|
18
|
+
public struct URLRequest: Equatable, Hashable, Sendable {
|
|
19
|
+
public enum CachePolicy: UInt, Sendable {
|
|
20
|
+
case useProtocolCachePolicy = 0
|
|
21
|
+
case reloadIgnoringLocalCacheData = 1
|
|
22
|
+
case reloadIgnoringLocalAndRemoteCacheData = 4
|
|
23
|
+
case returnCacheDataElseLoad = 2
|
|
24
|
+
case returnCacheDataDontLoad = 3
|
|
25
|
+
case reloadRevalidatingCacheData = 5
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public var url: URL?
|
|
29
|
+
public var cachePolicy: CachePolicy
|
|
30
|
+
public var timeoutInterval: TimeInterval
|
|
31
|
+
/// `GET` when nil, as Foundation reads it.
|
|
32
|
+
public var httpMethod: String? = "GET"
|
|
33
|
+
public var allHTTPHeaderFields: [String: String]?
|
|
34
|
+
public var httpBody: Data?
|
|
35
|
+
public var httpShouldHandleCookies = true
|
|
36
|
+
public var allowsCellularAccess = true
|
|
37
|
+
|
|
38
|
+
public init(url: URL, cachePolicy: CachePolicy = .useProtocolCachePolicy, timeoutInterval: TimeInterval = 60) {
|
|
39
|
+
self.url = url
|
|
40
|
+
self.cachePolicy = cachePolicy
|
|
41
|
+
self.timeoutInterval = timeoutInterval
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Header names compare case-insensitively, as in Foundation.
|
|
45
|
+
public func value(forHTTPHeaderField field: String) -> String? {
|
|
46
|
+
allHTTPHeaderFields?.first { $0.key.lowercased() == field.lowercased() }?.value
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public mutating func setValue(_ value: String?, forHTTPHeaderField field: String) {
|
|
50
|
+
var headers = allHTTPHeaderFields ?? [:]
|
|
51
|
+
for key in headers.keys where key.lowercased() == field.lowercased() { headers.removeValue(forKey: key) }
|
|
52
|
+
if let value { headers[field] = value }
|
|
53
|
+
allHTTPHeaderFields = headers.isEmpty ? nil : headers
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public mutating func addValue(_ value: String, forHTTPHeaderField field: String) {
|
|
57
|
+
if let existing = self.value(forHTTPHeaderField: field) {
|
|
58
|
+
setValue("\(existing),\(value)", forHTTPHeaderField: field)
|
|
59
|
+
} else {
|
|
60
|
+
setValue(value, forHTTPHeaderField: field)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// MARK: - Responses
|
|
66
|
+
|
|
67
|
+
/// Equal and hashed by identity, as an `NSObject` is on Apple platforms.
|
|
68
|
+
open class URLResponse: Hashable, CustomStringConvertible, @unchecked Sendable {
|
|
69
|
+
public let url: URL?
|
|
70
|
+
public let mimeType: String?
|
|
71
|
+
public let expectedContentLength: Int64
|
|
72
|
+
public let textEncodingName: String?
|
|
73
|
+
|
|
74
|
+
public init(url: URL, mimeType: String?, expectedContentLength length: Int, textEncodingName name: String?) {
|
|
75
|
+
self.url = url
|
|
76
|
+
self.mimeType = mimeType
|
|
77
|
+
self.expectedContentLength = Int64(length)
|
|
78
|
+
self.textEncodingName = name
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public var suggestedFilename: String? {
|
|
82
|
+
let name = url?.lastPathComponent ?? ""
|
|
83
|
+
return name.isEmpty || name == "/" ? "Unknown" : name
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
open var description: String {
|
|
87
|
+
"<\(type(of: self))> { URL: \(url?.absoluteString ?? "(null)") }"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public static func == (lhs: URLResponse, rhs: URLResponse) -> Bool { lhs === rhs }
|
|
91
|
+
public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public final class HTTPURLResponse: URLResponse, @unchecked Sendable {
|
|
95
|
+
public let statusCode: Int
|
|
96
|
+
/// Header names as the server sent them (lower-cased by the browser).
|
|
97
|
+
public let allHeaderFields: [AnyHashable: Any]
|
|
98
|
+
|
|
99
|
+
public init?(url: URL, statusCode: Int, httpVersion: String?, headerFields: [String: String]?) {
|
|
100
|
+
self.statusCode = statusCode
|
|
101
|
+
var fields: [AnyHashable: Any] = [:]
|
|
102
|
+
for (key, value) in headerFields ?? [:] { fields[key] = value }
|
|
103
|
+
allHeaderFields = fields
|
|
104
|
+
let contentType = headerFields?.first { $0.key.lowercased() == "content-type" }?.value
|
|
105
|
+
let length = headerFields?.first { $0.key.lowercased() == "content-length" }.flatMap { Int($0.value) } ?? -1
|
|
106
|
+
super.init(url: url, mimeType: contentType.map(Self.mimeType(of:)), expectedContentLength: length,
|
|
107
|
+
textEncodingName: contentType.flatMap(Self.charset(of:)))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public func value(forHTTPHeaderField field: String) -> String? {
|
|
111
|
+
for (key, value) in allHeaderFields {
|
|
112
|
+
if let name = key.base as? String, name.lowercased() == field.lowercased() { return value as? String }
|
|
113
|
+
}
|
|
114
|
+
return nil
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public class func localizedString(forStatusCode statusCode: Int) -> String {
|
|
118
|
+
switch statusCode {
|
|
119
|
+
case 200: "no error"
|
|
120
|
+
case 201: "created"
|
|
121
|
+
case 204: "no content"
|
|
122
|
+
case 301: "moved permanently"
|
|
123
|
+
case 302: "found"
|
|
124
|
+
case 304: "not modified"
|
|
125
|
+
case 400: "bad request"
|
|
126
|
+
case 401: "unauthorized"
|
|
127
|
+
case 403: "forbidden"
|
|
128
|
+
case 404: "not found"
|
|
129
|
+
case 405: "method not allowed"
|
|
130
|
+
case 408: "request timeout"
|
|
131
|
+
case 409: "conflict"
|
|
132
|
+
case 429: "too many requests"
|
|
133
|
+
case 500: "internal server error"
|
|
134
|
+
case 502: "bad gateway"
|
|
135
|
+
case 503: "service unavailable"
|
|
136
|
+
case 504: "gateway timeout"
|
|
137
|
+
case 100..<200: "informational"
|
|
138
|
+
case 200..<300: "success"
|
|
139
|
+
case 300..<400: "redirected"
|
|
140
|
+
case 400..<500: "client error"
|
|
141
|
+
case 500..<600: "server error"
|
|
142
|
+
default: "unknown"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private static func mimeType(of contentType: String) -> String {
|
|
147
|
+
_trimmed(String(contentType.split(separator: ";", maxSplits: 1).first ?? ""))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private static func charset(of contentType: String) -> String? {
|
|
151
|
+
for part in contentType.split(separator: ";").dropFirst() {
|
|
152
|
+
let pair = part.split(separator: "=", maxSplits: 1).map { _trimmed(String($0)) }
|
|
153
|
+
if pair.count == 2, pair[0].lowercased() == "charset" { return pair[1].lowercased() }
|
|
154
|
+
}
|
|
155
|
+
return nil
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// MARK: - URLError
|
|
160
|
+
|
|
161
|
+
public struct URLError: Error, Equatable, Hashable, CustomStringConvertible, LocalizedError, Sendable {
|
|
162
|
+
public struct Code: RawRepresentable, Equatable, Hashable, Sendable {
|
|
163
|
+
public let rawValue: Int
|
|
164
|
+
public init(rawValue: Int) { self.rawValue = rawValue }
|
|
165
|
+
|
|
166
|
+
public static let unknown = Code(rawValue: -1)
|
|
167
|
+
public static let cancelled = Code(rawValue: -999)
|
|
168
|
+
public static let badURL = Code(rawValue: -1000)
|
|
169
|
+
public static let timedOut = Code(rawValue: -1001)
|
|
170
|
+
public static let unsupportedURL = Code(rawValue: -1002)
|
|
171
|
+
public static let cannotFindHost = Code(rawValue: -1003)
|
|
172
|
+
public static let cannotConnectToHost = Code(rawValue: -1004)
|
|
173
|
+
public static let networkConnectionLost = Code(rawValue: -1005)
|
|
174
|
+
public static let dnsLookupFailed = Code(rawValue: -1006)
|
|
175
|
+
public static let resourceUnavailable = Code(rawValue: -1008)
|
|
176
|
+
public static let notConnectedToInternet = Code(rawValue: -1009)
|
|
177
|
+
public static let badServerResponse = Code(rawValue: -1011)
|
|
178
|
+
public static let userCancelledAuthentication = Code(rawValue: -1012)
|
|
179
|
+
public static let zeroByteResource = Code(rawValue: -1014)
|
|
180
|
+
public static let cannotDecodeRawData = Code(rawValue: -1015)
|
|
181
|
+
public static let cannotDecodeContentData = Code(rawValue: -1016)
|
|
182
|
+
public static let cannotParseResponse = Code(rawValue: -1017)
|
|
183
|
+
public static let internationalRoamingOff = Code(rawValue: -1018)
|
|
184
|
+
public static let callIsActive = Code(rawValue: -1019)
|
|
185
|
+
public static let dataNotAllowed = Code(rawValue: -1020)
|
|
186
|
+
public static let secureConnectionFailed = Code(rawValue: -1200)
|
|
187
|
+
public static let cannotLoadFromNetwork = Code(rawValue: -2000)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public static let errorDomain = "NSURLErrorDomain"
|
|
191
|
+
|
|
192
|
+
public let code: Code
|
|
193
|
+
public let userInfo: [String: any Sendable]
|
|
194
|
+
|
|
195
|
+
public init(_ code: Code, userInfo: [String: any Sendable] = [:]) {
|
|
196
|
+
self.code = code
|
|
197
|
+
self.userInfo = userInfo
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public var errorCode: Int { code.rawValue }
|
|
201
|
+
public var failingURL: URL? { userInfo["NSErrorFailingURLKey"] as? URL }
|
|
202
|
+
|
|
203
|
+
public var errorDescription: String? { description }
|
|
204
|
+
public var localizedDescription: String { description }
|
|
205
|
+
|
|
206
|
+
public var description: String {
|
|
207
|
+
if let message = userInfo["NSLocalizedDescription"] as? String { return message }
|
|
208
|
+
switch code {
|
|
209
|
+
case .cancelled: return "cancelled"
|
|
210
|
+
case .badURL: return "unsupported URL"
|
|
211
|
+
case .timedOut: return "The request timed out."
|
|
212
|
+
case .unsupportedURL: return "unsupported URL"
|
|
213
|
+
case .cannotFindHost: return "A server with the specified hostname could not be found."
|
|
214
|
+
case .cannotConnectToHost: return "Could not connect to the server."
|
|
215
|
+
case .networkConnectionLost: return "The network connection was lost."
|
|
216
|
+
case .notConnectedToInternet: return "The Internet connection appears to be offline."
|
|
217
|
+
case .badServerResponse: return "The server returned a bad response."
|
|
218
|
+
case .cannotDecodeContentData, .cannotDecodeRawData: return "The data could not be decoded."
|
|
219
|
+
case .cannotParseResponse: return "The response could not be parsed."
|
|
220
|
+
case .secureConnectionFailed: return "An SSL error has occurred and a secure connection to the server cannot be made."
|
|
221
|
+
case .cannotLoadFromNetwork: return "The resource could not be loaded from the network."
|
|
222
|
+
default: return "The operation couldn't be completed. (NSURLErrorDomain error \(code.rawValue).)"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public static func == (lhs: URLError, rhs: URLError) -> Bool { lhs.code == rhs.code }
|
|
227
|
+
public func hash(into hasher: inout Hasher) { hasher.combine(code) }
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// MARK: - Configuration and delegates
|
|
231
|
+
|
|
232
|
+
// Apple declares the delegate methods `@objc optional`, which Swift has
|
|
233
|
+
// only with the Objective-C runtime. Here they are requirements with
|
|
234
|
+
// default implementations that do what URLSession does when a delegate does
|
|
235
|
+
// not implement one (allow the response, follow the redirect, handle the
|
|
236
|
+
// challenge by default, cache the response). The CLI's staging turns the
|
|
237
|
+
// optional calls `delegate?.urlSession?(…)` into `delegate?.urlSession(…)`.
|
|
238
|
+
|
|
239
|
+
public protocol URLSessionDelegate: AnyObject, Sendable {
|
|
240
|
+
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: (any Error)?)
|
|
241
|
+
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
|
|
242
|
+
completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
extension URLSessionDelegate {
|
|
246
|
+
public func urlSession(_ session: URLSession, didBecomeInvalidWithError error: (any Error)?) {}
|
|
247
|
+
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge,
|
|
248
|
+
completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
|
|
249
|
+
completionHandler(.performDefaultHandling, nil)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public protocol URLSessionTaskDelegate: URLSessionDelegate {
|
|
254
|
+
func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask)
|
|
255
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: (any Error)?)
|
|
256
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics)
|
|
257
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse,
|
|
258
|
+
newRequest request: URLRequest, completionHandler: @escaping @Sendable (URLRequest?) -> Void)
|
|
259
|
+
func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask)
|
|
260
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge,
|
|
261
|
+
completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
|
|
262
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest,
|
|
263
|
+
completionHandler: @escaping @Sendable (URLSession.DelayedRequestDisposition, URLRequest?) -> Void)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
extension URLSessionTaskDelegate {
|
|
267
|
+
public func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) {}
|
|
268
|
+
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: (any Error)?) {}
|
|
269
|
+
public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {}
|
|
270
|
+
public func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse,
|
|
271
|
+
newRequest request: URLRequest, completionHandler: @escaping @Sendable (URLRequest?) -> Void) {
|
|
272
|
+
completionHandler(request)
|
|
273
|
+
}
|
|
274
|
+
public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {}
|
|
275
|
+
public func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge,
|
|
276
|
+
completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
|
|
277
|
+
completionHandler(.performDefaultHandling, nil)
|
|
278
|
+
}
|
|
279
|
+
public func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest,
|
|
280
|
+
completionHandler: @escaping @Sendable (URLSession.DelayedRequestDisposition, URLRequest?) -> Void) {
|
|
281
|
+
completionHandler(.continueLoading, nil)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public protocol URLSessionDataDelegate: URLSessionTaskDelegate {
|
|
286
|
+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse,
|
|
287
|
+
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
|
|
288
|
+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
|
|
289
|
+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse,
|
|
290
|
+
completionHandler: @escaping @Sendable (CachedURLResponse?) -> Void)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
extension URLSessionDataDelegate {
|
|
294
|
+
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse,
|
|
295
|
+
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
|
296
|
+
completionHandler(.allow)
|
|
297
|
+
}
|
|
298
|
+
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
|
|
299
|
+
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse,
|
|
300
|
+
completionHandler: @escaping @Sendable (CachedURLResponse?) -> Void) {
|
|
301
|
+
completionHandler(proposedResponse)
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/// A server's request for credentials. The browser handles authentication
|
|
306
|
+
/// itself, so a session never asks; the types exist for delegates' signatures.
|
|
307
|
+
public final class URLAuthenticationChallenge: @unchecked Sendable {
|
|
308
|
+
public let protectionSpace: URLProtectionSpace
|
|
309
|
+
public let proposedCredential: URLCredential?
|
|
310
|
+
public let previousFailureCount: Int
|
|
311
|
+
|
|
312
|
+
public init(protectionSpace: URLProtectionSpace, proposedCredential: URLCredential?, previousFailureCount: Int) {
|
|
313
|
+
self.protectionSpace = protectionSpace
|
|
314
|
+
self.proposedCredential = proposedCredential
|
|
315
|
+
self.previousFailureCount = previousFailureCount
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
public final class URLProtectionSpace: @unchecked Sendable {
|
|
320
|
+
public let host: String
|
|
321
|
+
public let port: Int
|
|
322
|
+
public let `protocol`: String?
|
|
323
|
+
public let realm: String?
|
|
324
|
+
public let authenticationMethod: String
|
|
325
|
+
|
|
326
|
+
public init(host: String, port: Int, protocol: String?, realm: String?, authenticationMethod: String?) {
|
|
327
|
+
self.host = host
|
|
328
|
+
self.port = port
|
|
329
|
+
self.protocol = `protocol`
|
|
330
|
+
self.realm = realm
|
|
331
|
+
self.authenticationMethod = authenticationMethod ?? "NSURLAuthenticationMethodDefault"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
public final class URLCredential: @unchecked Sendable {
|
|
336
|
+
public enum Persistence: UInt, Sendable { case none, forSession, permanent, synchronizable }
|
|
337
|
+
|
|
338
|
+
public let user: String?
|
|
339
|
+
public let password: String?
|
|
340
|
+
public let persistence: Persistence
|
|
341
|
+
public var hasPassword: Bool { password != nil }
|
|
342
|
+
|
|
343
|
+
public init(user: String, password: String, persistence: Persistence) {
|
|
344
|
+
self.user = user
|
|
345
|
+
self.password = password
|
|
346
|
+
self.persistence = persistence
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// Timing of a task. The browser does not report it: one transaction, no timings.
|
|
351
|
+
public final class URLSessionTaskMetrics: @unchecked Sendable {
|
|
352
|
+
public let taskInterval: DateInterval
|
|
353
|
+
public let redirectCount: Int
|
|
354
|
+
public let transactionMetrics: [Any]
|
|
355
|
+
|
|
356
|
+
init(start: Date) {
|
|
357
|
+
taskInterval = DateInterval(start: start, end: Date())
|
|
358
|
+
redirectCount = 0
|
|
359
|
+
transactionMetrics = []
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// A response with its body, as a cache stores it.
|
|
364
|
+
public final class CachedURLResponse: @unchecked Sendable {
|
|
365
|
+
public enum StoragePolicy: UInt, Sendable { case allowed, allowedInMemoryOnly, notAllowed }
|
|
366
|
+
|
|
367
|
+
public let response: URLResponse
|
|
368
|
+
public let data: Data
|
|
369
|
+
public let userInfo: [AnyHashable: Any]?
|
|
370
|
+
public let storagePolicy: StoragePolicy
|
|
371
|
+
|
|
372
|
+
public init(response: URLResponse, data: Data, userInfo: [AnyHashable: Any]? = nil, storagePolicy: StoragePolicy = .allowed) {
|
|
373
|
+
self.response = response
|
|
374
|
+
self.data = data
|
|
375
|
+
self.userInfo = userInfo
|
|
376
|
+
self.storagePolicy = storagePolicy
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/// The HTTP cache: the browser's, which every `fetch` goes through. This
|
|
381
|
+
/// object only records its capacities; it stores nothing itself.
|
|
382
|
+
public final class URLCache: @unchecked Sendable {
|
|
383
|
+
nonisolated(unsafe) public static var shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
|
|
384
|
+
|
|
385
|
+
public var memoryCapacity: Int
|
|
386
|
+
public var diskCapacity: Int
|
|
387
|
+
public var currentMemoryUsage: Int { 0 }
|
|
388
|
+
public var currentDiskUsage: Int { 0 }
|
|
389
|
+
|
|
390
|
+
public init(memoryCapacity: Int, diskCapacity: Int, diskPath path: String?) {
|
|
391
|
+
self.memoryCapacity = memoryCapacity
|
|
392
|
+
self.diskCapacity = diskCapacity
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
public init(memoryCapacity: Int, diskCapacity: Int, directory: URL? = nil) {
|
|
396
|
+
self.memoryCapacity = memoryCapacity
|
|
397
|
+
self.diskCapacity = diskCapacity
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
public func cachedResponse(for request: URLRequest) -> CachedURLResponse? { nil }
|
|
401
|
+
public func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) {}
|
|
402
|
+
public func removeCachedResponse(for request: URLRequest) {}
|
|
403
|
+
public func removeAllCachedResponses() {}
|
|
404
|
+
public func removeCachedResponses(since date: Date) {}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
public final class URLSessionConfiguration: @unchecked Sendable {
|
|
408
|
+
public static var `default`: URLSessionConfiguration { URLSessionConfiguration() }
|
|
409
|
+
public static var ephemeral: URLSessionConfiguration { URLSessionConfiguration() }
|
|
410
|
+
public static func background(withIdentifier identifier: String) -> URLSessionConfiguration { URLSessionConfiguration() }
|
|
411
|
+
|
|
412
|
+
public var timeoutIntervalForRequest: TimeInterval = 60
|
|
413
|
+
public var timeoutIntervalForResource: TimeInterval = 7 * 24 * 60 * 60
|
|
414
|
+
public var httpAdditionalHeaders: [AnyHashable: Any]?
|
|
415
|
+
public var requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy
|
|
416
|
+
public var waitsForConnectivity = false
|
|
417
|
+
public var allowsCellularAccess = true
|
|
418
|
+
public var httpShouldSetCookies = true
|
|
419
|
+
public var httpMaximumConnectionsPerHost = 6
|
|
420
|
+
public var urlCache: URLCache? = .shared
|
|
421
|
+
|
|
422
|
+
public init() {}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// MARK: - Tasks
|
|
426
|
+
|
|
427
|
+
open class URLSessionTask: Hashable, @unchecked Sendable {
|
|
428
|
+
public enum State: Int, Sendable { case running, suspended, canceling, completed }
|
|
429
|
+
|
|
430
|
+
public let taskIdentifier: Int
|
|
431
|
+
public let originalRequest: URLRequest?
|
|
432
|
+
public private(set) var state: State = .suspended
|
|
433
|
+
public var taskDescription: String?
|
|
434
|
+
public var priority: Float = 0.5
|
|
435
|
+
/// Accepted: the browser hands over the whole body at once.
|
|
436
|
+
public var prefersIncrementalDelivery = true
|
|
437
|
+
public var currentRequest: URLRequest? { originalRequest }
|
|
438
|
+
public internal(set) var countOfBytesReceived: Int64 = 0
|
|
439
|
+
public var countOfBytesExpectedToReceive: Int64 { response?.expectedContentLength ?? -1 }
|
|
440
|
+
|
|
441
|
+
public static func == (lhs: URLSessionTask, rhs: URLSessionTask) -> Bool { lhs === rhs }
|
|
442
|
+
public func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
|
|
443
|
+
public private(set) var response: URLResponse?
|
|
444
|
+
public private(set) var error: (any Error)?
|
|
445
|
+
|
|
446
|
+
private let work: @MainActor @Sendable (URLSessionTask) async -> Void
|
|
447
|
+
private var running: Task<Void, Never>?
|
|
448
|
+
|
|
449
|
+
init(identifier: Int, request: URLRequest?, work: @escaping @MainActor @Sendable (URLSessionTask) async -> Void) {
|
|
450
|
+
taskIdentifier = identifier
|
|
451
|
+
originalRequest = request
|
|
452
|
+
self.work = work
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/// Starts the request; the completion handler runs on the main actor
|
|
456
|
+
/// (Wasm is single-threaded) once the host answers.
|
|
457
|
+
public func resume() {
|
|
458
|
+
guard state == .suspended else { return }
|
|
459
|
+
state = .running
|
|
460
|
+
running = Task { @MainActor [self] in await work(self) }
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
open func cancel() {
|
|
464
|
+
guard state == .running || state == .suspended else { return }
|
|
465
|
+
state = .canceling
|
|
466
|
+
running?.cancel()
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
public func suspend() {}
|
|
470
|
+
|
|
471
|
+
func receive(response: URLResponse) {
|
|
472
|
+
self.response = response
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
func finish(response: URLResponse?, error: (any Error)?) {
|
|
476
|
+
self.response = response
|
|
477
|
+
self.error = error
|
|
478
|
+
state = .completed
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
public final class URLSessionDataTask: URLSessionTask, @unchecked Sendable {}
|
|
483
|
+
public final class URLSessionUploadTask: URLSessionTask, @unchecked Sendable {}
|
|
484
|
+
|
|
485
|
+
// MARK: - URLSession
|
|
486
|
+
|
|
487
|
+
public final class URLSession: @unchecked Sendable {
|
|
488
|
+
nonisolated(unsafe) public static let shared = URLSession(configuration: .default)
|
|
489
|
+
|
|
490
|
+
public let configuration: URLSessionConfiguration
|
|
491
|
+
public var sessionDescription: String?
|
|
492
|
+
/// Retained until the session is invalidated, as URLSession does.
|
|
493
|
+
public private(set) var delegate: (any URLSessionDelegate)?
|
|
494
|
+
/// Where delegate methods run (all on the main actor).
|
|
495
|
+
public let delegateQueue: OperationQueue
|
|
496
|
+
private var nextTaskIdentifier = 1
|
|
497
|
+
|
|
498
|
+
public init(configuration: URLSessionConfiguration) {
|
|
499
|
+
self.configuration = configuration
|
|
500
|
+
self.delegateQueue = OperationQueue()
|
|
501
|
+
delegateQueue.maxConcurrentOperationCount = 1
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
public init(configuration: URLSessionConfiguration, delegate: (any URLSessionDelegate)?, delegateQueue: OperationQueue?) {
|
|
505
|
+
self.configuration = configuration
|
|
506
|
+
self.delegate = delegate
|
|
507
|
+
self.delegateQueue = delegateQueue ?? OperationQueue()
|
|
508
|
+
if delegateQueue == nil { self.delegateQueue.maxConcurrentOperationCount = 1 }
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
public func finishTasksAndInvalidate() { invalidate(nil) }
|
|
512
|
+
public func invalidateAndCancel() { invalidate(nil) }
|
|
513
|
+
|
|
514
|
+
private func invalidate(_ error: (any Error)?) {
|
|
515
|
+
guard let delegate else { return }
|
|
516
|
+
self.delegate = nil
|
|
517
|
+
delegateQueue.addOperation { delegate.urlSession(self, didBecomeInvalidWithError: error) }
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// MARK: Swift concurrency
|
|
521
|
+
|
|
522
|
+
// Apple declares the forms without a delegate too (iOS 15); a protocol
|
|
523
|
+
// that requires `data(from:)` finds them.
|
|
524
|
+
public func data(from url: URL) async throws -> (Data, URLResponse) {
|
|
525
|
+
try await data(from: url, delegate: nil)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
public func data(for request: URLRequest) async throws -> (Data, URLResponse) {
|
|
529
|
+
try await data(for: request, delegate: nil)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
public func data(from url: URL, delegate: (any URLSessionTaskDelegate)? = nil) async throws -> (Data, URLResponse) {
|
|
533
|
+
try await data(for: URLRequest(url: url))
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
public func data(for request: URLRequest, delegate: (any URLSessionTaskDelegate)? = nil) async throws -> (Data, URLResponse) {
|
|
537
|
+
try await perform(request, body: request.httpBody)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
public func upload(for request: URLRequest, from bodyData: Data, delegate: (any URLSessionTaskDelegate)? = nil) async throws -> (Data, URLResponse) {
|
|
541
|
+
var request = request
|
|
542
|
+
if request.httpMethod == nil || request.httpMethod == "GET" { request.httpMethod = "POST" }
|
|
543
|
+
return try await perform(request, body: bodyData)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// MARK: Completion handlers
|
|
547
|
+
|
|
548
|
+
public func dataTask(with url: URL, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> URLSessionDataTask {
|
|
549
|
+
dataTask(with: URLRequest(url: url), completionHandler: completionHandler)
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
public func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> URLSessionDataTask {
|
|
553
|
+
let task = URLSessionDataTask(identifier: takeIdentifier(), request: request) { [self] task in
|
|
554
|
+
do {
|
|
555
|
+
let (data, response) = try await perform(request, body: request.httpBody)
|
|
556
|
+
task.finish(response: response, error: nil)
|
|
557
|
+
completionHandler(data, response, nil)
|
|
558
|
+
} catch {
|
|
559
|
+
let failure: any Error = Task.isCancelled ? URLError(.cancelled) : error
|
|
560
|
+
task.finish(response: nil, error: failure)
|
|
561
|
+
completionHandler(nil, nil, failure)
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return task
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// MARK: Delegate tasks
|
|
568
|
+
|
|
569
|
+
public func dataTask(with url: URL) -> URLSessionDataTask {
|
|
570
|
+
dataTask(with: URLRequest(url: url))
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/// A task that reports to the session's delegate: the response (which the
|
|
574
|
+
/// delegate may cancel), the body in one piece, then completion.
|
|
575
|
+
public func dataTask(with request: URLRequest) -> URLSessionDataTask {
|
|
576
|
+
let started = Date()
|
|
577
|
+
let task = URLSessionDataTask(identifier: takeIdentifier(), request: request) { [self] task in
|
|
578
|
+
let dataTask = task as! URLSessionDataTask
|
|
579
|
+
let delegate = self.delegate
|
|
580
|
+
do {
|
|
581
|
+
let (data, response) = try await perform(request, body: request.httpBody)
|
|
582
|
+
if Task.isCancelled { throw URLError(.cancelled) }
|
|
583
|
+
task.receive(response: response)
|
|
584
|
+
let disposition: ResponseDisposition = await withCheckedContinuation { continuation in
|
|
585
|
+
nonisolated(unsafe) let resume = continuation
|
|
586
|
+
self.delegateQueue.addOperation {
|
|
587
|
+
guard let delegate = delegate as? any URLSessionDataDelegate else { return resume.resume(returning: .allow) }
|
|
588
|
+
var answered = false
|
|
589
|
+
delegate.urlSession(self, dataTask: dataTask, didReceive: response) { disposition in
|
|
590
|
+
guard !answered else { return }
|
|
591
|
+
answered = true
|
|
592
|
+
resume.resume(returning: disposition)
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
guard disposition == .allow, !Task.isCancelled else { throw URLError(.cancelled) }
|
|
597
|
+
task.countOfBytesReceived = Int64(data.count)
|
|
598
|
+
task.finish(response: response, error: nil)
|
|
599
|
+
delegateQueue.addOperation {
|
|
600
|
+
guard let delegate = delegate as? any URLSessionTaskDelegate else { return }
|
|
601
|
+
if !data.isEmpty { (delegate as? any URLSessionDataDelegate)?.urlSession(self, dataTask: dataTask, didReceive: data) }
|
|
602
|
+
delegate.urlSession(self, task: dataTask, didFinishCollecting: URLSessionTaskMetrics(start: started))
|
|
603
|
+
delegate.urlSession(self, task: dataTask, didCompleteWithError: nil)
|
|
604
|
+
}
|
|
605
|
+
} catch {
|
|
606
|
+
let failure: any Error = Task.isCancelled ? URLError(.cancelled) : error
|
|
607
|
+
task.finish(response: task.response, error: failure)
|
|
608
|
+
delegateQueue.addOperation {
|
|
609
|
+
(delegate as? any URLSessionTaskDelegate)?.urlSession(self, task: dataTask, didCompleteWithError: failure)
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if let delegate = delegate as? any URLSessionTaskDelegate {
|
|
614
|
+
delegateQueue.addOperation { delegate.urlSession(self, didCreateTask: task) }
|
|
615
|
+
}
|
|
616
|
+
return task
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
public enum ResponseDisposition: Int, Sendable { case cancel, allow, becomeDownload, becomeStream }
|
|
620
|
+
public enum AuthChallengeDisposition: Int, Sendable { case useCredential, performDefaultHandling, cancelAuthenticationChallenge, rejectProtectionSpace }
|
|
621
|
+
public enum DelayedRequestDisposition: Int, Sendable { case continueLoading, useNewRequest, cancel }
|
|
622
|
+
|
|
623
|
+
public func uploadTask(with request: URLRequest, from bodyData: Data, completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void) -> URLSessionUploadTask {
|
|
624
|
+
var upload = request
|
|
625
|
+
upload.httpBody = bodyData
|
|
626
|
+
if upload.httpMethod == nil || upload.httpMethod == "GET" { upload.httpMethod = "POST" }
|
|
627
|
+
let request = upload
|
|
628
|
+
let task = URLSessionUploadTask(identifier: takeIdentifier(), request: request) { [self] task in
|
|
629
|
+
do {
|
|
630
|
+
let (data, response) = try await perform(request, body: bodyData)
|
|
631
|
+
task.finish(response: response, error: nil)
|
|
632
|
+
completionHandler(data, response, nil)
|
|
633
|
+
} catch {
|
|
634
|
+
task.finish(response: nil, error: error)
|
|
635
|
+
completionHandler(nil, nil, error)
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return task
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
func takeIdentifier() -> Int {
|
|
642
|
+
defer { nextTaskIdentifier += 1 }
|
|
643
|
+
return nextTaskIdentifier
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// MARK: The host request
|
|
647
|
+
|
|
648
|
+
/// Sends the request to the host and turns its answer into Foundation's
|
|
649
|
+
/// shapes. Non-2xx statuses are responses, not errors; failures to reach
|
|
650
|
+
/// the server (including CORS refusals, which the browser reports as a
|
|
651
|
+
/// network error) are `URLError`s.
|
|
652
|
+
private func perform(_ request: URLRequest, body: Data?) async throws -> (Data, URLResponse) {
|
|
653
|
+
guard let url = request.url else { throw URLError(.badURL) }
|
|
654
|
+
guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else {
|
|
655
|
+
throw URLError(.unsupportedURL, userInfo: ["NSErrorFailingURLKey": url])
|
|
656
|
+
}
|
|
657
|
+
var headers: [String: String] = [:]
|
|
658
|
+
for (key, value) in configuration.httpAdditionalHeaders ?? [:] {
|
|
659
|
+
if let name = key.base as? String, let text = value as? String { headers[name] = text }
|
|
660
|
+
}
|
|
661
|
+
for (key, value) in request.allHTTPHeaderFields ?? [:] { headers[key] = value }
|
|
662
|
+
let timeout = request.timeoutInterval > 0 ? min(request.timeoutInterval, configuration.timeoutIntervalForRequest) : configuration.timeoutIntervalForRequest
|
|
663
|
+
// OAuth redirects to the app's own URL scheme name the page's callback
|
|
664
|
+
// page instead (WebAuthRedirects.swift; docs/ops-protocol.md, "Signing in").
|
|
665
|
+
let sentURL = _WebAuthRedirects.rewriting(url: url)
|
|
666
|
+
let sentBody = _WebAuthRedirects.rewriting(body: body, contentType: headers.first { $0.key.lowercased() == "content-type" }?.value)
|
|
667
|
+
let params: _JSON = .object([
|
|
668
|
+
"url": .string(sentURL.absoluteString),
|
|
669
|
+
"method": .string(request.httpMethod ?? "GET"),
|
|
670
|
+
"headers": .object(headers.mapValues { .string($0) }),
|
|
671
|
+
"body": sentBody.map { .string($0.base64EncodedString()) } ?? .null,
|
|
672
|
+
"timeout": .number(timeout * 1000),
|
|
673
|
+
])
|
|
674
|
+
|
|
675
|
+
let value: _JSON
|
|
676
|
+
do {
|
|
677
|
+
value = try await _Runtime.shared._hostRequest(kind: "fetch", params: params)
|
|
678
|
+
} catch let failure as _HostRequestError {
|
|
679
|
+
throw Self.urlError(from: failure.message, url: url)
|
|
680
|
+
}
|
|
681
|
+
guard case .object(let fields) = value else { throw URLError(.badServerResponse, userInfo: ["NSErrorFailingURLKey": url]) }
|
|
682
|
+
|
|
683
|
+
var status = 200
|
|
684
|
+
if case .number(let n)? = fields["status"] { status = Int(n) }
|
|
685
|
+
var responseHeaders: [String: String] = [:]
|
|
686
|
+
if case .object(let raw)? = fields["headers"] {
|
|
687
|
+
for (key, item) in raw { if case .string(let text) = item { responseHeaders[key] = text } }
|
|
688
|
+
}
|
|
689
|
+
var data = Data()
|
|
690
|
+
if case .bytes(let bytes)? = fields["body"] {
|
|
691
|
+
// From the page, through linear memory (docs/ops-protocol.md, "Bytes").
|
|
692
|
+
data = Data(bytes)
|
|
693
|
+
} else if case .string(let encoded)? = fields["body"], !encoded.isEmpty {
|
|
694
|
+
guard let decoded = Data(base64Encoded: encoded) else { throw URLError(.cannotDecodeRawData, userInfo: ["NSErrorFailingURLKey": url]) }
|
|
695
|
+
data = decoded
|
|
696
|
+
}
|
|
697
|
+
var finalURL = url
|
|
698
|
+
if case .string(let text)? = fields["url"], let parsed = URL(string: text) { finalURL = parsed }
|
|
699
|
+
guard let response = HTTPURLResponse(url: finalURL, statusCode: status, httpVersion: "HTTP/1.1", headerFields: responseHeaders) else {
|
|
700
|
+
throw URLError(.badServerResponse, userInfo: ["NSErrorFailingURLKey": url])
|
|
701
|
+
}
|
|
702
|
+
return (data, response)
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/// The host reports failures as short messages (see Web/src/hostRequests.ts).
|
|
706
|
+
static func urlError(from message: String, url: URL) -> URLError {
|
|
707
|
+
let lowered = message.lowercased()
|
|
708
|
+
let code: URLError.Code = if lowered.hasPrefix("timeout") { .timedOut }
|
|
709
|
+
else if lowered.hasPrefix("abort") || lowered.hasPrefix("cancel") { .cancelled }
|
|
710
|
+
else if lowered.hasPrefix("offline") { .notConnectedToInternet }
|
|
711
|
+
else if lowered.hasPrefix("headless") { .cannotLoadFromNetwork }
|
|
712
|
+
else { .cannotConnectToHost }
|
|
713
|
+
return URLError(code, userInfo: ["NSErrorFailingURLKey": url, "NSLocalizedDescription": "\(URLError(code).description) (\(message))"])
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/// Leading and trailing spaces and tabs removed.
|
|
718
|
+
func _trimmed(_ text: String) -> String { text.trimmingCharacters(in: .whitespaces) }
|