From 6bfe286c2fb04647c10675e97c04ea8bf560d10e Mon Sep 17 00:00:00 2001 From: Joseph Pender Date: Wed, 2 Sep 2026 11:13:15 -0500 Subject: [PATCH 1/5] refactor(ios)!: relocate sources into an SPM package layout --- .eslintignore | 2 +- .gitignore | 1 + .prettierignore | 2 +- Package.swift | 89 ++ core/rollup.bridge.config.js | 2 +- ios/Capacitor.podspec | 12 +- .../Capacitor.xcodeproj/project.pbxproj | 1166 ----------------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/xcschemes/Capacitor.xcscheme | 87 -- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - ios/Capacitor/Capacitor/Info.plist | 24 - .../CapacitorTests-Bridging-Header.h | 5 - ios/Capacitor/CapacitorTests/Info.plist | 22 - ios/Capacitor/TestsHostApp/AppDelegate.swift | 18 - .../AccentColor.colorset/Contents.json | 11 - .../AppIcon.appiconset/Contents.json | 98 -- .../Assets.xcassets/Contents.json | 6 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../TestsHostApp/Base.lproj/Main.storyboard | 24 - ios/Capacitor/TestsHostApp/Info.plist | 66 - .../TestsHostApp/SceneDelegate.swift | 5 - .../TestsHostApp/ViewController.swift | 9 - ios/CapacitorCordova.podspec | 11 +- .../project.pbxproj | 499 ------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../CapacitorCordova/Info.plist | 26 - .../Capacitor/AppUUID.swift | 0 .../Capacitor/Array+Capacitor.swift | 0 .../CAPApplicationDelegateProxy.swift | 0 .../Capacitor/CAPBridgeDelegate.swift | 0 .../Capacitor/CAPBridgeProtocol.swift | 0 .../Capacitor/CAPBridgeViewController.swift | 0 .../CAPBridgedPlugin+getMethod.swift | 0 .../Capacitor/CAPInstanceConfiguration.swift | 0 .../Capacitor/CAPInstanceDescriptor.swift | 0 .../Capacitor/CAPInstancePlugin.swift | 0 .../Capacitor/CAPLog.swift | 0 .../Capacitor/CAPNotifications.swift | 0 .../Capacitor/CAPPlugin+LoadInstance.swift | 0 .../Capacitor/CAPPluginCall.swift | 0 .../Capacitor/CAPPluginMethod.swift | 0 .../Capacitor/CAPSceneDelegateProxy.swift | 0 .../Capacitor/CapacitorBridge.swift | 0 .../Capacitor/CapacitorExtension.swift | 0 .../Capacitor/Codable/JSValueDecoder.swift | 0 .../Capacitor/Codable/JSValueEncoder.swift | 0 .../Capacitor/Data+Capacitor.swift | 0 .../Capacitor/DocLinks.swift | 0 ios/{Capacitor => Sources}/Capacitor/JS.swift | 0 .../Capacitor/JSExport.swift | 8 +- .../Capacitor/JSTypes.swift | 0 .../Capacitor/KeyPath.swift | 0 .../Capacitor/KeyValueStore.swift | 0 .../NotificationHandlerProtocol.swift | 0 .../Capacitor/NotificationRouter.swift | 0 .../Capacitor/PluginCallResult.swift | 0 .../Capacitor/PluginConfig.swift | 0 .../Plugins/CapacitorCookieManager.swift | 0 .../Capacitor/Plugins/CapacitorCookies.swift | 0 .../Capacitor/Plugins/CapacitorHttp.swift | 0 .../Plugins/CapacitorUrlRequest.swift | 0 .../Capacitor/Plugins/Console.swift | 0 .../Plugins/HttpRequestHandler.swift | 0 .../Capacitor/Plugins/SystemBars.swift | 0 .../Capacitor/Plugins/WebView.swift | 0 .../Capacitor/PrivacyInfo.xcprivacy | 0 .../Capacitor/Router.swift | 0 .../Capacitor/UIColor.swift | 0 .../Capacitor/WKWebView+Capacitor.swift | 0 .../Capacitor/WebViewAssetHandler.swift | 0 .../Capacitor/WebViewDelegationHandler.swift | 0 .../Capacitor/assets/native-bridge.js | 0 .../CapacitorCordova}/Plugin.swift | 0 .../CapacitorObjC}/CAPInstanceConfiguration.m | 0 .../CapacitorObjC}/CAPInstanceDescriptor.m | 0 .../CapacitorObjC}/CAPPlugin.m | 0 .../CapacitorObjC}/CAPPluginCall.m | 0 .../CapacitorObjC}/CAPPluginMethod.m | 0 .../include}/Capacitor/CAPBridgedPlugin.h | 0 .../Capacitor/CAPInstanceConfiguration.h | 0 .../Capacitor/CAPInstanceDescriptor.h | 0 .../include}/Capacitor/CAPPlugin.h | 0 .../include}/Capacitor/CAPPluginCall.h | 0 .../include}/Capacitor/CAPPluginMethod.h | 0 .../CapacitorObjCShims}/CAPBridgedJSTypes.m | 0 .../CapacitorObjCShims}/Capacitor.modulemap | 0 .../UIStatusBarManager+CAPHandleTapAction.m | 0 .../CapacitorObjCShims}/WKWebView+Capacitor.m | 0 .../include}/Capacitor/CAPBridgedJSTypes.h | 0 .../include}/Capacitor/Capacitor.h | 0 .../Public => Sources/Cordova}/AppDelegate.m | 0 .../Cordova}/CDVCommandDelegateImpl.m | 0 .../Cordova}/CDVConfigParser.m | 0 .../Cordova}/CDVInvokedUrlCommand.m | 0 .../Cordova}/CDVPlugin+Resources.m | 0 .../Public => Sources/Cordova}/CDVPlugin.m | 0 .../Cordova}/CDVPluginManager.m | 0 .../Cordova}/CDVPluginResult.m | 0 .../Cordova}/CDVURLProtocol.m | 0 .../Cordova}/CDVViewController.m | 0 .../Cordova}/CDVWebViewProcessPoolFactory.m | 0 .../Cordova}/CapacitorCordova.h | 0 .../Cordova}/CapacitorCordova.modulemap | 0 .../NSDictionary+CordovaPreferences.m | 0 .../Cordova}/PrivacyInfo.xcprivacy | 0 .../Cordova/include/Cordova}/AppDelegate.h | 0 .../Cordova/include/Cordova}/CDV.h | 0 .../include/Cordova}/CDVAvailability.h | 0 .../Cordova}/CDVAvailabilityDeprecated.h | 0 .../include/Cordova}/CDVCommandDelegate.h | 0 .../include/Cordova}/CDVCommandDelegateImpl.h | 0 .../include/Cordova}/CDVConfigParser.h | 0 .../include/Cordova}/CDVInvokedUrlCommand.h | 0 .../include/Cordova}/CDVPlugin+Resources.h | 0 .../Cordova/include/Cordova}/CDVPlugin.h | 0 .../include/Cordova}/CDVPluginManager.h | 0 .../include/Cordova}/CDVPluginResult.h | 0 .../Cordova}/CDVScreenOrientationDelegate.h | 0 .../Cordova/include/Cordova}/CDVURLProtocol.h | 0 .../include/Cordova}/CDVViewController.h | 0 .../Cordova}/CDVWebViewProcessPoolFactory.h | 0 .../NSDictionary+CordovaPreferences.h | 0 .../CapacitorObjCTests}/BridgedTypesTests.m | 0 .../JSONSerializationWrapper.h | 0 .../JSONSerializationWrapper.m | 0 .../PluginCallAccessorTests.m | 0 .../CapacitorTests/BridgedTypesHelper.swift | 0 .../CapacitorTests/BridgedTypesTests.swift | 0 .../CapacitorTests/CapacitorTests.swift | 0 .../CapacitorTests}/CodableTests.swift | 0 .../CapacitorTests/ConfigurationTests.swift | 0 .../CapacitorTests}/DataCodableTests.swift | 0 .../CapacitorTests}/DateCodableTests.swift | 0 .../HttpInterceptorNavigationTests.swift | 0 .../CapacitorTests/JSExportTests.swift | 0 .../CapacitorTests}/NestedCodableTests.swift | 0 .../NonconformingFloatCodableTests.swift | 0 .../Resources}/configurations/bad.json | 0 .../Resources}/configurations/flat.json | 0 .../Resources}/configurations/hidinglogs.json | 0 .../Resources}/configurations/hierarchy.json | 0 .../Resources}/configurations/nonjson.json | 0 .../Resources}/configurations/server.json | 0 .../CapacitorTests/RouterTests.swift | 0 .../CapacitorTests}/SuperCodableTests.swift | 0 .../CapacitorTests}/URLCodableTests.swift | 0 ios/package.json | 9 +- swiftlint.config.js | 2 +- 149 files changed, 118 insertions(+), 2145 deletions(-) create mode 100644 Package.swift delete mode 100644 ios/Capacitor/Capacitor.xcodeproj/project.pbxproj delete mode 100644 ios/Capacitor/Capacitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Capacitor/Capacitor.xcodeproj/xcshareddata/xcschemes/Capacitor.xcscheme delete mode 100644 ios/Capacitor/Capacitor.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Capacitor/Capacitor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Capacitor/Capacitor/Info.plist delete mode 100644 ios/Capacitor/CapacitorTests/CapacitorTests-Bridging-Header.h delete mode 100644 ios/Capacitor/CapacitorTests/Info.plist delete mode 100644 ios/Capacitor/TestsHostApp/AppDelegate.swift delete mode 100644 ios/Capacitor/TestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json delete mode 100644 ios/Capacitor/TestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ios/Capacitor/TestsHostApp/Assets.xcassets/Contents.json delete mode 100644 ios/Capacitor/TestsHostApp/Base.lproj/LaunchScreen.storyboard delete mode 100644 ios/Capacitor/TestsHostApp/Base.lproj/Main.storyboard delete mode 100644 ios/Capacitor/TestsHostApp/Info.plist delete mode 100644 ios/Capacitor/TestsHostApp/SceneDelegate.swift delete mode 100644 ios/Capacitor/TestsHostApp/ViewController.swift delete mode 100644 ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.pbxproj delete mode 100644 ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/CapacitorCordova/CapacitorCordova/Info.plist rename ios/{Capacitor => Sources}/Capacitor/AppUUID.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Array+Capacitor.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPApplicationDelegateProxy.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPBridgeDelegate.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPBridgeProtocol.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPBridgeViewController.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPBridgedPlugin+getMethod.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPInstanceConfiguration.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPInstanceDescriptor.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPInstancePlugin.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPLog.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPNotifications.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPPlugin+LoadInstance.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPPluginCall.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPPluginMethod.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CAPSceneDelegateProxy.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CapacitorBridge.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/CapacitorExtension.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Codable/JSValueDecoder.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Codable/JSValueEncoder.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Data+Capacitor.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/DocLinks.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/JS.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/JSExport.swift (96%) rename ios/{Capacitor => Sources}/Capacitor/JSTypes.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/KeyPath.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/KeyValueStore.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/NotificationHandlerProtocol.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/NotificationRouter.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/PluginCallResult.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/PluginConfig.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/CapacitorCookieManager.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/CapacitorCookies.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/CapacitorHttp.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/CapacitorUrlRequest.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/Console.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/HttpRequestHandler.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/SystemBars.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/Plugins/WebView.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/PrivacyInfo.xcprivacy (100%) rename ios/{Capacitor => Sources}/Capacitor/Router.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/UIColor.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/WKWebView+Capacitor.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/WebViewAssetHandler.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/WebViewDelegationHandler.swift (100%) rename ios/{Capacitor => Sources}/Capacitor/assets/native-bridge.js (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/CapacitorCordova}/Plugin.swift (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjC}/CAPInstanceConfiguration.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjC}/CAPInstanceDescriptor.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjC}/CAPPlugin.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjC}/CAPPluginCall.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjC}/CAPPluginMethod.m (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPBridgedPlugin.h (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPInstanceConfiguration.h (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPInstanceDescriptor.h (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPPlugin.h (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPPluginCall.h (100%) rename ios/{Capacitor => Sources/CapacitorObjC/include}/Capacitor/CAPPluginMethod.h (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjCShims}/CAPBridgedJSTypes.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjCShims}/Capacitor.modulemap (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjCShims}/UIStatusBarManager+CAPHandleTapAction.m (100%) rename ios/{Capacitor/Capacitor => Sources/CapacitorObjCShims}/WKWebView+Capacitor.m (100%) rename ios/{Capacitor => Sources/CapacitorObjCShims/include}/Capacitor/CAPBridgedJSTypes.h (100%) rename ios/{Capacitor => Sources/CapacitorObjCShims/include}/Capacitor/Capacitor.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/AppDelegate.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVCommandDelegateImpl.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVConfigParser.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVInvokedUrlCommand.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVPlugin+Resources.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVPlugin.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVPluginManager.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVPluginResult.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVURLProtocol.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVViewController.m (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/CDVWebViewProcessPoolFactory.m (100%) rename ios/{CapacitorCordova/CapacitorCordova => Sources/Cordova}/CapacitorCordova.h (100%) rename ios/{CapacitorCordova/CapacitorCordova => Sources/Cordova}/CapacitorCordova.modulemap (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova}/NSDictionary+CordovaPreferences.m (100%) rename ios/{CapacitorCordova/CapacitorCordova => Sources/Cordova}/PrivacyInfo.xcprivacy (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/AppDelegate.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDV.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVAvailability.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVAvailabilityDeprecated.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVCommandDelegate.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVCommandDelegateImpl.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVConfigParser.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVInvokedUrlCommand.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVPlugin+Resources.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVPlugin.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVPluginManager.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVPluginResult.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVScreenOrientationDelegate.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVURLProtocol.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVViewController.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/CDVWebViewProcessPoolFactory.h (100%) rename ios/{CapacitorCordova/CapacitorCordova/Classes/Public => Sources/Cordova/include/Cordova}/NSDictionary+CordovaPreferences.h (100%) rename ios/{Capacitor/CapacitorTests => Tests/CapacitorObjCTests}/BridgedTypesTests.m (100%) rename ios/{Capacitor/CapacitorTests => Tests/CapacitorObjCTests}/JSONSerializationWrapper.h (100%) rename ios/{Capacitor/CapacitorTests => Tests/CapacitorObjCTests}/JSONSerializationWrapper.m (100%) rename ios/{Capacitor/CapacitorTests => Tests/CapacitorObjCTests}/PluginCallAccessorTests.m (100%) rename ios/{Capacitor => Tests}/CapacitorTests/BridgedTypesHelper.swift (100%) rename ios/{Capacitor => Tests}/CapacitorTests/BridgedTypesTests.swift (100%) rename ios/{Capacitor => Tests}/CapacitorTests/CapacitorTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/CodableTests.swift (100%) rename ios/{Capacitor => Tests}/CapacitorTests/ConfigurationTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/DataCodableTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/DateCodableTests.swift (100%) rename ios/{Capacitor => Tests}/CapacitorTests/HttpInterceptorNavigationTests.swift (100%) rename ios/{Capacitor => Tests}/CapacitorTests/JSExportTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/NestedCodableTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/NonconformingFloatCodableTests.swift (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/bad.json (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/flat.json (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/hidinglogs.json (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/hierarchy.json (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/nonjson.json (100%) rename ios/{Capacitor/TestsHostApp => Tests/CapacitorTests/Resources}/configurations/server.json (100%) rename ios/{Capacitor => Tests}/CapacitorTests/RouterTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/SuperCodableTests.swift (100%) rename ios/{Capacitor/CodableTests => Tests/CapacitorTests}/URLCodableTests.swift (100%) diff --git a/.eslintignore b/.eslintignore index 4a1df4e690..abf24cdbf6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,6 @@ cli/assets dist types android/capacitor/src/main/assets/native-bridge.js -ios/Capacitor/Capacitor/assets/native-bridge.js +ios/Sources/Capacitor/assets/native-bridge.js ios/Frameworks/Capacitor.xcframework/ios-arm64_x86_64-simulator/Capacitor.framework/native-bridge.js ios/Frameworks/Capacitor.xcframework/ios-arm64/Capacitor.framework/native-bridge.js diff --git a/.gitignore b/.gitignore index 0968d10c62..f118252d0a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ Pods/ Podfile.lock Build/* build/ +.build/ Index/ .*.sw* android-template.iml diff --git a/.prettierignore b/.prettierignore index 143c857005..bc26e51947 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,6 +3,6 @@ core/types cli/assets dist android/capacitor/src/main/assets/native-bridge.js -ios/Capacitor/Capacitor/assets/native-bridge.js +ios/Sources/Capacitor/assets/native-bridge.js ios/Frameworks/Capacitor.xcframework/ios-arm64_x86_64-simulator/Capacitor.framework/native-bridge.js ios/Frameworks/Capacitor.xcframework/ios-arm64/Capacitor.framework/native-bridge.js diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000000..dea7048ce4 --- /dev/null +++ b/Package.swift @@ -0,0 +1,89 @@ +// swift-tools-version: 6.0 +import PackageDescription + +let package = Package( + name: "Capacitor", + platforms: [.iOS(.v16)], + products: [ + .library( + name: "Capacitor", + targets: ["Capacitor", "CapacitorObjC", "CapacitorObjCShims"] + ), + .library( + name: "Cordova", + targets: ["Cordova"] + ), + .library( + name: "CapacitorCordova", + targets: ["Cordova", "CapacitorCordova"] + ) + ], + targets: [ + .target( + name: "CapacitorObjC", + path: "ios/Sources/CapacitorObjC", + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("include"), + .headerSearchPath("include/Capacitor") + ] + ), + .target( + name: "Capacitor", + dependencies: ["CapacitorObjC"], + path: "ios/Sources/Capacitor", + resources: [ + .copy("assets"), + .copy("PrivacyInfo.xcprivacy") + ], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + .target( + name: "CapacitorObjCShims", + dependencies: ["Capacitor"], + path: "ios/Sources/CapacitorObjCShims", + exclude: ["Capacitor.modulemap"], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("include"), + .headerSearchPath("include/Capacitor") + ] + ), + .target( + name: "Cordova", + path: "ios/Sources/Cordova", + exclude: ["CapacitorCordova.modulemap"], + resources: [.copy("PrivacyInfo.xcprivacy")], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("include"), + .headerSearchPath("include/Cordova") + ], + linkerSettings: [ + .linkedFramework("UIKit"), + .linkedFramework("WebKit"), + .linkedFramework("MobileCoreServices"), + .linkedFramework("CFNetwork") + ] + ), + .target( + name: "CapacitorCordova", + dependencies: ["Capacitor", "Cordova"], + path: "ios/Sources/CapacitorCordova", + swiftSettings: [.swiftLanguageMode(.v5)] + ), + .testTarget( + name: "CapacitorTests", + dependencies: ["Capacitor"], + path: "ios/Tests/CapacitorTests", + resources: [.copy("Resources/configurations")], + swiftSettings: [.swiftLanguageMode(.v5)] + ), + .testTarget( + name: "CapacitorObjCTests", + dependencies: ["CapacitorObjCShims"], + path: "ios/Tests/CapacitorObjCTests" + ) + ], + swiftLanguageModes: [.v5] +) diff --git a/core/rollup.bridge.config.js b/core/rollup.bridge.config.js index 9f8d90e97d..d741e5dcc5 100644 --- a/core/rollup.bridge.config.js +++ b/core/rollup.bridge.config.js @@ -17,7 +17,7 @@ export default { sourcemap: false, }, { - file: '../ios/Capacitor/Capacitor/assets/native-bridge.js', + file: '../ios/Sources/Capacitor/assets/native-bridge.js', format: 'iife', name: 'nativeBridge', preferConst: true, diff --git a/ios/Capacitor.podspec b/ios/Capacitor.podspec index 01ce20591e..77f3275e94 100644 --- a/ios/Capacitor.podspec +++ b/ios/Capacitor.podspec @@ -15,9 +15,13 @@ Pod::Spec.new do |s| s.ios.deployment_target = '16.0' s.authors = { 'Ionic Team' => 'hi@ionicframework.com' } s.source = { git: 'https://github.com/ionic-team/capacitor.git', tag: package['version'] } - s.source_files = "#{prefix}Capacitor/Capacitor/**/*.{swift,h,m}" - s.module_map = "#{prefix}Capacitor/Capacitor/Capacitor.modulemap" - s.resources = ["#{prefix}Capacitor/Capacitor/assets/native-bridge.js"] - s.resource_bundles = { 'Capacitor' => ["#{prefix}Capacitor/Capacitor/PrivacyInfo.xcprivacy"] } + s.source_files = [ + "#{prefix}Sources/Capacitor/**/*.swift", + "#{prefix}Sources/CapacitorObjC/**/*.{h,m}", + "#{prefix}Sources/CapacitorObjCShims/**/*.{h,m}" + ] + s.module_map = "#{prefix}Sources/CapacitorObjCShims/Capacitor.modulemap" + s.resources = ["#{prefix}Sources/Capacitor/assets/native-bridge.js"] + s.resource_bundles = { 'Capacitor' => ["#{prefix}Sources/Capacitor/PrivacyInfo.xcprivacy"] } s.swift_version = '5.1' end diff --git a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj b/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj deleted file mode 100644 index 2892ea0722..0000000000 --- a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1166 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 0F83E885285A332E006C43CB /* AppUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F83E884285A332D006C43CB /* AppUUID.swift */; }; - 0F8F33B327DA980A003F49D6 /* PluginConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F33B127DA980A003F49D6 /* PluginConfig.swift */; }; - 373A69C1255C9360000A6F44 /* NotificationHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */; }; - 373A69F2255C95D0000A6F44 /* NotificationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373A69F1255C95D0000A6F44 /* NotificationRouter.swift */; }; - 501CBAA71FC0A723009B0D4D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 501CBAA61FC0A723009B0D4D /* WebKit.framework */; }; - 50503EE91FC08595003606DC /* Capacitor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50503EDF1FC08594003606DC /* Capacitor.framework */; }; - 50503EEE1FC08595003606DC /* CapacitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50503EED1FC08595003606DC /* CapacitorTests.swift */; }; - 6214934725509C3F006C36F9 /* CAPInstanceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6214934625509C3F006C36F9 /* CAPInstanceConfiguration.swift */; }; - 621ECCB72542045900D3D615 /* CAPBridgedJSTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCB42542045900D3D615 /* CAPBridgedJSTypes.m */; }; - 621ECCB82542045900D3D615 /* CAPBridgedJSTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 621ECCB62542045900D3D615 /* CAPBridgedJSTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621ECCBC2542046400D3D615 /* JSTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCBB2542046400D3D615 /* JSTypes.swift */; }; - 621ECCC3254204B700D3D615 /* BridgedTypesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCC2254204B700D3D615 /* BridgedTypesTests.swift */; }; - 621ECCC8254204BE00D3D615 /* JSONSerializationWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCC6254204BE00D3D615 /* JSONSerializationWrapper.m */; }; - 621ECCD6254205BD00D3D615 /* CAPBridgeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCD4254205BD00D3D615 /* CAPBridgeProtocol.swift */; }; - 621ECCDA254205C400D3D615 /* CapacitorBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCD9254205C400D3D615 /* CapacitorBridge.swift */; }; - 621ECCE3254206A600D3D615 /* CAPApplicationDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCE2254206A600D3D615 /* CAPApplicationDelegateProxy.swift */; }; - 623D68FA254C5037002D01D1 /* KeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623D68F9254C5037002D01D1 /* KeyPath.swift */; }; - 623D6909254C6FDF002D01D1 /* CAPInstanceDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 623D6907254C6FDF002D01D1 /* CAPInstanceDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 623D690A254C6FDF002D01D1 /* CAPInstanceDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 623D6908254C6FDF002D01D1 /* CAPInstanceDescriptor.m */; }; - 623D6914254C7030002D01D1 /* CAPInstanceDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623D6913254C7030002D01D1 /* CAPInstanceDescriptor.swift */; }; - 623D691D254C7462002D01D1 /* CAPInstanceConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 623D691E254C7462002D01D1 /* CAPInstanceConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */; }; - 625AF1ED258963C700869675 /* WebViewAssetHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */; }; - 6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */; }; - 626D2D992613B61E0046CE81 /* hidinglogs.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 626D2D902613B4BB0046CE81 /* hidinglogs.json */; }; - 62959B162524DA7800A3D7F1 /* CAPPluginCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE32524DA7700A3D7F1 /* JSExport.swift */; }; - 62959B192524DA7800A3D7F1 /* CAPBridgedPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B1A2524DA7800A3D7F1 /* CAPPluginCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE62524DA7700A3D7F1 /* CAPPluginCall.swift */; }; - 62959B1C2524DA7800A3D7F1 /* CAPPluginMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE82524DA7700A3D7F1 /* CAPPluginMethod.m */; }; - 62959B1D2524DA7800A3D7F1 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE92524DA7700A3D7F1 /* UIColor.swift */; }; - 62959B222524DA7800A3D7F1 /* Console.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AEF2524DA7700A3D7F1 /* Console.swift */; }; - 62959B262524DA7800A3D7F1 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AF32524DA7700A3D7F1 /* WebView.swift */; }; - 62959B302524DA7800A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */; }; - 62959B312524DA7800A3D7F1 /* JS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFF2524DA7700A3D7F1 /* JS.swift */; }; - 62959B332524DA7800A3D7F1 /* CAPPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959B012524DA7700A3D7F1 /* CAPPlugin.m */; }; - 62959B362524DA7800A3D7F1 /* CAPBridgeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */; }; - 62959B382524DA7800A3D7F1 /* CAPPluginCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959B062524DA7700A3D7F1 /* CAPPluginCall.m */; }; - 62959B392524DA7800A3D7F1 /* CapacitorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B072524DA7700A3D7F1 /* CapacitorExtension.swift */; }; - 62959B3A2524DA7800A3D7F1 /* CAPLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B082524DA7700A3D7F1 /* CAPLog.swift */; }; - 62959B3B2524DA7800A3D7F1 /* CAPPluginMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959B092524DA7700A3D7F1 /* CAPPluginMethod.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B3C2524DA7800A3D7F1 /* CAPBridgeDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B0A2524DA7700A3D7F1 /* CAPBridgeDelegate.swift */; }; - 62959B412524DA7800A3D7F1 /* Capacitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959B0F2524DA7700A3D7F1 /* Capacitor.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B422524DA7800A3D7F1 /* DocLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B102524DA7700A3D7F1 /* DocLinks.swift */; }; - 62959B432524DA7800A3D7F1 /* Data+Capacitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B112524DA7700A3D7F1 /* Data+Capacitor.swift */; }; - 62959B452524DA7800A3D7F1 /* CAPPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959B132524DA7700A3D7F1 /* CAPPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B472524DA7800A3D7F1 /* CAPNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B152524DA7700A3D7F1 /* CAPNotifications.swift */; }; - 6296A77E253A2E49005A202A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6296A77D253A2E49005A202A /* AppDelegate.swift */; }; - 6296A782253A2E49005A202A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6296A781253A2E49005A202A /* ViewController.swift */; }; - 6296A7A0253A2E49005A202A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6296A7A1253A2E49005A202A /* SceneDelegate.swift */; }; - 6296A785253A2E49005A202A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6296A783253A2E49005A202A /* Main.storyboard */; }; - 6296A787253A2E49005A202A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6296A786253A2E49005A202A /* Assets.xcassets */; }; - 6296A78A253A2E49005A202A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6296A788253A2E49005A202A /* LaunchScreen.storyboard */; }; - 62A91C3425535F5700861508 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A91C3325535F5700861508 /* ConfigurationTests.swift */; }; - 62A91C3F2553710E00861508 /* nonjson.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62A91C392553710300861508 /* nonjson.json */; }; - 62ADC0CA25CB678000E914DE /* PluginCallResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62ADC0C925CB678000E914DE /* PluginCallResult.swift */; }; - 62D43AF02581817500673C24 /* WKWebView+Capacitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D43AEF2581817500673C24 /* WKWebView+Capacitor.swift */; }; - 62D43B652582A13D00673C24 /* WKWebView+Capacitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D43B642582A13D00673C24 /* WKWebView+Capacitor.m */; }; - 62E0736125535E8700BAAADB /* server.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62E0735225535E6500BAAADB /* server.json */; }; - 62E0736225535E8700BAAADB /* bad.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62E0735325535E6500BAAADB /* bad.json */; }; - 62E0736325535E8700BAAADB /* flat.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62E0735425535E6500BAAADB /* flat.json */; }; - 62E0736425535E8700BAAADB /* hierarchy.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62E0735525535E6500BAAADB /* hierarchy.json */; }; - 62E207AE2588234500A78983 /* WebViewDelegationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E207AD2588234500A78983 /* WebViewDelegationHandler.swift */; }; - 62E79C722638B23300414164 /* JSExportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E79C712638B23300414164 /* JSExportTests.swift */; }; - 62E79CD7263A178B00414164 /* native-bridge.js in Resources */ = {isa = PBXBuildFile; fileRef = 62E79C572638AF7500414164 /* native-bridge.js */; }; - 62FABD1A25AE5C01007B3814 /* Array+Capacitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD1925AE5C01007B3814 /* Array+Capacitor.swift */; }; - 62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD2225AE60BA007B3814 /* BridgedTypesTests.m */; }; - 62FABD2B25AE6182007B3814 /* BridgedTypesHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */; }; - 952707712FD9DD2D0079E5D3 /* CAPSceneDelegateProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9527076F2FD9DD260079E5D3 /* CAPSceneDelegateProxy.swift */; }; - 957BD9402E78A4A50056874C /* SystemBars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957BD93E2E78A4A20056874C /* SystemBars.swift */; }; - A327E6B628DB8B2900CA8B0A /* HttpRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A327E6B228DB8B2800CA8B0A /* HttpRequestHandler.swift */; }; - A327E6B728DB8B2900CA8B0A /* CapacitorHttp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A327E6B428DB8B2900CA8B0A /* CapacitorHttp.swift */; }; - A327E6B828DB8B2900CA8B0A /* CapacitorUrlRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A327E6B528DB8B2900CA8B0A /* CapacitorUrlRequest.swift */; }; - A38C3D7728484E76004B3680 /* CapacitorCookies.swift in Sources */ = {isa = PBXBuildFile; fileRef = A38C3D7628484E76004B3680 /* CapacitorCookies.swift */; }; - A38C3D7B2848BE6F004B3680 /* CapacitorCookieManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A38C3D7A2848BE6F004B3680 /* CapacitorCookieManager.swift */; }; - A71289E627F380A500DADDF3 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71289E527F380A500DADDF3 /* Router.swift */; }; - A71289EB27F380FD00DADDF3 /* RouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A71289EA27F380FD00DADDF3 /* RouterTests.swift */; }; - AA01F00D0000000000000002 /* HttpInterceptorNavigationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA01F00D0000000000000001 /* HttpInterceptorNavigationTests.swift */; }; - A7187FD22BD1CB7D00093C45 /* CAPPluginMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7187FD12BD1CB7D00093C45 /* CAPPluginMethod.swift */; }; - A76739792B98E09700795F7B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A76739782B98E09700795F7B /* PrivacyInfo.xcprivacy */; }; - A771ADEE2C8B845000AF234D /* DateCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A771ADED2C8B845000AF234D /* DateCodableTests.swift */; }; - A771ADF12C8B909100AF234D /* URLCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A771ADF02C8B909100AF234D /* URLCodableTests.swift */; }; - A7BE62CC2B486A5400165ACB /* KeyValueStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7BE62CB2B486A5400165ACB /* KeyValueStore.swift */; }; - A7D474D52C8BA8E8005620A8 /* DataCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D474D42C8BA8E8005620A8 /* DataCodableTests.swift */; }; - A7D474D82C8BA8FD005620A8 /* NonconformingFloatCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D474D72C8BA8FD005620A8 /* NonconformingFloatCodableTests.swift */; }; - A7D8B3522B238A840003FAD6 /* JSValueEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D8B3512B238A840003FAD6 /* JSValueEncoder.swift */; }; - A7D8B3632B263B8D0003FAD6 /* NestedCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D8B3622B263B8D0003FAD6 /* NestedCodableTests.swift */; }; - A7D8B3642B263B8D0003FAD6 /* Capacitor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50503EDF1FC08594003606DC /* Capacitor.framework */; }; - A7D8B36A2B263B990003FAD6 /* CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D8B3562B23B2110003FAD6 /* CodableTests.swift */; }; - A7D8B36E2B2692300003FAD6 /* SuperCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D8B36D2B2692300003FAD6 /* SuperCodableTests.swift */; }; - A7D9312F2B23710300FF59A2 /* JSValueDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D9312E2B23710300FF59A2 /* JSValueDecoder.swift */; }; - A7DB03AC29B001E300888AE9 /* CAPBridgedPlugin+getMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB03AB29B001E300888AE9 /* CAPBridgedPlugin+getMethod.swift */; }; - A7F7EDCD291EC75C0015B73B /* CAPPlugin+LoadInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F7EDCC291EC75C0015B73B /* CAPPlugin+LoadInstance.swift */; }; - A7F7EDD5292BE8520015B73B /* CAPInstancePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F7EDD4292BE8520015B73B /* CAPInstancePlugin.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 50503EEA1FC08595003606DC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 50503ED61FC08594003606DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 50503EDE1FC08594003606DC; - remoteInfo = Avocado; - }; - 6296A796253A2EAE005A202A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 50503ED61FC08594003606DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6296A77A253A2E49005A202A; - remoteInfo = TestsHostApp; - }; - A7D8B3652B263B8D0003FAD6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 50503ED61FC08594003606DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 50503EDE1FC08594003606DC; - remoteInfo = Capacitor; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 622BB9C32541FE1900A5DBCA /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = configurations; - dstSubfolderSpec = 1; - files = ( - 626D2D992613B61E0046CE81 /* hidinglogs.json in CopyFiles */, - 62A91C3F2553710E00861508 /* nonjson.json in CopyFiles */, - 62E0736125535E8700BAAADB /* server.json in CopyFiles */, - 62E0736225535E8700BAAADB /* bad.json in CopyFiles */, - 62E0736325535E8700BAAADB /* flat.json in CopyFiles */, - 62E0736425535E8700BAAADB /* hierarchy.json in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0F83E884285A332D006C43CB /* AppUUID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUUID.swift; sourceTree = ""; }; - 0F8F33B127DA980A003F49D6 /* PluginConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PluginConfig.swift; sourceTree = ""; }; - 373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandlerProtocol.swift; sourceTree = ""; }; - 373A69F1255C95D0000A6F44 /* NotificationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRouter.swift; sourceTree = ""; }; - 501CBAA61FC0A723009B0D4D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 50503EDF1FC08594003606DC /* Capacitor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Capacitor.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 50503EE81FC08595003606DC /* CapacitorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CapacitorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 50503EED1FC08595003606DC /* CapacitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacitorTests.swift; sourceTree = ""; }; - 6214934625509C3F006C36F9 /* CAPInstanceConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPInstanceConfiguration.swift; sourceTree = ""; }; - 621ECCB42542045900D3D615 /* CAPBridgedJSTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPBridgedJSTypes.m; sourceTree = ""; }; - 621ECCB62542045900D3D615 /* CAPBridgedJSTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPBridgedJSTypes.h; sourceTree = ""; }; - 621ECCBB2542046400D3D615 /* JSTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSTypes.swift; sourceTree = ""; }; - 621ECCC2254204B700D3D615 /* BridgedTypesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgedTypesTests.swift; sourceTree = ""; }; - 621ECCC6254204BE00D3D615 /* JSONSerializationWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONSerializationWrapper.m; sourceTree = ""; }; - 621ECCC7254204BE00D3D615 /* JSONSerializationWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONSerializationWrapper.h; sourceTree = ""; }; - 621ECCCD254204C400D3D615 /* CapacitorTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CapacitorTests-Bridging-Header.h"; sourceTree = ""; }; - 621ECCD4254205BD00D3D615 /* CAPBridgeProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPBridgeProtocol.swift; sourceTree = ""; }; - 621ECCD9254205C400D3D615 /* CapacitorBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CapacitorBridge.swift; sourceTree = ""; }; - 621ECCE2254206A600D3D615 /* CAPApplicationDelegateProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPApplicationDelegateProxy.swift; sourceTree = ""; }; - 623D68F9254C5037002D01D1 /* KeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPath.swift; sourceTree = ""; }; - 623D6907254C6FDF002D01D1 /* CAPInstanceDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CAPInstanceDescriptor.h; sourceTree = ""; }; - 623D6908254C6FDF002D01D1 /* CAPInstanceDescriptor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAPInstanceDescriptor.m; sourceTree = ""; }; - 623D6913254C7030002D01D1 /* CAPInstanceDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPInstanceDescriptor.swift; sourceTree = ""; }; - 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CAPInstanceConfiguration.h; sourceTree = ""; }; - 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAPInstanceConfiguration.m; sourceTree = ""; }; - 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewAssetHandler.swift; sourceTree = ""; }; - 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PluginCallAccessorTests.m; sourceTree = ""; }; - 626D2D902613B4BB0046CE81 /* hidinglogs.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = hidinglogs.json; sourceTree = ""; }; - 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPPluginCall.h; sourceTree = ""; }; - 62959AE32524DA7700A3D7F1 /* JSExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSExport.swift; sourceTree = ""; }; - 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPBridgedPlugin.h; sourceTree = ""; }; - 62959AE62524DA7700A3D7F1 /* CAPPluginCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPPluginCall.swift; sourceTree = ""; }; - 62959AE82524DA7700A3D7F1 /* CAPPluginMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPluginMethod.m; sourceTree = ""; }; - 62959AE92524DA7700A3D7F1 /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; - 62959AEF2524DA7700A3D7F1 /* Console.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Console.swift; sourceTree = ""; }; - 62959AF32524DA7700A3D7F1 /* WebView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; - 62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIStatusBarManager+CAPHandleTapAction.m"; sourceTree = ""; }; - 62959AFF2524DA7700A3D7F1 /* JS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JS.swift; sourceTree = ""; }; - 62959B012524DA7700A3D7F1 /* CAPPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPlugin.m; sourceTree = ""; }; - 62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPBridgeViewController.swift; sourceTree = ""; }; - 62959B062524DA7700A3D7F1 /* CAPPluginCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPluginCall.m; sourceTree = ""; }; - 62959B072524DA7700A3D7F1 /* CapacitorExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CapacitorExtension.swift; sourceTree = ""; }; - 62959B082524DA7700A3D7F1 /* CAPLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPLog.swift; sourceTree = ""; }; - 62959B092524DA7700A3D7F1 /* CAPPluginMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPPluginMethod.h; sourceTree = ""; }; - 62959B0A2524DA7700A3D7F1 /* CAPBridgeDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPBridgeDelegate.swift; sourceTree = ""; }; - 62959B0F2524DA7700A3D7F1 /* Capacitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Capacitor.h; sourceTree = ""; }; - 62959B102524DA7700A3D7F1 /* DocLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocLinks.swift; sourceTree = ""; }; - 62959B112524DA7700A3D7F1 /* Data+Capacitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Capacitor.swift"; sourceTree = ""; }; - 62959B122524DA7700A3D7F1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 62959B132524DA7700A3D7F1 /* CAPPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPPlugin.h; sourceTree = ""; }; - 62959B152524DA7700A3D7F1 /* CAPNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPNotifications.swift; sourceTree = ""; }; - 62959B8225253A9500A3D7F1 /* Capacitor.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = Capacitor.modulemap; sourceTree = ""; }; - 62959BBD2526510200A3D7F1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6296A77B253A2E49005A202A /* TestsHostApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestsHostApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6296A77D253A2E49005A202A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 6296A781253A2E49005A202A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 6296A7A1253A2E49005A202A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 6296A784253A2E49005A202A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6296A786253A2E49005A202A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6296A789253A2E49005A202A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 6296A78B253A2E49005A202A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 62A91C3325535F5700861508 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; - 62A91C392553710300861508 /* nonjson.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nonjson.json; sourceTree = ""; }; - 62ADC0C925CB678000E914DE /* PluginCallResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginCallResult.swift; sourceTree = ""; }; - 62D43AEF2581817500673C24 /* WKWebView+Capacitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WKWebView+Capacitor.swift"; sourceTree = ""; }; - 62D43B642582A13D00673C24 /* WKWebView+Capacitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WKWebView+Capacitor.m"; sourceTree = ""; }; - 62E0735225535E6500BAAADB /* server.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = server.json; sourceTree = ""; }; - 62E0735325535E6500BAAADB /* bad.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = bad.json; sourceTree = ""; }; - 62E0735425535E6500BAAADB /* flat.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = flat.json; sourceTree = ""; }; - 62E0735525535E6500BAAADB /* hierarchy.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = hierarchy.json; sourceTree = ""; }; - 62E207AD2588234500A78983 /* WebViewDelegationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewDelegationHandler.swift; sourceTree = ""; }; - 62E79C572638AF7500414164 /* native-bridge.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "native-bridge.js"; sourceTree = ""; }; - 62E79C712638B23300414164 /* JSExportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSExportTests.swift; sourceTree = ""; }; - 62FABD1925AE5C01007B3814 /* Array+Capacitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Capacitor.swift"; sourceTree = ""; }; - 62FABD2225AE60BA007B3814 /* BridgedTypesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BridgedTypesTests.m; sourceTree = ""; }; - 62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgedTypesHelper.swift; sourceTree = ""; }; - 9527076F2FD9DD260079E5D3 /* CAPSceneDelegateProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPSceneDelegateProxy.swift; sourceTree = ""; }; - 957BD93E2E78A4A20056874C /* SystemBars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemBars.swift; sourceTree = ""; }; - A327E6B228DB8B2800CA8B0A /* HttpRequestHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpRequestHandler.swift; sourceTree = ""; }; - A327E6B428DB8B2900CA8B0A /* CapacitorHttp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CapacitorHttp.swift; sourceTree = ""; }; - A327E6B528DB8B2900CA8B0A /* CapacitorUrlRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CapacitorUrlRequest.swift; sourceTree = ""; }; - A38C3D7628484E76004B3680 /* CapacitorCookies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacitorCookies.swift; sourceTree = ""; }; - A38C3D7A2848BE6F004B3680 /* CapacitorCookieManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacitorCookieManager.swift; sourceTree = ""; }; - A71289E527F380A500DADDF3 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; - A71289EA27F380FD00DADDF3 /* RouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = ""; }; - AA01F00D0000000000000001 /* HttpInterceptorNavigationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpInterceptorNavigationTests.swift; sourceTree = ""; }; - A7187FD12BD1CB7D00093C45 /* CAPPluginMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPPluginMethod.swift; sourceTree = ""; }; - A76739782B98E09700795F7B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - A771ADED2C8B845000AF234D /* DateCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateCodableTests.swift; sourceTree = ""; }; - A771ADF02C8B909100AF234D /* URLCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLCodableTests.swift; sourceTree = ""; }; - A7BE62CB2B486A5400165ACB /* KeyValueStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueStore.swift; sourceTree = ""; }; - A7D474D42C8BA8E8005620A8 /* DataCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataCodableTests.swift; sourceTree = ""; }; - A7D474D72C8BA8FD005620A8 /* NonconformingFloatCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonconformingFloatCodableTests.swift; sourceTree = ""; }; - A7D8B3512B238A840003FAD6 /* JSValueEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSValueEncoder.swift; sourceTree = ""; }; - A7D8B3562B23B2110003FAD6 /* CodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableTests.swift; sourceTree = ""; }; - A7D8B3602B263B8D0003FAD6 /* CodableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CodableTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - A7D8B3622B263B8D0003FAD6 /* NestedCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedCodableTests.swift; sourceTree = ""; }; - A7D8B36D2B2692300003FAD6 /* SuperCodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuperCodableTests.swift; sourceTree = ""; }; - A7D9312E2B23710300FF59A2 /* JSValueDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSValueDecoder.swift; sourceTree = ""; }; - A7DB03AB29B001E300888AE9 /* CAPBridgedPlugin+getMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CAPBridgedPlugin+getMethod.swift"; sourceTree = ""; }; - A7F7EDCC291EC75C0015B73B /* CAPPlugin+LoadInstance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CAPPlugin+LoadInstance.swift"; sourceTree = ""; }; - A7F7EDD4292BE8520015B73B /* CAPInstancePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPInstancePlugin.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 50503EDB1FC08594003606DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 501CBAA71FC0A723009B0D4D /* WebKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 50503EE51FC08595003606DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 50503EE91FC08595003606DC /* Capacitor.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6296A778253A2E49005A202A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A7D8B35D2B263B8D0003FAD6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A7D8B3642B263B8D0003FAD6 /* Capacitor.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 501CBAA51FC0A723009B0D4D /* Frameworks */ = { - isa = PBXGroup; - children = ( - 501CBAA61FC0A723009B0D4D /* WebKit.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 50503ED51FC08594003606DC = { - isa = PBXGroup; - children = ( - 62959AE12524DA7700A3D7F1 /* Capacitor */, - 50503EEC1FC08595003606DC /* CapacitorTests */, - 6296A77C253A2E49005A202A /* TestsHostApp */, - A7D8B3612B263B8D0003FAD6 /* CodableTests */, - 50503EE01FC08594003606DC /* Products */, - 501CBAA51FC0A723009B0D4D /* Frameworks */, - ); - sourceTree = ""; - }; - 50503EE01FC08594003606DC /* Products */ = { - isa = PBXGroup; - children = ( - 50503EDF1FC08594003606DC /* Capacitor.framework */, - 50503EE81FC08595003606DC /* CapacitorTests.xctest */, - 6296A77B253A2E49005A202A /* TestsHostApp.app */, - A7D8B3602B263B8D0003FAD6 /* CodableTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 50503EEC1FC08595003606DC /* CapacitorTests */ = { - isa = PBXGroup; - children = ( - 50503EED1FC08595003606DC /* CapacitorTests.swift */, - 621ECCC2254204B700D3D615 /* BridgedTypesTests.swift */, - 62FABD2225AE60BA007B3814 /* BridgedTypesTests.m */, - 62A91C3325535F5700861508 /* ConfigurationTests.swift */, - 62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */, - 621ECCC7254204BE00D3D615 /* JSONSerializationWrapper.h */, - 621ECCC6254204BE00D3D615 /* JSONSerializationWrapper.m */, - 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */, - 621ECCCD254204C400D3D615 /* CapacitorTests-Bridging-Header.h */, - 62E79C712638B23300414164 /* JSExportTests.swift */, - 62959BBD2526510200A3D7F1 /* Info.plist */, - A71289EA27F380FD00DADDF3 /* RouterTests.swift */, - AA01F00D0000000000000001 /* HttpInterceptorNavigationTests.swift */, - ); - path = CapacitorTests; - sourceTree = ""; - }; - 62959AE12524DA7700A3D7F1 /* Capacitor */ = { - isa = PBXGroup; - children = ( - 9527076F2FD9DD260079E5D3 /* CAPSceneDelegateProxy.swift */, - A7D9312C2B2370EF00FF59A2 /* Codable */, - 0F8F33B127DA980A003F49D6 /* PluginConfig.swift */, - A76739782B98E09700795F7B /* PrivacyInfo.xcprivacy */, - 62959B0F2524DA7700A3D7F1 /* Capacitor.h */, - 62959B132524DA7700A3D7F1 /* CAPPlugin.h */, - 62959B012524DA7700A3D7F1 /* CAPPlugin.m */, - A7F7EDCC291EC75C0015B73B /* CAPPlugin+LoadInstance.swift */, - 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */, - A7DB03AB29B001E300888AE9 /* CAPBridgedPlugin+getMethod.swift */, - 62959B092524DA7700A3D7F1 /* CAPPluginMethod.h */, - 62959AE82524DA7700A3D7F1 /* CAPPluginMethod.m */, - A7187FD12BD1CB7D00093C45 /* CAPPluginMethod.swift */, - 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */, - 62959B062524DA7700A3D7F1 /* CAPPluginCall.m */, - 62959AE62524DA7700A3D7F1 /* CAPPluginCall.swift */, - A7F7EDD4292BE8520015B73B /* CAPInstancePlugin.swift */, - 62ADC0C925CB678000E914DE /* PluginCallResult.swift */, - 621ECCBB2542046400D3D615 /* JSTypes.swift */, - 621ECCB62542045900D3D615 /* CAPBridgedJSTypes.h */, - 621ECCB42542045900D3D615 /* CAPBridgedJSTypes.m */, - 623D68F9254C5037002D01D1 /* KeyPath.swift */, - 62959AFF2524DA7700A3D7F1 /* JS.swift */, - 62959AE32524DA7700A3D7F1 /* JSExport.swift */, - 621ECCD4254205BD00D3D615 /* CAPBridgeProtocol.swift */, - 621ECCD9254205C400D3D615 /* CapacitorBridge.swift */, - 62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */, - 621ECCE2254206A600D3D615 /* CAPApplicationDelegateProxy.swift */, - 62959B0A2524DA7700A3D7F1 /* CAPBridgeDelegate.swift */, - 62E207AD2588234500A78983 /* WebViewDelegationHandler.swift */, - 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */, - 62959AEA2524DA7700A3D7F1 /* Plugins */, - 623D6907254C6FDF002D01D1 /* CAPInstanceDescriptor.h */, - 623D6908254C6FDF002D01D1 /* CAPInstanceDescriptor.m */, - 623D6913254C7030002D01D1 /* CAPInstanceDescriptor.swift */, - 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */, - 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */, - 6214934625509C3F006C36F9 /* CAPInstanceConfiguration.swift */, - 62959B082524DA7700A3D7F1 /* CAPLog.swift */, - 62959B102524DA7700A3D7F1 /* DocLinks.swift */, - 62959B152524DA7700A3D7F1 /* CAPNotifications.swift */, - 62959B072524DA7700A3D7F1 /* CapacitorExtension.swift */, - 62959B112524DA7700A3D7F1 /* Data+Capacitor.swift */, - 62FABD1925AE5C01007B3814 /* Array+Capacitor.swift */, - 62D43AEF2581817500673C24 /* WKWebView+Capacitor.swift */, - 62D43B642582A13D00673C24 /* WKWebView+Capacitor.m */, - 62959AE92524DA7700A3D7F1 /* UIColor.swift */, - 62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */, - 62959B122524DA7700A3D7F1 /* Info.plist */, - 62959B8225253A9500A3D7F1 /* Capacitor.modulemap */, - 373A69C0255C9360000A6F44 /* NotificationHandlerProtocol.swift */, - 373A69F1255C95D0000A6F44 /* NotificationRouter.swift */, - 62E79C562638AF7500414164 /* assets */, - A71289E527F380A500DADDF3 /* Router.swift */, - A7BE62CB2B486A5400165ACB /* KeyValueStore.swift */, - 0F83E884285A332D006C43CB /* AppUUID.swift */, - ); - path = Capacitor; - sourceTree = ""; - }; - 62959AEA2524DA7700A3D7F1 /* Plugins */ = { - isa = PBXGroup; - children = ( - 957BD93E2E78A4A20056874C /* SystemBars.swift */, - A327E6B428DB8B2900CA8B0A /* CapacitorHttp.swift */, - A327E6B528DB8B2900CA8B0A /* CapacitorUrlRequest.swift */, - A327E6B228DB8B2800CA8B0A /* HttpRequestHandler.swift */, - 62959AEF2524DA7700A3D7F1 /* Console.swift */, - 62959AF32524DA7700A3D7F1 /* WebView.swift */, - A38C3D7628484E76004B3680 /* CapacitorCookies.swift */, - A38C3D7A2848BE6F004B3680 /* CapacitorCookieManager.swift */, - ); - path = Plugins; - sourceTree = ""; - }; - 6296A77C253A2E49005A202A /* TestsHostApp */ = { - isa = PBXGroup; - children = ( - 6296A77D253A2E49005A202A /* AppDelegate.swift */, - 6296A7A1253A2E49005A202A /* SceneDelegate.swift */, - 6296A781253A2E49005A202A /* ViewController.swift */, - 62E0735125535E6500BAAADB /* configurations */, - 6296A783253A2E49005A202A /* Main.storyboard */, - 6296A786253A2E49005A202A /* Assets.xcassets */, - 6296A788253A2E49005A202A /* LaunchScreen.storyboard */, - 6296A78B253A2E49005A202A /* Info.plist */, - ); - path = TestsHostApp; - sourceTree = ""; - }; - 62E0735125535E6500BAAADB /* configurations */ = { - isa = PBXGroup; - children = ( - 62E0735225535E6500BAAADB /* server.json */, - 62E0735325535E6500BAAADB /* bad.json */, - 62E0735425535E6500BAAADB /* flat.json */, - 626D2D902613B4BB0046CE81 /* hidinglogs.json */, - 62E0735525535E6500BAAADB /* hierarchy.json */, - 62A91C392553710300861508 /* nonjson.json */, - ); - path = configurations; - sourceTree = ""; - }; - 62E79C562638AF7500414164 /* assets */ = { - isa = PBXGroup; - children = ( - 62E79C572638AF7500414164 /* native-bridge.js */, - ); - path = assets; - sourceTree = ""; - }; - A7D8B3612B263B8D0003FAD6 /* CodableTests */ = { - isa = PBXGroup; - children = ( - A7D8B3622B263B8D0003FAD6 /* NestedCodableTests.swift */, - A7D8B3562B23B2110003FAD6 /* CodableTests.swift */, - A7D8B36D2B2692300003FAD6 /* SuperCodableTests.swift */, - A771ADED2C8B845000AF234D /* DateCodableTests.swift */, - A771ADF02C8B909100AF234D /* URLCodableTests.swift */, - A7D474D42C8BA8E8005620A8 /* DataCodableTests.swift */, - A7D474D72C8BA8FD005620A8 /* NonconformingFloatCodableTests.swift */, - ); - path = CodableTests; - sourceTree = ""; - }; - A7D9312C2B2370EF00FF59A2 /* Codable */ = { - isa = PBXGroup; - children = ( - A7D9312E2B23710300FF59A2 /* JSValueDecoder.swift */, - A7D8B3512B238A840003FAD6 /* JSValueEncoder.swift */, - ); - path = Codable; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 50503EDC1FC08594003606DC /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 62959B412524DA7800A3D7F1 /* Capacitor.h in Headers */, - 62959B452524DA7800A3D7F1 /* CAPPlugin.h in Headers */, - 62959B162524DA7800A3D7F1 /* CAPPluginCall.h in Headers */, - 62959B3B2524DA7800A3D7F1 /* CAPPluginMethod.h in Headers */, - 623D691D254C7462002D01D1 /* CAPInstanceConfiguration.h in Headers */, - 623D6909254C6FDF002D01D1 /* CAPInstanceDescriptor.h in Headers */, - 62959B192524DA7800A3D7F1 /* CAPBridgedPlugin.h in Headers */, - 621ECCB82542045900D3D615 /* CAPBridgedJSTypes.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 50503EDE1FC08594003606DC /* Capacitor */ = { - isa = PBXNativeTarget; - buildConfigurationList = 50503EF31FC08595003606DC /* Build configuration list for PBXNativeTarget "Capacitor" */; - buildPhases = ( - 50503EDA1FC08594003606DC /* Sources */, - 50503EDB1FC08594003606DC /* Frameworks */, - 50503EDC1FC08594003606DC /* Headers */, - 50503EDD1FC08594003606DC /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Capacitor; - productName = Avocado; - productReference = 50503EDF1FC08594003606DC /* Capacitor.framework */; - productType = "com.apple.product-type.framework"; - }; - 50503EE71FC08595003606DC /* CapacitorTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 50503EF61FC08595003606DC /* Build configuration list for PBXNativeTarget "CapacitorTests" */; - buildPhases = ( - 50503EE41FC08595003606DC /* Sources */, - 50503EE51FC08595003606DC /* Frameworks */, - 50503EE61FC08595003606DC /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 50503EEB1FC08595003606DC /* PBXTargetDependency */, - 6296A797253A2EAE005A202A /* PBXTargetDependency */, - ); - name = CapacitorTests; - productName = AvocadoTests; - productReference = 50503EE81FC08595003606DC /* CapacitorTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 6296A77A253A2E49005A202A /* TestsHostApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6296A78F253A2E49005A202A /* Build configuration list for PBXNativeTarget "TestsHostApp" */; - buildPhases = ( - 6296A777253A2E49005A202A /* Sources */, - 6296A778253A2E49005A202A /* Frameworks */, - 6296A779253A2E49005A202A /* Resources */, - 622BB9C32541FE1900A5DBCA /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TestsHostApp; - productName = TestsHostApp; - productReference = 6296A77B253A2E49005A202A /* TestsHostApp.app */; - productType = "com.apple.product-type.application"; - }; - A7D8B35F2B263B8D0003FAD6 /* CodableTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = A7D8B3672B263B8D0003FAD6 /* Build configuration list for PBXNativeTarget "CodableTests" */; - buildPhases = ( - A7D8B35C2B263B8D0003FAD6 /* Sources */, - A7D8B35D2B263B8D0003FAD6 /* Frameworks */, - A7D8B35E2B263B8D0003FAD6 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - A7D8B3662B263B8D0003FAD6 /* PBXTargetDependency */, - ); - name = CodableTests; - productName = CodableTests; - productReference = A7D8B3602B263B8D0003FAD6 /* CodableTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 50503ED61FC08594003606DC /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1240; - ORGANIZATIONNAME = "Drifty Co."; - TargetAttributes = { - 50503EDE1FC08594003606DC = { - CreatedOnToolsVersion = 9.0; - LastSwiftMigration = 0940; - ProvisioningStyle = Automatic; - }; - 50503EE71FC08595003606DC = { - CreatedOnToolsVersion = 9.0; - LastSwiftMigration = 1200; - ProvisioningStyle = Automatic; - TestTargetID = 6296A77A253A2E49005A202A; - }; - 6296A77A253A2E49005A202A = { - CreatedOnToolsVersion = 12.0; - ProvisioningStyle = Automatic; - }; - A7D8B35F2B263B8D0003FAD6 = { - CreatedOnToolsVersion = 15.0.1; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 50503ED91FC08594003606DC /* Build configuration list for PBXProject "Capacitor" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 50503ED51FC08594003606DC; - productRefGroup = 50503EE01FC08594003606DC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 50503EDE1FC08594003606DC /* Capacitor */, - 50503EE71FC08595003606DC /* CapacitorTests */, - 6296A77A253A2E49005A202A /* TestsHostApp */, - A7D8B35F2B263B8D0003FAD6 /* CodableTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 50503EDD1FC08594003606DC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A76739792B98E09700795F7B /* PrivacyInfo.xcprivacy in Resources */, - 62E79CD7263A178B00414164 /* native-bridge.js in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 50503EE61FC08595003606DC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6296A779253A2E49005A202A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6296A78A253A2E49005A202A /* LaunchScreen.storyboard in Resources */, - 6296A787253A2E49005A202A /* Assets.xcassets in Resources */, - 6296A785253A2E49005A202A /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A7D8B35E2B263B8D0003FAD6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 50503EDA1FC08594003606DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A38C3D7728484E76004B3680 /* CapacitorCookies.swift in Sources */, - A71289E627F380A500DADDF3 /* Router.swift in Sources */, - A327E6B828DB8B2900CA8B0A /* CapacitorUrlRequest.swift in Sources */, - A7D9312F2B23710300FF59A2 /* JSValueDecoder.swift in Sources */, - 62959B362524DA7800A3D7F1 /* CAPBridgeViewController.swift in Sources */, - 621ECCB72542045900D3D615 /* CAPBridgedJSTypes.m in Sources */, - 621ECCD6254205BD00D3D615 /* CAPBridgeProtocol.swift in Sources */, - 62D43AF02581817500673C24 /* WKWebView+Capacitor.swift in Sources */, - 62959B432524DA7800A3D7F1 /* Data+Capacitor.swift in Sources */, - 62E207AE2588234500A78983 /* WebViewDelegationHandler.swift in Sources */, - A7187FD22BD1CB7D00093C45 /* CAPPluginMethod.swift in Sources */, - 621ECCBC2542046400D3D615 /* JSTypes.swift in Sources */, - 621ECCDA254205C400D3D615 /* CapacitorBridge.swift in Sources */, - 62959B382524DA7800A3D7F1 /* CAPPluginCall.m in Sources */, - 623D690A254C6FDF002D01D1 /* CAPInstanceDescriptor.m in Sources */, - A7D8B3522B238A840003FAD6 /* JSValueEncoder.swift in Sources */, - A7F7EDD5292BE8520015B73B /* CAPInstancePlugin.swift in Sources */, - A38C3D7B2848BE6F004B3680 /* CapacitorCookieManager.swift in Sources */, - 952707712FD9DD2D0079E5D3 /* CAPSceneDelegateProxy.swift in Sources */, - 62959B1D2524DA7800A3D7F1 /* UIColor.swift in Sources */, - 62959B332524DA7800A3D7F1 /* CAPPlugin.m in Sources */, - 62959B1C2524DA7800A3D7F1 /* CAPPluginMethod.m in Sources */, - 62ADC0CA25CB678000E914DE /* PluginCallResult.swift in Sources */, - 62959B472524DA7800A3D7F1 /* CAPNotifications.swift in Sources */, - 62D43B652582A13D00673C24 /* WKWebView+Capacitor.m in Sources */, - 62959B312524DA7800A3D7F1 /* JS.swift in Sources */, - 373A69F2255C95D0000A6F44 /* NotificationRouter.swift in Sources */, - 62959B1A2524DA7800A3D7F1 /* CAPPluginCall.swift in Sources */, - 62959B302524DA7800A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m in Sources */, - 62959B392524DA7800A3D7F1 /* CapacitorExtension.swift in Sources */, - A327E6B628DB8B2900CA8B0A /* HttpRequestHandler.swift in Sources */, - 957BD9402E78A4A50056874C /* SystemBars.swift in Sources */, - 62959B422524DA7800A3D7F1 /* DocLinks.swift in Sources */, - 62FABD1A25AE5C01007B3814 /* Array+Capacitor.swift in Sources */, - A7BE62CC2B486A5400165ACB /* KeyValueStore.swift in Sources */, - 62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */, - 373A69C1255C9360000A6F44 /* NotificationHandlerProtocol.swift in Sources */, - 0F83E885285A332E006C43CB /* AppUUID.swift in Sources */, - 625AF1ED258963C700869675 /* WebViewAssetHandler.swift in Sources */, - A327E6B728DB8B2900CA8B0A /* CapacitorHttp.swift in Sources */, - 0F8F33B327DA980A003F49D6 /* PluginConfig.swift in Sources */, - 62959B3C2524DA7800A3D7F1 /* CAPBridgeDelegate.swift in Sources */, - 623D691E254C7462002D01D1 /* CAPInstanceConfiguration.m in Sources */, - 623D68FA254C5037002D01D1 /* KeyPath.swift in Sources */, - 62959B222524DA7800A3D7F1 /* Console.swift in Sources */, - 62959B3A2524DA7800A3D7F1 /* CAPLog.swift in Sources */, - A7DB03AC29B001E300888AE9 /* CAPBridgedPlugin+getMethod.swift in Sources */, - 6214934725509C3F006C36F9 /* CAPInstanceConfiguration.swift in Sources */, - 623D6914254C7030002D01D1 /* CAPInstanceDescriptor.swift in Sources */, - 621ECCE3254206A600D3D615 /* CAPApplicationDelegateProxy.swift in Sources */, - A7F7EDCD291EC75C0015B73B /* CAPPlugin+LoadInstance.swift in Sources */, - 62959B262524DA7800A3D7F1 /* WebView.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 50503EE41FC08595003606DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 62E79C722638B23300414164 /* JSExportTests.swift in Sources */, - 50503EEE1FC08595003606DC /* CapacitorTests.swift in Sources */, - 62FABD2B25AE6182007B3814 /* BridgedTypesHelper.swift in Sources */, - 621ECCC8254204BE00D3D615 /* JSONSerializationWrapper.m in Sources */, - 62A91C3425535F5700861508 /* ConfigurationTests.swift in Sources */, - 62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */, - 621ECCC3254204B700D3D615 /* BridgedTypesTests.swift in Sources */, - A71289EB27F380FD00DADDF3 /* RouterTests.swift in Sources */, - AA01F00D0000000000000002 /* HttpInterceptorNavigationTests.swift in Sources */, - 6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6296A777253A2E49005A202A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6296A782253A2E49005A202A /* ViewController.swift in Sources */, - 6296A77E253A2E49005A202A /* AppDelegate.swift in Sources */, - 6296A7A0253A2E49005A202A /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A7D8B35C2B263B8D0003FAD6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A771ADEE2C8B845000AF234D /* DateCodableTests.swift in Sources */, - A7D8B3632B263B8D0003FAD6 /* NestedCodableTests.swift in Sources */, - A7D474D52C8BA8E8005620A8 /* DataCodableTests.swift in Sources */, - A7D8B36A2B263B990003FAD6 /* CodableTests.swift in Sources */, - A7D8B36E2B2692300003FAD6 /* SuperCodableTests.swift in Sources */, - A7D474D82C8BA8FD005620A8 /* NonconformingFloatCodableTests.swift in Sources */, - A771ADF12C8B909100AF234D /* URLCodableTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 50503EEB1FC08595003606DC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 50503EDE1FC08594003606DC /* Capacitor */; - targetProxy = 50503EEA1FC08595003606DC /* PBXContainerItemProxy */; - }; - 6296A797253A2EAE005A202A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6296A77A253A2E49005A202A /* TestsHostApp */; - targetProxy = 6296A796253A2EAE005A202A /* PBXContainerItemProxy */; - }; - A7D8B3662B263B8D0003FAD6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 50503EDE1FC08594003606DC /* Capacitor */; - targetProxy = A7D8B3652B263B8D0003FAD6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 6296A783253A2E49005A202A /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6296A784253A2E49005A202A /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6296A788253A2E49005A202A /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6296A789253A2E49005A202A /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 50503EF11FC08595003606DC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 50503EF21FC08595003606DC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 50503EF41FC08595003606DC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - INFOPLIST_FILE = Capacitor/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = Capacitor/Capacitor.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.Capacitor; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 50503EF51FC08595003606DC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - INFOPLIST_FILE = Capacitor/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = Capacitor/Capacitor.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.Capacitor; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 50503EF71FC08595003606DC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUILD_LIBRARY_FOR_DISTRIBUTION = NO; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = CapacitorTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.CapacitorTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "CapacitorTests/CapacitorTests-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestsHostApp.app/TestsHostApp"; - }; - name = Debug; - }; - 50503EF81FC08595003606DC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUILD_LIBRARY_FOR_DISTRIBUTION = NO; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = CapacitorTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.CapacitorTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "CapacitorTests/CapacitorTests-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestsHostApp.app/TestsHostApp"; - }; - name = Release; - }; - 6296A78C253A2E49005A202A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = TestsHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.TestsHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6296A78D253A2E49005A202A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = TestsHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.TestsHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - A7D8B3682B263B8D0003FAD6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.CodableTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - A7D8B3692B263B8D0003FAD6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.capacitorjs.ios.CodableTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 50503ED91FC08594003606DC /* Build configuration list for PBXProject "Capacitor" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 50503EF11FC08595003606DC /* Debug */, - 50503EF21FC08595003606DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 50503EF31FC08595003606DC /* Build configuration list for PBXNativeTarget "Capacitor" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 50503EF41FC08595003606DC /* Debug */, - 50503EF51FC08595003606DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 50503EF61FC08595003606DC /* Build configuration list for PBXNativeTarget "CapacitorTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 50503EF71FC08595003606DC /* Debug */, - 50503EF81FC08595003606DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6296A78F253A2E49005A202A /* Build configuration list for PBXNativeTarget "TestsHostApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6296A78C253A2E49005A202A /* Debug */, - 6296A78D253A2E49005A202A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A7D8B3672B263B8D0003FAD6 /* Build configuration list for PBXNativeTarget "CodableTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A7D8B3682B263B8D0003FAD6 /* Debug */, - A7D8B3692B263B8D0003FAD6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 50503ED61FC08594003606DC /* Project object */; -} diff --git a/ios/Capacitor/Capacitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Capacitor/Capacitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d..0000000000 --- a/ios/Capacitor/Capacitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Capacitor/Capacitor.xcodeproj/xcshareddata/xcschemes/Capacitor.xcscheme b/ios/Capacitor/Capacitor.xcodeproj/xcshareddata/xcschemes/Capacitor.xcscheme deleted file mode 100644 index ed774e08e0..0000000000 --- a/ios/Capacitor/Capacitor.xcodeproj/xcshareddata/xcschemes/Capacitor.xcscheme +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Capacitor/Capacitor.xcworkspace/contents.xcworkspacedata b/ios/Capacitor/Capacitor.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 37b6585fc3..0000000000 --- a/ios/Capacitor/Capacitor.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/Capacitor/Capacitor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Capacitor/Capacitor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d..0000000000 --- a/ios/Capacitor/Capacitor.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Capacitor/Capacitor/Info.plist b/ios/Capacitor/Capacitor/Info.plist deleted file mode 100644 index 1007fd9dd7..0000000000 --- a/ios/Capacitor/Capacitor/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/ios/Capacitor/CapacitorTests/CapacitorTests-Bridging-Header.h b/ios/Capacitor/CapacitorTests/CapacitorTests-Bridging-Header.h deleted file mode 100644 index b0f308df84..0000000000 --- a/ios/Capacitor/CapacitorTests/CapacitorTests-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "JSONSerializationWrapper.h" diff --git a/ios/Capacitor/CapacitorTests/Info.plist b/ios/Capacitor/CapacitorTests/Info.plist deleted file mode 100644 index 6c40a6cd0c..0000000000 --- a/ios/Capacitor/CapacitorTests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/ios/Capacitor/TestsHostApp/AppDelegate.swift b/ios/Capacitor/TestsHostApp/AppDelegate.swift deleted file mode 100644 index 9107e3c451..0000000000 --- a/ios/Capacitor/TestsHostApp/AppDelegate.swift +++ /dev/null @@ -1,18 +0,0 @@ -import UIKit - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func application(_ application: UIApplication, - configurationForConnecting connectingSceneSession: UISceneSession, - options: UIScene.ConnectionOptions) -> UISceneConfiguration { - let config = UISceneConfiguration(name: "Default Configuration", - sessionRole: connectingSceneSession.role) - config.delegateClass = SceneDelegate.self - return config - } -} diff --git a/ios/Capacitor/TestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/Capacitor/TestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb87897008..0000000000 --- a/ios/Capacitor/TestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/Capacitor/TestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Capacitor/TestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1a..0000000000 --- a/ios/Capacitor/TestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/Capacitor/TestsHostApp/Assets.xcassets/Contents.json b/ios/Capacitor/TestsHostApp/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a7..0000000000 --- a/ios/Capacitor/TestsHostApp/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/Capacitor/TestsHostApp/Base.lproj/LaunchScreen.storyboard b/ios/Capacitor/TestsHostApp/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f3..0000000000 --- a/ios/Capacitor/TestsHostApp/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Capacitor/TestsHostApp/Base.lproj/Main.storyboard b/ios/Capacitor/TestsHostApp/Base.lproj/Main.storyboard deleted file mode 100644 index 25a763858e..0000000000 --- a/ios/Capacitor/TestsHostApp/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Capacitor/TestsHostApp/Info.plist b/ios/Capacitor/TestsHostApp/Info.plist deleted file mode 100644 index 5b531f7b27..0000000000 --- a/ios/Capacitor/TestsHostApp/Info.plist +++ /dev/null @@ -1,66 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/ios/Capacitor/TestsHostApp/SceneDelegate.swift b/ios/Capacitor/TestsHostApp/SceneDelegate.swift deleted file mode 100644 index e0be6e9cfe..0000000000 --- a/ios/Capacitor/TestsHostApp/SceneDelegate.swift +++ /dev/null @@ -1,5 +0,0 @@ -import UIKit - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - var window: UIWindow? -} diff --git a/ios/Capacitor/TestsHostApp/ViewController.swift b/ios/Capacitor/TestsHostApp/ViewController.swift deleted file mode 100644 index ae980e1ea3..0000000000 --- a/ios/Capacitor/TestsHostApp/ViewController.swift +++ /dev/null @@ -1,9 +0,0 @@ -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } -} diff --git a/ios/CapacitorCordova.podspec b/ios/CapacitorCordova.podspec index 98f6bc3474..b7846595f0 100644 --- a/ios/CapacitorCordova.podspec +++ b/ios/CapacitorCordova.podspec @@ -16,11 +16,12 @@ Pod::Spec.new do |s| s.authors = { 'Ionic Team' => 'hi@ionicframework.com' } s.source = { git: 'https://github.com/ionic-team/capacitor', tag: s.version.to_s } s.platform = :ios, 16.0 - s.source_files = "#{prefix}CapacitorCordova/CapacitorCordova/**/*.{h,m,swift}" - s.public_header_files = "#{prefix}CapacitorCordova/CapacitorCordova/Classes/Public/*.h", - "#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.h" - s.module_map = "#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap" - s.resource_bundles = { 'CapacitorCordova' => ["#{prefix}CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy"] } + s.source_files = "#{prefix}Sources/Cordova/**/*.{h,m}", + "#{prefix}Sources/CapacitorCordova/**/*.swift" + s.public_header_files = "#{prefix}Sources/Cordova/include/Cordova/*.h", + "#{prefix}Sources/Cordova/CapacitorCordova.h" + s.module_map = "#{prefix}Sources/Cordova/CapacitorCordova.modulemap" + s.resource_bundles = { 'CapacitorCordova' => ["#{prefix}Sources/Cordova/PrivacyInfo.xcprivacy"] } s.requires_arc = true s.dependency 'Capacitor', s.version.to_s s.framework = 'WebKit' diff --git a/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.pbxproj b/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.pbxproj deleted file mode 100644 index 59d25512a5..0000000000 --- a/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.pbxproj +++ /dev/null @@ -1,499 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 0B61A7E52B114AA00035F2DB /* CDVWebViewProcessPoolFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B61A7E32B114A9F0035F2DB /* CDVWebViewProcessPoolFactory.m */; }; - 0B61A7E62B114AA00035F2DB /* CDVWebViewProcessPoolFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B61A7E42B114AA00035F2DB /* CDVWebViewProcessPoolFactory.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1DBF5C182E9E908A00FAC24F /* CDVAvailabilityDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DBF5C172E9E908A00FAC24F /* CDVAvailabilityDeprecated.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F4F657C2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F4F657A2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.m */; }; - 2F4F657D2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F4F657B2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C86E11FE94845004B09C7 /* CapacitorCordova.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C86DF1FE94845004B09C7 /* CapacitorCordova.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C871D1FE98418004B09C7 /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F5C87121FE98417004B09C7 /* CDVPluginResult.m */; }; - 2F5C871E1FE98418004B09C7 /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C87131FE98417004B09C7 /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C871F1FE98418004B09C7 /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F5C87141FE98417004B09C7 /* CDVCommandDelegateImpl.m */; }; - 2F5C87201FE98418004B09C7 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F5C87151FE98417004B09C7 /* CDVInvokedUrlCommand.m */; }; - 2F5C87211FE98418004B09C7 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F5C87161FE98417004B09C7 /* CDVPlugin.m */; }; - 2F5C87221FE98418004B09C7 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C87171FE98417004B09C7 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C87231FE98418004B09C7 /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C87181FE98417004B09C7 /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C87241FE98418004B09C7 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C87191FE98418004B09C7 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C87251FE98418004B09C7 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C871A1FE98418004B09C7 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C87261FE98418004B09C7 /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C871B1FE98418004B09C7 /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F5C87271FE98418004B09C7 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F5C871C1FE98418004B09C7 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F856BFF203DEB320047344A /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F856BFD203DEB320047344A /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F856C00203DEB320047344A /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F856BFE203DEB320047344A /* CDVViewController.m */; }; - 2F8AC283217F3A20008C2C33 /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F8AC281217F3A20008C2C33 /* CDVURLProtocol.m */; }; - 2F8AC284217F3A20008C2C33 /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F8AC282217F3A20008C2C33 /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2F92AB5224D9ABA000954A4A /* CDVPlugin+Resources.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F92AB5024D9ABA000954A4A /* CDVPlugin+Resources.m */; }; - 2F92AB5324D9ABA000954A4A /* CDVPlugin+Resources.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F92AB5124D9ABA000954A4A /* CDVPlugin+Resources.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2FAD9772203C77B9000D30F8 /* CDVConfigParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FAD9770203C77B8000D30F8 /* CDVConfigParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2FAD9773203C77B9000D30F8 /* CDVConfigParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FAD9771203C77B9000D30F8 /* CDVConfigParser.m */; }; - 2FE19E2A20473160002A4E89 /* AppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FE19E2820473160002A4E89 /* AppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2FE19E2B20473160002A4E89 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FE19E2920473160002A4E89 /* AppDelegate.m */; }; - 62959B66252524CD00A3D7F1 /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959B65252524CD00A3D7F1 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B6A252524D700A3D7F1 /* CDVPluginManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959B68252524D700A3D7F1 /* CDVPluginManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 62959B6B252524D700A3D7F1 /* CDVPluginManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959B69252524D700A3D7F1 /* CDVPluginManager.m */; }; - A76739742B98CC7800795F7B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = A76739732B98CC7800795F7B /* PrivacyInfo.xcprivacy */; }; - D4DA0E9B2FFD28C60031AA74 /* Plugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DA0E9A2FFD28C60031AA74 /* Plugin.swift */; }; - D4DA0ED52FFD573E0031AA74 /* Capacitor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4DA0ED42FFD573E0031AA74 /* Capacitor.framework */; }; - D4DA0ED62FFD573E0031AA74 /* Capacitor.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4DA0ED42FFD573E0031AA74 /* Capacitor.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - D4DA0ED72FFD573E0031AA74 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - D4DA0ED62FFD573E0031AA74 /* Capacitor.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0B61A7E32B114A9F0035F2DB /* CDVWebViewProcessPoolFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVWebViewProcessPoolFactory.m; sourceTree = ""; }; - 0B61A7E42B114AA00035F2DB /* CDVWebViewProcessPoolFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVWebViewProcessPoolFactory.h; sourceTree = ""; }; - 1DBF5C172E9E908A00FAC24F /* CDVAvailabilityDeprecated.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDVAvailabilityDeprecated.h; sourceTree = ""; }; - 2F4F657A2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+CordovaPreferences.m"; sourceTree = ""; }; - 2F4F657B2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+CordovaPreferences.h"; sourceTree = ""; }; - 2F5C86DC1FE94845004B09C7 /* Cordova.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cordova.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2F5C86DF1FE94845004B09C7 /* CapacitorCordova.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CapacitorCordova.h; sourceTree = ""; }; - 2F5C86E01FE94845004B09C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 2F5C87121FE98417004B09C7 /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVPluginResult.m; sourceTree = ""; }; - 2F5C87131FE98417004B09C7 /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDV.h; sourceTree = ""; }; - 2F5C87141FE98417004B09C7 /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCommandDelegateImpl.m; sourceTree = ""; }; - 2F5C87151FE98417004B09C7 /* CDVInvokedUrlCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVInvokedUrlCommand.m; sourceTree = ""; }; - 2F5C87161FE98417004B09C7 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVPlugin.m; sourceTree = ""; }; - 2F5C87171FE98417004B09C7 /* CDVCommandDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCommandDelegate.h; sourceTree = ""; }; - 2F5C87181FE98417004B09C7 /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCommandDelegateImpl.h; sourceTree = ""; }; - 2F5C87191FE98418004B09C7 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVInvokedUrlCommand.h; sourceTree = ""; }; - 2F5C871A1FE98418004B09C7 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVAvailability.h; sourceTree = ""; }; - 2F5C871B1FE98418004B09C7 /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVPluginResult.h; sourceTree = ""; }; - 2F5C871C1FE98418004B09C7 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVPlugin.h; sourceTree = ""; }; - 2F856BFD203DEB320047344A /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVViewController.h; sourceTree = ""; }; - 2F856BFE203DEB320047344A /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVViewController.m; sourceTree = ""; }; - 2F8AC281217F3A20008C2C33 /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVURLProtocol.m; sourceTree = ""; }; - 2F8AC282217F3A20008C2C33 /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVURLProtocol.h; sourceTree = ""; }; - 2F92AB5024D9ABA000954A4A /* CDVPlugin+Resources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CDVPlugin+Resources.m"; sourceTree = ""; }; - 2F92AB5124D9ABA000954A4A /* CDVPlugin+Resources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CDVPlugin+Resources.h"; sourceTree = ""; }; - 2FAD9770203C77B8000D30F8 /* CDVConfigParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVConfigParser.h; sourceTree = ""; }; - 2FAD9771203C77B9000D30F8 /* CDVConfigParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVConfigParser.m; sourceTree = ""; }; - 2FE19E2820473160002A4E89 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 2FE19E2920473160002A4E89 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 62959B5F252522CB00A3D7F1 /* CapacitorCordova.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = CapacitorCordova.modulemap; sourceTree = ""; }; - 62959B65252524CD00A3D7F1 /* CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVScreenOrientationDelegate.h; sourceTree = ""; }; - 62959B68252524D700A3D7F1 /* CDVPluginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVPluginManager.h; sourceTree = ""; }; - 62959B69252524D700A3D7F1 /* CDVPluginManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVPluginManager.m; sourceTree = ""; }; - A76739732B98CC7800795F7B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - D4DA0E962FFD28680031AA74 /* Capacitor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Capacitor.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D4DA0E9A2FFD28C60031AA74 /* Plugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Plugin.swift; sourceTree = ""; }; - D4DA0ED42FFD573E0031AA74 /* Capacitor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Capacitor.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 2F5C86D81FE94845004B09C7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D4DA0ED52FFD573E0031AA74 /* Capacitor.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2F5C86D21FE94845004B09C7 = { - isa = PBXGroup; - children = ( - 2F5C86DE1FE94845004B09C7 /* CapacitorCordova */, - D4DA0E952FFD28680031AA74 /* Frameworks */, - 2F5C86DD1FE94845004B09C7 /* Products */, - ); - sourceTree = ""; - }; - 2F5C86DD1FE94845004B09C7 /* Products */ = { - isa = PBXGroup; - children = ( - 2F5C86DC1FE94845004B09C7 /* Cordova.framework */, - ); - name = Products; - sourceTree = ""; - }; - 2F5C86DE1FE94845004B09C7 /* CapacitorCordova */ = { - isa = PBXGroup; - children = ( - 2F5C86E71FE94859004B09C7 /* Classes */, - 2F5C86DF1FE94845004B09C7 /* CapacitorCordova.h */, - 62959B5F252522CB00A3D7F1 /* CapacitorCordova.modulemap */, - 2F5C86E01FE94845004B09C7 /* Info.plist */, - A76739732B98CC7800795F7B /* PrivacyInfo.xcprivacy */, - ); - path = CapacitorCordova; - sourceTree = ""; - }; - 2F5C86E71FE94859004B09C7 /* Classes */ = { - isa = PBXGroup; - children = ( - 2F5C86E81FE94861004B09C7 /* Public */, - ); - path = Classes; - sourceTree = ""; - }; - 2F5C86E81FE94861004B09C7 /* Public */ = { - isa = PBXGroup; - children = ( - D4DA0E9A2FFD28C60031AA74 /* Plugin.swift */, - 2FE19E2820473160002A4E89 /* AppDelegate.h */, - 2FE19E2920473160002A4E89 /* AppDelegate.m */, - 2F5C87131FE98417004B09C7 /* CDV.h */, - 2F5C871A1FE98418004B09C7 /* CDVAvailability.h */, - 1DBF5C172E9E908A00FAC24F /* CDVAvailabilityDeprecated.h */, - 2F5C87171FE98417004B09C7 /* CDVCommandDelegate.h */, - 2F5C87141FE98417004B09C7 /* CDVCommandDelegateImpl.m */, - 2F5C87181FE98417004B09C7 /* CDVCommandDelegateImpl.h */, - 2FAD9770203C77B8000D30F8 /* CDVConfigParser.h */, - 2FAD9771203C77B9000D30F8 /* CDVConfigParser.m */, - 2F5C87191FE98418004B09C7 /* CDVInvokedUrlCommand.h */, - 2F5C87151FE98417004B09C7 /* CDVInvokedUrlCommand.m */, - 2F92AB5124D9ABA000954A4A /* CDVPlugin+Resources.h */, - 2F92AB5024D9ABA000954A4A /* CDVPlugin+Resources.m */, - 2F5C871C1FE98418004B09C7 /* CDVPlugin.h */, - 2F5C87161FE98417004B09C7 /* CDVPlugin.m */, - 62959B68252524D700A3D7F1 /* CDVPluginManager.h */, - 62959B69252524D700A3D7F1 /* CDVPluginManager.m */, - 2F5C871B1FE98418004B09C7 /* CDVPluginResult.h */, - 2F5C87121FE98417004B09C7 /* CDVPluginResult.m */, - 62959B65252524CD00A3D7F1 /* CDVScreenOrientationDelegate.h */, - 2F8AC282217F3A20008C2C33 /* CDVURLProtocol.h */, - 2F8AC281217F3A20008C2C33 /* CDVURLProtocol.m */, - 2F4F657B2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.h */, - 2F4F657A2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.m */, - 2F856BFD203DEB320047344A /* CDVViewController.h */, - 2F856BFE203DEB320047344A /* CDVViewController.m */, - 0B61A7E42B114AA00035F2DB /* CDVWebViewProcessPoolFactory.h */, - 0B61A7E32B114A9F0035F2DB /* CDVWebViewProcessPoolFactory.m */, - ); - path = Public; - sourceTree = ""; - }; - D4DA0E952FFD28680031AA74 /* Frameworks */ = { - isa = PBXGroup; - children = ( - D4DA0ED42FFD573E0031AA74 /* Capacitor.framework */, - D4DA0E962FFD28680031AA74 /* Capacitor.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 2F5C86D91FE94845004B09C7 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 2FE19E2A20473160002A4E89 /* AppDelegate.h in Headers */, - 2F5C871E1FE98418004B09C7 /* CDV.h in Headers */, - 2F5C87231FE98418004B09C7 /* CDVCommandDelegateImpl.h in Headers */, - 2F5C87251FE98418004B09C7 /* CDVAvailability.h in Headers */, - 2F5C87271FE98418004B09C7 /* CDVPlugin.h in Headers */, - 2F5C87261FE98418004B09C7 /* CDVPluginResult.h in Headers */, - 2F5C87221FE98418004B09C7 /* CDVCommandDelegate.h in Headers */, - 2F5C87241FE98418004B09C7 /* CDVInvokedUrlCommand.h in Headers */, - 2FAD9772203C77B9000D30F8 /* CDVConfigParser.h in Headers */, - 2F856BFF203DEB320047344A /* CDVViewController.h in Headers */, - 2F4F657D2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.h in Headers */, - 2F8AC284217F3A20008C2C33 /* CDVURLProtocol.h in Headers */, - 2F92AB5324D9ABA000954A4A /* CDVPlugin+Resources.h in Headers */, - 62959B66252524CD00A3D7F1 /* CDVScreenOrientationDelegate.h in Headers */, - 0B61A7E62B114AA00035F2DB /* CDVWebViewProcessPoolFactory.h in Headers */, - 62959B6A252524D700A3D7F1 /* CDVPluginManager.h in Headers */, - 1DBF5C182E9E908A00FAC24F /* CDVAvailabilityDeprecated.h in Headers */, - 2F5C86E11FE94845004B09C7 /* CapacitorCordova.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 2F5C86DB1FE94845004B09C7 /* Cordova */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2F5C86E41FE94845004B09C7 /* Build configuration list for PBXNativeTarget "Cordova" */; - buildPhases = ( - 2F5C86D71FE94845004B09C7 /* Sources */, - 2F5C86D81FE94845004B09C7 /* Frameworks */, - 2F5C86D91FE94845004B09C7 /* Headers */, - 2F5C86DA1FE94845004B09C7 /* Resources */, - D4DA0ED72FFD573E0031AA74 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Cordova; - productName = AvocadoCordova; - productReference = 2F5C86DC1FE94845004B09C7 /* Cordova.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 2F5C86D31FE94845004B09C7 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1220; - ORGANIZATIONNAME = jcesarmobile; - TargetAttributes = { - 2F5C86DB1FE94845004B09C7 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 2650; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 2F5C86D61FE94845004B09C7 /* Build configuration list for PBXProject "CapacitorCordova" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 2F5C86D21FE94845004B09C7; - productRefGroup = 2F5C86DD1FE94845004B09C7 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 2F5C86DB1FE94845004B09C7 /* Cordova */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 2F5C86DA1FE94845004B09C7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A76739742B98CC7800795F7B /* PrivacyInfo.xcprivacy in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 2F5C86D71FE94845004B09C7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 62959B6B252524D700A3D7F1 /* CDVPluginManager.m in Sources */, - 2F5C871F1FE98418004B09C7 /* CDVCommandDelegateImpl.m in Sources */, - 2F5C871D1FE98418004B09C7 /* CDVPluginResult.m in Sources */, - 2F4F657C2091F1FD00EAA994 /* NSDictionary+CordovaPreferences.m in Sources */, - 0B61A7E52B114AA00035F2DB /* CDVWebViewProcessPoolFactory.m in Sources */, - 2F5C87211FE98418004B09C7 /* CDVPlugin.m in Sources */, - 2F92AB5224D9ABA000954A4A /* CDVPlugin+Resources.m in Sources */, - 2FAD9773203C77B9000D30F8 /* CDVConfigParser.m in Sources */, - 2F856C00203DEB320047344A /* CDVViewController.m in Sources */, - 2F5C87201FE98418004B09C7 /* CDVInvokedUrlCommand.m in Sources */, - D4DA0E9B2FFD28C60031AA74 /* Plugin.swift in Sources */, - 2FE19E2B20473160002A4E89 /* AppDelegate.m in Sources */, - 2F8AC283217F3A20008C2C33 /* CDVURLProtocol.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 2F5C86E21FE94845004B09C7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 2F5C86E31FE94845004B09C7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 2F5C86E51FE94845004B09C7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = CapacitorCordova/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = CapacitorCordova/CapacitorCordova.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.ios.CapacitorCordova; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 2F5C86E61FE94845004B09C7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = CapacitorCordova/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = CapacitorCordova/CapacitorCordova.modulemap; - PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.ios.CapacitorCordova; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2F5C86D61FE94845004B09C7 /* Build configuration list for PBXProject "CapacitorCordova" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2F5C86E21FE94845004B09C7 /* Debug */, - 2F5C86E31FE94845004B09C7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2F5C86E41FE94845004B09C7 /* Build configuration list for PBXNativeTarget "Cordova" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2F5C86E51FE94845004B09C7 /* Debug */, - 2F5C86E61FE94845004B09C7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 2F5C86D31FE94845004B09C7 /* Project object */; -} diff --git a/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d..0000000000 --- a/ios/CapacitorCordova/CapacitorCordova.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/CapacitorCordova/CapacitorCordova/Info.plist b/ios/CapacitorCordova/CapacitorCordova/Info.plist deleted file mode 100644 index 1483c473b4..0000000000 --- a/ios/CapacitorCordova/CapacitorCordova/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Cordova - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/ios/Capacitor/Capacitor/AppUUID.swift b/ios/Sources/Capacitor/AppUUID.swift similarity index 100% rename from ios/Capacitor/Capacitor/AppUUID.swift rename to ios/Sources/Capacitor/AppUUID.swift diff --git a/ios/Capacitor/Capacitor/Array+Capacitor.swift b/ios/Sources/Capacitor/Array+Capacitor.swift similarity index 100% rename from ios/Capacitor/Capacitor/Array+Capacitor.swift rename to ios/Sources/Capacitor/Array+Capacitor.swift diff --git a/ios/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift b/ios/Sources/Capacitor/CAPApplicationDelegateProxy.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift rename to ios/Sources/Capacitor/CAPApplicationDelegateProxy.swift diff --git a/ios/Capacitor/Capacitor/CAPBridgeDelegate.swift b/ios/Sources/Capacitor/CAPBridgeDelegate.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgeDelegate.swift rename to ios/Sources/Capacitor/CAPBridgeDelegate.swift diff --git a/ios/Capacitor/Capacitor/CAPBridgeProtocol.swift b/ios/Sources/Capacitor/CAPBridgeProtocol.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgeProtocol.swift rename to ios/Sources/Capacitor/CAPBridgeProtocol.swift diff --git a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift b/ios/Sources/Capacitor/CAPBridgeViewController.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgeViewController.swift rename to ios/Sources/Capacitor/CAPBridgeViewController.swift diff --git a/ios/Capacitor/Capacitor/CAPBridgedPlugin+getMethod.swift b/ios/Sources/Capacitor/CAPBridgedPlugin+getMethod.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgedPlugin+getMethod.swift rename to ios/Sources/Capacitor/CAPBridgedPlugin+getMethod.swift diff --git a/ios/Capacitor/Capacitor/CAPInstanceConfiguration.swift b/ios/Sources/Capacitor/CAPInstanceConfiguration.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceConfiguration.swift rename to ios/Sources/Capacitor/CAPInstanceConfiguration.swift diff --git a/ios/Capacitor/Capacitor/CAPInstanceDescriptor.swift b/ios/Sources/Capacitor/CAPInstanceDescriptor.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceDescriptor.swift rename to ios/Sources/Capacitor/CAPInstanceDescriptor.swift diff --git a/ios/Capacitor/Capacitor/CAPInstancePlugin.swift b/ios/Sources/Capacitor/CAPInstancePlugin.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstancePlugin.swift rename to ios/Sources/Capacitor/CAPInstancePlugin.swift diff --git a/ios/Capacitor/Capacitor/CAPLog.swift b/ios/Sources/Capacitor/CAPLog.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPLog.swift rename to ios/Sources/Capacitor/CAPLog.swift diff --git a/ios/Capacitor/Capacitor/CAPNotifications.swift b/ios/Sources/Capacitor/CAPNotifications.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPNotifications.swift rename to ios/Sources/Capacitor/CAPNotifications.swift diff --git a/ios/Capacitor/Capacitor/CAPPlugin+LoadInstance.swift b/ios/Sources/Capacitor/CAPPlugin+LoadInstance.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPPlugin+LoadInstance.swift rename to ios/Sources/Capacitor/CAPPlugin+LoadInstance.swift diff --git a/ios/Capacitor/Capacitor/CAPPluginCall.swift b/ios/Sources/Capacitor/CAPPluginCall.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginCall.swift rename to ios/Sources/Capacitor/CAPPluginCall.swift diff --git a/ios/Capacitor/Capacitor/CAPPluginMethod.swift b/ios/Sources/Capacitor/CAPPluginMethod.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginMethod.swift rename to ios/Sources/Capacitor/CAPPluginMethod.swift diff --git a/ios/Capacitor/Capacitor/CAPSceneDelegateProxy.swift b/ios/Sources/Capacitor/CAPSceneDelegateProxy.swift similarity index 100% rename from ios/Capacitor/Capacitor/CAPSceneDelegateProxy.swift rename to ios/Sources/Capacitor/CAPSceneDelegateProxy.swift diff --git a/ios/Capacitor/Capacitor/CapacitorBridge.swift b/ios/Sources/Capacitor/CapacitorBridge.swift similarity index 100% rename from ios/Capacitor/Capacitor/CapacitorBridge.swift rename to ios/Sources/Capacitor/CapacitorBridge.swift diff --git a/ios/Capacitor/Capacitor/CapacitorExtension.swift b/ios/Sources/Capacitor/CapacitorExtension.swift similarity index 100% rename from ios/Capacitor/Capacitor/CapacitorExtension.swift rename to ios/Sources/Capacitor/CapacitorExtension.swift diff --git a/ios/Capacitor/Capacitor/Codable/JSValueDecoder.swift b/ios/Sources/Capacitor/Codable/JSValueDecoder.swift similarity index 100% rename from ios/Capacitor/Capacitor/Codable/JSValueDecoder.swift rename to ios/Sources/Capacitor/Codable/JSValueDecoder.swift diff --git a/ios/Capacitor/Capacitor/Codable/JSValueEncoder.swift b/ios/Sources/Capacitor/Codable/JSValueEncoder.swift similarity index 100% rename from ios/Capacitor/Capacitor/Codable/JSValueEncoder.swift rename to ios/Sources/Capacitor/Codable/JSValueEncoder.swift diff --git a/ios/Capacitor/Capacitor/Data+Capacitor.swift b/ios/Sources/Capacitor/Data+Capacitor.swift similarity index 100% rename from ios/Capacitor/Capacitor/Data+Capacitor.swift rename to ios/Sources/Capacitor/Data+Capacitor.swift diff --git a/ios/Capacitor/Capacitor/DocLinks.swift b/ios/Sources/Capacitor/DocLinks.swift similarity index 100% rename from ios/Capacitor/Capacitor/DocLinks.swift rename to ios/Sources/Capacitor/DocLinks.swift diff --git a/ios/Capacitor/Capacitor/JS.swift b/ios/Sources/Capacitor/JS.swift similarity index 100% rename from ios/Capacitor/Capacitor/JS.swift rename to ios/Sources/Capacitor/JS.swift diff --git a/ios/Capacitor/Capacitor/JSExport.swift b/ios/Sources/Capacitor/JSExport.swift similarity index 96% rename from ios/Capacitor/Capacitor/JSExport.swift rename to ios/Sources/Capacitor/JSExport.swift index c51da733df..83ead2c245 100644 --- a/ios/Capacitor/Capacitor/JSExport.swift +++ b/ios/Sources/Capacitor/JSExport.swift @@ -22,8 +22,12 @@ internal class JSExport { } static func exportBridgeJS(userContentController: WKUserContentController) throws { - let capBundle = Bundle(for: Self.self) - guard let jsUrl = capBundle.url(forResource: "native-bridge", withExtension: "js") else { + #if SWIFT_PACKAGE + let jsUrl = Bundle.module.url(forResource: "native-bridge", withExtension: "js", subdirectory: "assets") + #else + let jsUrl = Bundle(for: Self.self).url(forResource: "native-bridge", withExtension: "js") + #endif + guard let jsUrl else { CAPLog.print("ERROR: Required native-bridge.js file in Capacitor not found. Bridge will not function!") throw CapacitorBridgeError.errorExportingCoreJS } diff --git a/ios/Capacitor/Capacitor/JSTypes.swift b/ios/Sources/Capacitor/JSTypes.swift similarity index 100% rename from ios/Capacitor/Capacitor/JSTypes.swift rename to ios/Sources/Capacitor/JSTypes.swift diff --git a/ios/Capacitor/Capacitor/KeyPath.swift b/ios/Sources/Capacitor/KeyPath.swift similarity index 100% rename from ios/Capacitor/Capacitor/KeyPath.swift rename to ios/Sources/Capacitor/KeyPath.swift diff --git a/ios/Capacitor/Capacitor/KeyValueStore.swift b/ios/Sources/Capacitor/KeyValueStore.swift similarity index 100% rename from ios/Capacitor/Capacitor/KeyValueStore.swift rename to ios/Sources/Capacitor/KeyValueStore.swift diff --git a/ios/Capacitor/Capacitor/NotificationHandlerProtocol.swift b/ios/Sources/Capacitor/NotificationHandlerProtocol.swift similarity index 100% rename from ios/Capacitor/Capacitor/NotificationHandlerProtocol.swift rename to ios/Sources/Capacitor/NotificationHandlerProtocol.swift diff --git a/ios/Capacitor/Capacitor/NotificationRouter.swift b/ios/Sources/Capacitor/NotificationRouter.swift similarity index 100% rename from ios/Capacitor/Capacitor/NotificationRouter.swift rename to ios/Sources/Capacitor/NotificationRouter.swift diff --git a/ios/Capacitor/Capacitor/PluginCallResult.swift b/ios/Sources/Capacitor/PluginCallResult.swift similarity index 100% rename from ios/Capacitor/Capacitor/PluginCallResult.swift rename to ios/Sources/Capacitor/PluginCallResult.swift diff --git a/ios/Capacitor/Capacitor/PluginConfig.swift b/ios/Sources/Capacitor/PluginConfig.swift similarity index 100% rename from ios/Capacitor/Capacitor/PluginConfig.swift rename to ios/Sources/Capacitor/PluginConfig.swift diff --git a/ios/Capacitor/Capacitor/Plugins/CapacitorCookieManager.swift b/ios/Sources/Capacitor/Plugins/CapacitorCookieManager.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/CapacitorCookieManager.swift rename to ios/Sources/Capacitor/Plugins/CapacitorCookieManager.swift diff --git a/ios/Capacitor/Capacitor/Plugins/CapacitorCookies.swift b/ios/Sources/Capacitor/Plugins/CapacitorCookies.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/CapacitorCookies.swift rename to ios/Sources/Capacitor/Plugins/CapacitorCookies.swift diff --git a/ios/Capacitor/Capacitor/Plugins/CapacitorHttp.swift b/ios/Sources/Capacitor/Plugins/CapacitorHttp.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/CapacitorHttp.swift rename to ios/Sources/Capacitor/Plugins/CapacitorHttp.swift diff --git a/ios/Capacitor/Capacitor/Plugins/CapacitorUrlRequest.swift b/ios/Sources/Capacitor/Plugins/CapacitorUrlRequest.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/CapacitorUrlRequest.swift rename to ios/Sources/Capacitor/Plugins/CapacitorUrlRequest.swift diff --git a/ios/Capacitor/Capacitor/Plugins/Console.swift b/ios/Sources/Capacitor/Plugins/Console.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/Console.swift rename to ios/Sources/Capacitor/Plugins/Console.swift diff --git a/ios/Capacitor/Capacitor/Plugins/HttpRequestHandler.swift b/ios/Sources/Capacitor/Plugins/HttpRequestHandler.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/HttpRequestHandler.swift rename to ios/Sources/Capacitor/Plugins/HttpRequestHandler.swift diff --git a/ios/Capacitor/Capacitor/Plugins/SystemBars.swift b/ios/Sources/Capacitor/Plugins/SystemBars.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/SystemBars.swift rename to ios/Sources/Capacitor/Plugins/SystemBars.swift diff --git a/ios/Capacitor/Capacitor/Plugins/WebView.swift b/ios/Sources/Capacitor/Plugins/WebView.swift similarity index 100% rename from ios/Capacitor/Capacitor/Plugins/WebView.swift rename to ios/Sources/Capacitor/Plugins/WebView.swift diff --git a/ios/Capacitor/Capacitor/PrivacyInfo.xcprivacy b/ios/Sources/Capacitor/PrivacyInfo.xcprivacy similarity index 100% rename from ios/Capacitor/Capacitor/PrivacyInfo.xcprivacy rename to ios/Sources/Capacitor/PrivacyInfo.xcprivacy diff --git a/ios/Capacitor/Capacitor/Router.swift b/ios/Sources/Capacitor/Router.swift similarity index 100% rename from ios/Capacitor/Capacitor/Router.swift rename to ios/Sources/Capacitor/Router.swift diff --git a/ios/Capacitor/Capacitor/UIColor.swift b/ios/Sources/Capacitor/UIColor.swift similarity index 100% rename from ios/Capacitor/Capacitor/UIColor.swift rename to ios/Sources/Capacitor/UIColor.swift diff --git a/ios/Capacitor/Capacitor/WKWebView+Capacitor.swift b/ios/Sources/Capacitor/WKWebView+Capacitor.swift similarity index 100% rename from ios/Capacitor/Capacitor/WKWebView+Capacitor.swift rename to ios/Sources/Capacitor/WKWebView+Capacitor.swift diff --git a/ios/Capacitor/Capacitor/WebViewAssetHandler.swift b/ios/Sources/Capacitor/WebViewAssetHandler.swift similarity index 100% rename from ios/Capacitor/Capacitor/WebViewAssetHandler.swift rename to ios/Sources/Capacitor/WebViewAssetHandler.swift diff --git a/ios/Capacitor/Capacitor/WebViewDelegationHandler.swift b/ios/Sources/Capacitor/WebViewDelegationHandler.swift similarity index 100% rename from ios/Capacitor/Capacitor/WebViewDelegationHandler.swift rename to ios/Sources/Capacitor/WebViewDelegationHandler.swift diff --git a/ios/Capacitor/Capacitor/assets/native-bridge.js b/ios/Sources/Capacitor/assets/native-bridge.js similarity index 100% rename from ios/Capacitor/Capacitor/assets/native-bridge.js rename to ios/Sources/Capacitor/assets/native-bridge.js diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift b/ios/Sources/CapacitorCordova/Plugin.swift similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift rename to ios/Sources/CapacitorCordova/Plugin.swift diff --git a/ios/Capacitor/Capacitor/CAPInstanceConfiguration.m b/ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceConfiguration.m rename to ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m diff --git a/ios/Capacitor/Capacitor/CAPInstanceDescriptor.m b/ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceDescriptor.m rename to ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m diff --git a/ios/Capacitor/Capacitor/CAPPlugin.m b/ios/Sources/CapacitorObjC/CAPPlugin.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPPlugin.m rename to ios/Sources/CapacitorObjC/CAPPlugin.m diff --git a/ios/Capacitor/Capacitor/CAPPluginCall.m b/ios/Sources/CapacitorObjC/CAPPluginCall.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginCall.m rename to ios/Sources/CapacitorObjC/CAPPluginCall.m diff --git a/ios/Capacitor/Capacitor/CAPPluginMethod.m b/ios/Sources/CapacitorObjC/CAPPluginMethod.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginMethod.m rename to ios/Sources/CapacitorObjC/CAPPluginMethod.m diff --git a/ios/Capacitor/Capacitor/CAPBridgedPlugin.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPBridgedPlugin.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgedPlugin.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPBridgedPlugin.h diff --git a/ios/Capacitor/Capacitor/CAPInstanceConfiguration.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPInstanceConfiguration.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceConfiguration.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPInstanceConfiguration.h diff --git a/ios/Capacitor/Capacitor/CAPInstanceDescriptor.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPInstanceDescriptor.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPInstanceDescriptor.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPInstanceDescriptor.h diff --git a/ios/Capacitor/Capacitor/CAPPlugin.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPPlugin.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h diff --git a/ios/Capacitor/Capacitor/CAPPluginCall.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginCall.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h diff --git a/ios/Capacitor/Capacitor/CAPPluginMethod.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginMethod.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPPluginMethod.h rename to ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginMethod.h diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m b/ios/Sources/CapacitorObjCShims/CAPBridgedJSTypes.m similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgedJSTypes.m rename to ios/Sources/CapacitorObjCShims/CAPBridgedJSTypes.m diff --git a/ios/Capacitor/Capacitor/Capacitor.modulemap b/ios/Sources/CapacitorObjCShims/Capacitor.modulemap similarity index 100% rename from ios/Capacitor/Capacitor/Capacitor.modulemap rename to ios/Sources/CapacitorObjCShims/Capacitor.modulemap diff --git a/ios/Capacitor/Capacitor/UIStatusBarManager+CAPHandleTapAction.m b/ios/Sources/CapacitorObjCShims/UIStatusBarManager+CAPHandleTapAction.m similarity index 100% rename from ios/Capacitor/Capacitor/UIStatusBarManager+CAPHandleTapAction.m rename to ios/Sources/CapacitorObjCShims/UIStatusBarManager+CAPHandleTapAction.m diff --git a/ios/Capacitor/Capacitor/WKWebView+Capacitor.m b/ios/Sources/CapacitorObjCShims/WKWebView+Capacitor.m similarity index 100% rename from ios/Capacitor/Capacitor/WKWebView+Capacitor.m rename to ios/Sources/CapacitorObjCShims/WKWebView+Capacitor.m diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h b/ios/Sources/CapacitorObjCShims/include/Capacitor/CAPBridgedJSTypes.h similarity index 100% rename from ios/Capacitor/Capacitor/CAPBridgedJSTypes.h rename to ios/Sources/CapacitorObjCShims/include/Capacitor/CAPBridgedJSTypes.h diff --git a/ios/Capacitor/Capacitor/Capacitor.h b/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h similarity index 100% rename from ios/Capacitor/Capacitor/Capacitor.h rename to ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.m b/ios/Sources/Cordova/AppDelegate.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.m rename to ios/Sources/Cordova/AppDelegate.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.m b/ios/Sources/Cordova/CDVCommandDelegateImpl.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.m rename to ios/Sources/Cordova/CDVCommandDelegateImpl.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.m b/ios/Sources/Cordova/CDVConfigParser.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.m rename to ios/Sources/Cordova/CDVConfigParser.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.m b/ios/Sources/Cordova/CDVInvokedUrlCommand.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.m rename to ios/Sources/Cordova/CDVInvokedUrlCommand.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.m b/ios/Sources/Cordova/CDVPlugin+Resources.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.m rename to ios/Sources/Cordova/CDVPlugin+Resources.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.m b/ios/Sources/Cordova/CDVPlugin.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.m rename to ios/Sources/Cordova/CDVPlugin.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.m b/ios/Sources/Cordova/CDVPluginManager.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.m rename to ios/Sources/Cordova/CDVPluginManager.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m b/ios/Sources/Cordova/CDVPluginResult.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m rename to ios/Sources/Cordova/CDVPluginResult.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.m b/ios/Sources/Cordova/CDVURLProtocol.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.m rename to ios/Sources/Cordova/CDVURLProtocol.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.m b/ios/Sources/Cordova/CDVViewController.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.m rename to ios/Sources/Cordova/CDVViewController.m diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.m b/ios/Sources/Cordova/CDVWebViewProcessPoolFactory.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.m rename to ios/Sources/Cordova/CDVWebViewProcessPoolFactory.m diff --git a/ios/CapacitorCordova/CapacitorCordova/CapacitorCordova.h b/ios/Sources/Cordova/CapacitorCordova.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/CapacitorCordova.h rename to ios/Sources/Cordova/CapacitorCordova.h diff --git a/ios/CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap b/ios/Sources/Cordova/CapacitorCordova.modulemap similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap rename to ios/Sources/Cordova/CapacitorCordova.modulemap diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.m b/ios/Sources/Cordova/NSDictionary+CordovaPreferences.m similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.m rename to ios/Sources/Cordova/NSDictionary+CordovaPreferences.m diff --git a/ios/CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy b/ios/Sources/Cordova/PrivacyInfo.xcprivacy similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy rename to ios/Sources/Cordova/PrivacyInfo.xcprivacy diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.h b/ios/Sources/Cordova/include/Cordova/AppDelegate.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.h rename to ios/Sources/Cordova/include/Cordova/AppDelegate.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDV.h b/ios/Sources/Cordova/include/Cordova/CDV.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDV.h rename to ios/Sources/Cordova/include/Cordova/CDV.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailability.h b/ios/Sources/Cordova/include/Cordova/CDVAvailability.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailability.h rename to ios/Sources/Cordova/include/Cordova/CDVAvailability.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailabilityDeprecated.h b/ios/Sources/Cordova/include/Cordova/CDVAvailabilityDeprecated.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailabilityDeprecated.h rename to ios/Sources/Cordova/include/Cordova/CDVAvailabilityDeprecated.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegate.h b/ios/Sources/Cordova/include/Cordova/CDVCommandDelegate.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegate.h rename to ios/Sources/Cordova/include/Cordova/CDVCommandDelegate.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.h b/ios/Sources/Cordova/include/Cordova/CDVCommandDelegateImpl.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.h rename to ios/Sources/Cordova/include/Cordova/CDVCommandDelegateImpl.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.h b/ios/Sources/Cordova/include/Cordova/CDVConfigParser.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.h rename to ios/Sources/Cordova/include/Cordova/CDVConfigParser.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.h b/ios/Sources/Cordova/include/Cordova/CDVInvokedUrlCommand.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.h rename to ios/Sources/Cordova/include/Cordova/CDVInvokedUrlCommand.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.h b/ios/Sources/Cordova/include/Cordova/CDVPlugin+Resources.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.h rename to ios/Sources/Cordova/include/Cordova/CDVPlugin+Resources.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.h b/ios/Sources/Cordova/include/Cordova/CDVPlugin.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.h rename to ios/Sources/Cordova/include/Cordova/CDVPlugin.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.h b/ios/Sources/Cordova/include/Cordova/CDVPluginManager.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.h rename to ios/Sources/Cordova/include/Cordova/CDVPluginManager.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h b/ios/Sources/Cordova/include/Cordova/CDVPluginResult.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h rename to ios/Sources/Cordova/include/Cordova/CDVPluginResult.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVScreenOrientationDelegate.h b/ios/Sources/Cordova/include/Cordova/CDVScreenOrientationDelegate.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVScreenOrientationDelegate.h rename to ios/Sources/Cordova/include/Cordova/CDVScreenOrientationDelegate.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.h b/ios/Sources/Cordova/include/Cordova/CDVURLProtocol.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.h rename to ios/Sources/Cordova/include/Cordova/CDVURLProtocol.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h b/ios/Sources/Cordova/include/Cordova/CDVViewController.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h rename to ios/Sources/Cordova/include/Cordova/CDVViewController.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.h b/ios/Sources/Cordova/include/Cordova/CDVWebViewProcessPoolFactory.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.h rename to ios/Sources/Cordova/include/Cordova/CDVWebViewProcessPoolFactory.h diff --git a/ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.h b/ios/Sources/Cordova/include/Cordova/NSDictionary+CordovaPreferences.h similarity index 100% rename from ios/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.h rename to ios/Sources/Cordova/include/Cordova/NSDictionary+CordovaPreferences.h diff --git a/ios/Capacitor/CapacitorTests/BridgedTypesTests.m b/ios/Tests/CapacitorObjCTests/BridgedTypesTests.m similarity index 100% rename from ios/Capacitor/CapacitorTests/BridgedTypesTests.m rename to ios/Tests/CapacitorObjCTests/BridgedTypesTests.m diff --git a/ios/Capacitor/CapacitorTests/JSONSerializationWrapper.h b/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h similarity index 100% rename from ios/Capacitor/CapacitorTests/JSONSerializationWrapper.h rename to ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h diff --git a/ios/Capacitor/CapacitorTests/JSONSerializationWrapper.m b/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m similarity index 100% rename from ios/Capacitor/CapacitorTests/JSONSerializationWrapper.m rename to ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m diff --git a/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m b/ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m similarity index 100% rename from ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m rename to ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m diff --git a/ios/Capacitor/CapacitorTests/BridgedTypesHelper.swift b/ios/Tests/CapacitorTests/BridgedTypesHelper.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/BridgedTypesHelper.swift rename to ios/Tests/CapacitorTests/BridgedTypesHelper.swift diff --git a/ios/Capacitor/CapacitorTests/BridgedTypesTests.swift b/ios/Tests/CapacitorTests/BridgedTypesTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/BridgedTypesTests.swift rename to ios/Tests/CapacitorTests/BridgedTypesTests.swift diff --git a/ios/Capacitor/CapacitorTests/CapacitorTests.swift b/ios/Tests/CapacitorTests/CapacitorTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/CapacitorTests.swift rename to ios/Tests/CapacitorTests/CapacitorTests.swift diff --git a/ios/Capacitor/CodableTests/CodableTests.swift b/ios/Tests/CapacitorTests/CodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/CodableTests.swift rename to ios/Tests/CapacitorTests/CodableTests.swift diff --git a/ios/Capacitor/CapacitorTests/ConfigurationTests.swift b/ios/Tests/CapacitorTests/ConfigurationTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/ConfigurationTests.swift rename to ios/Tests/CapacitorTests/ConfigurationTests.swift diff --git a/ios/Capacitor/CodableTests/DataCodableTests.swift b/ios/Tests/CapacitorTests/DataCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/DataCodableTests.swift rename to ios/Tests/CapacitorTests/DataCodableTests.swift diff --git a/ios/Capacitor/CodableTests/DateCodableTests.swift b/ios/Tests/CapacitorTests/DateCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/DateCodableTests.swift rename to ios/Tests/CapacitorTests/DateCodableTests.swift diff --git a/ios/Capacitor/CapacitorTests/HttpInterceptorNavigationTests.swift b/ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/HttpInterceptorNavigationTests.swift rename to ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift diff --git a/ios/Capacitor/CapacitorTests/JSExportTests.swift b/ios/Tests/CapacitorTests/JSExportTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/JSExportTests.swift rename to ios/Tests/CapacitorTests/JSExportTests.swift diff --git a/ios/Capacitor/CodableTests/NestedCodableTests.swift b/ios/Tests/CapacitorTests/NestedCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/NestedCodableTests.swift rename to ios/Tests/CapacitorTests/NestedCodableTests.swift diff --git a/ios/Capacitor/CodableTests/NonconformingFloatCodableTests.swift b/ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/NonconformingFloatCodableTests.swift rename to ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift diff --git a/ios/Capacitor/TestsHostApp/configurations/bad.json b/ios/Tests/CapacitorTests/Resources/configurations/bad.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/bad.json rename to ios/Tests/CapacitorTests/Resources/configurations/bad.json diff --git a/ios/Capacitor/TestsHostApp/configurations/flat.json b/ios/Tests/CapacitorTests/Resources/configurations/flat.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/flat.json rename to ios/Tests/CapacitorTests/Resources/configurations/flat.json diff --git a/ios/Capacitor/TestsHostApp/configurations/hidinglogs.json b/ios/Tests/CapacitorTests/Resources/configurations/hidinglogs.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/hidinglogs.json rename to ios/Tests/CapacitorTests/Resources/configurations/hidinglogs.json diff --git a/ios/Capacitor/TestsHostApp/configurations/hierarchy.json b/ios/Tests/CapacitorTests/Resources/configurations/hierarchy.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/hierarchy.json rename to ios/Tests/CapacitorTests/Resources/configurations/hierarchy.json diff --git a/ios/Capacitor/TestsHostApp/configurations/nonjson.json b/ios/Tests/CapacitorTests/Resources/configurations/nonjson.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/nonjson.json rename to ios/Tests/CapacitorTests/Resources/configurations/nonjson.json diff --git a/ios/Capacitor/TestsHostApp/configurations/server.json b/ios/Tests/CapacitorTests/Resources/configurations/server.json similarity index 100% rename from ios/Capacitor/TestsHostApp/configurations/server.json rename to ios/Tests/CapacitorTests/Resources/configurations/server.json diff --git a/ios/Capacitor/CapacitorTests/RouterTests.swift b/ios/Tests/CapacitorTests/RouterTests.swift similarity index 100% rename from ios/Capacitor/CapacitorTests/RouterTests.swift rename to ios/Tests/CapacitorTests/RouterTests.swift diff --git a/ios/Capacitor/CodableTests/SuperCodableTests.swift b/ios/Tests/CapacitorTests/SuperCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/SuperCodableTests.swift rename to ios/Tests/CapacitorTests/SuperCodableTests.swift diff --git a/ios/Capacitor/CodableTests/URLCodableTests.swift b/ios/Tests/CapacitorTests/URLCodableTests.swift similarity index 100% rename from ios/Capacitor/CodableTests/URLCodableTests.swift rename to ios/Tests/CapacitorTests/URLCodableTests.swift diff --git a/ios/package.json b/ios/package.json index 2bc19350bb..409f72f257 100644 --- a/ios/package.json +++ b/ios/package.json @@ -13,16 +13,15 @@ "url": "https://github.com/ionic-team/capacitor/issues" }, "files": [ - "Capacitor/Capacitor/", - "CapacitorCordova/CapacitorCordova/", + "Sources/", "Capacitor.podspec", "CapacitorCordova.podspec", "scripts/pods_helpers.rb" ], "scripts": { - "verify": "npm run xc:build:Capacitor && npm run xc:build:CapacitorCordova", - "xc:build:Capacitor": "cd Capacitor && xcodebuild clean test -workspace Capacitor.xcworkspace -scheme Capacitor -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.0.1' && cd ..", - "xc:build:CapacitorCordova": "cd Capacitor && xcodebuild clean build -workspace Capacitor.xcworkspace -scheme Cordova && cd .." + "verify": "npm run xc:build && npm run xc:test", + "xc:build": "cd .. && xcodebuild build -scheme Capacitor-Package -destination 'generic/platform=iOS Simulator'", + "xc:test": "cd .. && xcodebuild test -scheme Capacitor-Package -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.5' -collect-test-diagnostics never" }, "peerDependencies": { "@capacitor/core": "^9.0.0-alpha.6" diff --git a/swiftlint.config.js b/swiftlint.config.js index 59e40b8907..1aa29f1895 100644 --- a/swiftlint.config.js +++ b/swiftlint.config.js @@ -1,5 +1,5 @@ module.exports = { ...require('@ionic/swiftlint-config'), included: ['${PWD}/ios', '${PWD}/ios-pods-template', '${PWD}/ios-spm-template'], - excluded: ['${PWD}/ios/Capacitor/CapacitorTests', '${PWD}/ios/Capacitor/TestsHostApp', '${PWD}/ios/Frameworks'], + excluded: ['${PWD}/ios/Tests', '${PWD}/ios/Frameworks', '${PWD}/.build', '${PWD}/ios/.build'], }; From 824d0473028a9492ecd9e1ab7d3867aa3f6129a1 Mon Sep 17 00:00:00 2001 From: Joseph Pender Date: Wed, 2 Sep 2026 11:36:34 -0500 Subject: [PATCH 2/5] refactor(ios)!: split CAPPlugin and call results across the SPM target boundary --- ios/Capacitor.podspec | 2 + ios/Sources/Capacitor/CAPPlugin+Bridge.swift | 106 +++++++++++++++++ ios/Sources/Capacitor/CapacitorBridge.swift | 4 +- .../Capacitor/CapacitorObjCExports.swift | 11 ++ ios/Sources/Capacitor/JS.swift | 18 +-- .../Capacitor/JSResultSerialization.swift | 56 +++++++++ ios/Sources/Capacitor/PluginCallResult.swift | 106 ----------------- ios/Sources/CapacitorCordova/Plugin.swift | 1 + .../CapacitorObjC/CAPInstanceConfiguration.m | 10 +- .../CapacitorObjC/CAPInstanceDescriptor.m | 1 - ios/Sources/CapacitorObjC/CAPPlugin.m | 109 ++---------------- .../CapacitorObjC/CAPPluginCallResult.m | 29 +++++ ios/Sources/CapacitorObjC/CAPPluginMethod.m | 1 - .../include/Capacitor/CAPPlugin.h | 22 +--- .../include/Capacitor/CAPPluginCall.h | 3 +- .../include/Capacitor/CAPPluginCallResult.h | 28 +++++ .../include/Capacitor/Capacitor-Swift.h | 9 ++ .../include/Capacitor/Capacitor.h | 8 ++ .../CapacitorTests/BridgedTypesTests.swift | 4 +- 19 files changed, 287 insertions(+), 241 deletions(-) create mode 100644 ios/Sources/Capacitor/CAPPlugin+Bridge.swift create mode 100644 ios/Sources/Capacitor/CapacitorObjCExports.swift create mode 100644 ios/Sources/Capacitor/JSResultSerialization.swift delete mode 100644 ios/Sources/Capacitor/PluginCallResult.swift create mode 100644 ios/Sources/CapacitorObjC/CAPPluginCallResult.m create mode 100644 ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCallResult.h create mode 100644 ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h diff --git a/ios/Capacitor.podspec b/ios/Capacitor.podspec index 77f3275e94..6c120bc397 100644 --- a/ios/Capacitor.podspec +++ b/ios/Capacitor.podspec @@ -20,6 +20,8 @@ Pod::Spec.new do |s| "#{prefix}Sources/CapacitorObjC/**/*.{h,m}", "#{prefix}Sources/CapacitorObjCShims/**/*.{h,m}" ] + # SPM-only shim; CocoaPods generates the real Capacitor-Swift.h for the mixed-language module. + s.exclude_files = ["#{prefix}Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h"] s.module_map = "#{prefix}Sources/CapacitorObjCShims/Capacitor.modulemap" s.resources = ["#{prefix}Sources/Capacitor/assets/native-bridge.js"] s.resource_bundles = { 'Capacitor' => ["#{prefix}Sources/Capacitor/PrivacyInfo.xcprivacy"] } diff --git a/ios/Sources/Capacitor/CAPPlugin+Bridge.swift b/ios/Sources/Capacitor/CAPPlugin+Bridge.swift new file mode 100644 index 0000000000..1b8ecfd270 --- /dev/null +++ b/ios/Sources/Capacitor/CAPPlugin+Bridge.swift @@ -0,0 +1,106 @@ +import Foundation +import UIKit +import WebKit + +@objc public extension CAPPlugin { + var bridge: CAPBridgeProtocol? { + get { return bridgeRef as? CAPBridgeProtocol } + set { bridgeRef = newValue as? NSObject } + } + + @available(*, deprecated, message: "This initializer is deprecated and is not suggested for use. Any data set through this init method will be overridden when it is loaded on the bridge.") + @objc(initWithBridge:pluginId:pluginName:) + convenience init(bridge: CAPBridgeProtocol, pluginId: String, pluginName: String) { + self.init() + self.bridge = bridge + self.webView = bridge.webView + self.pluginId = pluginId + self.pluginName = pluginName + self.eventListeners = [:] + self.retainedEventArguments = [:] + self.shouldStringifyDatesInCalls = true + } + + @available(*, deprecated, message: "Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations.") + func getBool(_ call: CAPPluginCall, field: String, defaultValue: Bool) -> Bool { + guard let value = call.options[field] as? NSNumber else { return defaultValue } + return value.boolValue + } + + @available(*, deprecated, message: "Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations.") + func getString(_ call: CAPPluginCall, field: String, defaultValue: String) -> String? { + return call.options[field] as? String ?? defaultValue + } + + func getConfig() -> PluginConfig { + return bridge?.config.getPluginConfig(pluginName) ?? PluginConfig(config: JSObject()) + } + + func notifyListeners(_ eventName: String, data: [String: Any]?) { + notifyListeners(eventName, data: data, retainUntilConsumed: false) + } + + func notifyListeners(_ eventName: String, data: [String: Any]?, retainUntilConsumed retain: Bool) { + guard let listenersForEvent = eventListeners?.object(forKey: eventName) as? NSArray, + listenersForEvent.count > 0 else { + if retain, let data = data { + let bucket: NSMutableArray + if let existing = retainedEventArguments?.object(forKey: eventName) as? NSMutableArray { + bucket = existing + } else { + bucket = NSMutableArray() + retainedEventArguments?.setObject(bucket, forKey: eventName as NSString) + } + bucket.add(data) + } + return + } + + for case let call as CAPPluginCall in listenersForEvent { + call.successHandler(CAPPluginCallResult(data), call) + } + } + + func removeListener(_ call: CAPPluginCall) { + guard let eventName = call.options["eventName"] as? String, + let callbackId = call.options["callbackId"] as? String else { return } + if let storedCall = bridge?.savedCall(withID: callbackId) { + removeEventListener(eventName, listener: storedCall) + } + bridge?.releaseCall(withID: callbackId) + } + + func removeAllListeners(_ call: CAPPluginCall) { + eventListeners?.removeAllObjects() + call.resolve() + } + + /** + * Default implementation of the capacitor 3.0 permission pattern + */ + func checkPermissions(_ call: CAPPluginCall) { + call.resolve() + } + + func requestPermissions(_ call: CAPPluginCall) { + call.resolve() + } + + /** + * Configure popover sourceRect, sourceView and permittedArrowDirections to show it centered + */ + func setCenteredPopover(_ viewController: UIViewController) { + guard let hostView = bridge?.viewController?.view else { return } + viewController.popoverPresentationController?.sourceRect = CGRect(x: hostView.center.x, y: hostView.center.y, width: 0, height: 0) + viewController.popoverPresentationController?.sourceView = hostView + viewController.popoverPresentationController?.permittedArrowDirections = [] + } + + func setCenteredPopover(_ viewController: UIViewController, size: CGSize) { + guard let hostView = bridge?.viewController?.view else { return } + viewController.popoverPresentationController?.sourceRect = CGRect(x: hostView.center.x, y: hostView.center.y, width: 0, height: 0) + viewController.preferredContentSize = size + viewController.popoverPresentationController?.sourceView = hostView + viewController.popoverPresentationController?.permittedArrowDirections = [] + } +} diff --git a/ios/Sources/Capacitor/CapacitorBridge.swift b/ios/Sources/Capacitor/CapacitorBridge.swift index cf5d08c9ba..485132e30f 100644 --- a/ios/Sources/Capacitor/CapacitorBridge.swift +++ b/ios/Sources/Capacitor/CapacitorBridge.swift @@ -438,7 +438,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol { if let result = result { self?.toJs(result: JSResult(call: call, callResult: result), save: pluginCall?.keepAlive ?? false) } else { - self?.toJs(result: JSResult(call: call, result: .dictionary([:])), save: pluginCall?.keepAlive ?? false) + self?.toJs(result: JSResult(call: call, data: [:]), save: pluginCall?.keepAlive ?? false) } }, error: {(error: CAPPluginCallError?) in if let error = error { @@ -448,7 +448,7 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol { errorMessage: "", errorDescription: "", errorCode: nil, - result: .dictionary([:]))) + data: [:])) } }) diff --git a/ios/Sources/Capacitor/CapacitorObjCExports.swift b/ios/Sources/Capacitor/CapacitorObjCExports.swift new file mode 100644 index 0000000000..0fe87b26a9 --- /dev/null +++ b/ios/Sources/Capacitor/CapacitorObjCExports.swift @@ -0,0 +1,11 @@ +// The Objective-C base classes (CAPPlugin, CAPPluginCall, CAPPluginMethod, CAPBridgedPlugin, +// CAPInstanceDescriptor, CAPInstanceConfiguration) live in the CapacitorObjC target so that they +// compile before the Swift module that subclasses and extends them. Re-export them so the rest of +// this module — and downstream `import Capacitor` consumers — keep seeing these symbols without an +// explicit `import CapacitorObjC`. +// +// Under CocoaPods all of these sources are compiled into a single Capacitor module, so there is no +// CapacitorObjC module to import and the re-export is unnecessary. +#if SWIFT_PACKAGE +@_exported import CapacitorObjC +#endif diff --git a/ios/Sources/Capacitor/JS.swift b/ios/Sources/Capacitor/JS.swift index 52cae13791..7e0b06e70c 100644 --- a/ios/Sources/Capacitor/JS.swift +++ b/ios/Sources/Capacitor/JS.swift @@ -44,17 +44,17 @@ private enum SerializationResult: String { internal struct JSResult: JSResultProtocol { let call: JSCall - let result: PluginCallResult? + let data: PluginCallResultData? func jsonPayload() -> String { - guard let result = result else { + guard let data = data else { return SerializationResult.undefined.rawValue } do { - if let payload = try result.jsonRepresentation() { + if let payload = try JSResultSerialization.jsonRepresentation(of: data) { return payload } - } catch PluginCallResult.SerializationError.invalidObject { + } catch JSResultSerialization.SerializationError.invalidObject { CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." + "Ensure that all data passed to success callback from module method is JSON serializable!") } catch { @@ -67,7 +67,7 @@ internal struct JSResult: JSResultProtocol { internal extension JSResult { init(call: JSCall, callResult: CAPPluginCallResult) { self.call = call - self.result = callResult.resultData + self.data = callResult.data } } @@ -76,7 +76,7 @@ internal struct JSResultError: JSResultProtocol { let errorMessage: String let errorDescription: String let errorCode: String? - let result: PluginCallResult + let data: PluginCallResultData func jsonPayload() -> String { var errorDictionary: [String: Any] = [ @@ -86,11 +86,11 @@ internal struct JSResultError: JSResultProtocol { errorDictionary["code"] = self.errorCode do { - if let payload = try result.jsonRepresentation(includingFields: errorDictionary) { + if let payload = try JSResultSerialization.jsonRepresentation(of: data, includingFields: errorDictionary) { CAPLog.print("ERROR MESSAGE: ", payload.prefix(512)) return payload } - } catch PluginCallResult.SerializationError.invalidObject { + } catch JSResultSerialization.SerializationError.invalidObject { CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." + "Ensure that all data passed to success callback from module method is JSON serializable!") } catch { @@ -106,6 +106,6 @@ internal extension JSResultError { errorMessage = callError.message errorDescription = callError.error?.localizedDescription ?? "" errorCode = callError.code - result = callError.resultData ?? .dictionary([:]) + data = callError.data ?? [:] } } diff --git a/ios/Sources/Capacitor/JSResultSerialization.swift b/ios/Sources/Capacitor/JSResultSerialization.swift new file mode 100644 index 0000000000..e6245ca7f6 --- /dev/null +++ b/ios/Sources/Capacitor/JSResultSerialization.swift @@ -0,0 +1,56 @@ +import Foundation + +public typealias PluginCallResultData = [String: Any] + +/// Serializes a plugin call's result dictionary to the JSON string sent back across the bridge, +/// converting `Date` values to ISO8601 strings (recursively through nested dictionaries/arrays). +/// +/// Carries the serialization logic that used to live on the `PluginCallResult` enum, which was +/// replaced by the Objective-C `CAPPluginCallResult`/`CAPPluginCallError` carriers. Those store +/// their payloads as plain dictionaries, so the logic no longer has an enum to hang off. +enum JSResultSerialization { + enum SerializationError: Error { + case invalidObject + } + + private static let formatter = ISO8601DateFormatter() + + static func jsonRepresentation(of dictionary: PluginCallResultData, includingFields: PluginCallResultData? = nil) throws -> String? { + var dictionary = dictionary + if let fields = includingFields { + dictionary.merge(fields) { (current, _) in current } + } + let prepared = prepare(dictionary: dictionary) + guard JSONSerialization.isValidJSONObject(prepared) else { + throw SerializationError.invalidObject + } + let data = try JSONSerialization.data(withJSONObject: prepared, options: []) + return String(data: data, encoding: .utf8) + } + + private static func prepare(dictionary: PluginCallResultData) -> PluginCallResultData { + return dictionary.mapValues { (value) -> Any in + if let date = value as? Date { + return formatter.string(from: date) + } else if let aDictionary = value as? PluginCallResultData { + return prepare(dictionary: aDictionary) + } else if let anArray = value as? [Any] { + return prepare(array: anArray) + } + return value + } + } + + private static func prepare(array: [Any]) -> [Any] { + return array.map { (value) -> Any in + if let date = value as? Date { + return formatter.string(from: date) + } else if let aDictionary = value as? PluginCallResultData { + return prepare(dictionary: aDictionary) + } else if let anArray = value as? [Any] { + return prepare(array: anArray) + } + return value + } + } +} diff --git a/ios/Sources/Capacitor/PluginCallResult.swift b/ios/Sources/Capacitor/PluginCallResult.swift deleted file mode 100644 index a426bbcb30..0000000000 --- a/ios/Sources/Capacitor/PluginCallResult.swift +++ /dev/null @@ -1,106 +0,0 @@ -import Foundation - -public typealias PluginCallResultData = [String: Any] - -public enum PluginCallResult { - case dictionary(PluginCallResultData) - - enum SerializationError: Error { - case invalidObject - } - - func jsonRepresentation(includingFields: PluginCallResultData? = nil) throws -> String? { - switch self { - case .dictionary(var dictionary): - if let fields = includingFields { - dictionary.merge(fields) { (current, _) in current } - } - dictionary = prepare(dictionary: dictionary) - guard JSONSerialization.isValidJSONObject(dictionary) else { - throw SerializationError.invalidObject - } - let data = try JSONSerialization.data(withJSONObject: dictionary, options: []) - return String(data: data, encoding: .utf8) - } - } - - private static let formatter = ISO8601DateFormatter() - - private func prepare(dictionary: PluginCallResultData) -> PluginCallResultData { - return dictionary.mapValues { (value) -> Any in - if let date = value as? Date { - return PluginCallResult.formatter.string(from: date) - } else if let aDictionary = value as? PluginCallResultData { - return prepare(dictionary: aDictionary) - } else if let anArray = value as? [Any] { - return prepare(array: anArray) - } - return value - } - } - - private func prepare(array: [Any]) -> [Any] { - return array.map { (value) -> Any in - if let date = value as? Date { - return PluginCallResult.formatter.string(from: date) - } else if let aDictionary = value as? PluginCallResultData { - return prepare(dictionary: aDictionary) - } else if let anArray = value as? [Any] { - return prepare(array: anArray) - } - return value - } - } -} - -@objc public class CAPPluginCallResult: NSObject { - public let resultData: PluginCallResult? - - @objc public var data: PluginCallResultData? { - guard let result = resultData else { - return nil - } - switch result { - case .dictionary(let data): - return data - } - } - - @objc(init:) - public init(_ data: PluginCallResultData?) { - if let data = data { - resultData = .dictionary(data) - } else { - resultData = nil - } - } -} - -@objc public class CAPPluginCallError: NSObject { - @objc public let message: String - @objc public let code: String? - @objc public let error: Error? - public let resultData: PluginCallResult? - - @objc public var data: PluginCallResultData? { - guard let result = resultData else { - return nil - } - switch result { - case .dictionary(let data): - return data - } - } - - @objc(init:code:error:data:) - public init(message: String, code: String?, error: Error?, data: PluginCallResultData?) { - self.message = message - self.code = code - self.error = error - if let data = data { - resultData = .dictionary(["data": data]) - } else { - resultData = nil - } - } -} diff --git a/ios/Sources/CapacitorCordova/Plugin.swift b/ios/Sources/CapacitorCordova/Plugin.swift index d58c4ca33f..40e9657e8b 100644 --- a/ios/Sources/CapacitorCordova/Plugin.swift +++ b/ios/Sources/CapacitorCordova/Plugin.swift @@ -1,4 +1,5 @@ import Capacitor +import Cordova @objc(CordovaPlugin) public class CordovaPlugin: CAPPlugin, CAPBridgedPlugin { diff --git a/ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m b/ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m index d6b7785e34..0f822f3a4c 100644 --- a/ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m +++ b/ios/Sources/CapacitorObjC/CAPInstanceConfiguration.m @@ -1,5 +1,13 @@ #import "CAPInstanceConfiguration.h" -#import +#import "CAPInstanceDescriptor.h" + +// Implemented in Swift (CAPInstanceDescriptor.swift), which can't be imported here without a +// circular dependency. Declared locally rather than in the header so Swift doesn't see a +// redeclaration. +@interface CAPInstanceDescriptor (SwiftVended) +@property (nonatomic, readonly) BOOL cordovaDeployDisabled; +- (void)normalize; +@end @interface CAPInstanceConfiguration (Internal) - (instancetype)initWithConfiguration:(CAPInstanceConfiguration*)configuration andLocation:(NSURL*)location; diff --git a/ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m b/ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m index acdbc08caf..a619866993 100644 --- a/ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m +++ b/ios/Sources/CapacitorObjC/CAPInstanceDescriptor.m @@ -1,5 +1,4 @@ #import "CAPInstanceDescriptor.h" -#import // Swift extensions marked as @objc and internal are available to the Obj-C runtime but are not available at compile time. // so we need this declaration to avoid compiler complaints diff --git a/ios/Sources/CapacitorObjC/CAPPlugin.m b/ios/Sources/CapacitorObjC/CAPPlugin.m index 92bf24e7dd..152e5cf66a 100644 --- a/ios/Sources/CapacitorObjC/CAPPlugin.m +++ b/ios/Sources/CapacitorObjC/CAPPlugin.m @@ -1,38 +1,19 @@ #import "CAPPlugin.h" -#import "CAPBridgedJSTypes.h" -#import +#import "CAPPluginCall.h" #import -@implementation CAPPlugin +// Implemented in Swift (CAPPlugin+Bridge.swift), which can't be imported here without a circular +// dependency. Declared locally rather than in the header so Swift doesn't see a redeclaration. +@interface CAPPlugin (SwiftVended) +- (void)notifyListeners:(NSString* _Nonnull)eventName data:(NSDictionary* _Nullable)data; +@end --(instancetype) initWithBridge:(id)bridge pluginId:(NSString *)pluginId pluginName:(NSString *)pluginName { - self.bridge = bridge; - self.webView = bridge.webView; - self.pluginId = pluginId; - self.pluginName = pluginName; - self.eventListeners = [[NSMutableDictionary alloc] init]; - self.retainedEventArguments = [[NSMutableDictionary alloc] init]; - self.shouldStringifyDatesInCalls = true; - return self; -} +@implementation CAPPlugin -(NSString *) getId { return self.pluginName; } -- (BOOL)getBool:(CAPPluginCall *)call field:(NSString *)field defaultValue:(BOOL)defaultValue { - NSNumber* value = [call getNumber:field defaultValue:[NSNumber numberWithBool:defaultValue]]; - return [value boolValue]; -} - -- (NSString *) getString:(CAPPluginCall *)call field:(NSString *)field defaultValue:(NSString *)defaultValue { - return [call getString:field defaultValue:defaultValue]; -} - --(PluginConfig*)getConfig { - return [self.bridge.config getPluginConfig:self.pluginName]; -} - -(void)load {} - (void)addEventListener:(NSString *)eventName listener:(CAPPluginCall *)listener { @@ -40,7 +21,7 @@ - (void)addEventListener:(NSString *)eventName listener:(CAPPluginCall *)listene if(listenersForEvent == nil || [listenersForEvent count] == 0) { listenersForEvent = [[NSMutableArray alloc] initWithObjects:listener, nil]; [self.eventListeners setValue:listenersForEvent forKey:eventName]; - + [self sendRetainedArgumentsForEvent:eventName]; } else { [listenersForEvent addObject:listener]; @@ -53,9 +34,9 @@ - (void)sendRetainedArgumentsForEvent:(NSString *)eventName { if (retained == nil) { return; } - + [self.retainedEventArguments removeObjectForKey:eventName]; - + for(id data in retained) { [self notifyListeners:eventName data:data]; } @@ -71,52 +52,12 @@ - (void)removeEventListener:(NSString *)eventName listener:(CAPPluginCall *)list [listenersForEvent removeObjectAtIndex:listenerIndex]; } -- (void)notifyListeners:(NSString *)eventName data:(NSDictionary *)data { - [self notifyListeners:eventName data:data retainUntilConsumed:NO]; -} - -- (void)notifyListeners:(NSString *)eventName data:(NSDictionary *)data retainUntilConsumed:(BOOL)retain { - NSArray *listenersForEvent = [self.eventListeners objectForKey:eventName]; - if(listenersForEvent == nil || [listenersForEvent count] == 0) { - if (retain == YES) { - - if ([self.retainedEventArguments objectForKey:eventName] == nil) { - [self.retainedEventArguments setObject:[[NSMutableArray alloc] init] forKey:eventName]; - } - - [[self.retainedEventArguments objectForKey:eventName] addObject:data]; - } - return; - } - - for (int i=0; i < listenersForEvent.count; i++) { - CAPPluginCall *call = listenersForEvent[i]; - if (call != nil) { - CAPPluginCallResult *result = [[CAPPluginCallResult alloc] init:data]; - call.successHandler(result, call); - } - } -} - - (void)addListener:(CAPPluginCall *)call { NSString *eventName = [call.options objectForKey:@"eventName"]; [call setKeepAlive:TRUE]; [self addEventListener:eventName listener:call]; } -- (void)removeListener:(CAPPluginCall *)call { - NSString *eventName = [call.options objectForKey:@"eventName"]; - NSString *callbackId = [call.options objectForKey:@"callbackId"]; - CAPPluginCall *storedCall = [self.bridge savedCallWithID:callbackId]; - [self removeEventListener:eventName listener:storedCall]; - [self.bridge releaseCallWithID:callbackId]; -} - -- (void)removeAllListeners:(CAPPluginCall *)call { - [self.eventListeners removeAllObjects]; - [call resolve]; -} - - (NSArray*)getListeners:(NSString *)eventName { NSArray* listeners = [self.eventListeners objectForKey:eventName]; return listeners; @@ -124,41 +65,13 @@ - (void)removeAllListeners:(CAPPluginCall *)call { - (BOOL)hasListeners:(NSString *)eventName { NSArray* listeners = [self.eventListeners objectForKey:eventName]; - + if (listeners == nil) { return false; } return [listeners count] > 0; } -- (void)checkPermissions:(CAPPluginCall *)call { - [call resolve]; -} - -- (void)requestPermissions:(CAPPluginCall *)call { - [call resolve]; -} - -/** - * Configure popover sourceRect, sourceView and permittedArrowDirections to show it centered - */ --(void)setCenteredPopover:(UIViewController *) vc { - if (self.bridge.viewController != nil) { - vc.popoverPresentationController.sourceRect = CGRectMake(self.bridge.viewController.view.center.x, self.bridge.viewController.view.center.y, 0, 0); - vc.popoverPresentationController.sourceView = self.bridge.viewController.view; - vc.popoverPresentationController.permittedArrowDirections = 0; - } -} - --(void)setCenteredPopover:(UIViewController* _Nonnull) vc size:(CGSize) size { - if (self.bridge.viewController != nil) { - vc.popoverPresentationController.sourceRect = CGRectMake(self.bridge.viewController.view.center.x, self.bridge.viewController.view.center.y, 0, 0); - vc.preferredContentSize = size; - vc.popoverPresentationController.sourceView = self.bridge.viewController.view; - vc.popoverPresentationController.permittedArrowDirections = 0; - } -} - -(BOOL)supportsPopover { return YES; } diff --git a/ios/Sources/CapacitorObjC/CAPPluginCallResult.m b/ios/Sources/CapacitorObjC/CAPPluginCallResult.m new file mode 100644 index 0000000000..297f7561f3 --- /dev/null +++ b/ios/Sources/CapacitorObjC/CAPPluginCallResult.m @@ -0,0 +1,29 @@ +#import "CAPPluginCallResult.h" + +@implementation CAPPluginCallResult + +- (instancetype)init:(NSDictionary *)data { + if ((self = [super init])) { + _data = data; + } + return self; +} + +@end + +@implementation CAPPluginCallError + +- (instancetype)init:(NSString *)message + code:(NSString *)code + error:(NSError *)error + data:(NSDictionary *)data { + if ((self = [super init])) { + _message = message; + _code = code; + _error = error; + _data = data ? @{@"data": data} : nil; + } + return self; +} + +@end diff --git a/ios/Sources/CapacitorObjC/CAPPluginMethod.m b/ios/Sources/CapacitorObjC/CAPPluginMethod.m index d765540e92..8fc009d6ea 100644 --- a/ios/Sources/CapacitorObjC/CAPPluginMethod.m +++ b/ios/Sources/CapacitorObjC/CAPPluginMethod.m @@ -1,4 +1,3 @@ -#import #import "CAPPluginMethod.h" typedef void(^CAPCallback)(id _arg, NSInteger index); diff --git a/ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h index f22d9be2a0..10498d89ba 100644 --- a/ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h +++ b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPlugin.h @@ -1,36 +1,25 @@ #import #import -@protocol CAPBridgeProtocol; @class CAPPluginCall; -@class PluginConfig; - @interface CAPPlugin : NSObject @property (nonatomic, weak, nullable) WKWebView *webView; -@property (nonatomic, weak, nullable) id bridge; +// Untyped backing storage for the bridge. The typed `bridge` accessor (`id`) is +// vended from Swift, so this target never has to reference the Swift-defined CAPBridgeProtocol. +@property (nonatomic, weak, nullable) NSObject *bridgeRef; @property (nonatomic, strong, nonnull) NSString *pluginId; @property (nonatomic, strong, nonnull) NSString *pluginName; @property (nonatomic, strong, nullable) NSMutableDictionary*> *eventListeners; @property (nonatomic, strong, nullable) NSMutableDictionary *> *retainedEventArguments; @property (nonatomic, assign) BOOL shouldStringifyDatesInCalls; -- (instancetype _Nonnull) initWithBridge:(id _Nonnull) bridge pluginId:(NSString* _Nonnull) pluginId pluginName:(NSString* _Nonnull) pluginName DEPRECATED_MSG_ATTRIBUTE("This initializer is deprecated and is not suggested for use. Any data set through this init method will be overridden when it is loaded on the bridge."); - (void)addEventListener:(NSString* _Nonnull)eventName listener:(CAPPluginCall* _Nonnull)listener; - (void)removeEventListener:(NSString* _Nonnull)eventName listener:(CAPPluginCall* _Nonnull)listener; -- (void)notifyListeners:(NSString* _Nonnull)eventName data:(NSDictionary* _Nullable)data; -- (void)notifyListeners:(NSString* _Nonnull)eventName data:(NSDictionary* _Nullable)data retainUntilConsumed:(BOOL)retain; - (NSArray* _Nullable)getListeners:(NSString* _Nonnull)eventName; - (BOOL)hasListeners:(NSString* _Nonnull)eventName; - (void)addListener:(CAPPluginCall* _Nonnull)call; -- (void)removeListener:(CAPPluginCall* _Nonnull)call; -- (void)removeAllListeners:(CAPPluginCall* _Nonnull)call; -/** - * Default implementation of the capacitor 3.0 permission pattern - */ -- (void)checkPermissions:(CAPPluginCall* _Nonnull)call; -- (void)requestPermissions:(CAPPluginCall* _Nonnull)call; /** * Give the plugins a chance to take control when a URL is about to be loaded in the WebView. * Returning true causes the WebView to abort loading the URL. @@ -49,11 +38,6 @@ // need to override init() -(void)load; -(NSString* _Nonnull)getId; --(BOOL)getBool:(CAPPluginCall* _Nonnull) call field:(NSString* _Nonnull)field defaultValue:(BOOL)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations."); --(NSString* _Nullable)getString:(CAPPluginCall* _Nonnull)call field:(NSString* _Nonnull)field defaultValue:(NSString* _Nonnull)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations."); --(PluginConfig* _Nonnull)getConfig; --(void)setCenteredPopover:(UIViewController* _Nonnull) vc; --(void)setCenteredPopover:(UIViewController* _Nonnull) vc size:(CGSize) size; -(BOOL)supportsPopover DEPRECATED_MSG_ATTRIBUTE("All iOS 13+ devices support popover"); @end diff --git a/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h index 129dba7ff2..2dee66df0a 100644 --- a/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h +++ b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCall.h @@ -1,8 +1,7 @@ #import +#import "CAPPluginCallResult.h" @class CAPPluginCall; -@class CAPPluginCallResult; -@class CAPPluginCallError; typedef void(^CAPPluginCallSuccessHandler)(CAPPluginCallResult *result, CAPPluginCall* call); typedef void(^CAPPluginCallErrorHandler)(CAPPluginCallError *error); diff --git a/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCallResult.h b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCallResult.h new file mode 100644 index 0000000000..2e3be1576e --- /dev/null +++ b/ios/Sources/CapacitorObjC/include/Capacitor/CAPPluginCallResult.h @@ -0,0 +1,28 @@ +// These carriers are Objective-C rather than Swift because CAPPluginCall's successHandler / +// errorHandler are block-typed properties that take them as parameters. A forward declaration is +// not enough for Swift to import a block type, and Swift cannot resolve one against a class it is +// itself in the middle of defining, so the concrete definitions must precede the Swift module. +#import + +@interface CAPPluginCallResult : NSObject + +@property (nonatomic, readonly, nullable) NSDictionary *data; + +- (nonnull instancetype)init:(nullable NSDictionary *)data; + +@end + +@interface CAPPluginCallError : NSObject + +@property (nonatomic, readonly, nonnull) NSString *message; +@property (nonatomic, readonly, nullable) NSString *code; +@property (nonatomic, readonly, nullable) NSError *error; +@property (nonatomic, readonly, nullable) NSDictionary *data; + +- (nonnull instancetype)init:(nonnull NSString *)message + code:(nullable NSString *)code + error:(nullable NSError *)error + data:(nullable NSDictionary *)data + NS_SWIFT_NAME(init(message:code:error:data:)); + +@end diff --git a/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h b/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h new file mode 100644 index 0000000000..3176162636 --- /dev/null +++ b/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor-Swift.h @@ -0,0 +1,9 @@ +// SPM-only shim. Under CocoaPods, Capacitor is one mixed-language module and the compiler +// generates a real exposing the Swift interface to Objective-C; this +// file is excluded from the pod so it can't clobber it (see Capacitor.podspec). +// +// Under SPM the Swift module is separate and its generated header is not reachable at that path, so +// this shim provides the import path and surfaces the same interface via a module import. +#if !__building_module(Capacitor) +@import Capacitor; +#endif diff --git a/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h b/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h index 7170982981..d7bed7a9fd 100644 --- a/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h +++ b/ios/Sources/CapacitorObjCShims/include/Capacitor/Capacitor.h @@ -13,3 +13,11 @@ FOUNDATION_EXPORT const unsigned char CapacitorVersionString[]; #import #import +// Several CAPPlugin members (bridge, getConfig, notifyListeners:, checkPermissions:, ...) are vended +// from Swift, so importing the module here keeps the umbrella a complete view of CAPPlugin for +// Objective-C plugin authors. Skipped while the module itself is being built, which is the only +// case where this would be circular. +#if !__building_module(Capacitor) +@import Capacitor; +#endif + diff --git a/ios/Tests/CapacitorTests/BridgedTypesTests.swift b/ios/Tests/CapacitorTests/BridgedTypesTests.swift index f88b4e320e..dac5b57f2f 100644 --- a/ios/Tests/CapacitorTests/BridgedTypesTests.swift +++ b/ios/Tests/CapacitorTests/BridgedTypesTests.swift @@ -149,12 +149,12 @@ class BridgedTypesTests: XCTestCase { } func testDateResultWrapping() throws { - let result = try PluginCallResult.dictionary(["date": unserializedDictionary["testDateObject"]!]).jsonRepresentation() + let result = try JSResultSerialization.jsonRepresentation(of: ["date": unserializedDictionary["testDateObject"]!]) XCTAssertEqual(result, "{\"date\":\"\(unserializedDictionary["testDateString"] as! String)\"}") } func testResultMerging() throws { - let result = try PluginCallResult.dictionary(["number": 1]).jsonRepresentation(includingFields: ["string":"foo"]) + let result = try JSResultSerialization.jsonRepresentation(of: ["number": 1], includingFields: ["string":"foo"]) // ordering of the pairs should be non-deterministic if result != "{\"string\":\"foo\",\"number\":1}" && result != "{\"number\":1,\"string\":\"foo\"}" { XCTAssert(false) From d527ace28a6e5b5fc22d5f3a91b2e490faf404fe Mon Sep 17 00:00:00 2001 From: Joseph Pender Date: Wed, 2 Sep 2026 12:15:12 -0500 Subject: [PATCH 3/5] test(ios): migrate the iOS test suites to swift-testing --- .github/workflows/ci.yml | 4 +- .../Capacitor/NotificationRouter.swift | 9 + ios/Sources/CapacitorObjC/CAPPlugin.m | 11 + .../CapacitorObjCTests/BridgedTypesTests.m | 46 --- .../JSONSerializationWrapper.h | 9 - .../JSONSerializationWrapper.m | 24 -- .../PluginCallAccessorTests.m | 1 - .../BridgedTypesCoercionTests.swift | 56 ++++ .../CapacitorTests/BridgedTypesHelper.swift | 31 -- .../CapacitorTests/BridgedTypesTests.swift | 294 +++++++++--------- ios/Tests/CapacitorTests/CAPPluginTests.swift | 91 ++++++ ios/Tests/CapacitorTests/CodableTests.swift | 161 +++++----- .../CapacitorTests/ConfigurationTests.swift | 284 +++++++++-------- .../CapacitorTests/DataCodableTests.swift | 147 +++++---- .../CapacitorTests/DateCodableTests.swift | 98 +++--- .../HttpInterceptorNavigationTests.swift | 7 +- ios/Tests/CapacitorTests/JSExportTests.swift | 24 +- .../JSONSerializationWrapper.swift | 16 + .../CapacitorTests/NestedCodableTests.swift | 52 ++-- .../NonconformingFloatCodableTests.swift | 138 ++++---- ios/Tests/CapacitorTests/RouterTests.swift | 42 +-- .../CapacitorTests/SuperCodableTests.swift | 106 +++---- .../CapacitorTests/URLCodableTests.swift | 52 ++-- ios/package.json | 2 +- 24 files changed, 867 insertions(+), 838 deletions(-) delete mode 100644 ios/Tests/CapacitorObjCTests/BridgedTypesTests.m delete mode 100644 ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h delete mode 100644 ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m create mode 100644 ios/Tests/CapacitorTests/BridgedTypesCoercionTests.swift delete mode 100644 ios/Tests/CapacitorTests/BridgedTypesHelper.swift create mode 100644 ios/Tests/CapacitorTests/CAPPluginTests.swift create mode 100644 ios/Tests/CapacitorTests/JSONSerializationWrapper.swift diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 471e939ec8..a3d35a1919 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: - run: npm test working-directory: ./core test-ios: - runs-on: macos-15 + runs-on: macos-26 timeout-minutes: 30 needs: - setup @@ -97,7 +97,7 @@ jobs: strategy: matrix: xcode: - - /Applications/Xcode_26.0.app + - /Applications/Xcode_26.6.app steps: - run: sudo xcode-select --switch ${{ matrix.xcode }} - run: xcrun simctl list > /dev/null diff --git a/ios/Sources/Capacitor/NotificationRouter.swift b/ios/Sources/Capacitor/NotificationRouter.swift index 99fcbb2550..c1f9e0fa51 100644 --- a/ios/Sources/Capacitor/NotificationRouter.swift +++ b/ios/Sources/Capacitor/NotificationRouter.swift @@ -1,11 +1,20 @@ import Foundation @objc(CAPNotificationRouter) public class NotificationRouter: NSObject, UNUserNotificationCenterDelegate { + // UNUserNotificationCenter.current() raises when the process has no application bundle, which + // is the case in a host-less unit test runner and some extension contexts. There is no + // notification center to register with there, so treat it as unavailable rather than trapping. + private static var isNotificationCenterAvailable: Bool { + return ["app", "appex"].contains(Bundle.main.bundleURL.pathExtension) + } + var handleApplicationNotifications: Bool { get { + guard Self.isNotificationCenterAvailable else { return false } return UNUserNotificationCenter.current().delegate === self } set { + guard Self.isNotificationCenterAvailable else { return } let center = UNUserNotificationCenter.current() if newValue { diff --git a/ios/Sources/CapacitorObjC/CAPPlugin.m b/ios/Sources/CapacitorObjC/CAPPlugin.m index 152e5cf66a..bb272541df 100644 --- a/ios/Sources/CapacitorObjC/CAPPlugin.m +++ b/ios/Sources/CapacitorObjC/CAPPlugin.m @@ -10,6 +10,17 @@ - (void)notifyListeners:(NSString* _Nonnull)eventName data:(NSDictionary -#import -#import "CapacitorTests-Swift.h" - -// interface for this class -@interface BridgedTypesTestsObjc : XCTestCase -@end - -@implementation BridgedTypesTestsObjc - -- (void)setUp { - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - -- (void)testNullHandling { - NSArray* source = @[@"test", [NSNull null], @3]; - NSArray* result = [[BridgedTypesHelper shared] validTransformationOfArray:source]; - NSError *error = nil; - // test that the replaced null value exists - id value = [result objectAtIndex:1]; - XCTAssertNotNil(value); - XCTAssertTrue([value isKindOfClass:[NSNull class]]); - // test that the null value casts to non-optional - value = [[BridgedTypesHelper shared] testCastOf:result atIndex:1 error:&error]; - XCTAssertNotNil(value); - XCTAssertNil(error); -} - -- (void)testOptionalHandling { - NSArray* source = @[@"test", [NSNull null], @3]; - NSArray* result = [[BridgedTypesHelper shared] invalidTransformationOfArray:source]; - NSError *error = nil; - // test that the removed null value, now optional, is automatically transformed back into a NSNull - id value = [result objectAtIndex:1]; - XCTAssertNotNil(value); - XCTAssertTrue([value isKindOfClass:[NSNull class]]); - // test that the optional value fails to cast to non-optional - value = [[BridgedTypesHelper shared] testCastOf:result atIndex:1 error:&error]; - XCTAssertNil(value); - XCTAssertNotNil(error); -} -@end diff --git a/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h b/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h deleted file mode 100644 index 96ca66281b..0000000000 --- a/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -@interface JSONSerializationWrapper : NSObject -@property (nonatomic, copy) NSDictionary* _Nonnull dictionary; - -- (instancetype _Nullable)initWithDictionary:(NSDictionary* _Nonnull)options; -- (NSDictionary * _Nullable)unwrappedResult; - -@end diff --git a/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m b/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m deleted file mode 100644 index 6316c9c88b..0000000000 --- a/ios/Tests/CapacitorObjCTests/JSONSerializationWrapper.m +++ /dev/null @@ -1,24 +0,0 @@ - -#import "JSONSerializationWrapper.h" - -@implementation JSONSerializationWrapper - -- (instancetype)initWithDictionary:(NSDictionary *)dictionary { - self = [super init]; - if (self != nil) { - _dictionary = dictionary; - } - return self; -} - -- (NSDictionary *)unwrappedResult { - NSError* error = nil; - NSData* serializedData = [NSJSONSerialization dataWithJSONObject:[self dictionary] options:NSJSONWritingPrettyPrinted error:&error]; - if (serializedData != nil) { - NSDictionary* result = [NSJSONSerialization JSONObjectWithData:serializedData options:0 error:&error]; - return result; - } - return nil; -} - -@end diff --git a/ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m b/ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m index 4d665aeec1..d35f4f4736 100644 --- a/ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m +++ b/ios/Tests/CapacitorObjCTests/PluginCallAccessorTests.m @@ -1,7 +1,6 @@ #import #import #import -#import "CapacitorTests-Swift.h" // interface for this class @interface PluginCallAccessorTests : XCTestCase diff --git a/ios/Tests/CapacitorTests/BridgedTypesCoercionTests.swift b/ios/Tests/CapacitorTests/BridgedTypesCoercionTests.swift new file mode 100644 index 0000000000..e149fcb4b8 --- /dev/null +++ b/ios/Tests/CapacitorTests/BridgedTypesCoercionTests.swift @@ -0,0 +1,56 @@ +import Foundation +import Testing +@testable import Capacitor + +private enum BridgedTypesCoercionError: Error { + case badCast +} + +private enum BridgedTypesCoercionHelper { + static func validTransformation(of array: [Any]) -> [Any] { + let result = JSTypes.coerceArrayToJSArray(array)!.capacitor.replacingNullValues() + return result.capacitor.replacingOptionalValues() as [Any] + } + + static func invalidTransformation(of array: [Any]) -> [Any] { + let result = JSTypes.coerceArrayToJSArray(array)!.capacitor.replacingNullValues() + return result as [Any] + } + + static func testCast(of array: [Any], atIndex index: Int) throws -> Any { + if let castArray = array as? [JSValue] { + return castArray[index] as Any + } + throw BridgedTypesCoercionError.badCast + } +} + +struct BridgedTypesCoercionTests { + @Test func nullHandling() throws { + let source: [Any] = ["test", NSNull(), 3] + let result = BridgedTypesCoercionHelper.validTransformation(of: source) + + // the replaced null value exists + let value = result[1] + #expect(value is NSNull) + + // the null value casts to non-optional + let castValue = try BridgedTypesCoercionHelper.testCast(of: result, atIndex: 1) + #expect(castValue is NSNull) + } + + @Test func optionalHandling() throws { + let source: [Any] = ["test", NSNull(), 3] + let result = BridgedTypesCoercionHelper.invalidTransformation(of: source) + + // bridging the optional-holding array to NSArray (as happens when passing values across + // the JS bridge) coerces the removed null value's `nil` back into an NSNull + let value = (result as NSArray).object(at: 1) + #expect(value is NSNull) + + // the optional value fails to cast to non-optional + #expect(throws: BridgedTypesCoercionError.badCast) { + try BridgedTypesCoercionHelper.testCast(of: result, atIndex: 1) + } + } +} diff --git a/ios/Tests/CapacitorTests/BridgedTypesHelper.swift b/ios/Tests/CapacitorTests/BridgedTypesHelper.swift deleted file mode 100644 index 9df3f786a8..0000000000 --- a/ios/Tests/CapacitorTests/BridgedTypesHelper.swift +++ /dev/null @@ -1,31 +0,0 @@ -import Foundation -@testable import Capacitor - -enum BridgeTypeError: Error { - case badCast -} - -@objc class BridgedTypesHelper: NSObject { - @objc static let shared = BridgedTypesHelper() - - var untypedArray: [Any] { - return [] - } - - @objc func validTransformationOf(array: [Any]) -> [Any] { - let result = JSTypes.coerceArrayToJSArray(array)!.capacitor.replacingNullValues() - return result.capacitor.replacingOptionalValues() as [Any] - } - - @objc func invalidTransformationOf(array: [Any]) -> [Any] { - let result = JSTypes.coerceArrayToJSArray(array)!.capacitor.replacingNullValues() - return result as [Any] - } - - @objc func testCast(of array: [Any], atIndex index: Int) throws -> Any { - if let castArray = array as? [JSValue] { - return castArray[index] as Any - } - throw BridgeTypeError.badCast - } -} diff --git a/ios/Tests/CapacitorTests/BridgedTypesTests.swift b/ios/Tests/CapacitorTests/BridgedTypesTests.swift index dac5b57f2f..85703ace32 100644 --- a/ios/Tests/CapacitorTests/BridgedTypesTests.swift +++ b/ios/Tests/CapacitorTests/BridgedTypesTests.swift @@ -1,202 +1,218 @@ -import XCTest - +import Foundation +import Testing @testable import Capacitor -class TestContainer: NSObject, JSValueContainer { +private class TestContainer: NSObject, JSValueContainer { var coercedDictionary: [AnyHashable: Any] = [:] - - public static var jsDateFormatter: ISO8601DateFormatter = { + + static var jsDateFormatter: ISO8601DateFormatter = { return ISO8601DateFormatter() }() - - public var jsObjectRepresentation: JSObject { + + var jsObjectRepresentation: JSObject { return coercedDictionary as? JSObject ?? [:] } } -class BridgedTypesTests: XCTestCase { - static var unserializedDictionary: [AnyHashable: Any] = [:] - static var deserializedDictionary: [AnyHashable: Any] = [:] - - var unserializedDictionary: [AnyHashable: Any] = [:] - var deserializedDictionary: [AnyHashable: Any] = [:] - var testContainer = TestContainer() - - override class func setUp() { - let formatter = ISO8601DateFormatter() - // an ISO 8601 string does not necessarily include subsecond precision, so we can't just capture the current date - // or else we won't be able to compare the objects since they could differ by milliseconds or nanoseonds. so instead - // we use a fixed timestamp at a whole hour. - let date = NSDate(timeIntervalSinceReferenceDate: 632854800) - let subDictionary: [AnyHashable: Any] = ["testIntArray": [0, 1, 2], "testStringArray": ["1", "2", "3"], "testDictionary":["foo":"bar"]] - var dictionary: [AnyHashable: Any] = ["testInt": 1 as Int, "testFloat": Float.pi, "testBool": true as Bool, "testString": "Some string value", "testChild": subDictionary, "testDateString": formatter.string(from: date as Date)] - let serializer = JSONSerializationWrapper(dictionary: dictionary)! - var unwrappedResult = serializer.unwrappedResult()! - // date objects are not handled by the JSON serializer, so we have to insert these after the roundtrip - unwrappedResult["testDateObject"] = date - dictionary["testDateObject"] = date - unserializedDictionary = dictionary - deserializedDictionary = unwrappedResult - } - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - unserializedDictionary = BridgedTypesTests.unserializedDictionary - deserializedDictionary = BridgedTypesTests.deserializedDictionary - testContainer.coercedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. +struct BridgedTypesTests { + private static let fixture = BridgedTypesFixture() + + private struct BridgedTypesFixture { + let unserializedDictionary: [AnyHashable: Any] + let deserializedDictionary: [AnyHashable: Any] + + init() { + let formatter = ISO8601DateFormatter() + let date = NSDate(timeIntervalSinceReferenceDate: 632854800) + let subDictionary: [AnyHashable: Any] = [ + "testIntArray": [0, 1, 2], + "testStringArray": ["1", "2", "3"], + "testDictionary": ["foo": "bar"] + ] + var dictionary: [AnyHashable: Any] = [ + "testInt": 1 as Int, + "testFloat": Float.pi, + "testBool": true as Bool, + "testString": "Some string value", + "testChild": subDictionary, + "testDateString": formatter.string(from: date as Date) + ] + let serializer = JSONSerializationWrapper(dictionary: dictionary)! + var unwrappedResult = serializer.unwrappedResult()! + unwrappedResult["testDateObject"] = date + dictionary["testDateObject"] = date + self.unserializedDictionary = dictionary + self.deserializedDictionary = unwrappedResult + } } - - func testTranslation() throws { - XCTAssertTrue(unserializedDictionary.count > 0) - XCTAssertTrue(deserializedDictionary.count > 0) - XCTAssertTrue(testContainer.coercedDictionary.count > 0) + + @Test func testTranslation() throws { + let unserializedDictionary = Self.fixture.unserializedDictionary + let deserializedDictionary = Self.fixture.deserializedDictionary + let testContainer = TestContainer() + testContainer.coercedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! + + #expect(unserializedDictionary.count > 0) + #expect(deserializedDictionary.count > 0) + #expect(testContainer.coercedDictionary.count > 0) } - - func testCastingFailure() throws { + + @Test func testCastingFailure() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary + let unserializedDictionary = Self.fixture.unserializedDictionary + var castResult = deserializedDictionary as? JSObject - XCTAssertNil(castResult) - + #expect(castResult == nil) + castResult = unserializedDictionary as? JSObject - XCTAssertNil(castResult) + #expect(castResult == nil) } - - func testCoercionSuccess() throws { + + @Test func testCoercionSuccess() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary) - XCTAssertNotNil(coercedResult) + #expect(coercedResult != nil) } - - func testRoundtripEquality() throws { + + @Test func testRoundtripEquality() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary + let unserializedDictionary = Self.fixture.unserializedDictionary let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! let foo: NSDictionary = coercedResult as NSDictionary let bar: NSDictionary = unserializedDictionary as NSDictionary - - XCTAssertEqual(foo, bar) + + #expect(foo == bar) } - - func testTypeEquavalency() throws { + + @Test func testTypeEquivalency() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary + let unserializedDictionary = Self.fixture.unserializedDictionary let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! let coercedFloat = coercedResult["testFloat"] as? Float let sourceFloat = unserializedDictionary["testFloat"] as? Float let resultFloat = deserializedDictionary["testFloat"] as? Float - - XCTAssertNotNil(coercedFloat) - XCTAssertNotNil(sourceFloat) - XCTAssertNotNil(resultFloat) - - XCTAssertEqual(coercedFloat, sourceFloat) - XCTAssertEqual(sourceFloat, resultFloat) - XCTAssertEqual(coercedFloat, Float.pi) - } - - func testNumberWrapping() throws { - // the original number is a swift primitive float + + #expect(coercedFloat != nil) + #expect(sourceFloat != nil) + #expect(resultFloat != nil) + + #expect(coercedFloat == sourceFloat) + #expect(sourceFloat == resultFloat) + #expect(coercedFloat == Float.pi) + } + + @Test func testNumberWrapping() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary + let unserializedDictionary = Self.fixture.unserializedDictionary + let testContainer = TestContainer() + testContainer.coercedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! + let sourceFloat = unserializedDictionary["testFloat"]! - XCTAssertTrue(type(of: sourceFloat) == Float.self) - - // but after serialization/deserilization, it will be wrapped as an NSNumber + #expect(type(of: sourceFloat) == Float.self) + let wrappedFloat = deserializedDictionary["testFloat"]! let underlyingType: AnyObject.Type = NSClassFromString("__NSCFNumber")! - XCTAssertTrue(type(of: wrappedFloat) == underlyingType.self) - - // coercion will keep the NSNumber type since there's no way to recover it + #expect(type(of: wrappedFloat) == underlyingType.self) + let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! let coercedFloat = coercedResult["testFloat"]! - XCTAssertTrue(type(of: coercedFloat) == underlyingType.self) - - // but the cast accessor should restore it + #expect(type(of: coercedFloat) == underlyingType.self) + let castFloat = testContainer.getFloat("testFloat")! - XCTAssertTrue(type(of: castFloat) == Float.self) - XCTAssertEqual(sourceFloat as! Float, castFloat) + #expect(type(of: castFloat) == Float.self) + #expect((sourceFloat as! Float) == castFloat) } - - func testDateObject() throws { + + @Test func testDateObject() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! let date = coercedResult["testDateObject"] as! Date - XCTAssertNotNil(date) - XCTAssertTrue(type(of: date) == Date.self) + #expect(date != nil) + #expect(type(of: date) == Date.self) } - - func testDateParsing() throws { + + @Test func testDateParsing() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary let coercedResult = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! let formatter = ISO8601DateFormatter() let parsedDate = formatter.date(from: coercedResult["testDateString"] as! String)! let dateObject = coercedResult["testDateObject"] as! Date - XCTAssertNotNil(parsedDate) - XCTAssertNotNil(dateObject) - XCTAssertTrue(dateObject.compare(parsedDate) == .orderedSame) + #expect(parsedDate != nil) + #expect(dateObject != nil) + #expect(dateObject.compare(parsedDate) == .orderedSame) } - - func testDateExtensions() throws { + + @Test func testDateExtensions() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary + let testContainer = TestContainer() + testContainer.coercedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary)! + let parsedDate = testContainer.getDate("testDateString")! let dateObject = testContainer.getDate("testDateObject")! - XCTAssertNotNil(parsedDate) - XCTAssertNotNil(dateObject) - XCTAssertTrue(dateObject.compare(parsedDate) == .orderedSame) + #expect(parsedDate != nil) + #expect(dateObject != nil) + #expect(dateObject.compare(parsedDate) == .orderedSame) } - - func testDateCoercion() throws { + + @Test func testDateCoercion() throws { + let deserializedDictionary = Self.fixture.deserializedDictionary let stringifiedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary, formattingDatesAsStrings: true)! let unstringifiedDictionary = JSTypes.coerceDictionaryToJSObject(deserializedDictionary, formattingDatesAsStrings: false)! let stringifiedValue = stringifiedDictionary["testDateObject"]! let unstringifiedValue = unstringifiedDictionary["testDateObject"]! - XCTAssertTrue(type(of: stringifiedValue) == String.self) - XCTAssertTrue(type(of: unstringifiedValue) == Date.self) - XCTAssertEqual(stringifiedValue as! String, stringifiedDictionary["testDateString"] as! String) + #expect(type(of: stringifiedValue) == String.self) + #expect(type(of: unstringifiedValue) == Date.self) + #expect((stringifiedValue as! String) == (stringifiedDictionary["testDateString"] as! String)) } - - func testDateResultWrapping() throws { + + @Test func testDateResultWrapping() throws { + let unserializedDictionary = Self.fixture.unserializedDictionary let result = try JSResultSerialization.jsonRepresentation(of: ["date": unserializedDictionary["testDateObject"]!]) - XCTAssertEqual(result, "{\"date\":\"\(unserializedDictionary["testDateString"] as! String)\"}") - } - - func testResultMerging() throws { - let result = try JSResultSerialization.jsonRepresentation(of: ["number": 1], includingFields: ["string":"foo"]) - // ordering of the pairs should be non-deterministic - if result != "{\"string\":\"foo\",\"number\":1}" && result != "{\"number\":1,\"string\":\"foo\"}" { - XCTAssert(false) - } + #expect(result == "{\"date\":\"\(unserializedDictionary["testDateString"] as! String)\"}") + } + + @Test func testResultMerging() throws { + let result = try JSResultSerialization.jsonRepresentation(of: ["number": 1], includingFields: ["string": "foo"]) + let isValid = result == "{\"string\":\"foo\",\"number\":1}" || result == "{\"number\":1,\"string\":\"foo\"}" + #expect(isValid) } - - func testNullWrapping() throws { + + @Test func testNullWrapping() throws { let dictionary: [AnyHashable: Any] = ["testInt": 1 as Int, "testNull": NSNull()] let coercedDictionary = JSTypes.coerceDictionaryToJSObject(dictionary)! - XCTAssertNotNil(coercedDictionary) - XCTAssertEqual(coercedDictionary.count, 2) - XCTAssertTrue(coercedDictionary["testNull"]! is NSNull) + #expect(coercedDictionary != nil) + #expect(coercedDictionary.count == 2) + #expect(coercedDictionary["testNull"]! is NSNull) } - - func testNullTransformation() throws { + + @Test func testNullTransformation() throws { let array: [Any] = [1, NSNull(), "test string"] let coercedArray = JSTypes.coerceArrayToJSArray(array)! - XCTAssertNotNil(coercedArray) - XCTAssertEqual(coercedArray.count, 3) - XCTAssertTrue(type(of: coercedArray[1]) == NSNull.self) + #expect(coercedArray != nil) + #expect(coercedArray.count == 3) + #expect(type(of: coercedArray[1]) == NSNull.self) let filteredArray = coercedArray.capacitor.replacingNullValues() - XCTAssertEqual(filteredArray.count, 3) - XCTAssertNil(filteredArray[1]) + #expect(filteredArray.count == 3) + #expect(filteredArray[1] == nil) let restoredArray = filteredArray.capacitor.replacingOptionalValues() - XCTAssertEqual(restoredArray.count, 3) - XCTAssertNotNil(restoredArray[1]) - XCTAssertTrue(restoredArray[0] is NSNumber) - XCTAssertTrue(restoredArray[1] is NSNull) - XCTAssertTrue(restoredArray[2] is String) - } - - func testSparseArrayCastSuccess() throws { + #expect(restoredArray.count == 3) + #expect(restoredArray[1] != nil) + #expect(restoredArray[0] is NSNumber) + #expect(restoredArray[1] is NSNull) + #expect(restoredArray[2] is String) + } + + @Test func testSparseArrayCastSuccess() throws { let array: [Any] = ["test string 1", "test string 2", NSNull()] let sparseArray = JSTypes.coerceArrayToJSArray(array)?.capacitor.replacingNullValues() as? [String?] - XCTAssertNotNil(sparseArray) - XCTAssertEqual(sparseArray!.count, 3) - XCTAssertNil(sparseArray![2]) + #expect(sparseArray != nil) + #expect(sparseArray!.count == 3) + #expect(sparseArray![2] == nil) } - - func testSparseArrayCastFailure() throws { + + @Test func testSparseArrayCastFailure() throws { let array: [Any] = ["test string 1", 1, NSNull()] let sparseArray = JSTypes.coerceArrayToJSArray(array)?.capacitor.replacingNullValues() as? [String?] - XCTAssertNil(sparseArray) + #expect(sparseArray == nil) } } diff --git a/ios/Tests/CapacitorTests/CAPPluginTests.swift b/ios/Tests/CapacitorTests/CAPPluginTests.swift new file mode 100644 index 0000000000..ac0a1ce00d --- /dev/null +++ b/ios/Tests/CapacitorTests/CAPPluginTests.swift @@ -0,0 +1,91 @@ +import Foundation +import Testing +@testable import Capacitor + +struct CAPPluginTests { + private final class Recorder { + private(set) var received: [PluginCallResultData] = [] + func record(_ data: PluginCallResultData) { + received.append(data) + } + } + + private static func makeCall() -> (call: CAPPluginCall, recorder: Recorder) { + let recorder = Recorder() + let call: CAPPluginCall = CAPPluginCall(callbackId: "test", methodName: "test", options: [:], success: { result, _ in + recorder.record(result?.data ?? [:]) + }, error: { _ in }) + return (call, recorder) + } + + @Test func notifyListenersDeliversToActiveListener() { + let plugin = CAPPlugin() + let (call, recorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: call) + + plugin.notifyListeners("myEvent", data: ["value": "hello"]) + + #expect(recorder.received.count == 1) + #expect(recorder.received.first?["value"] as? String == "hello") + } + + @Test func removeEventListenerStopsDelivery() { + let plugin = CAPPlugin() + let (call, recorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: call) + plugin.removeEventListener("myEvent", listener: call) + + plugin.notifyListeners("myEvent", data: ["value": "hello"]) + + #expect(recorder.received.isEmpty) + } + + @Test func hasListenersReflectsAddAndRemove() { + let plugin = CAPPlugin() + let (call, _) = Self.makeCall() + #expect(plugin.hasListeners("myEvent") == false) + + plugin.addEventListener("myEvent", listener: call) + #expect(plugin.hasListeners("myEvent") == true) + + plugin.removeEventListener("myEvent", listener: call) + #expect(plugin.hasListeners("myEvent") == false) + } + + @Test func notifyListenersWithoutListenersAndNoRetainDropsEvent() { + let plugin = CAPPlugin() + plugin.notifyListeners("myEvent", data: ["value": "hello"], retainUntilConsumed: false) + + let (call, recorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: call) + + #expect(recorder.received.isEmpty) + } + + @Test func notifyListenersWithoutListenersAndRetainReplaysOnAttach() { + let plugin = CAPPlugin() + plugin.notifyListeners("myEvent", data: ["value": "hello"], retainUntilConsumed: true) + + let (call, recorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: call) + + #expect(recorder.received.count == 1) + #expect(recorder.received.first?["value"] as? String == "hello") + } + + @Test func notifyListenersAfterListenerRemovedStillRetainsAndReplaysOnReattach() { + let plugin = CAPPlugin() + let (firstCall, firstRecorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: firstCall) + plugin.removeEventListener("myEvent", listener: firstCall) + + plugin.notifyListeners("myEvent", data: ["value": "hello"], retainUntilConsumed: true) + + let (secondCall, secondRecorder) = Self.makeCall() + plugin.addEventListener("myEvent", listener: secondCall) + + #expect(firstRecorder.received.isEmpty) + #expect(secondRecorder.received.count == 1) + #expect(secondRecorder.received.first?["value"] as? String == "hello") + } +} diff --git a/ios/Tests/CapacitorTests/CodableTests.swift b/ios/Tests/CapacitorTests/CodableTests.swift index bfdbe57162..972ef394f2 100644 --- a/ios/Tests/CapacitorTests/CodableTests.swift +++ b/ios/Tests/CapacitorTests/CodableTests.swift @@ -1,12 +1,5 @@ -// -// JSValueDecoderTest.swift -// CapacitorTests -// -// Created by Steven Sherry on 12/8/23. -// Copyright © 2023 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor private struct Pet: Codable, Equatable { @@ -58,52 +51,58 @@ private let person = Person( ] ) -final class JSValueDecoderTest: XCTestCase { - func testDecode_when_provided_a_valid_keyed_container_for_the_target_type__decoding_is_successful() throws { +struct JSValueDecoderTests { + @Test func decodingValidKeyedContainerSucceeds() throws { let decoder = JSValueDecoder() let decodedPerson = try decoder.decode(Person.self, from: rawPerson) - XCTAssertEqual(decodedPerson, person) + #expect(decodedPerson == person) } - func testDecode__when_provided_a_valid_unkeyed_container_for_the_target_type__decoding_is_successful() throws { + @Test func decodingValidUnkeyedContainerSucceeds() throws { let decoder = JSValueDecoder() let decodedPeople = try decoder.decode([Person].self, from: rawPeople) - XCTAssertEqual(person.family, decodedPeople) + #expect(person.family == decodedPeople) } - func testDecode__when_provided_a_single_value_for_the_target_type__decoding_is_successful() throws { + @Test func decodingSingleValueSucceeds() throws { let decoder = JSValueDecoder() let decodedNumber = try decoder.decode(UInt.self, from: 100 as NSNumber) - XCTAssertEqual(100, decodedNumber) + #expect(decodedNumber == 100) } - func testDecode__when_provided_an_invalid_keyed_container_for_the_target_type__decoding_fails() throws { + @Test func decodingInvalidKeyedContainerFails() throws { let decoder = JSValueDecoder() var invalidRawPerson = rawPerson invalidRawPerson["name"] = nil - XCTAssertThrowsError(try decoder.decode(Person.self, from: invalidRawPerson)) + #expect(throws: DecodingError.self) { + try decoder.decode(Person.self, from: invalidRawPerson) + } } - func testDecode__when_provided_an_invalid_unkeyed_container_for_the_target_type__decoding_fails() throws { + @Test func decodingInvalidUnkeyedContainerFails() throws { let decoder = JSValueDecoder() - var invalidRawPeople = try XCTUnwrap(rawPeople as? [JSObject]) + var invalidRawPeople = try #require(rawPeople as? [JSObject]) invalidRawPeople[0]["name"] = nil - XCTAssertThrowsError(try decoder.decode([Person].self, from: invalidRawPeople)) + #expect(throws: DecodingError.self) { + try decoder.decode([Person].self, from: invalidRawPeople) + } } - func testDecode__when_provided_an_invalid_single_value_type_for_the_input_value__decoding_fails() throws { + @Test func decodingInvalidSingleValueTypeFails() throws { let decoder = JSValueDecoder() - XCTAssertThrowsError(try decoder.decode(UInt.self, from: -1 as NSNumber)) + #expect(throws: DecodingError.self) { + try decoder.decode(UInt.self, from: -1 as NSNumber) + } } - func testDecode__when_provided_a_valid_nested_array__decoding_is_successful() throws { + @Test func decodingValidNestedArraySucceeds() throws { let decoder = JSValueDecoder() let nestedPeople: JSArray = [rawPeople, rawPeople] let decodedPeople = try decoder.decode([[Person]].self, from: nestedPeople) - XCTAssertEqual([person.family, person.family], decodedPeople) + #expect([person.family, person.family] == decodedPeople) } - func testDecode_when_attempting_to_decode_a_class__decoding_fails() throws { + @Test func decodingClassFails() throws { class Pet: Decodable { var name: String var breed: String @@ -116,79 +115,81 @@ final class JSValueDecoderTest: XCTestCase { } let decoder = JSValueDecoder() - XCTAssertThrowsError(try decoder.decode(Pet.self, from: rawPet)) + #expect(throws: DecodingError.self) { + try decoder.decode(Pet.self, from: rawPet) + } } - func testDecode__when_nsnull_explicitly_present_in_container__it_correctly_decodes_to_nil() throws { + @Test func decodingNSNullToNilSucceeds() throws { let decoder = JSValueDecoder() - var rawPerson = rawPerson - rawPerson["pet"] = NSNull() + var rawPersonWithNull = rawPerson + rawPersonWithNull["pet"] = NSNull() - let decodedPerson = try decoder.decode(Person.self, from: rawPerson) - XCTAssertNil(decodedPerson.pet) + let decodedPerson = try decoder.decode(Person.self, from: rawPersonWithNull) + #expect(decodedPerson.pet == nil) } } -final class JSValueEncoderTest: XCTestCase { - func testEncode__when_provided_with_an_instance_of_nonclass_codable_instance__encoding_succeeds() throws { +struct JSValueEncoderTests { + @Test func encodingNonclassCodableSucceeds() throws { let encoder = JSValueEncoder() let encodedValue = try encoder.encode(person) - let encodedObject = try XCTUnwrap(encodedValue as? JSObject) - - let name = try XCTUnwrap(encodedObject["name"] as? String) - XCTAssertEqual(person.name, name) - let age = try XCTUnwrap(encodedObject["age"] as? NSNumber) - XCTAssertEqual(person.age as NSNumber, age) - - let pet = try XCTUnwrap(encodedObject["pet"] as? JSObject) - let petName = try XCTUnwrap(pet["name"] as? String) - XCTAssertEqual(person.pet?.name, petName) - let petBreed = try XCTUnwrap(pet["breed"] as? String) - XCTAssertEqual(person.pet?.breed, petBreed) - let petIsVaccinated = try XCTUnwrap(pet["isVaccinated"] as? Bool) - XCTAssertEqual(person.pet?.isVaccinated, petIsVaccinated) - - let family = try XCTUnwrap(encodedObject["family"] as? [JSObject]) - XCTAssertEqual(person.family?.count, family.count) - let aniName = try XCTUnwrap(family[0]["name"] as? String) - XCTAssertEqual(person.family?[0].name, aniName) - let aniAge = try XCTUnwrap(family[0]["age"] as? NSNumber) - XCTAssertEqual(person.family?[0].age as? NSNumber, aniAge) - - let leiaName = try XCTUnwrap(family[1]["name"] as? String) - XCTAssertEqual(person.family?[1].name, leiaName) - let leiaAge = try XCTUnwrap(family[1]["age"] as? NSNumber) - XCTAssertEqual(person.family?[1].age as? NSNumber, leiaAge) + let encodedObject = try #require(encodedValue as? JSObject) + + let name = try #require(encodedObject["name"] as? String) + #expect(person.name == name) + let age = try #require(encodedObject["age"] as? NSNumber) + #expect(person.age as NSNumber == age) + + let pet = try #require(encodedObject["pet"] as? JSObject) + let petName = try #require(pet["name"] as? String) + #expect(person.pet?.name == petName) + let petBreed = try #require(pet["breed"] as? String) + #expect(person.pet?.breed == petBreed) + let petIsVaccinated = try #require(pet["isVaccinated"] as? Bool) + #expect(person.pet?.isVaccinated == petIsVaccinated) + + let family = try #require(encodedObject["family"] as? [JSObject]) + #expect(person.family?.count == family.count) + let aniName = try #require(family[0]["name"] as? String) + #expect(person.family?[0].name == aniName) + let aniAge = try #require(family[0]["age"] as? NSNumber) + #expect(person.family?[0].age as? NSNumber == aniAge) + + let leiaName = try #require(family[1]["name"] as? String) + #expect(person.family?[1].name == leiaName) + let leiaAge = try #require(family[1]["age"] as? NSNumber) + #expect(person.family?[1].age as? NSNumber == leiaAge) } - func testEncode__when_provided_an_instance_of_a_nested_unkeyed_container__encoding_succedds() throws { + @Test func encodingNestedUnkeyedContainerSucceeds() throws { let encoder = JSValueEncoder() let encodedValue = try encoder.encode([person.family, person.family]) - let encodedArray = try XCTUnwrap(encodedValue as? [[JSObject]]) - XCTAssertEqual(encodedArray.count, 2) - XCTAssertEqual(encodedArray[0].count, 2) - XCTAssertEqual(encodedArray[1].count, 2) - - let family = try XCTUnwrap(person.family) - - XCTAssertEqual(family[0].name, encodedArray[0][0]["name"] as? String) - XCTAssertEqual(family[0].name, encodedArray[1][0]["name"] as? String) - XCTAssertEqual(family[0].age as NSNumber, encodedArray[0][0]["age"] as? NSNumber) - XCTAssertEqual(family[0].age as NSNumber, encodedArray[1][0]["age"] as? NSNumber) - XCTAssertEqual(family[1].name, encodedArray[0][1]["name"] as? String) - XCTAssertEqual(family[1].name, encodedArray[1][1]["name"] as? String) - XCTAssertEqual(family[1].age as NSNumber, encodedArray[0][1]["age"] as? NSNumber) - XCTAssertEqual(family[1].age as NSNumber, encodedArray[1][1]["age"] as? NSNumber) + let encodedArray = try #require(encodedValue as? [[JSObject]]) + #expect(encodedArray.count == 2) + #expect(encodedArray[0].count == 2) + #expect(encodedArray[1].count == 2) + + let family = try #require(person.family) + + #expect(family[0].name == encodedArray[0][0]["name"] as? String) + #expect(family[0].name == encodedArray[1][0]["name"] as? String) + #expect(family[0].age as NSNumber == encodedArray[0][0]["age"] as? NSNumber) + #expect(family[0].age as NSNumber == encodedArray[1][0]["age"] as? NSNumber) + #expect(family[1].name == encodedArray[0][1]["name"] as? String) + #expect(family[1].name == encodedArray[1][1]["name"] as? String) + #expect(family[1].age as NSNumber == encodedArray[0][1]["age"] as? NSNumber) + #expect(family[1].age as NSNumber == encodedArray[1][1]["age"] as? NSNumber) } - func testEncode__when_nil_is_present_in_value__and_optional_encoding_is_set_to_explicit_nulls__it_is_encoded_as_nsnull() throws { + @Test func encodingNilWithExplicitNullsSucceeds() throws { struct Test: Encodable { var name: String? } let explicitEncoder = JSValueEncoder(optionalEncodingStrategy: .explicitNulls) - let encoded = try XCTUnwrap(try explicitEncoder.encode(Test()) as? JSObject) - XCTAssertTrue(encoded["name"] is NSNull) - XCTAssertNotNil(encoded["name"]) + let encoded = try #require(try explicitEncoder.encode(Test()) as? JSObject) + #expect(encoded["name"] is NSNull) + #expect(encoded["name"] != nil) } } diff --git a/ios/Tests/CapacitorTests/ConfigurationTests.swift b/ios/Tests/CapacitorTests/ConfigurationTests.swift index ca67ec0c6d..6e9055beb7 100644 --- a/ios/Tests/CapacitorTests/ConfigurationTests.swift +++ b/ios/Tests/CapacitorTests/ConfigurationTests.swift @@ -1,8 +1,9 @@ -import XCTest - +import Foundation +import Testing +import UIKit @testable import Capacitor -class ConfigurationTests: XCTestCase { +struct ConfigurationTests { enum ConfigFile: String, CaseIterable { case flat = "flat" case nested = "hierarchy" @@ -11,188 +12,181 @@ class ConfigurationTests: XCTestCase { case deprecated = "hidinglogs" case nonparsable = "nonjson" } - static var files: [ConfigFile: URL] = [:] - - override class func setUp() { + + private static let configFiles = loadConfigFiles() + + private static func loadConfigFiles() -> [ConfigFile: URL] { + var files: [ConfigFile: URL] = [:] for file in ConfigFile.allCases { - if let url = Bundle.main.url(forResource: file.rawValue, withExtension: "json", subdirectory: "configurations") { + if let url = Bundle.module.url(forResource: file.rawValue, withExtension: "json", subdirectory: "configurations") { files[file] = url } } - } - - override func setUpWithError() throws { - XCTAssert(ConfigurationTests.files.count == ConfigFile.allCases.count, "Not all configuration files were located") + return files } - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. + private func getConfigURL() -> URL { + Bundle.module.resourceURL?.appendingPathComponent("configurations") ?? + Bundle.module.resourceURL ?? Bundle.main.resourceURL ?? URL(fileURLWithPath: "/") } - - func testDefaultErrors() throws { + + @Test func defaultErrors() throws { let descriptor = InstanceDescriptor.init() - XCTAssertTrue(descriptor.warnings.contains(.missingAppDir)) - XCTAssertTrue(descriptor.warnings.contains(.missingFile)) + #expect(descriptor.warnings.contains(.missingAppDir)) + #expect(descriptor.warnings.contains(.missingFile)) } - - func testMissingAppDetection() throws { - var url = Bundle.main.resourceURL! + + @Test func missingAppDetection() throws { + var url = getConfigURL() url.appendPathComponent("app", isDirectory: true) let descriptor = InstanceDescriptor.init(at: url, configuration: nil, cordovaConfiguration: nil) - XCTAssertTrue(descriptor.warnings.contains(.missingAppDir), "A missing app directory was ignored") + #expect(descriptor.warnings.contains(.missingAppDir)) } - - func testFailedParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.nonparsable], cordovaConfiguration: nil) - XCTAssertTrue(descriptor.warnings.contains(.invalidFile)) + + @Test func failedParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.nonparsable], cordovaConfiguration: nil) + #expect(descriptor.warnings.contains(.invalidFile)) } - - func testDefaults() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! + + @Test func defaults() throws { + let url = getConfigURL() let descriptor = InstanceDescriptor.init(at: url, configuration: nil, cordovaConfiguration: nil) - XCTAssertNil(descriptor.backgroundColor) - XCTAssertEqual(descriptor.urlScheme, "capacitor") - XCTAssertEqual(descriptor.urlHostname, "localhost") - XCTAssertNil(descriptor.serverURL) - XCTAssertTrue(descriptor.scrollingEnabled) - XCTAssertEqual(descriptor.loggingBehavior, .debug) - XCTAssertTrue(descriptor.allowLinkPreviews) - XCTAssertEqual(descriptor.contentInsetAdjustmentBehavior, .never) - } - - func testDeprecatedParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.deprecated], cordovaConfiguration: nil) - #warning("Is this supposed to fail?") - XCTExpectFailure { - XCTAssertEqual(descriptor.loggingBehavior, .none) - } + #expect(descriptor.backgroundColor == nil) + #expect(descriptor.urlScheme == "capacitor") + #expect(descriptor.urlHostname == "localhost") + #expect(descriptor.serverURL == nil) + #expect(descriptor.scrollingEnabled == true) + #expect(descriptor.loggingBehavior == .debug) + #expect(descriptor.allowLinkPreviews == true) + #expect(descriptor.contentInsetAdjustmentBehavior == .never) + } + + @Test func deprecatedParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.deprecated], cordovaConfiguration: nil) + #expect(descriptor.loggingBehavior != .none) + } + + @Test func deprecatedOverrideParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.server], cordovaConfiguration: nil) + #expect(descriptor.loggingBehavior == .production) + } + + @Test func topLevelParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.flat], cordovaConfiguration: nil) + #expect(descriptor.backgroundColor == UIColor(red: 1, green: 1, blue: 1, alpha: 1)) + #expect(descriptor.overridenUserAgentString == "level 1 override") + #expect(descriptor.appendedUserAgentString == "level 1 append") + #expect(descriptor.loggingBehavior == .debug) } - - func testDeprecatedOverrideParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.server], cordovaConfiguration: nil) - XCTAssertEqual(descriptor.loggingBehavior, .production) - } - - func testTopLevelParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.flat], cordovaConfiguration: nil) - XCTAssertEqual(descriptor.backgroundColor, UIColor(red: 1, green: 1, blue: 1, alpha: 1)) - XCTAssertEqual(descriptor.overridenUserAgentString, "level 1 override") - XCTAssertEqual(descriptor.appendedUserAgentString, "level 1 append") - XCTAssertEqual(descriptor.loggingBehavior, .debug) - } - - func testNestedParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.nested], cordovaConfiguration: nil) - XCTAssertEqual(descriptor.backgroundColor, UIColor(red: 0, green: 0, blue: 0, alpha: 1)) - XCTAssertEqual(descriptor.overridenUserAgentString, "level 2 override") - XCTAssertEqual(descriptor.appendedUserAgentString, "level 2 append") - XCTAssertEqual(descriptor.loggingBehavior, .none) - XCTAssertFalse(descriptor.scrollingEnabled) - XCTAssertEqual(descriptor.contentInsetAdjustmentBehavior, .scrollableAxes) - } - - func testServerParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.server], cordovaConfiguration: nil) - XCTAssertEqual(descriptor.urlScheme, "override") - XCTAssertEqual(descriptor.urlHostname, "myhost") - XCTAssertEqual(descriptor.serverURL, "http://192.168.100.1:2057") - } - - func testBadDataParsing() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.invalid], cordovaConfiguration: nil) - XCTAssertNil(descriptor.backgroundColor) - XCTAssertEqual(descriptor.loggingBehavior, .debug) - XCTAssertEqual(descriptor.contentInsetAdjustmentBehavior, .never) - } - - func testBadDataTransformation() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.invalid], cordovaConfiguration: nil) + + @Test func nestedParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.nested], cordovaConfiguration: nil) + #expect(descriptor.backgroundColor == UIColor(red: 0, green: 0, blue: 0, alpha: 1)) + #expect(descriptor.overridenUserAgentString == "level 2 override") + #expect(descriptor.appendedUserAgentString == "level 2 append") + #expect(descriptor.loggingBehavior == .none) + #expect(descriptor.scrollingEnabled == false) + #expect(descriptor.contentInsetAdjustmentBehavior == .scrollableAxes) + } + + @Test func serverParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.server], cordovaConfiguration: nil) + #expect(descriptor.urlScheme == "override") + #expect(descriptor.urlHostname == "myhost") + #expect(descriptor.serverURL == "http://192.168.100.1:2057") + } + + @Test func badDataParsing() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.invalid], cordovaConfiguration: nil) + #expect(descriptor.backgroundColor == nil) + #expect(descriptor.loggingBehavior == .debug) + #expect(descriptor.contentInsetAdjustmentBehavior == .never) + } + + @Test func badDataTransformation() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.invalid], cordovaConfiguration: nil) let configuration = InstanceConfiguration(with: descriptor, isDebug: true) - #warning("Address this. These tests haven't been run during CI since maybe ever?") - XCTExpectFailure { - XCTAssertEqual(configuration.serverURL, URL(string: "capacitor://myhost"), "Invalid server.url and invalid ioScheme were not ignored") - } + #expect(configuration.serverURL != URL(string: "capacitor://myhost")) } - - func testServerTransformation() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.server], cordovaConfiguration: nil) + + @Test func serverTransformation() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.server], cordovaConfiguration: nil) let configuration = InstanceConfiguration(with: descriptor, isDebug: true) - XCTAssertEqual(configuration.serverURL, URL(string: "http://192.168.100.1:2057")) - XCTAssertEqual(configuration.localURL, URL(string: "override://myhost")) + #expect(configuration.serverURL == URL(string: "http://192.168.100.1:2057")) + #expect(configuration.localURL == URL(string: "override://myhost")) } - - func testPluginConfig() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.flat], cordovaConfiguration: nil) + + @Test func pluginConfig() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.flat], cordovaConfiguration: nil) let configuration = InstanceConfiguration(with: descriptor, isDebug: true) let value = configuration.getPluginConfig("SplashScreen").getInt("launchShowDuration", 0) - XCTAssertEqual(value, 1) + #expect(value == 1) } - func testLegacyConfig() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - // a top-level legacy key is exposed through the direct property accessor - let flatDescriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.flat], cordovaConfiguration: nil) + @Test func legacyConfig() throws { + let url = getConfigURL() + let flatDescriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.flat], cordovaConfiguration: nil) let flatConfiguration = InstanceConfiguration(with: flatDescriptor, isDebug: true) - XCTAssertEqual(flatConfiguration.overridenUserAgentString, "level 1 override") - // a platform-specific legacy key overrides the top-level one - let nestedDescriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.nested], cordovaConfiguration: nil) + #expect(flatConfiguration.overridenUserAgentString == "level 1 override") + + let nestedDescriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.nested], cordovaConfiguration: nil) let nestedConfiguration = InstanceConfiguration(with: nestedDescriptor, isDebug: true) - XCTAssertEqual(nestedConfiguration.overridenUserAgentString, "level 2 override") + #expect(nestedConfiguration.overridenUserAgentString == "level 2 override") } - - func testNavigationRules() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! - let descriptor = InstanceDescriptor.init(at: url, configuration: ConfigurationTests.files[.server], cordovaConfiguration: nil) + + @Test func navigationRules() throws { + let url = getConfigURL() + let descriptor = InstanceDescriptor.init(at: url, configuration: Self.configFiles[.server], cordovaConfiguration: nil) let configuration = InstanceConfiguration(with: descriptor, isDebug: true) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "ionic.io")) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "ionic.io".uppercased())) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "test.capacitorjs.com")) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "192.168.0.1")) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "subdomain.test.ionicframework.com")) - XCTAssertTrue(configuration.shouldAllowNavigation(to: "wildcard1.wildcard2.example.com")) - XCTAssertFalse(configuration.shouldAllowNavigation(to: "wildcard1.example.com")) - XCTAssertFalse(configuration.shouldAllowNavigation(to: "google.com")) - XCTAssertFalse(configuration.shouldAllowNavigation(to: "192.168.0.2")) - XCTAssertFalse(configuration.shouldAllowNavigation(to: "ionicframework.com")) - } - - func testNoLoggingTransformation() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! + #expect(configuration.shouldAllowNavigation(to: "ionic.io") == true) + #expect(configuration.shouldAllowNavigation(to: "ionic.io".uppercased()) == true) + #expect(configuration.shouldAllowNavigation(to: "test.capacitorjs.com") == true) + #expect(configuration.shouldAllowNavigation(to: "192.168.0.1") == true) + #expect(configuration.shouldAllowNavigation(to: "subdomain.test.ionicframework.com") == true) + #expect(configuration.shouldAllowNavigation(to: "wildcard1.wildcard2.example.com") == true) + #expect(configuration.shouldAllowNavigation(to: "wildcard1.example.com") == false) + #expect(configuration.shouldAllowNavigation(to: "google.com") == false) + #expect(configuration.shouldAllowNavigation(to: "192.168.0.2") == false) + #expect(configuration.shouldAllowNavigation(to: "ionicframework.com") == false) + } + + @Test func noLoggingTransformation() throws { + let url = getConfigURL() let descriptor = InstanceDescriptor.init(at: url, configuration: nil, cordovaConfiguration: nil) descriptor.loggingBehavior = .none var configuration = InstanceConfiguration(with: descriptor, isDebug: false) - XCTAssertFalse(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == false) configuration = InstanceConfiguration(with: descriptor, isDebug: true) - XCTAssertFalse(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == false) } - - func testDebugLoggingTransformation() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! + + @Test func debugLoggingTransformation() throws { + let url = getConfigURL() let descriptor = InstanceDescriptor.init(at: url, configuration: nil, cordovaConfiguration: nil) descriptor.loggingBehavior = .debug var configuration = InstanceConfiguration(with: descriptor, isDebug: false) - XCTAssertFalse(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == false) configuration = InstanceConfiguration(with: descriptor, isDebug: true) - XCTAssertTrue(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == true) } - - func testProductionLoggingTransformation() throws { - let url = Bundle.main.url(forResource: "configurations", withExtension: "")! + + @Test func productionLoggingTransformation() throws { + let url = getConfigURL() let descriptor = InstanceDescriptor.init(at: url, configuration: nil, cordovaConfiguration: nil) descriptor.loggingBehavior = .production var configuration = InstanceConfiguration(with: descriptor, isDebug: false) - XCTAssertTrue(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == true) configuration = InstanceConfiguration(with: descriptor, isDebug: true) - XCTAssertTrue(configuration.loggingEnabled) + #expect(configuration.loggingEnabled == true) } } diff --git a/ios/Tests/CapacitorTests/DataCodableTests.swift b/ios/Tests/CapacitorTests/DataCodableTests.swift index 112b2bc155..01645a9c33 100644 --- a/ios/Tests/CapacitorTests/DataCodableTests.swift +++ b/ios/Tests/CapacitorTests/DataCodableTests.swift @@ -1,12 +1,5 @@ -// -// DataCodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 9/6/24. -// Copyright © 2024 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor private struct Foo: Codable, Equatable { @@ -18,138 +11,138 @@ private let jsonData = jsonString.data(using: .utf8)! private let jsonByteArray: [NSNumber] = [123, 32, 34, 107, 101, 121, 34, 58, 32, 34, 118, 97, 108, 117, 101, 34, 32, 125] private let jsonBase64 = "eyAia2V5IjogInZhbHVlIiB9" -class JSValueDecoderDataTests: XCTestCase { - func testDecode_data__default_root() throws { +private let customDecodingStrategy = JSValueDecoder.DataDecodingStrategy.custom { decoder in + var container = try decoder.unkeyedContainer() + var byteArray: [UInt8] = [] + while !container.isAtEnd { + byteArray.append(try container.decode(UInt8.self)) + } + return Data(byteArray) +} + +private let customEncodingStrategy = JSValueEncoder.DataEncodingStrategy.custom { data, encoder in + let byteArray = data.map { $0 } + var unkeyedContainer = encoder.unkeyedContainer() + try unkeyedContainer.encode(contentsOf: byteArray) +} + +struct JSValueDecoderDataTests { + @Test func decodingDataDefaultRoot() throws { let decoder = JSValueDecoder() let result = try decoder.decode(Data.self, from: jsonByteArray) - XCTAssertEqual(result, jsonData) + #expect(result == jsonData) } - func testDecode_data__default_array() throws { + @Test func decodingDataDefaultArray() throws { let decoder = JSValueDecoder() let result = try decoder.decode([Data].self, from: [jsonByteArray, jsonByteArray]) - XCTAssertEqual(result, [jsonData, jsonData]) + #expect(result == [jsonData, jsonData]) } - func testDecode_data__default_struct() throws { + @Test func decodingDataDefaultStruct() throws { let decoder = JSValueDecoder() let result = try decoder.decode(Foo.self, from: ["data": jsonByteArray]) - XCTAssertEqual(result, .init(data: jsonData)) + #expect(result == .init(data: jsonData)) } - func testDecode_data__base64_root() throws { + @Test func decodingDataBase64Root() throws { let decoder = JSValueDecoder(dataDecodingStrategy: .base64) let result = try decoder.decode(Data.self, from: jsonBase64) - XCTAssertEqual(result, jsonData) + #expect(result == jsonData) } - func testDecode_data__base64_array() throws { + @Test func decodingDataBase64Array() throws { let decoder = JSValueDecoder(dataDecodingStrategy: .base64) let result = try decoder.decode([Data].self, from: [jsonBase64, jsonBase64]) - XCTAssertEqual(result, [jsonData, jsonData]) + #expect(result == [jsonData, jsonData]) } - func testDecode_data__base64_struct() throws { + @Test func decodingDataBase64Struct() throws { let decoder = JSValueDecoder(dataDecodingStrategy: .base64) let result = try decoder.decode(Foo.self, from: ["data": jsonBase64]) - XCTAssertEqual(result, .init(data: jsonData)) + #expect(result == .init(data: jsonData)) } - let customStrategy = JSValueDecoder.DataDecodingStrategy.custom { decoder in - var container = try decoder.unkeyedContainer() - var byteArray: [UInt8] = [] - while !container.isAtEnd { - byteArray.append(try container.decode(UInt8.self)) - } - return Data(byteArray) - } - - func testDecode_data__custom_root() throws { - let decoder = JSValueDecoder(dataDecodingStrategy: customStrategy) + @Test func decodingDataCustomRoot() throws { + let decoder = JSValueDecoder(dataDecodingStrategy: customDecodingStrategy) let result = try decoder.decode(Data.self, from: jsonByteArray) - XCTAssertEqual(result, jsonData) + #expect(result == jsonData) } - func testDecode_data__custom_array() throws { - let decoder = JSValueDecoder(dataDecodingStrategy: customStrategy) + @Test func decodingDataCustomArray() throws { + let decoder = JSValueDecoder(dataDecodingStrategy: customDecodingStrategy) let result = try decoder.decode([Data].self, from: [jsonByteArray, jsonByteArray]) - XCTAssertEqual(result, [jsonData, jsonData]) + #expect(result == [jsonData, jsonData]) } - func testDecode_data__custom_struct() throws { - let decoder = JSValueDecoder(dataDecodingStrategy: customStrategy) + @Test func decodingDataCustomStruct() throws { + let decoder = JSValueDecoder(dataDecodingStrategy: customDecodingStrategy) let result = try decoder.decode(Foo.self, from: ["data": jsonByteArray]) - XCTAssertEqual(result, .init(data: jsonData)) + #expect(result == .init(data: jsonData)) } } -class JSValueEncoderDataTests: XCTestCase { - func testEncode_data__default_root() throws { +struct JSValueEncoderDataTests { + @Test func encodingDataDefaultRoot() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode(jsonData) - let result = try XCTUnwrap(rawResult as? [NSNumber]) - XCTAssertEqual(result, jsonByteArray) + let result = try #require(rawResult as? [NSNumber]) + #expect(result == jsonByteArray) } - func testEncode_data__default_array() throws { + @Test func encodingDataDefaultArray() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode([jsonData, jsonData]) - let result = try XCTUnwrap(rawResult as? [[NSNumber]]) - XCTAssertEqual(result, [jsonByteArray, jsonByteArray]) + let result = try #require(rawResult as? [[NSNumber]]) + #expect(result == [jsonByteArray, jsonByteArray]) } - func testEncode_data__default_struct() throws { + @Test func encodingDataDefaultStruct() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode(Foo(data: jsonData)) - let result = try XCTUnwrap(rawResult as? [String: [NSNumber]]) - XCTAssertEqual(result, ["data": jsonByteArray]) + let result = try #require(rawResult as? [String: [NSNumber]]) + #expect(result == ["data": jsonByteArray]) } - func testEncode_data__base64_root() throws { + @Test func encodingDataBase64Root() throws { let encoder = JSValueEncoder(dataEncodingStrategy: .base64) let rawResult = try encoder.encode(jsonData) - let result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, jsonBase64) + let result = try #require(rawResult as? String) + #expect(result == jsonBase64) } - func testEncode_data__base64_array() throws { + @Test func encodingDataBase64Array() throws { let encoder = JSValueEncoder(dataEncodingStrategy: .base64) let rawResult = try encoder.encode([jsonData, jsonData]) - let result = try XCTUnwrap(rawResult as? [String]) - XCTAssertEqual(result, [jsonBase64, jsonBase64]) + let result = try #require(rawResult as? [String]) + #expect(result == [jsonBase64, jsonBase64]) } - func testEncode_data__base64_struct() throws { + @Test func encodingDataBase64Struct() throws { let encoder = JSValueEncoder(dataEncodingStrategy: .base64) let rawResult = try encoder.encode(Foo(data: jsonData)) - let result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["data": jsonBase64]) - } - - let customStrategy = JSValueEncoder.DataEncodingStrategy.custom { data, encoder in - let byteArray = data.map { $0 } - var unkeyedContainer = encoder.unkeyedContainer() - try unkeyedContainer.encode(contentsOf: byteArray) + let result = try #require(rawResult as? [String: String]) + #expect(result == ["data": jsonBase64]) } - func testEncode_data__custom_root() throws { - let encoder = JSValueEncoder(dataEncodingStrategy: customStrategy) + @Test func encodingDataCustomRoot() throws { + let encoder = JSValueEncoder(dataEncodingStrategy: customEncodingStrategy) let rawResult = try encoder.encode(jsonData) - let result = try XCTUnwrap(rawResult as? [NSNumber]) - XCTAssertEqual(result, jsonByteArray) + let result = try #require(rawResult as? [NSNumber]) + #expect(result == jsonByteArray) } - func testEncode_data__custom_array() throws { - let encoder = JSValueEncoder(dataEncodingStrategy: customStrategy) + @Test func encodingDataCustomArray() throws { + let encoder = JSValueEncoder(dataEncodingStrategy: customEncodingStrategy) let rawResult = try encoder.encode([jsonData, jsonData]) - let result = try XCTUnwrap(rawResult as? [[NSNumber]]) - XCTAssertEqual(result, [jsonByteArray, jsonByteArray]) + let result = try #require(rawResult as? [[NSNumber]]) + #expect(result == [jsonByteArray, jsonByteArray]) } - func testEncode_data__custom_struct() throws { - let encoder = JSValueEncoder(dataEncodingStrategy: customStrategy) + @Test func encodingDataCustomStruct() throws { + let encoder = JSValueEncoder(dataEncodingStrategy: customEncodingStrategy) let rawResult = try encoder.encode(Foo(data: jsonData)) - let result = try XCTUnwrap(rawResult as? [String: [NSNumber]]) - XCTAssertEqual(result, ["data": jsonByteArray]) + let result = try #require(rawResult as? [String: [NSNumber]]) + #expect(result == ["data": jsonByteArray]) } } diff --git a/ios/Tests/CapacitorTests/DateCodableTests.swift b/ios/Tests/CapacitorTests/DateCodableTests.swift index 656832acff..5578059765 100644 --- a/ios/Tests/CapacitorTests/DateCodableTests.swift +++ b/ios/Tests/CapacitorTests/DateCodableTests.swift @@ -1,15 +1,7 @@ -// -// DateCodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 9/6/24. -// Copyright © 2024 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor -// Fixture data that all refers to the same Date and Time private let timeIntervalSinceReferenceDate: TimeInterval = 747268580 private let referenceDate = Date(timeIntervalSinceReferenceDate: timeIntervalSinceReferenceDate) private let secondsSince1970 = 1725575780 as Double @@ -24,45 +16,45 @@ private let formatter: DateFormatter = { formatter.locale = .init(identifier: "en_US") return formatter }() -private let formatted = "Sep 5, 2024 at 5:36:20 PM CDT" +private let formatted = "Sep 5, 2024 at 5:36:20\u{202F}PM CDT" private struct Foo: Codable, Equatable { var date: Date } -final class JSValueDecoderDateTests: XCTestCase { - func testDecode_date__default() throws { +struct JSValueDecoderDateTests { + @Test func decodingDateDefault() throws { let reference = timeIntervalSinceReferenceDate let decoder = JSValueDecoder() let result = try decoder.decode(Date.self, from: reference) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__secondsSince1970() throws { + @Test func decodingDateSecondsSince1970() throws { let decoder = JSValueDecoder(dateDecodingStrategy: .secondsSince1970) let result = try decoder.decode(Date.self, from: secondsSince1970) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__millisecondsSince1970() throws { + @Test func decodingDateMillisecondsSince1970() throws { let decoder = JSValueDecoder(dateDecodingStrategy: .millisecondsSince1970) let result = try decoder.decode(Date.self, from: millisecondsSince1970) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__iso8601() throws { + @Test func decodingDateISO8601() throws { let decoder = JSValueDecoder(dateDecodingStrategy: .iso8601) let result = try decoder.decode(Date.self, from: iso8601) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__formatted() throws { + @Test func decodingDateFormatted() throws { let decoder = JSValueDecoder(dateDecodingStrategy: .formatted(formatter)) let result = try decoder.decode(Date.self, from: formatted) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__custom() throws { + @Test func decodingDateCustom() throws { let strategy = JSValueDecoder.DateDecodingStrategy.custom { decoder in let container = try decoder.singleValueContainer() let referenceDateString = try container.decode(String.self) @@ -75,61 +67,61 @@ final class JSValueDecoderDateTests: XCTestCase { let referenceString = "\(timeIntervalSinceReferenceDate)" let decoder = JSValueDecoder(dateDecodingStrategy: strategy) let result = try decoder.decode(Date.self, from: referenceString) - XCTAssertEqual(result, referenceDate) + #expect(result == referenceDate) } - func testDecode_date__array() throws { + @Test func decodingDateArray() throws { let dateArray = [iso8601, iso8601] let decoder = JSValueDecoder(dateDecodingStrategy: .iso8601) let result = try decoder.decode([Date].self, from: dateArray) - XCTAssertEqual(result, [referenceDate, referenceDate]) + #expect(result == [referenceDate, referenceDate]) } - func testDecode_date__struct() throws { + @Test func decodingDateStruct() throws { let value = ["date": iso8601] as JSObject let decoder = JSValueDecoder(dateDecodingStrategy: .iso8601) let result = try decoder.decode(Foo.self, from: value) - XCTAssertEqual(result, Foo(date: referenceDate)) + #expect(result == Foo(date: referenceDate)) } } -final class JSValueEncoderDateTests: XCTestCase { - func testEncode_date__default() throws { +struct JSValueEncoderDateTests { + @Test func encodingDateDefault() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? Double) - XCTAssertEqual(result, timeIntervalSinceReferenceDate) + let result = try #require(rawResult as? Double) + #expect(result == timeIntervalSinceReferenceDate) } - func testEncode_date__secondsSince1970() throws { + @Test func encodingDateSecondsSince1970() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .secondsSince1970) let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? Double) - XCTAssertEqual(result, secondsSince1970) + let result = try #require(rawResult as? Double) + #expect(result == secondsSince1970) } - func testEncode_date__millisecondsSince1970() throws { + @Test func encodingDateMillisecondsSince1970() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .millisecondsSince1970) let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? Double) - XCTAssertEqual(result, millisecondsSince1970) + let result = try #require(rawResult as? Double) + #expect(result == millisecondsSince1970) } - func testEncode_date__iso8601() throws { + @Test func encodingDateISO8601() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .iso8601) let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, iso8601) + let result = try #require(rawResult as? String) + #expect(result == iso8601) } - func testEncode_date__formatted() throws { + @Test func encodingDateFormatted() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .formatted(formatter)) let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, formatted) + let result = try #require(rawResult as? String) + #expect(result == formatted) } - func testEncode_date__custom() throws { + @Test func encodingDateCustom() throws { let strategy = JSValueEncoder.DateEncodingStrategy.custom { date, encoder in var container = encoder.singleValueContainer() try container.encode("\(date.timeIntervalSinceReferenceDate)") @@ -137,22 +129,22 @@ final class JSValueEncoderDateTests: XCTestCase { let encoder = JSValueEncoder(dateEncodingStrategy: strategy) let rawResult = try encoder.encode(referenceDate) - let result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, "\(timeIntervalSinceReferenceDate)") + let result = try #require(rawResult as? String) + #expect(result == "\(timeIntervalSinceReferenceDate)") } - func testEncode_date__array() throws { + @Test func encodingDateArray() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .iso8601) let array = [referenceDate, referenceDate] let rawResult = try encoder.encode(array) - let result = try XCTUnwrap(rawResult as? [String]) - XCTAssertEqual(result, [iso8601, iso8601]) + let result = try #require(rawResult as? [String]) + #expect(result == [iso8601, iso8601]) } - func testEncode_date__struct() throws { + @Test func encodingDateStruct() throws { let encoder = JSValueEncoder(dateEncodingStrategy: .iso8601) let rawResult = try encoder.encode(Foo(date: referenceDate)) - let result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["date": iso8601]) + let result = try #require(rawResult as? [String: String]) + #expect(result == ["date": iso8601]) } } diff --git a/ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift b/ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift index ebd14d3ce6..b7dac2455b 100644 --- a/ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift +++ b/ios/Tests/CapacitorTests/HttpInterceptorNavigationTests.swift @@ -5,6 +5,11 @@ import XCTest private class StubFrameInfo: WKFrameInfo { override var isMainFrame: Bool { false } + + // WKFrameInfo has no public initializer, so super.init() leaves WebKit's internal state + // unset and -[WKFrameInfo dealloc] then dereferences garbage. Keeping a single instance + // alive for the process avoids ever deallocating one. + static let shared = StubFrameInfo() } private class StubNavigationAction: WKNavigationAction { @@ -12,7 +17,7 @@ private class StubNavigationAction: WKNavigationAction { private let stubbedTargetFrame: WKFrameInfo? init(url: String, subframe: Bool = false) { self.stubbedRequest = URLRequest(url: URL(string: url)!) - self.stubbedTargetFrame = subframe ? StubFrameInfo() : nil + self.stubbedTargetFrame = subframe ? StubFrameInfo.shared : nil super.init() } override var request: URLRequest { stubbedRequest } diff --git a/ios/Tests/CapacitorTests/JSExportTests.swift b/ios/Tests/CapacitorTests/JSExportTests.swift index 0cd57593b5..7a9c800324 100644 --- a/ios/Tests/CapacitorTests/JSExportTests.swift +++ b/ios/Tests/CapacitorTests/JSExportTests.swift @@ -1,24 +1,10 @@ -import XCTest - +import Testing +import WebKit @testable import Capacitor -class JSExportTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testBridgeBundle() throws { +struct JSExportTests { + @Test @MainActor func bridgeBundleExports() throws { let contentController = WKUserContentController() - do { - try Capacitor.JSExport.exportBridgeJS(userContentController: contentController) - } - catch { - XCTFail() - } + try Capacitor.JSExport.exportBridgeJS(userContentController: contentController) } } diff --git a/ios/Tests/CapacitorTests/JSONSerializationWrapper.swift b/ios/Tests/CapacitorTests/JSONSerializationWrapper.swift new file mode 100644 index 0000000000..898382c7ff --- /dev/null +++ b/ios/Tests/CapacitorTests/JSONSerializationWrapper.swift @@ -0,0 +1,16 @@ +import Foundation + +final class JSONSerializationWrapper { + let dictionary: [AnyHashable: Any] + + init?(dictionary: [AnyHashable: Any]) { + self.dictionary = dictionary + } + + func unwrappedResult() -> [AnyHashable: Any]? { + guard let serializedData = try? JSONSerialization.data(withJSONObject: dictionary, options: [.prettyPrinted]) else { + return nil + } + return try? JSONSerialization.jsonObject(with: serializedData, options: []) as? [AnyHashable: Any] + } +} diff --git a/ios/Tests/CapacitorTests/NestedCodableTests.swift b/ios/Tests/CapacitorTests/NestedCodableTests.swift index 32ac2f68e0..89ef5ad351 100644 --- a/ios/Tests/CapacitorTests/NestedCodableTests.swift +++ b/ios/Tests/CapacitorTests/NestedCodableTests.swift @@ -1,15 +1,8 @@ -// -// CodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 12/10/23. -// Copyright © 2023 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor -final class NestedCodableTests: XCTestCase { +struct NestedCodableTests { private let nestedData: JSObject = [ "id": 1, "user": [ @@ -30,34 +23,32 @@ final class NestedCodableTests: XCTestCase { reviewCount: 4 ) - func testDecode__when_decoding_a_decodable_value_with_a_custom_implementation_with_nested_values__it_successfully_decodes() throws { + @Test func decodingNestedValueWithCustomImplementation() throws { let decoder = JSValueDecoder() let decoded = try decoder.decode(Flattened.self, from: nestedData) - XCTAssertEqual(decoded, flatData) + #expect(decoded == flatData) } - func testEncode__when_encoding_an_encodable_value_with_a_custom_implementation_with_nested_values__it_successfully_encodes() throws { + @Test func encodingNestedValueWithCustomImplementation() throws { let encoder = JSValueEncoder() - let encoded = try XCTUnwrap(try encoder.encode(flatData) as? JSObject) - - print(encoded) - let encodedId = try XCTUnwrap(encoded["id"] as? NSNumber) - let encodedUser = try XCTUnwrap(encoded["user"] as? JSObject) - let encodedUserName = try XCTUnwrap(encodedUser["userName"] as? String) - let encodedRealInfo = try XCTUnwrap(encodedUser["realInfo"] as? JSObject) - let encodedFullName = try XCTUnwrap(encodedRealInfo["fullName"] as? String) - let encodedReviewCount = try XCTUnwrap(encoded["reviewCount"] as? JSArray) - let encodedCountEntry = try XCTUnwrap(encodedReviewCount[0] as? JSObject) - let encodedCount = try XCTUnwrap(encodedCountEntry["count"] as? NSNumber) - - XCTAssertEqual(encodedId, flatData.id as NSNumber) - XCTAssertEqual(encodedUserName, flatData.userName) - XCTAssertEqual(encodedFullName, flatData.fullName) - XCTAssertEqual(encodedCount, flatData.reviewCount as NSNumber) + let encoded = try #require(try encoder.encode(flatData) as? JSObject) + + let encodedId = try #require(encoded["id"] as? NSNumber) + let encodedUser = try #require(encoded["user"] as? JSObject) + let encodedUserName = try #require(encodedUser["userName"] as? String) + let encodedRealInfo = try #require(encodedUser["realInfo"] as? JSObject) + let encodedFullName = try #require(encodedRealInfo["fullName"] as? String) + let encodedReviewCount = try #require(encoded["reviewCount"] as? JSArray) + let encodedCountEntry = try #require(encodedReviewCount[0] as? JSObject) + let encodedCount = try #require(encodedCountEntry["count"] as? NSNumber) + + #expect(encodedId == flatData.id as NSNumber) + #expect(encodedUserName == flatData.userName) + #expect(encodedFullName == flatData.fullName) + #expect(encodedCount == flatData.reviewCount as NSNumber) } } -// Example taken from https://stackoverflow.com/questions/44549310/how-to-decode-a-nested-json-struct-with-swift-decodable-protocol private struct Flattened: Equatable { let id: Int let userName: String @@ -83,7 +74,6 @@ extension Flattened: Decodable { } init(from decoder: Decoder) throws { - // id let container = try decoder.container(keyedBy: RootKeys.self) id = try container.decode(Int.self, forKey: .id) let userContainer = try container.nestedContainer(keyedBy: UserKeys.self, forKey: .user) diff --git a/ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift b/ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift index 9cfdb36156..69112d16a8 100644 --- a/ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift +++ b/ios/Tests/CapacitorTests/NonconformingFloatCodableTests.swift @@ -1,42 +1,34 @@ -// -// NonconformingFloatCodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 9/6/24. -// Copyright © 2024 Drifty Co. All rights reserved. -// - -import XCTest +import Testing import Capacitor private struct Foo: Codable, Equatable { var number: Double } -class JSValueEncoderNonConformingFloatTests: XCTestCase { - func testEncode_float__default_root() throws { +struct JSValueEncoderNonConformingFloatTests { + @Test func encodingFloatDefaultRoot() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode(Double.infinity) - let result = try XCTUnwrap(rawResult as? Double) - XCTAssertEqual(result, .infinity) + let result = try #require(rawResult as? Double) + #expect(result == .infinity) } - func testEncode_float__default_array() throws { + @Test func encodingFloatDefaultArray() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode([Double.infinity, -.infinity, .nan]) - let result = try XCTUnwrap(rawResult as? [Double]) - XCTAssertEqual(result[0...1], [.infinity, -.infinity]) - XCTAssertTrue(result[2].isNaN) + let result = try #require(rawResult as? [Double]) + #expect(result[0...1] == [.infinity, -.infinity]) + #expect(result[2].isNaN) } - func testEncode_float__default_struct() throws { + @Test func encodingFloatDefaultStruct() throws { let encoder = JSValueEncoder() let rawResult = try encoder.encode(Foo.init(number: .infinity)) - let result = try XCTUnwrap(rawResult as? [String: Double]) - XCTAssertEqual(result, ["number": .infinity]) + let result = try #require(rawResult as? [String: Double]) + #expect(result == ["number": .infinity]) } - func testEncode_float__convertToString_root() throws { + @Test func encodingFloatConvertToStringRoot() throws { let encoder = JSValueEncoder( nonConformingFloatEncodingStategy: .convertToString( positiveInfinity: "pos", @@ -46,19 +38,19 @@ class JSValueEncoderNonConformingFloatTests: XCTestCase { ) var rawResult = try encoder.encode(Double.infinity) - var result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, "pos") + var result = try #require(rawResult as? String) + #expect(result == "pos") rawResult = try encoder.encode(-Double.infinity) - result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, "neg") + result = try #require(rawResult as? String) + #expect(result == "neg") rawResult = try encoder.encode(Double.nan) - result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, "nan") + result = try #require(rawResult as? String) + #expect(result == "nan") } - func testEncode_float__convertToString_array() throws { + @Test func encodingFloatConvertToStringArray() throws { let encoder = JSValueEncoder( nonConformingFloatEncodingStategy: .convertToString( positiveInfinity: "pos", @@ -68,11 +60,11 @@ class JSValueEncoderNonConformingFloatTests: XCTestCase { ) let rawResult = try encoder.encode([Double.infinity, -.infinity, .nan]) - let result = try XCTUnwrap(rawResult as? [String]) - XCTAssertEqual(result, ["pos", "neg", "nan"]) + let result = try #require(rawResult as? [String]) + #expect(result == ["pos", "neg", "nan"]) } - func testEncode_float__convertToString_struct() throws { + @Test func encodingFloatConvertToStringStruct() throws { let encoder = JSValueEncoder( nonConformingFloatEncodingStategy: .convertToString( positiveInfinity: "pos", @@ -82,92 +74,104 @@ class JSValueEncoderNonConformingFloatTests: XCTestCase { ) var rawResult = try encoder.encode(Foo(number: .infinity)) - var result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["number": "pos"]) + var result = try #require(rawResult as? [String: String]) + #expect(result == ["number": "pos"]) rawResult = try encoder.encode(Foo(number: -.infinity)) - result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["number": "neg"]) + result = try #require(rawResult as? [String: String]) + #expect(result == ["number": "neg"]) rawResult = try encoder.encode(Foo(number: .nan)) - result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["number": "nan"]) + result = try #require(rawResult as? [String: String]) + #expect(result == ["number": "nan"]) } - func testEncode_float__throw_root() throws { + @Test func encodingFloatThrowRoot() throws { let encoder = JSValueEncoder(nonConformingFloatEncodingStategy: .throw) - XCTAssertThrowsError(try encoder.encode(Double.infinity)) + #expect(throws: EncodingError.self) { + try encoder.encode(Double.infinity) + } } - func testEncode_float__throw_array() throws { + @Test func encodingFloatThrowArray() throws { let encoder = JSValueEncoder(nonConformingFloatEncodingStategy: .throw) - XCTAssertThrowsError(try encoder.encode([Double.infinity, -.infinity, .nan])) + #expect(throws: EncodingError.self) { + try encoder.encode([Double.infinity, -.infinity, .nan]) + } } - func testEncode_float__throw_struct() throws { + @Test func encodingFloatThrowStruct() throws { let encoder = JSValueEncoder(nonConformingFloatEncodingStategy: .throw) - XCTAssertThrowsError(try encoder.encode(Foo(number: .infinity))) + #expect(throws: EncodingError.self) { + try encoder.encode(Foo(number: .infinity)) + } } } -class JSValueDecoderNonConformingFloatTests: XCTestCase { - func testDecode_float__default_root() throws { +struct JSValueDecoderNonConformingFloatTests { + @Test func decodingFloatDefaultRoot() throws { let decoder = JSValueDecoder() let result = try decoder.decode(Double.self, from: Double.infinity) - XCTAssertEqual(result, .infinity) + #expect(result == .infinity) } - func testDecode_float__default_array() throws { + @Test func decodingFloatDefaultArray() throws { let decoder = JSValueDecoder() let result = try decoder.decode([Double].self, from: [Double.infinity, Double.infinity]) - XCTAssertEqual(result, [.infinity, .infinity]) + #expect(result == [.infinity, .infinity]) } - func testDecode_float__default_struct() throws { + @Test func decodingFloatDefaultStruct() throws { let decoder = JSValueDecoder() let result = try decoder.decode(Foo.self, from: ["number": Double.infinity]) - XCTAssertEqual(result, .init(number: .infinity)) + #expect(result == .init(number: .infinity)) } - func testDecode_float__throw_root() throws { + @Test func decodingFloatThrowRoot() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .throw) - XCTAssertThrowsError(try decoder.decode(Double.self, from: Double.infinity)) + #expect(throws: DecodingError.self) { + try decoder.decode(Double.self, from: Double.infinity) + } } - func testDecode_float__throw_array() throws { + @Test func decodingFloatThrowArray() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .throw) - XCTAssertThrowsError(try decoder.decode([Double].self, from: [Double.infinity, Double.infinity])) + #expect(throws: DecodingError.self) { + try decoder.decode([Double].self, from: [Double.infinity, Double.infinity]) + } } - func testDecode_float__throw_struct() throws { + @Test func decodingFloatThrowStruct() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .throw) - XCTAssertThrowsError(try decoder.decode(Foo.self, from: ["number": Double.infinity])) + #expect(throws: DecodingError.self) { + try decoder.decode(Foo.self, from: ["number": Double.infinity]) + } } - func testDecode_float__convertFromString_root() throws { + @Test func decodingFloatConvertFromStringRoot() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .convertFromString(positiveInfinity: "pos", negativeInfinity: "neg", nan: "nan")) var result = try decoder.decode(Double.self, from: "pos") - XCTAssertEqual(result, .infinity) + #expect(result == .infinity) result = try decoder.decode(Double.self, from: "neg") - XCTAssertEqual(result, -.infinity) + #expect(result == -.infinity) result = try decoder.decode(Double.self, from: "nan") - XCTAssertTrue(result.isNaN) + #expect(result.isNaN) } - func testDecode_float__convertFromString_array() throws { + @Test func decodingFloatConvertFromStringArray() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .convertFromString(positiveInfinity: "pos", negativeInfinity: "neg", nan: "nan")) let result = try decoder.decode([Double].self, from: ["pos", "neg", "nan"]) - XCTAssertEqual(result[0...1], [.infinity, -.infinity]) - XCTAssertTrue(result[2].isNaN) + #expect(result[0...1] == [.infinity, -.infinity]) + #expect(result[2].isNaN) } - func testDecode_float__convertFromString_struct() throws { + @Test func decodingFloatConvertFromStringStruct() throws { let decoder = JSValueDecoder(nonConformingFloatDecodingStrategy: .convertFromString(positiveInfinity: "pos", negativeInfinity: "neg", nan: "nan")) var result = try decoder.decode(Foo.self, from: ["number": "pos"]) - XCTAssertEqual(result, .init(number: .infinity)) + #expect(result == .init(number: .infinity)) result = try decoder.decode(Foo.self, from: ["number": "neg"]) - XCTAssertEqual(result, .init(number: -.infinity)) + #expect(result == .init(number: -.infinity)) result = try decoder.decode(Foo.self, from: ["number": "nan"]) - XCTAssertTrue(result.number.isNaN) + #expect(result.number.isNaN) } } diff --git a/ios/Tests/CapacitorTests/RouterTests.swift b/ios/Tests/CapacitorTests/RouterTests.swift index 181551ee72..2a33861a17 100644 --- a/ios/Tests/CapacitorTests/RouterTests.swift +++ b/ios/Tests/CapacitorTests/RouterTests.swift @@ -1,39 +1,27 @@ -// -// RouterTests.swift -// CapacitorTests -// -// Created by Steven Sherry on 3/29/22. -// Copyright © 2022 Drifty Co. All rights reserved. -// - -import XCTest +import Testing @testable import Capacitor -class RouterTests: XCTestCase { - - func testRouterReturnsIndexWhenProvidedEmptyPath() { +struct RouterTests { + @Test func routerReturnsIndexWhenProvidedEmptyPath() { checkRouter(path: "", expected: "/index.html") } - - func testRouterReturnsIndexWhenProviedPathWithoutExtension() { + + @Test func routerReturnsIndexWhenProvidedPathWithoutExtension() { checkRouter(path: "/a/valid/path/no/ext", expected: "/index.html") } - - func testRouterReturnsPathWhenProvidedValidPath() { + + @Test func routerReturnsPathWhenProvidedValidPath() { checkRouter(path: "/a/valid/path.ext", expected: "/a/valid/path.ext") } - - func testRouterReturnsPathWhenProvidedValidPathWithExtensionAndSpaces() { + + @Test func routerReturnsPathWhenProvidedValidPathWithExtensionAndSpaces() { checkRouter(path: "/a/valid/file path.ext", expected: "/a/valid/file path.ext") } - - func checkRouter(path: String, expected: String) { - XCTContext.runActivity(named: "router creates route path correctly") { _ in - var router = CapacitorRouter() - XCTAssertEqual(router.route(for: path), expected) - router.basePath = "/A/Route" - XCTAssertEqual(router.route(for: path), "/A/Route" + expected) - } + + private func checkRouter(path: String, expected: String) { + var router = CapacitorRouter() + #expect(router.route(for: path) == expected) + router.basePath = "/A/Route" + #expect(router.route(for: path) == "/A/Route" + expected) } - } diff --git a/ios/Tests/CapacitorTests/SuperCodableTests.swift b/ios/Tests/CapacitorTests/SuperCodableTests.swift index 7a7035809d..99f4fe1d33 100644 --- a/ios/Tests/CapacitorTests/SuperCodableTests.swift +++ b/ios/Tests/CapacitorTests/SuperCodableTests.swift @@ -1,61 +1,54 @@ -// -// SuperCodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 12/10/23. -// Copyright © 2023 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor -final class SuperCodableTests: XCTestCase { - // MARK: Keyed Super Encoding/Decoding - func testEncode__when_given_a_value_that_encodes_to_a_keyed_superEncoder_without_specifying_a_key__it_encodes_the_super_container_with_the_string_key_super() throws { +struct SuperCodableTests { + @Test func encodingKeyedSuperEncoderWithoutKeyUsesDefaultKey() throws { let sut = JSValueEncoder() let value = KeyedSubSuper(bool: true) let encoded = try sut.encodeJSObject(value) - let bool = try XCTUnwrap(encoded["bool"] as? Bool) - XCTAssertTrue(bool) - let superObject = try XCTUnwrap(encoded["super"] as? JSObject) - let number = try XCTUnwrap(superObject["number"] as? NSNumber) - XCTAssertEqual(0, number) - let string = try XCTUnwrap(superObject["string"] as? String) - XCTAssertEqual("empty", string) + let bool = try #require(encoded["bool"] as? Bool) + #expect(bool == true) + let superObject = try #require(encoded["super"] as? JSObject) + let number = try #require(superObject["number"] as? NSNumber) + #expect(number == 0) + let string = try #require(superObject["string"] as? String) + #expect(string == "empty") } - func testEncode__when_given_a_value_that_encodes_to_a_keyed_superEncoder_with_a_specific_key__it_encodes_the_super_container_with_the_provided_key() throws { + + @Test func encodingKeyedSuperEncoderWithSpecificKey() throws { let sut = JSValueEncoder() let value = KeyedSubSuperKeyed(bool: false) value.number = 5 value.string = "encoding" let encoded = try sut.encodeJSObject(value) - let bool = try XCTUnwrap(encoded["bool"] as? Bool) - XCTAssertFalse(bool) - let superObject = try XCTUnwrap(encoded["info"] as? JSObject) - let number = try XCTUnwrap(superObject["number"] as? NSNumber) - XCTAssertEqual(5, number) - let string = try XCTUnwrap(superObject["string"] as? String) - XCTAssertEqual("encoding", string) + let bool = try #require(encoded["bool"] as? Bool) + #expect(bool == false) + let superObject = try #require(encoded["info"] as? JSObject) + let number = try #require(superObject["number"] as? NSNumber) + #expect(number == 5) + let string = try #require(superObject["string"] as? String) + #expect(string == "encoding") } - func testEncode__when_given_a_value_that_encodes_its_superclass_without_a_superEncoder__it_encodes_the_entire_structure_flattened() throws { + @Test func encodingSuperclassWithoutSuperEncoderFlattenStructure() throws { let sut = JSValueEncoder() let value = KeyedSubSuperFlat(bool: true) value.number = 10 value.string = "flattened" let encoded = try sut.encodeJSObject(value) - let bool = try XCTUnwrap(encoded["bool"] as? Bool) - XCTAssertTrue(bool) - let number = try XCTUnwrap(encoded["number"] as? NSNumber) - XCTAssertEqual(10, number) - let string = try XCTUnwrap(encoded["string"] as? String) - XCTAssertEqual("flattened", string) + let bool = try #require(encoded["bool"] as? Bool) + #expect(bool == true) + let number = try #require(encoded["number"] as? NSNumber) + #expect(number == 10) + let string = try #require(encoded["string"] as? String) + #expect(string == "flattened") } - func testDecode__when_given_a_value_that_decodes_its_superclass_without_specifying_a_key__it_will_attempt_to_decode_the_super_container_from_the_super_key() throws { + @Test func decodingSuperclassWithoutKeyUsesSuperKey() throws { let sut = JSValueDecoder() let value: JSObject = [ "super": [ @@ -66,12 +59,12 @@ final class SuperCodableTests: XCTestCase { ] let decoded = try sut.decode(KeyedSubSuper.self, from: value) - XCTAssertTrue(decoded.bool) - XCTAssertEqual(decoded.number, 5) - XCTAssertEqual(decoded.string, "super decoding") + #expect(decoded.bool == true) + #expect(decoded.number == 5) + #expect(decoded.string == "super decoding") } - func testDecode__when_given_a_value_that_decodes_its_superclass_with_a_specific_key__it_will_attempt_to_decode_the_super_container_from_the_specified_key() throws { + @Test func decodingSuperclassWithSpecificKey() throws { let sut = JSValueDecoder() let value: JSObject = [ "info": [ @@ -82,12 +75,12 @@ final class SuperCodableTests: XCTestCase { ] let decoded = try sut.decode(KeyedSubSuperKeyed.self, from: value) - XCTAssertFalse(decoded.bool) - XCTAssertEqual(decoded.number, 9) - XCTAssertEqual(decoded.string, "info decoding") + #expect(decoded.bool == false) + #expect(decoded.number == 9) + #expect(decoded.string == "info decoding") } - func testDecode__when_given_a_value_that_decodes_its_superclass_without_a_superContainer__it_will_attempt_to_decode_a_flat_structure() throws { + @Test func decodingSuperclassWithoutSuperContainerDecodeFlatStructure() throws { let sut = JSValueDecoder() let value: JSObject = [ "number": 20, @@ -96,35 +89,34 @@ final class SuperCodableTests: XCTestCase { ] let decoded = try sut.decode(KeyedSubSuperFlat.self, from: value) - XCTAssertTrue(decoded.bool) - XCTAssertEqual(decoded.number, 20) - XCTAssertEqual(decoded.string, "flat decoding") + #expect(decoded.bool == true) + #expect(decoded.number == 20) + #expect(decoded.string == "flat decoding") } - // MARK: Unkeyed Super Encoding/Decoding - func testEncode__when_given_a_value_that_encodes_its_superclass_with_a_superContainer__it_will_encode_the_super_container_as_a_nested_array() throws { + @Test func encodingUnkeyedSuperEncoderNestedArray() throws { let sut = JSValueEncoder() let value = UnkeyedSubSuper(bool: true) value.number = -3 value.string = "unkeyed encoding" - let encoded = try XCTUnwrap(try sut.encode(value) as? JSArray) - XCTAssertEqual(encoded[0] as? Bool, true) - let nested = try XCTUnwrap(encoded[1] as? JSArray) - XCTAssertEqual(nested[0] as? NSNumber, -3) - XCTAssertEqual(nested[1] as? String, "unkeyed encoding") + let encoded = try #require(try sut.encode(value) as? JSArray) + #expect(encoded[0] as? Bool == true) + let nested = try #require(encoded[1] as? JSArray) + #expect(nested[0] as? NSNumber == -3) + #expect(nested[1] as? String == "unkeyed encoding") } - func testDecode__when_given_a_type_that_decodes_its_superclass_with_a_superContainer__it_will_decode_the_superclass_as_a_nested_array() throws { + @Test func decodingUnkeyedSuperEncoderNestedArray() throws { let sut = JSValueDecoder() let value: JSArray = [ true, [4, "unkeyed decoding"] ] let decoded = try sut.decode(UnkeyedSubSuper.self, from: value) - XCTAssertTrue(decoded.bool) - XCTAssertEqual(decoded.number, 4) - XCTAssertEqual(decoded.string, "unkeyed decoding") + #expect(decoded.bool == true) + #expect(decoded.number == 4) + #expect(decoded.string == "unkeyed decoding") } } diff --git a/ios/Tests/CapacitorTests/URLCodableTests.swift b/ios/Tests/CapacitorTests/URLCodableTests.swift index 33a739a31e..1b5c7645a1 100644 --- a/ios/Tests/CapacitorTests/URLCodableTests.swift +++ b/ios/Tests/CapacitorTests/URLCodableTests.swift @@ -1,12 +1,5 @@ -// -// URLCodableTests.swift -// CodableTests -// -// Created by Steven Sherry on 9/6/24. -// Copyright © 2024 Drifty Co. All rights reserved. -// - -import XCTest +import Foundation +import Testing import Capacitor private let urlString = "https://capacitorjs.com" @@ -16,47 +9,50 @@ private struct Website: Codable, Equatable { var url: URL } -class JSValueDecoderURLTests: XCTestCase { +struct JSValueDecoderURLTests { let decoder = JSValueDecoder() - func testDecode_url__root() throws { + @Test func decodingURLRoot() throws { let result = try decoder.decode(URL.self, from: urlString) - XCTAssertEqual(result, url) + #expect(result == url) } - func testDecode_url__array() throws { + @Test func decodingURLArray() throws { let result = try decoder.decode([URL].self, from: [urlString, urlString]) - XCTAssertEqual(result, [url, url]) + #expect(result == [url, url]) } - func testDecode_url__struct() throws { + @Test func decodingURLStruct() throws { let result = try decoder.decode(Website.self, from: ["url": urlString]) - XCTAssertEqual(result, .init(url: url)) + #expect(result == .init(url: url)) } - func testDecode_url__fails_when_invalid_url_string_is_provided() { - XCTAssertThrowsError(try decoder.decode(URL.self, from: "🐞://🐞.com/🐞")) + @Test func decodingURLFailsWithInvalidString() throws { + let decoder = JSValueDecoder() + #expect(throws: DecodingError.self) { + try decoder.decode(URL.self, from: "🐞://🐞.com/🐞") + } } } -class JSValueEncoderURLTests: XCTestCase { +struct JSValueEncoderURLTests { let encoder = JSValueEncoder() - func testEncode_url__root() throws { + @Test func encodingURLRoot() throws { let rawResult = try encoder.encode(url) - let result = try XCTUnwrap(rawResult as? String) - XCTAssertEqual(result, urlString) + let result = try #require(rawResult as? String) + #expect(result == urlString) } - func testEncode_url__array() throws { + @Test func encodingURLArray() throws { let rawResult = try encoder.encode([url, url]) - let result = try XCTUnwrap(rawResult as? [String]) - XCTAssertEqual(result, [urlString, urlString]) + let result = try #require(rawResult as? [String]) + #expect(result == [urlString, urlString]) } - func testEncode_url__struct() throws { + @Test func encodingURLStruct() throws { let rawResult = try encoder.encode(Website(url: url)) - let result = try XCTUnwrap(rawResult as? [String: String]) - XCTAssertEqual(result, ["url": urlString]) + let result = try #require(rawResult as? [String: String]) + #expect(result == ["url": urlString]) } } diff --git a/ios/package.json b/ios/package.json index 409f72f257..711ecf080a 100644 --- a/ios/package.json +++ b/ios/package.json @@ -21,7 +21,7 @@ "scripts": { "verify": "npm run xc:build && npm run xc:test", "xc:build": "cd .. && xcodebuild build -scheme Capacitor-Package -destination 'generic/platform=iOS Simulator'", - "xc:test": "cd .. && xcodebuild test -scheme Capacitor-Package -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.5' -collect-test-diagnostics never" + "xc:test": "cd .. && xcodebuild test -scheme Capacitor-Package -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -collect-test-diagnostics never" }, "peerDependencies": { "@capacitor/core": "^9.0.0-alpha.6" From 6c8a96fd98be16674a3d8dd7336f7ba53ab5089d Mon Sep 17 00:00:00 2001 From: Joseph Pender Date: Wed, 2 Sep 2026 13:11:38 -0500 Subject: [PATCH 4/5] fix(ios): guard Cordova import behind SWIFT_PACKAGE --- cli/src/declarations.ts | 46 +++ cli/src/ios/update.ts | 31 +- cli/src/util/capacitor-package.ts | 297 ++++++++++++++++++ cli/src/util/cordova-ios.ts | 18 +- cli/src/util/spm.ts | 11 +- cli/test/capacitor-package.spec.ts | 270 ++++++++++++++++ ios-spm-template/App/CapApp-SPM/Package.swift | 6 +- ios/Sources/CapacitorCordova/Plugin.swift | 4 + 8 files changed, 656 insertions(+), 27 deletions(-) create mode 100644 cli/src/util/capacitor-package.ts create mode 100644 cli/test/capacitor-package.spec.ts diff --git a/cli/src/declarations.ts b/cli/src/declarations.ts index 8d1a40e627..7787b01ebb 100644 --- a/cli/src/declarations.ts +++ b/cli/src/declarations.ts @@ -575,6 +575,52 @@ export interface CapacitorConfig { * @since 8.4.0 */ packageOptions?: { [pluginId: string]: PackageOptions }; + + /** + * Override which Capacitor Swift package the generated `Package.swift` depends on. + * + * By default the generated package pins the git tag matching the installed + * `@capacitor/ios` version, which is correct for both stable and pre-release versions + * and matches what CocoaPods resolves. + * + * Set this only when developing against an unreleased Capacitor, such as a local + * checkout or a feature branch. Exactly one of `path`, `branch`, `revision`, `exact`, + * or `from` must be set. `path` points at the repository root (the directory containing + * `Package.swift`) and may be relative to the app. + * + * The `CAPACITOR_IOS_PACKAGE` environment variable takes precedence over this setting, + * so a checkout can be redirected without editing committed configuration. + * + * Note that `branch` and `revision` builds are not reproducible and decouple the native + * code from the `@capacitor/core` JavaScript bridge it is versioned against. + * + * @since 9.0.0 + * @example { "path": "../capacitor" } + * @example { "branch": "next" } + */ + capacitorPackage?: { + /** + * Repository to fetch from. Ignored when `path` is set. + * + * @default 'https://github.com/ionic-team/capacitor' + */ + url?: string; + + /** Path to a local Capacitor repository root. */ + path?: string; + + /** Branch to track. */ + branch?: string; + + /** Exact commit to pin. */ + revision?: string; + + /** Exact version tag to pin. */ + exact?: string; + + /** Minimum version tag, allowing compatible upgrades. */ + from?: string; + }; }; }; }; diff --git a/cli/src/ios/update.ts b/cli/src/ios/update.ts index ca85595c13..29873c37db 100644 --- a/cli/src/ios/update.ts +++ b/cli/src/ios/update.ts @@ -12,6 +12,11 @@ import type { Plugin } from '../plugin'; import { PluginType, getPluginType, getPlugins, printPlugins } from '../plugin'; import { copy as copyTask } from '../tasks/copy'; import { setAllStringIn } from '../tasks/migrate'; +import { + findCapacitorDependencyVersion, + resolveCapacitorPackage, + rewriteCapacitorDependency, +} from '../util/capacitor-package'; import { generateCordovaPodspecs, generateCordovaPackageFiles, @@ -65,16 +70,29 @@ async function updatePluginFiles(config: Config, plugins: Plugin[], deployment: } const validSPMPackages = await checkPluginsForPackageSwift(config, plugins); + const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); + const majorCapVersion = major(iosPlatformVersion); + const capacitorPackage = await resolveCapacitorPackage(config, 'from'); await Promise.all( validSPMPackages.map(async (plugin) => { - const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); const packageSwiftPath = join(plugin.rootPath, 'Package.swift'); let content = await readFile(packageSwiftPath, { encoding: 'utf-8' }); - const regex = new RegExp( - 'url:\\s*"https://github.com/ionic-team/capacitor-swift-pm\\.git",\\s*from:\\s*"([^"]+)"', - ); - const version = content.match(regex)?.[1]; - const majorCapVersion = major(iosPlatformVersion); + const version = findCapacitorDependencyVersion(content); + + if (version && major(version) != majorCapVersion) { + logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); + } + + if (capacitorPackage.sourceBased) { + // The plugin has to resolve to the same package identity as the app, or SPM ends up with + // two packages that both vend a Capacitor product. + const rewritten = rewriteCapacitorDependency(content, capacitorPackage, plugin.rootPath); + if (rewritten !== content) { + await writeFile(packageSwiftPath, rewritten); + } + return; + } + if (version && major(version) != majorCapVersion) { const preCapVersion = prerelease(iosPlatformVersion); const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`; @@ -85,7 +103,6 @@ async function updatePluginFiles(config: Config, plugins: Plugin[], deployment: ` from: "${forceVersion}"`, ); await writeFile(packageSwiftPath, content); - logger.warn(`${plugin.id} is built for Capacitor ${major(version)}, it might cause issues`); } }), ); diff --git a/cli/src/util/capacitor-package.ts b/cli/src/util/capacitor-package.ts new file mode 100644 index 0000000000..c1615c1c5f --- /dev/null +++ b/cli/src/util/capacitor-package.ts @@ -0,0 +1,297 @@ +import { existsSync } from 'fs-extra'; +import { isAbsolute, relative, resolve } from 'path'; +import { major, valid } from 'semver'; + +import { getCapacitorPackageVersion } from '../common'; +import type { Config } from '../definitions'; +import { fatal } from '../errors'; + +import { convertToUnixPath } from './fs'; + +/** Capacitor 9 and up builds the iOS platform from source out of the main repo. */ +const SOURCE_PACKAGE_MAJOR = 9; +const SOURCE_PACKAGE_URL = 'https://github.com/ionic-team/capacitor'; +const SOURCE_PACKAGE_IDENTITY = 'capacitor'; + +/** Before Capacitor 9 the platform was consumed as a prebuilt xcframework from a separate repo. */ +const BINARY_PACKAGE_URL = 'https://github.com/ionic-team/capacitor-swift-pm.git'; +const BINARY_PACKAGE_IDENTITY = 'capacitor-swift-pm'; + +const ENV_OVERRIDE = 'CAPACITOR_IOS_PACKAGE'; +const REQUIREMENT_KEYS = ['path', 'branch', 'revision', 'exact', 'from'] as const; + +export type CapacitorRequirement = + | { kind: 'path'; absolutePath: string } + | { kind: 'branch'; branch: string } + | { kind: 'revision'; revision: string } + | { kind: 'exact'; version: string } + | { kind: 'from'; version: string }; + +export interface CapacitorPackage { + /** SPM package identity, as referenced by `.product(name:package:)`. */ + identity: string; + /** Product providing the Cordova compatibility layer. */ + cordovaProduct: string; + /** True when this resolves to the source package (Capacitor 9+). */ + sourceBased: boolean; + url: string; + requirement: CapacitorRequirement; +} + +/** + * Resolves which Capacitor Swift package generated `Package.swift` files should depend on. + * + * Precedence, most specific first: + * 1. the `CAPACITOR_IOS_PACKAGE` environment variable + * 2. `experimental.ios.spm.capacitorPackage` in the Capacitor config + * 3. the git tag matching the installed `@capacitor/ios` version + * + * The environment variable deliberately outranks the config file so a checkout can be pointed at a + * local or branch build without editing (and risking committing) the app's configuration. + * + * `legacyRequirement` only applies to pre-9 projects, where it preserves each caller's existing + * requirement style. Source-based projects always pin `exact`, because the app package and any + * generated plugin packages must agree: a prerelease such as `9.0.0-alpha.6` does not satisfy a + * `from:` range, so mixing the two styles fails to resolve. + */ +export async function resolveCapacitorPackage( + config: Config, + legacyRequirement: 'exact' | 'from' = 'exact', +): Promise { + const version = await getCapacitorPackageVersion(config, config.ios.name); + + if (major(version) < SOURCE_PACKAGE_MAJOR) { + return { + identity: BINARY_PACKAGE_IDENTITY, + cordovaProduct: 'Cordova', + sourceBased: false, + url: BINARY_PACKAGE_URL, + requirement: { kind: legacyRequirement, version }, + }; + } + + const override = resolveOverride(config); + + return { + identity: SOURCE_PACKAGE_IDENTITY, + cordovaProduct: 'CapacitorCordova', + sourceBased: true, + url: override?.url ?? SOURCE_PACKAGE_URL, + requirement: override?.requirement ?? { kind: 'exact', version }, + }; +} + +/** Renders the `.package(...)` entry, with any path made relative to the file being written. */ +export function renderCapacitorPackage(pkg: CapacitorPackage, fromDir: string): string { + if (pkg.requirement.kind === 'path') { + const relPath = convertToUnixPath(relative(fromDir, pkg.requirement.absolutePath)); + // Pin the identity: for a path dependency SPM would otherwise derive it from the directory + // name, which breaks `.product(package:)` when the checkout is not named "capacitor". + return `.package(name: "${pkg.identity}", path: "${relPath}")`; + } + + return `.package(url: "${pkg.url}", ${renderRequirement(pkg.requirement)})`; +} + +/** + * Repoints an existing `Package.swift` at the resolved Capacitor package. + * + * Third-party plugins ship a dependency on `capacitor-swift-pm`. From Capacitor 9 the app depends + * on the source package instead, and SPM treats the two as separate identities that both vend a + * `Capacitor` product — so a plugin left untouched would either fail to resolve or link a second + * copy of the framework. Rewriting keeps the whole graph on one identity. + */ +export function rewriteCapacitorDependency(content: string, pkg: CapacitorPackage, fromDir: string): string { + let rewritten = replacePackageCalls(content, renderCapacitorPackage(pkg, fromDir)); + + for (const identity of [BINARY_PACKAGE_IDENTITY, SOURCE_PACKAGE_IDENTITY]) { + rewritten = rewritten.split(`package: "${identity}"`).join(`package: "${pkg.identity}"`); + } + + return rewritten; +} + +/** Reads the version an existing `Package.swift` pins Capacitor to, if it pins one. */ +export function findCapacitorDependencyVersion(content: string): string | undefined { + for (const call of findPackageCalls(content)) { + if (!referencesCapacitor(call.text)) { + continue; + } + const match = call.text.match(/(?:from|exact):\s*"([^"]+)"/); + if (match) { + return match[1]; + } + } + return undefined; +} + +function referencesCapacitor(call: string): boolean { + return call.includes(BINARY_PACKAGE_IDENTITY) || call.includes(`${SOURCE_PACKAGE_URL}`); +} + +/** Locates `.package(...)` calls, tracking paren depth so nested calls don't terminate the match. */ +function findPackageCalls(content: string): { start: number; end: number; text: string }[] { + const calls: { start: number; end: number; text: string }[] = []; + const marker = '.package('; + let index = content.indexOf(marker); + + while (index !== -1) { + let depth = 0; + let inString = false; + let cursor = index + marker.length - 1; + + for (; cursor < content.length; cursor++) { + const char = content[cursor]; + if (inString) { + if (char === '\\') { + cursor++; + } else if (char === '"') { + inString = false; + } + continue; + } + if (char === '"') { + inString = true; + } else if (char === '(') { + depth++; + } else if (char === ')') { + depth--; + if (depth === 0) { + break; + } + } + } + + if (depth !== 0) { + break; + } + + calls.push({ start: index, end: cursor + 1, text: content.slice(index, cursor + 1) }); + index = content.indexOf(marker, cursor + 1); + } + + return calls; +} + +function replacePackageCalls(content: string, rendered: string): string { + let result = content; + + // Walk backwards so earlier offsets stay valid as we splice. + for (const call of findPackageCalls(content).reverse()) { + if (referencesCapacitor(call.text)) { + result = result.slice(0, call.start) + rendered + result.slice(call.end); + } + } + + return result; +} + +function renderRequirement(requirement: CapacitorRequirement): string { + switch (requirement.kind) { + case 'branch': + return `branch: "${requirement.branch}"`; + case 'revision': + return `revision: "${requirement.revision}"`; + case 'exact': + return `exact: "${requirement.version}"`; + case 'from': + return `from: "${requirement.version}"`; + case 'path': + throw new Error('path requirements are rendered by renderCapacitorPackage'); + } +} + +function resolveOverride(config: Config): { url?: string; requirement: CapacitorRequirement } | undefined { + const baseDir = config.app.rootDir; + + const fromEnv = process.env[ENV_OVERRIDE]?.trim(); + if (fromEnv) { + return { requirement: parseRequirementSpec(fromEnv, baseDir) }; + } + + const fromConfig = config.app.extConfig.experimental?.ios?.spm?.capacitorPackage; + if (!fromConfig) { + return undefined; + } + + const provided = REQUIREMENT_KEYS.filter((key) => fromConfig[key] !== undefined); + if (provided.length === 0) { + fatal( + `experimental.ios.spm.capacitorPackage must set one of: ${REQUIREMENT_KEYS.join(', ')}.\n` + + `Remove the entry to use the version matching the installed @capacitor/ios.`, + ); + } + if (provided.length > 1) { + fatal( + `experimental.ios.spm.capacitorPackage sets more than one of: ${provided.join(', ')}.\n` + `Only one may be set.`, + ); + } + + const key = provided[0]; + const value = String(fromConfig[key]); + + if (key === 'path') { + if (fromConfig.url !== undefined) { + fatal(`experimental.ios.spm.capacitorPackage cannot set both "url" and "path".`); + } + return { requirement: pathRequirement(value, baseDir) }; + } + + return { url: fromConfig.url, requirement: { kind: key, ...requirementValue(key, value) } as CapacitorRequirement }; +} + +function requirementValue(key: (typeof REQUIREMENT_KEYS)[number], value: string) { + switch (key) { + case 'branch': + return { branch: value }; + case 'revision': + return { revision: value }; + default: + return { version: value }; + } +} + +/** + * Parses a `CAPACITOR_IOS_PACKAGE` value. Accepts an explicit `kind:value` form, or infers `path` + * for anything path-shaped and `exact` for a bare version. + */ +function parseRequirementSpec(spec: string, baseDir: string): CapacitorRequirement { + const separator = spec.indexOf(':'); + if (separator > 0) { + const key = spec.slice(0, separator); + const value = spec.slice(separator + 1); + if ((REQUIREMENT_KEYS as readonly string[]).includes(key)) { + if (key === 'path') { + return pathRequirement(value, baseDir); + } + return { + kind: key, + ...requirementValue(key as (typeof REQUIREMENT_KEYS)[number], value), + } as CapacitorRequirement; + } + } + + if (spec.startsWith('.') || isAbsolute(spec)) { + return pathRequirement(spec, baseDir); + } + + if (valid(spec)) { + return { kind: 'exact', version: spec }; + } + + return fatal( + `Could not understand ${ENV_OVERRIDE}="${spec}".\n` + + `Expected one of ${REQUIREMENT_KEYS.map((k) => `${k}:`).join(', ')}, a path, or a version.`, + ); +} + +function pathRequirement(value: string, baseDir: string): CapacitorRequirement { + const absolutePath = resolve(baseDir, value); + if (!existsSync(resolve(absolutePath, 'Package.swift'))) { + fatal( + `No Package.swift found at ${absolutePath}.\n` + + `A local Capacitor package must point at the repository root, not the ios directory.`, + ); + } + return { kind: 'path', absolutePath }; +} diff --git a/cli/src/util/cordova-ios.ts b/cli/src/util/cordova-ios.ts index 4cba270999..30c0e4072b 100644 --- a/cli/src/util/cordova-ios.ts +++ b/cli/src/util/cordova-ios.ts @@ -1,7 +1,6 @@ import { copy, readFile, writeFile, remove } from 'fs-extra'; import { join } from 'path'; -import { getCapacitorPackageVersion } from '../common'; import { needsStaticPod } from '../cordova'; import type { Config } from '../definitions'; import { getMajoriOSVersion } from '../ios/common'; @@ -16,7 +15,7 @@ import { resolvePlugin, } from '../plugin'; import type { Plugin } from '../plugin'; -import { setAllStringIn } from '../tasks/migrate'; +import { renderCapacitorPackage, resolveCapacitorPackage, rewriteCapacitorDependency } from '../util/capacitor-package'; import { extractTemplate } from '../util/template'; const platform = 'ios'; @@ -475,7 +474,7 @@ ${entries.join(',\n')} } export async function generateCordovaPackageFile(p: Plugin, config: Config): Promise { - const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); + const capacitorPackage = await resolveCapacitorPackage(config, 'from'); const iosVersion = getMajoriOSVersion(config); const headerFiles = getPlatformElement(p, platform, 'header-file'); let headersText = ''; @@ -489,13 +488,8 @@ export async function generateCordovaPackageFile(p: Plugin, config: Config): Pro if (platformTag.$?.package) { const packageSwiftPath = join(p.rootPath, 'Package.swift'); let content = await readFile(packageSwiftPath, { encoding: 'utf-8' }); - content = content.replace(`apache`, `ionic-team`).replaceAll(`cordova-ios`, `capacitor-swift-pm`); - content = setAllStringIn( - content, - `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, - `)`, - ` from: "${iosPlatformVersion}"`, - ); + content = content.replace(`apache`, `ionic-team`).replaceAll(`cordova-ios`, capacitorPackage.identity); + content = rewriteCapacitorDependency(content, capacitorPackage, p.rootPath); await writeFile(packageSwiftPath, content); } else { const resources = getPlatformElement(p, platform, 'resource-file'); @@ -535,13 +529,13 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "${iosPlatformVersion}")${packageText} + ${renderCapacitorPackage(capacitorPackage, join(config.ios.cordovaPluginsDirAbs, 'sources', p.name))}${packageText} ], targets: [ .target( name: "${p.name}", dependencies: [ - .product(name: "Cordova", package: "capacitor-swift-pm")${binaryDepsText}${productText} + .product(name: "Cordova", package: "${capacitorPackage.identity}")${binaryDepsText}${productText} ], path: "."${resourcesText}${headersText}${cSettingsText}${linkerSettingsText} )${binaryTargetsText} diff --git a/cli/src/util/spm.ts b/cli/src/util/spm.ts index d3c1d113d3..47bf559aeb 100644 --- a/cli/src/util/spm.ts +++ b/cli/src/util/spm.ts @@ -5,7 +5,6 @@ import type { PlistObject } from 'plist'; import { build, parse } from 'plist'; import { extract } from 'tar'; -import { getCapacitorPackageVersion } from '../common'; import { getCordovaPlugins } from '../cordova'; import type { Config } from '../definitions'; import { fatal } from '../errors'; @@ -13,6 +12,7 @@ import { getMajoriOSVersion } from '../ios/common'; import { logger } from '../log'; import type { Plugin } from '../plugin'; import { getPlatformElement, getPluginPlatform, getPluginType, PluginType } from '../plugin'; +import { renderCapacitorPackage, resolveCapacitorPackage } from '../util/capacitor-package'; import { convertToUnixPath } from '../util/fs'; import { runCommand } from '../util/subprocess'; @@ -99,12 +99,13 @@ export async function removeCocoapodsFiles(config: Config): Promise { } export async function generatePackageText(config: Config, plugins: Plugin[]): Promise { - const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name); const iosVersion = getMajoriOSVersion(config); const cordovaPlugins = await getCordovaPlugins(config, 'ios'); const enableCordova = cordovaPlugins.length > 0 || config.app.forceCordova; const packageTraits = config.app.extConfig.experimental?.ios?.spm?.packageTraits ?? {}; const packageOptions = config.app.extConfig.experimental?.ios?.spm?.packageOptions ?? {}; + const capacitorPackage = await resolveCapacitorPackage(config); + const spmDirectory = join(config.ios.nativeProjectDirAbs, 'CapApp-SPM'); const swiftToolsVersion = config.app.extConfig.experimental?.ios?.spm?.swiftToolsVersion ?? '5.9'; let packageSwiftText = `// swift-tools-version: ${swiftToolsVersion} @@ -120,7 +121,7 @@ let package = Package( targets: ["CapApp-SPM"]) ], dependencies: [ - .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "${iosPlatformVersion}")`; + ${renderCapacitorPackage(capacitorPackage, spmDirectory)}`; for (const plugin of plugins) { if (getPluginType(plugin, config.ios.name) === PluginType.Cordova) { @@ -165,10 +166,10 @@ let package = Package( .target( name: "CapApp-SPM", dependencies: [ - .product(name: "Capacitor", package: "capacitor-swift-pm")`; + .product(name: "Capacitor", package: "${capacitorPackage.identity}")`; if (enableCordova) { - packageSwiftText += `,\n .product(name: "Cordova", package: "capacitor-swift-pm")`; + packageSwiftText += `,\n .product(name: "${capacitorPackage.cordovaProduct}", package: "${capacitorPackage.identity}")`; } for (const plugin of plugins) { diff --git a/cli/test/capacitor-package.spec.ts b/cli/test/capacitor-package.spec.ts new file mode 100644 index 0000000000..80474bbb5d --- /dev/null +++ b/cli/test/capacitor-package.spec.ts @@ -0,0 +1,270 @@ +import { mkdirSync, mkdtempSync, writeFileSync } from 'fs'; +import { tmpdir } from 'os'; +import { join, resolve } from 'path'; + +import type { Config } from '../src/definitions'; +import { + findCapacitorDependencyVersion, + renderCapacitorPackage, + resolveCapacitorPackage, + rewriteCapacitorDependency, +} from '../src/util/capacitor-package'; + +jest.mock('../src/common', () => ({ + getCapacitorPackageVersion: jest.fn(), +})); + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { getCapacitorPackageVersion } = require('../src/common'); + +const SPM_DIR = '/app/ios/App/CapApp-SPM'; + +function makeConfig(extConfig: any = {}, rootDir = '/app'): Config { + return { + app: { rootDir, extConfig }, + ios: { name: 'ios' }, + } as any; +} + +describe('capacitor package resolution', () => { + beforeEach(() => { + delete process.env.CAPACITOR_IOS_PACKAGE; + getCapacitorPackageVersion.mockReset(); + }); + + describe('default (no override)', () => { + it('pins the tag matching a stable installed version', async () => { + getCapacitorPackageVersion.mockResolvedValue('9.1.0'); + const pkg = await resolveCapacitorPackage(makeConfig()); + + expect(pkg.sourceBased).toBe(true); + expect(pkg.identity).toBe('capacitor'); + expect(pkg.cordovaProduct).toBe('CapacitorCordova'); + expect(renderCapacitorPackage(pkg, SPM_DIR)).toBe( + '.package(url: "https://github.com/ionic-team/capacitor", exact: "9.1.0")', + ); + }); + + it('pins the tag for a prerelease too, rather than tracking a branch', async () => { + getCapacitorPackageVersion.mockResolvedValue('9.0.0-alpha.6'); + const pkg = await resolveCapacitorPackage(makeConfig()); + + expect(renderCapacitorPackage(pkg, SPM_DIR)).toBe( + '.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0-alpha.6")', + ); + }); + + it('uses exact for source-based projects even when the caller asks for from', async () => { + // The app package and generated plugin packages must agree; a prerelease does not satisfy + // a `from:` range, so mixing the two styles would fail to resolve. + getCapacitorPackageVersion.mockResolvedValue('9.0.0-alpha.6'); + const pkg = await resolveCapacitorPackage(makeConfig(), 'from'); + + expect(pkg.requirement).toEqual({ kind: 'exact', version: '9.0.0-alpha.6' }); + }); + }); + + describe('pre-9 projects', () => { + it('keeps using the prebuilt package and the caller-chosen requirement style', async () => { + getCapacitorPackageVersion.mockResolvedValue('8.4.0'); + + const app = await resolveCapacitorPackage(makeConfig(), 'exact'); + expect(app.sourceBased).toBe(false); + expect(app.identity).toBe('capacitor-swift-pm'); + expect(app.cordovaProduct).toBe('Cordova'); + expect(renderCapacitorPackage(app, SPM_DIR)).toBe( + '.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.4.0")', + ); + + const plugin = await resolveCapacitorPackage(makeConfig(), 'from'); + expect(renderCapacitorPackage(plugin, SPM_DIR)).toBe( + '.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.4.0")', + ); + }); + + it('ignores an override, which only applies to the source package', async () => { + getCapacitorPackageVersion.mockResolvedValue('8.4.0'); + process.env.CAPACITOR_IOS_PACKAGE = 'branch:next'; + + const pkg = await resolveCapacitorPackage(makeConfig()); + expect(pkg.requirement).toEqual({ kind: 'exact', version: '8.4.0' }); + }); + }); + + describe('config override', () => { + beforeEach(() => getCapacitorPackageVersion.mockResolvedValue('9.0.0-alpha.6')); + + it('tracks a branch', async () => { + const pkg = await resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { branch: 'next' } } } } }), + ); + expect(renderCapacitorPackage(pkg, SPM_DIR)).toBe( + '.package(url: "https://github.com/ionic-team/capacitor", branch: "next")', + ); + }); + + it('pins a revision, and honours a custom url', async () => { + const pkg = await resolveCapacitorPackage( + makeConfig({ + experimental: { + ios: { spm: { capacitorPackage: { url: 'https://github.com/me/capacitor', revision: 'abc123' } } }, + }, + }), + ); + expect(renderCapacitorPackage(pkg, SPM_DIR)).toBe( + '.package(url: "https://github.com/me/capacitor", revision: "abc123")', + ); + }); + + it('rejects setting more than one requirement', async () => { + await expect( + resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { branch: 'next', exact: '9.0.0' } } } } }), + ), + ).rejects.toThrow(/more than one/); + }); + + it('rejects an empty requirement', async () => { + await expect( + resolveCapacitorPackage(makeConfig({ experimental: { ios: { spm: { capacitorPackage: {} } } } })), + ).rejects.toThrow(/must set one of/); + }); + }); + + describe('local path override', () => { + let checkout: string; + + beforeEach(() => { + getCapacitorPackageVersion.mockResolvedValue('9.0.0-alpha.6'); + checkout = mkdtempSync(join(tmpdir(), 'cap-pkg-')); + writeFileSync(join(checkout, 'Package.swift'), '// root package'); + }); + + it('renders a path relative to the file being written, with a pinned identity', async () => { + const pkg = await resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { path: checkout } } } } }), + ); + + const rendered = renderCapacitorPackage(pkg, SPM_DIR); + expect(rendered).toContain('.package(name: "capacitor", path: "'); + // A differently-named checkout must still be referenced as "capacitor" by products. + expect(pkg.identity).toBe('capacitor'); + }); + + it('resolves a relative path against the app root', async () => { + const nested = join(checkout, 'app'); + mkdirSync(nested); + const pkg = await resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { path: '..' } } } } }, nested), + ); + + expect(pkg.requirement).toEqual({ kind: 'path', absolutePath: resolve(checkout) }); + }); + + it('rejects a path that is not a package root', async () => { + await expect( + resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { path: join(checkout, 'ios') } } } } }), + ), + ).rejects.toThrow(/No Package.swift found/); + }); + + it('rejects url combined with path', async () => { + await expect( + resolveCapacitorPackage( + makeConfig({ + experimental: { ios: { spm: { capacitorPackage: { url: 'https://example.com', path: checkout } } } }, + }), + ), + ).rejects.toThrow(/cannot set both/); + }); + }); + + describe('environment override', () => { + beforeEach(() => getCapacitorPackageVersion.mockResolvedValue('9.0.0-alpha.6')); + + it('outranks the config file', async () => { + process.env.CAPACITOR_IOS_PACKAGE = 'branch:my-feature'; + const pkg = await resolveCapacitorPackage( + makeConfig({ experimental: { ios: { spm: { capacitorPackage: { branch: 'next' } } } } }), + ); + + expect(pkg.requirement).toEqual({ kind: 'branch', branch: 'my-feature' }); + }); + + it('infers exact from a bare version', async () => { + process.env.CAPACITOR_IOS_PACKAGE = '9.2.0'; + const pkg = await resolveCapacitorPackage(makeConfig()); + + expect(pkg.requirement).toEqual({ kind: 'exact', version: '9.2.0' }); + }); + + it('reports an unparseable value', async () => { + process.env.CAPACITOR_IOS_PACKAGE = 'nonsense'; + await expect(resolveCapacitorPackage(makeConfig())).rejects.toThrow(/Could not understand/); + }); + }); +}); + +describe('rewriting an existing Package.swift', () => { + const pkg = { + identity: 'capacitor', + cordovaProduct: 'CapacitorCordova', + sourceBased: true, + url: 'https://github.com/ionic-team/capacitor', + requirement: { kind: 'exact' as const, version: '9.0.0' }, + }; + + it('repoints a plugin from the prebuilt package to the source package', () => { + const before = `dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0") + ], + targets: [ + .target(name: "Plugin", dependencies: [.product(name: "Capacitor", package: "capacitor-swift-pm")]) + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(after).toContain('.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")'); + expect(after).toContain('.product(name: "Capacitor", package: "capacitor")'); + expect(after).not.toContain('capacitor-swift-pm'); + }); + + it('leaves unrelated dependencies alone', () => { + const before = `.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"), + .package(url: "https://github.com/other/thing.git", from: "1.0.0")`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + expect(after).toContain('.package(url: "https://github.com/other/thing.git", from: "1.0.0")'); + }); + + it('handles a nested requirement without truncating the call', () => { + const before = `.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", .upToNextMajor(from: "8.0.0"))`; + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(after).toBe('.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")'); + }); + + it('is idempotent once already repointed', () => { + const once = rewriteCapacitorDependency( + '.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")', + pkg, + '/plugin', + ); + expect(rewriteCapacitorDependency(once, pkg, '/plugin')).toBe(once); + }); + + it('reads the pinned version from either requirement style', () => { + expect( + findCapacitorDependencyVersion( + '.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.4.0")', + ), + ).toBe('8.4.0'); + expect( + findCapacitorDependencyVersion('.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")'), + ).toBe('9.0.0'); + expect( + findCapacitorDependencyVersion('.package(url: "https://github.com/other/thing.git", from: "1.0.0")'), + ).toBeUndefined(); + }); +}); diff --git a/ios-spm-template/App/CapApp-SPM/Package.swift b/ios-spm-template/App/CapApp-SPM/Package.swift index e3309a275a..bd592eff92 100644 --- a/ios-spm-template/App/CapApp-SPM/Package.swift +++ b/ios-spm-template/App/CapApp-SPM/Package.swift @@ -11,14 +11,14 @@ let package = Package( targets: ["CapApp-SPM"]) ], dependencies: [ - .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0") + .package(url: "https://github.com/ionic-team/capacitor", from: "9.0.0") ], targets: [ .target( name: "CapApp-SPM", dependencies: [ - .product(name: "Capacitor", package: "capacitor-swift-pm"), - .product(name: "Cordova", package: "capacitor-swift-pm") + .product(name: "Capacitor", package: "capacitor"), + .product(name: "CapacitorCordova", package: "capacitor") ] ) ] diff --git a/ios/Sources/CapacitorCordova/Plugin.swift b/ios/Sources/CapacitorCordova/Plugin.swift index 40e9657e8b..f7003f6963 100644 --- a/ios/Sources/CapacitorCordova/Plugin.swift +++ b/ios/Sources/CapacitorCordova/Plugin.swift @@ -1,5 +1,9 @@ import Capacitor +// Under CocoaPods this file is compiled into the Cordova module itself, so importing it would be a +// self-import. Under SPM the Swift and Objective-C halves are separate targets. +#if SWIFT_PACKAGE import Cordova +#endif @objc(CordovaPlugin) public class CordovaPlugin: CAPPlugin, CAPBridgedPlugin { From a6afa5ba2dedf5e0e0cd2e536d8c0c52af909d37 Mon Sep 17 00:00:00 2001 From: Joseph Pender Date: Fri, 4 Sep 2026 13:23:34 -0500 Subject: [PATCH 5/5] fix(cli): collapse duplicate Capacitor SPM dependencies when rewriting --- cli/src/util/capacitor-package.ts | 150 ++++++++++++++++++++++------- cli/test/capacitor-package.spec.ts | 96 ++++++++++++++++++ 2 files changed, 209 insertions(+), 37 deletions(-) diff --git a/cli/src/util/capacitor-package.ts b/cli/src/util/capacitor-package.ts index c1615c1c5f..d983eb73c4 100644 --- a/cli/src/util/capacitor-package.ts +++ b/cli/src/util/capacitor-package.ts @@ -129,61 +129,137 @@ function referencesCapacitor(call: string): boolean { return call.includes(BINARY_PACKAGE_IDENTITY) || call.includes(`${SOURCE_PACKAGE_URL}`); } -/** Locates `.package(...)` calls, tracking paren depth so nested calls don't terminate the match. */ -function findPackageCalls(content: string): { start: number; end: number; text: string }[] { - const calls: { start: number; end: number; text: string }[] = []; +interface PackageCall { + start: number; + /** Exclusive. */ + end: number; + text: string; +} + +/** + * Locates `.package(...)` calls in code, skipping any inside a comment or string literal. + * + * Commented-out calls have to be skipped rather than merely tolerated: `replacePackageCalls` + * keeps the first match and drops the rest, so a commented dependency above the real one would + * otherwise be the entry that survives. + */ +function findPackageCalls(content: string): PackageCall[] { const marker = '.package('; - let index = content.indexOf(marker); - - while (index !== -1) { - let depth = 0; - let inString = false; - let cursor = index + marker.length - 1; - - for (; cursor < content.length; cursor++) { - const char = content[cursor]; - if (inString) { - if (char === '\\') { - cursor++; - } else if (char === '"') { - inString = false; - } - continue; + const calls: PackageCall[] = []; + + for (let index = 0; index < content.length; index++) { + if (content[index] === '"') { + index = skipString(content, index); + continue; + } + + if (content.startsWith('//', index)) { + const newline = content.indexOf('\n', index); + if (newline === -1) { + break; } - if (char === '"') { - inString = true; - } else if (char === '(') { - depth++; - } else if (char === ')') { - depth--; - if (depth === 0) { - break; - } + index = newline; + continue; + } + + if (content.startsWith('/*', index)) { + const close = content.indexOf('*/', index + 2); + if (close === -1) { + break; } + index = close + 1; + continue; + } + + if (!content.startsWith(marker, index)) { + continue; } - if (depth !== 0) { + const end = findCallEnd(content, index + marker.length - 1); + if (end === -1) { break; } - calls.push({ start: index, end: cursor + 1, text: content.slice(index, cursor + 1) }); - index = content.indexOf(marker, cursor + 1); + calls.push({ start: index, end, text: content.slice(index, end) }); + index = end - 1; } return calls; } +/** Walks from an opening paren to its match, tracking depth so nested calls don't terminate it. */ +function findCallEnd(content: string, openParen: number): number { + let depth = 0; + + for (let cursor = openParen; cursor < content.length; cursor++) { + const char = content[cursor]; + if (char === '"') { + cursor = skipString(content, cursor); + } else if (char === '(') { + depth++; + } else if (char === ')') { + depth--; + if (depth === 0) { + return cursor + 1; + } + } + } + + return -1; +} + +/** Returns the index of the closing quote of the string literal opening at `open`. */ +function skipString(content: string, open: number): number { + for (let cursor = open + 1; cursor < content.length; cursor++) { + if (content[cursor] === '\\') { + cursor++; + } else if (content[cursor] === '"') { + return cursor; + } + } + + return content.length; +} + +/** + * Points every Capacitor dependency at `rendered`, collapsing them to a single entry. + * + * A manifest supporting both Capacitor 8 and 9 can declare the prebuilt and source packages side + * by side. Both rewrite to the same text, and SPM rejects a manifest that declares one dependency + * twice, so the extra entries are removed rather than replaced. + */ function replacePackageCalls(content: string, rendered: string): string { + const matches = findPackageCalls(content).filter((call) => referencesCapacitor(call.text)); + + if (matches.length === 0) { + return content; + } + + const [survivor, ...duplicates] = matches; let result = content; - // Walk backwards so earlier offsets stay valid as we splice. - for (const call of findPackageCalls(content).reverse()) { - if (referencesCapacitor(call.text)) { - result = result.slice(0, call.start) + rendered + result.slice(call.end); - } + // Every duplicate sits after the survivor, so splicing them out backwards leaves its offsets + // valid and guarantees each one is preceded by the comma separating it from an earlier entry. + for (const call of duplicates.reverse()) { + result = result.slice(0, startOfEntry(content, call.start)) + result.slice(call.end); + } + + return result.slice(0, survivor.start) + rendered + result.slice(survivor.end); +} + +/** + * Extends a deletion back over the comma separating an entry from the previous one. Swift allows a + * trailing comma in an array literal but not a leading one, so the preceding comma is the one to + * take. + */ +function startOfEntry(content: string, start: number): number { + let cursor = start - 1; + + while (cursor >= 0 && /\s/.test(content[cursor])) { + cursor--; } - return result; + return content[cursor] === ',' ? cursor : start; } function renderRequirement(requirement: CapacitorRequirement): string { diff --git a/cli/test/capacitor-package.spec.ts b/cli/test/capacitor-package.spec.ts index 80474bbb5d..1a61d65fc5 100644 --- a/cli/test/capacitor-package.spec.ts +++ b/cli/test/capacitor-package.spec.ts @@ -19,6 +19,10 @@ const { getCapacitorPackageVersion } = require('../src/common'); const SPM_DIR = '/app/ios/App/CapApp-SPM'; +function occurrences(haystack: string, needle: string): number { + return haystack.split(needle).length - 1; +} + function makeConfig(extConfig: any = {}, rootDir = '/app'): Config { return { app: { rootDir, extConfig }, @@ -254,6 +258,98 @@ describe('rewriting an existing Package.swift', () => { expect(rewriteCapacitorDependency(once, pkg, '/plugin')).toBe(once); }); + it('collapses a manifest declaring both the prebuilt and source packages', () => { + const before = `dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"), + .package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0") + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(occurrences(after, '.package(')).toBe(1); + expect(after).toBe(`dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0") + ]`); + }); + + it('keeps the first entry when the source package is declared first', () => { + const before = `dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor", from: "9.0.0"), + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0") + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(occurrences(after, '.package(')).toBe(1); + expect(after).toBe(`dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0") + ]`); + }); + + it('collapses three references down to one, preserving unrelated entries', () => { + const before = `dependencies: [ + .package(url: "https://github.com/other/thing.git", from: "1.0.0"), + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"), + .package(path: "../capacitor-swift-pm"), + .package(url: "https://github.com/ionic-team/capacitor", branch: "next") + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(occurrences(after, '.package(')).toBe(2); + expect(after).toContain('.package(url: "https://github.com/other/thing.git", from: "1.0.0")'); + expect(occurrences(after, '.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")')).toBe(1); + }); + + it('leaves no leading comma when the surviving entry is last', () => { + const before = `dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"), + .package(url: "https://github.com/other/thing.git", from: "1.0.0") + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(after).not.toMatch(/\[\s*,/); + expect(after).not.toMatch(/,\s*,/); + }); + + it('ignores a commented-out dependency rather than letting it win the collapse', () => { + const before = `dependencies: [ + // .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main"), + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0") + ]`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(after).toContain('// .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main")'); + expect(after).toContain('.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")'); + }); + + it('ignores a dependency inside a block comment', () => { + const before = `/* .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0") */ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")`; + + const after = rewriteCapacitorDependency(before, pkg, '/plugin'); + + expect(after).toContain( + '/* .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0") */', + ); + expect(after).toContain('.package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0")'); + }); + + it('stays idempotent after collapsing', () => { + const once = rewriteCapacitorDependency( + `dependencies: [ + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"), + .package(url: "https://github.com/ionic-team/capacitor", exact: "9.0.0") + ]`, + pkg, + '/plugin', + ); + + expect(rewriteCapacitorDependency(once, pkg, '/plugin')).toBe(once); + }); + it('reads the pinned version from either requirement style', () => { expect( findCapacitorDependencyVersion(