@depup/react-native 0.86.2-depup.0 → 0.87.1-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/ActionSheetIOS/ActionSheetIOS.js +19 -24
- package/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec +1 -1
- package/Libraries/Alert/Alert.js +38 -1
- package/Libraries/Animated/AnimatedEvent.js +1 -1
- package/Libraries/Animated/AnimatedExports.js +22 -0
- package/Libraries/Animated/AnimatedExports.js.flow +1 -1
- package/Libraries/Animated/AnimatedImplementation.js +126 -5
- package/Libraries/Animated/Easing.js +4 -3
- package/Libraries/Animated/NativeAnimatedAllowlist.js +37 -0
- package/Libraries/Animated/animations/Animation.js +14 -5
- package/Libraries/Animated/animations/DecayAnimation.js +1 -0
- package/Libraries/Animated/animations/SpringAnimation.js +1 -0
- package/Libraries/Animated/animations/TimingAnimation.js +9 -0
- package/Libraries/Animated/components/AnimatedScrollView.js +1 -1
- package/Libraries/Animated/createAnimatedComponent.js +3 -3
- package/Libraries/Animated/nodes/AnimatedColor.js +8 -8
- package/Libraries/Animated/nodes/AnimatedInterpolation.js +106 -0
- package/Libraries/Animated/nodes/AnimatedNode.js +1 -1
- package/Libraries/Animated/nodes/AnimatedProps.js +27 -3
- package/Libraries/Animated/nodes/AnimatedValue.js +10 -2
- package/Libraries/Animated/nodes/AnimatedValueXY.js +2 -2
- package/Libraries/AppDelegate/RCTAppDelegate.h +5 -9
- package/Libraries/AppDelegate/RCTAppDelegate.mm +0 -20
- package/Libraries/AppDelegate/RCTAppSetupUtils.h +0 -18
- package/Libraries/AppDelegate/RCTAppSetupUtils.mm +0 -78
- package/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm +18 -21
- package/Libraries/AppDelegate/RCTReactNativeFactory.h +5 -41
- package/Libraries/AppDelegate/RCTReactNativeFactory.mm +0 -82
- package/Libraries/AppDelegate/RCTRootViewFactory.h +4 -1
- package/Libraries/AppDelegate/RCTRootViewFactory.mm +3 -101
- package/Libraries/AppDelegate/React-RCTAppDelegate.podspec +2 -1
- package/Libraries/AppState/AppState.d.ts +4 -1
- package/Libraries/AppState/AppState.js +32 -17
- package/Libraries/BatchedBridge/MessageQueue.js +42 -51
- package/Libraries/BatchedBridge/NativeModules.js +7 -0
- package/Libraries/Blob/Blob.js +7 -1
- package/Libraries/Blob/FileReader.js +6 -0
- package/Libraries/Blob/React-RCTBlob.podspec +1 -1
- package/Libraries/Blob/URLSearchParams.js.flow +1 -1
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts +20 -9
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +30 -43
- package/Libraries/Components/ActivityIndicator/ActivityIndicator.js +59 -49
- package/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js +2 -2
- package/Libraries/Components/Button.js +98 -183
- package/Libraries/Components/Clipboard/Clipboard.js +5 -0
- package/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js +2 -2
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +8 -69
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.d.ts +10 -1
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.ios.js +2 -0
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.js +26 -31
- package/Libraries/Components/Keyboard/Keyboard.js +23 -60
- package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +15 -7
- package/Libraries/Components/Pressable/Pressable.js +39 -17
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +5 -6
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js +4 -4
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.js +2 -2
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidTypes.js +17 -0
- package/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js +2 -2
- package/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js +2 -2
- package/Libraries/Components/RefreshControl/RefreshControl.js +40 -50
- package/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js +2 -2
- package/Libraries/Components/SafeAreaView/SafeAreaView.js +8 -8
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js +2 -2
- package/Libraries/Components/ScrollView/ScrollView.d.ts +55 -43
- package/Libraries/Components/ScrollView/ScrollView.js +205 -118
- package/Libraries/Components/ScrollView/ScrollViewCommands.js +4 -4
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +1 -1
- package/Libraries/Components/StatusBar/StatusBar.d.ts +7 -54
- package/Libraries/Components/StatusBar/StatusBar.js +84 -160
- package/Libraries/Components/Switch/AndroidSwitchNativeComponent.js +2 -2
- package/Libraries/Components/Switch/Switch.js +76 -75
- package/Libraries/Components/Switch/SwitchNativeComponent.js +2 -2
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +1 -1
- package/Libraries/Components/TextInput/InputAccessoryView.js +13 -61
- package/Libraries/Components/TextInput/RCTInputAccessoryViewNativeComponent.js +2 -2
- package/Libraries/Components/TextInput/TextInput.d.ts +9 -2
- package/Libraries/Components/TextInput/TextInput.flow.js +20 -3
- package/Libraries/Components/TextInput/TextInput.js +116 -111
- package/Libraries/Components/TextInput/TextInputNativeCommands.js +3 -3
- package/Libraries/Components/ToastAndroid/ToastAndroid.android.js +25 -19
- package/Libraries/Components/Touchable/Touchable.d.ts +1 -1
- package/Libraries/Components/Touchable/Touchable.js +94 -95
- package/Libraries/Components/Touchable/TouchableHighlight.js +45 -112
- package/Libraries/Components/Touchable/TouchableNativeFeedback.js +13 -25
- package/Libraries/Components/Touchable/TouchableOpacity.js +14 -84
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +4 -3
- package/Libraries/Components/UnimplementedViews/UnimplementedNativeViewNativeComponent.js +2 -2
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +1 -0
- package/Libraries/Components/View/View.js +83 -86
- package/Libraries/Components/View/ViewAccessibility.d.ts +12 -2
- package/Libraries/Components/View/ViewAccessibility.js +17 -6
- package/Libraries/Components/View/ViewNativeComponent.js +4 -6
- package/Libraries/Components/View/ViewPropTypes.js +65 -13
- package/Libraries/Core/InitializeCore.js +9 -1
- package/Libraries/Core/ReactFiberErrorDialog.js +3 -3
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Core/Timers/JSTimers.js +53 -52
- package/Libraries/Core/setUpGlobals.js +9 -4
- package/Libraries/Core/setUpNavigator.js +7 -2
- package/Libraries/Core/setUpReactDevTools.js +0 -118
- package/Libraries/Core/setUpXHR.js +6 -2
- package/Libraries/Debugging/DebuggingOverlay.js +2 -2
- package/Libraries/Debugging/DebuggingOverlayNativeComponent.js +2 -2
- package/Libraries/EventEmitter/NativeEventEmitter.js +29 -0
- package/Libraries/EventEmitter/RCTDeviceEventEmitter.js +7 -7
- package/Libraries/EventEmitter/RCTNativeAppEventEmitter.d.ts +1 -1
- package/Libraries/EventEmitter/RCTNativeAppEventEmitter.js +3 -0
- package/Libraries/FBLazyVector/FBLazyVector.podspec +1 -1
- package/Libraries/Image/AssetSourceResolver.js +18 -27
- package/Libraries/Image/Image.android.js +13 -2
- package/Libraries/Image/Image.ios.js +3 -1
- package/Libraries/Image/ImageBackground.js +30 -18
- package/Libraries/Image/ImageProps.js +116 -117
- package/Libraries/Image/ImageSource.d.ts +1 -1
- package/Libraries/Image/ImageSource.js +9 -9
- package/Libraries/Image/ImageSourceUtils.js +10 -7
- package/Libraries/Image/ImageTypes.flow.js +2 -0
- package/Libraries/Image/ImageViewNativeComponent.js +1 -1
- package/Libraries/Image/RCTImageLoader.mm +61 -64
- package/Libraries/Image/RCTImageStoreManager.h +0 -2
- package/Libraries/Image/React-RCTImage.podspec +1 -1
- package/Libraries/Image/RelativeImageStub.js +1 -1
- package/Libraries/Image/resolveAssetSource.js +1 -1
- package/Libraries/Interaction/PanResponder.js +102 -97
- package/Libraries/LayoutAnimation/LayoutAnimation.js +22 -6
- package/Libraries/Linking/Linking.js +24 -23
- package/Libraries/LinkingIOS/React-RCTLinking.podspec +1 -1
- package/Libraries/Lists/FlatList.d.ts +6 -17
- package/Libraries/Lists/FlatList.js +7 -8
- package/Libraries/Lists/SectionList.js +7 -0
- package/Libraries/Lists/VirtualizedList.js +3 -0
- package/Libraries/Lists/VirtualizedSectionList.js +4 -0
- package/Libraries/LogBox/LogBox.js +3 -3
- package/Libraries/LogBox/UI/AnsiHighlight.js +2 -1
- package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.js +2 -2
- package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +4 -1
- package/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js +3 -1
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +8 -2
- package/Libraries/LogBox/UI/LogBoxInspectorMessageHeader.js +9 -2
- package/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js +17 -4
- package/Libraries/LogBox/UI/LogBoxInspectorSection.js +3 -1
- package/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js +3 -1
- package/Libraries/LogBox/UI/LogBoxInspectorStackFrame.js +2 -0
- package/Libraries/LogBox/UI/LogBoxInspectorStackFrames.js +4 -2
- package/Libraries/LogBox/UI/LogBoxMessage.js +18 -5
- package/Libraries/LogBox/UI/LogBoxNotificationCountBadge.js +4 -1
- package/Libraries/LogBox/UI/LogBoxNotificationMessage.js +1 -0
- package/Libraries/LogBox/UI/LogBoxStyle.js +0 -4
- package/Libraries/Modal/Modal.d.ts +5 -4
- package/Libraries/Modal/Modal.js +71 -37
- package/Libraries/Modal/RCTModalHostViewNativeComponent.js +2 -2
- package/Libraries/NativeAnimation/React-RCTAnimation.podspec +1 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +17 -0
- package/Libraries/NativeComponent/ViewConfig.js +3 -3
- package/Libraries/NativeComponent/ViewConfigIgnore.js +1 -1
- package/Libraries/Network/RCTHTTPRequestHandler.h +1 -1
- package/Libraries/Network/React-RCTNetwork.podspec +1 -1
- package/Libraries/Performance/Systrace.js +36 -0
- package/Libraries/PermissionsAndroid/PermissionsAndroid.d.ts +4 -2
- package/Libraries/PermissionsAndroid/PermissionsAndroid.js +29 -17
- package/Libraries/Pressability/Pressability.js +1 -1
- package/Libraries/PushNotificationIOS/PushNotificationIOS.js +4 -0
- package/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +1 -1
- package/Libraries/ReactNative/AppContainer-dev.js +3 -1
- package/Libraries/ReactNative/AppRegistry.flow.js +1 -0
- package/Libraries/ReactNative/AppRegistry.js +15 -11
- package/Libraries/ReactNative/AppRegistryImpl.js +57 -11
- package/Libraries/ReactNative/DisplayMode.js +1 -1
- package/Libraries/ReactNative/FabricUIManager.js +29 -26
- package/Libraries/ReactNative/I18nManager.js +20 -0
- package/Libraries/ReactNative/UIManager.js +53 -0
- package/Libraries/ReactNative/renderApplication.js +1 -1
- package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +5 -126
- package/Libraries/ReactPrivate/ReactNativePrivateInterface.js.flow +5 -41
- package/Libraries/Renderer/README.md +2 -2
- package/Libraries/Renderer/shims/ReactNativeTypes.js +36 -36
- package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +4 -4
- package/Libraries/Required/RCTRequired.podspec +1 -1
- package/Libraries/Settings/React-RCTSettings.podspec +1 -1
- package/Libraries/Settings/Settings.ios.js +22 -0
- package/Libraries/Share/Share.js +25 -28
- package/Libraries/StyleSheet/PlatformColorValueTypes.js.flow +6 -0
- package/Libraries/StyleSheet/StyleSheet.js +42 -2
- package/Libraries/StyleSheet/StyleSheet.js.flow +1 -1
- package/Libraries/StyleSheet/StyleSheetExports.js +7 -5
- package/Libraries/StyleSheet/StyleSheetExports.js.flow +1 -1
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +24 -3
- package/Libraries/StyleSheet/StyleSheetTypes.js +34 -6
- package/Libraries/StyleSheet/flattenStyle.js +28 -13
- package/Libraries/StyleSheet/private/_TransformStyle.js +16 -14
- package/Libraries/Text/React-RCTText.podspec +1 -1
- package/Libraries/Text/Text.js +12 -9
- package/Libraries/Text/TextEffectNativeComponent.js +31 -0
- package/Libraries/Text/TextInput/Multiline/RCTUITextView.mm +0 -1
- package/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +0 -1
- package/Libraries/Text/TextInput/Singleline/RCTUITextField.mm +0 -1
- package/Libraries/Text/TextProps.js +59 -93
- package/Libraries/Text/requireNativeTextEffect.js +28 -0
- package/Libraries/TurboModule/RCTExport.js +1 -1
- package/Libraries/TypeSafety/RCTTypeSafety.podspec +1 -1
- package/Libraries/Types/CoreEventTypes.d.ts +8 -0
- package/Libraries/Types/CoreEventTypes.js +32 -29
- package/Libraries/Types/UIManagerJSInterface.js +2 -2
- package/Libraries/Utilities/Appearance.d.ts +32 -17
- package/Libraries/Utilities/Appearance.js +35 -18
- package/Libraries/Utilities/BackHandler.android.js +13 -28
- package/Libraries/Utilities/BackHandler.js.flow +18 -2
- package/Libraries/Utilities/DevSettings.js +8 -1
- package/Libraries/Utilities/Dimensions.js +18 -12
- package/Libraries/Utilities/PixelRatio.js +5 -2
- package/Libraries/Utilities/Platform.js.flow +4 -0
- package/Libraries/Utilities/PlatformTypes.js +77 -0
- package/Libraries/Utilities/PolyfillFunctions.js +1 -1
- package/Libraries/Utilities/differ/deepDiffer.js +5 -2
- package/Libraries/Utilities/useColorScheme.js +11 -1
- package/Libraries/Utilities/useWindowDimensions.js +6 -0
- package/Libraries/Vibration/React-RCTVibration.podspec +1 -1
- package/Libraries/Vibration/Vibration.js +14 -11
- package/Libraries/vendor/emitter/EventEmitter.js +3 -3
- package/README.md +7 -9
- package/React/Base/RCTBridge+Private.h +0 -22
- package/React/Base/RCTBridge.h +10 -8
- package/React/Base/RCTBridge.mm +5 -447
- package/React/Base/RCTBridgeDelegate.h +1 -56
- package/React/Base/RCTBridgeModule.h +0 -9
- package/React/Base/RCTBridgeProxy.h +8 -0
- package/React/Base/RCTBridgeProxy.mm +3 -20
- package/React/Base/RCTBundleManager.h +0 -3
- package/React/Base/RCTBundleManager.m +0 -31
- package/React/Base/RCTBundleURLProvider.mm +4 -4
- package/React/Base/RCTCallableJSModules.m +0 -18
- package/React/Base/RCTConstants.h +1 -0
- package/React/Base/RCTConstants.m +1 -0
- package/React/Base/RCTConvert.mm +3 -0
- package/React/Base/RCTDisplayLink.h +3 -1
- package/React/Base/RCTJavaScriptExecutor.h +0 -69
- package/React/Base/RCTModuleData.mm +2 -483
- package/React/Base/RCTModuleRegistry.m +0 -25
- package/React/Base/RCTRootView.m +3 -374
- package/React/Base/RCTUtils.h +0 -3
- package/React/Base/RCTUtils.mm +17 -27
- package/React/Base/RCTVersion.m +2 -2
- package/React/Base/RCTViewRegistry.m +1 -29
- package/React/Base/Surface/RCTSurface.mm +1 -582
- package/React/Base/Surface/RCTSurfaceRootShadowView.m +0 -89
- package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +0 -1
- package/React/CoreModules/PlatformStubs/RCTStatusBarManager.mm +0 -2
- package/React/CoreModules/RCTAlertController.mm +1 -0
- package/React/CoreModules/RCTAlertManager.mm +0 -5
- package/React/CoreModules/RCTLogBox.mm +0 -11
- package/React/CoreModules/RCTLogBoxView.h +0 -3
- package/React/CoreModules/RCTLogBoxView.mm +0 -31
- package/React/CoreModules/RCTPerfMonitor.mm +0 -2
- package/React/CoreModules/RCTStatusBarManager.mm +0 -11
- package/React/CoreModules/React-CoreModules.podspec +1 -1
- package/React/CxxModule/RCTCxxUtils.h +0 -8
- package/React/CxxModule/RCTCxxUtils.mm +0 -17
- package/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm +179 -7
- package/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +100 -2
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +373 -119
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/ComponentDescriptors.cpp +1 -1
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/ComponentDescriptors.h +1 -1
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/EventEmitters.cpp +71 -71
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/EventEmitters.h +96 -96
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/Props.cpp +357 -363
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/Props.h +211 -212
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/RCTComponentViewHelpers.h +107 -107
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/ShadowNodes.cpp +1 -1
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/ShadowNodes.h +11 -11
- package/React/FBReactNativeSpec/react/renderer/components/FBReactNativeSpec/States.h +2 -2
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.h +4 -0
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +4 -0
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.h +4 -0
- package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm +5 -0
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +0 -1
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm +14 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +13 -4
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTVirtualViewContainerState.mm +12 -26
- package/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +39 -4
- package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +1 -1
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +5 -5
- package/React/Fabric/Mounting/ComponentViews/VirtualView/RCTVirtualViewComponentView.mm +0 -18
- package/React/Fabric/Mounting/RCTComponentViewFactory.mm +9 -5
- package/React/Fabric/RCTSurfacePresenter.mm +86 -5
- package/React/Fabric/RCTSurfacePresenterBridgeAdapter.h +2 -0
- package/React/I18n/RCTLocalizedString.mm +38 -2
- package/React/Modules/RCTEventEmitter.m +30 -10
- package/React/Modules/RCTI18nUtil.m +3 -1
- package/React/Modules/RCTUIManager.mm +0 -1501
- package/React/React-RCTFBReactNativeSpec.podspec +2 -2
- package/React/React-RCTFabric.podspec +1 -1
- package/React/Runtime/React-RCTRuntime.podspec +1 -1
- package/React/Tests/Text/RCTAttributedTextUtilsTest.mm +27 -0
- package/React/Views/RCTModalHostViewController.h +0 -15
- package/React/Views/RCTModalHostViewManager.h +0 -24
- package/React/Views/RCTShadowView.h +0 -2
- package/React/Views/RCTShadowView.m +0 -723
- package/React/Views/ScrollView/RCTScrollView.h +0 -81
- package/React/Views/ScrollView/RCTScrollableProtocol.h +0 -4
- package/React-Core-prebuilt.podspec +45 -17
- package/React-Core.podspec +10 -3
- package/React.podspec +1 -1
- package/ReactAndroid/api/ReactAndroid.api +128 -142
- package/ReactAndroid/build.gradle.kts +27 -22
- package/ReactAndroid/external-artifacts/build.gradle.kts +49 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/hermes-engine/build.gradle.kts +14 -14
- package/ReactAndroid/publish.gradle +5 -5
- package/ReactAndroid/src/debug/AndroidManifest.xml +6 -0
- package/ReactAndroid/src/debugOptimized/AndroidManifest.xml +22 -0
- package/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.kt +3 -7
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +4 -2
- package/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt +4 -6
- package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +0 -3
- package/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.kt +212 -0
- package/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +0 -16
- package/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.kt +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.kt +287 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +15 -2
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/interop/InteropModuleRegistry.kt +1 -3
- package/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.kt +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt +50 -2
- package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt +63 -22
- package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt +33 -0
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +4 -12
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt +14 -10
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +6 -6
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.kt +50 -47
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.kt +0 -4
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.kt +10 -10
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/LocalNetworkPermissionUtil.kt +49 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/MultipartStreamReader.kt +101 -26
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +40 -38
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt +1 -10
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerProviderImpl.kt +0 -3
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/ViewTransitionSnapshotManager.kt +15 -11
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.kt +7 -13
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.kt +160 -187
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/SynchronousMountItem.kt +12 -8
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +30 -66
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -111
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -23
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +12 -24
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +57 -123
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android.kt +7 -5
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt +3 -5
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -23
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeNewArchitectureFeatureFlags.kt +0 -24
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeNewArchitectureFeatureFlagsDefaults.kt +0 -4
- package/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/AppearanceModule.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.kt +3 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.kt +50 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt +8 -4
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt +53 -3
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt +2 -77
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.kt +9 -4
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +4 -19
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.kt +2 -6
- package/ReactAndroid/src/main/java/com/facebook/react/touch/ReactInterceptingViewGroup.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +47 -10
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.kt +1 -49
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/HasChildPressedStateDelay.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.kt +796 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.kt +2 -4
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.kt +27 -27
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.kt +184 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.kt +486 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNodeImpl.java +8 -8
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ShadowNodeRegistry.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/SkewMatrixHelper.kt +200 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.kt +3 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.kt +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIBlock.kt +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.kt +645 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.kt +2 -3
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.kt +142 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.kt +0 -10
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java +3 -3
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.kt +527 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt +3 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderRadiusStyle.kt +6 -6
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ColorStop.kt +6 -0
- package/ReactAndroid/src/main/java/com/facebook/react/util/AndroidVersion.kt +7 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayout.kt +8 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt +0 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/safeareaview/ReactSafeAreaView.kt +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.kt +1640 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.kt +6 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactNestedScrollView.kt +1317 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactNestedScrollViewManager.kt +8 -8
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.kt +1309 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt +7 -7
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/VirtualViewContainer.kt +19 -33
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/VirtualViewContainerStateClassic.kt +8 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/VirtualViewContainerStateExperimental.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/generate-nested-scroll-view.js +13 -20
- package/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout.kt +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/MutableSpannableLayout.kt +107 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/PreparedLayoutTextView.kt +122 -10
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +92 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt +3 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTypefaceUtils.kt +41 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt +48 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextDecorationStyle.kt +200 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextEffectRegistry.kt +45 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextEffectSpanFactory.kt +17 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt +361 -15
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/AnimatedEffectSpan.kt +37 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/{DrawCommandSpan.kt → CanvasEffectSpan.kt} +3 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt +23 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/ReactStrikethroughSpan.kt +30 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/ReactUnderlineSpan.kt +25 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/SetSpanOperation.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/StatefulSpan.kt +21 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/TextEffectSpan.kt +19 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/TouchableSpan.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt +83 -11
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt +6 -2
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextSelectionWatcher.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +3 -17
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +8 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/WindowUtil.kt +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/virtual/VirtualViewRenderState.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/virtual/view/ReactVirtualView.kt +7 -8
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.kt +45 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaBoxSizing.kt +27 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfig.kt +15 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaConfigJNIBase.kt +6 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.kt +27 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.kt +31 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.kt +41 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.kt +37 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.kt +27 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.kt +31 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaGridTrackType.kt +33 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaGutter.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.kt +43 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.kt +39 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNative.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt +12 -2
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt +762 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.kt +4 -4
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.kt +27 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.kt +29 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt +24 -2
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.kt +37 -0
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.kt +29 -0
- package/ReactAndroid/src/main/jni/CMakeLists.txt +1 -2
- package/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp +94 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JCxxInspectorPackagerConnectionDelegateImpl.cpp +3 -0
- package/ReactAndroid/src/main/jni/react/fabric/AndroidAnimationChoreographer.h +10 -10
- package/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp +3 -0
- package/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp +12 -15
- package/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h +1 -3
- package/ReactAndroid/src/main/jni/react/fabric/test/FabricMountingManagerTest.cpp +159 -0
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +69 -153
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +15 -33
- package/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp +10 -24
- package/ReactAndroid/src/main/jni/react/jni/JReactMarker.h +0 -2
- package/ReactAndroid/src/main/jni/react/mapbuffer/react/common/mapbuffer/JWritableMapBuffer.cpp +13 -0
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +4 -1
- package/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.cpp +8 -0
- package/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/TurboModuleManager.h +4 -0
- package/ReactAndroid/src/main/res/views/uimanager/values/ids.xml +5 -0
- package/ReactAndroid/src/main/res/views/uimanager/values-zu/strings.xml +3 -0
- package/ReactApple/Libraries/RCTFoundation/RCTDeprecation/RCTDeprecation.podspec +1 -1
- package/ReactApple/RCTAnimatedModuleProvider/React-RCTAnimatedModuleProvider.podspec +63 -0
- package/ReactApple/RCTSwiftUI/RCTSwiftUI.podspec +1 -1
- package/ReactApple/RCTSwiftUIWrapper/RCTSwiftUIWrapper.podspec +1 -1
- package/ReactCommon/React-Fabric.podspec +3 -1
- package/ReactCommon/React-FabricComponents.podspec +1 -1
- package/ReactCommon/React-FabricImage.podspec +1 -1
- package/ReactCommon/React-Mapbuffer.podspec +1 -1
- package/ReactCommon/ReactCommon.podspec +3 -13
- package/ReactCommon/callinvoker/React-callinvoker.podspec +1 -1
- package/ReactCommon/cmake-utils/react-native-flags.cmake +1 -3
- package/ReactCommon/cxxreact/CMakeLists.txt +1 -0
- package/ReactCommon/cxxreact/ErrorUtils.h +2 -32
- package/ReactCommon/cxxreact/Instance.cpp +1 -26
- package/ReactCommon/cxxreact/Instance.h +0 -2
- package/ReactCommon/cxxreact/NativeToJsBridge.cpp +3 -2
- package/ReactCommon/cxxreact/RAMBundleRegistry.cpp +0 -12
- package/ReactCommon/cxxreact/RAMBundleRegistry.h +0 -5
- package/ReactCommon/cxxreact/React-cxxreact.podspec +3 -2
- package/ReactCommon/cxxreact/ReactMarker.cpp +4 -30
- package/ReactCommon/cxxreact/ReactMarker.h +38 -21
- package/ReactCommon/cxxreact/ReactNativeVersion.h +4 -4
- package/ReactCommon/cxxreact/TraceSection.h +1 -1
- package/ReactCommon/cxxreact/tests/methodcall.cpp +4 -0
- package/ReactCommon/hermes/React-hermes.podspec +1 -1
- package/ReactCommon/hermes/executor/HermesExecutorFactory.cpp +6 -79
- package/ReactCommon/hermes/executor/React-jsitracing.podspec +1 -1
- package/ReactCommon/jserrorhandler/ErrorUtils.cpp +42 -0
- package/{React/CxxLogUtils/RCTDefaultCxxLogFunction.h → ReactCommon/jserrorhandler/ErrorUtils.h} +2 -2
- package/ReactCommon/jserrorhandler/JsErrorHandler.cpp +1 -1
- package/ReactCommon/jserrorhandler/React-jserrorhandler.podspec +3 -4
- package/ReactCommon/jsi/React-jsi.podspec +1 -1
- package/ReactCommon/jsi/jsi/hermes-interfaces.h +53 -0
- package/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +3 -2
- package/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp +3 -14
- package/ReactCommon/jsiexecutor/jsireact/JSINativeModules.cpp +4 -13
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +54 -0
- package/ReactCommon/jsinspector-modern/HostTarget.h +0 -7
- package/ReactCommon/jsinspector-modern/HostTargetTraceRecording.cpp +10 -7
- package/ReactCommon/jsinspector-modern/InspectorPackagerConnection.cpp +4 -1
- package/ReactCommon/jsinspector-modern/React-jsinspector.podspec +1 -1
- package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +7 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +20 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.h +16 -0
- package/ReactCommon/jsinspector-modern/SessionState.h +31 -0
- package/ReactCommon/jsinspector-modern/cdp/React-jsinspectorcdp.podspec +1 -1
- package/ReactCommon/jsinspector-modern/network/React-jsinspectornetwork.podspec +1 -1
- package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +53 -0
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfile.h +14 -1
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceRecordingState.h +11 -0
- package/ReactCommon/jsitooling/React-jsitooling.podspec +1 -1
- package/ReactCommon/logger/React-logger.podspec +1 -1
- package/ReactCommon/oscompat/React-oscompat.podspec +1 -1
- package/ReactCommon/react/bridging/ArrayBuffer.h +180 -0
- package/ReactCommon/react/bridging/Bridging.h +1 -0
- package/ReactCommon/react/bridging/Convert.h +12 -0
- package/ReactCommon/react/bridging/React-bridging.podspec +44 -0
- package/ReactCommon/react/bridging/tests/BridgingTest.cpp +185 -11
- package/ReactCommon/react/bridging/tests/ClassTest.cpp +22 -0
- package/ReactCommon/react/cxxstableapi/CMakeLists.txt +18 -0
- package/ReactCommon/react/cxxstableapi/FrameworksGuard.h +35 -0
- package/ReactCommon/react/cxxstableapi/PrivateGuard.h +34 -0
- package/ReactCommon/react/cxxstableapi/React-cxxstableapi.podspec +34 -0
- package/ReactCommon/react/cxxstableapi/UmbrellaGuard.h +53 -0
- package/ReactCommon/react/debug/React-debug.podspec +1 -1
- package/ReactCommon/react/debug/redbox/JscSafeUrl.h +1 -1
- package/ReactCommon/react/featureflags/React-featureflags.podspec +1 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -45
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -56
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +134 -242
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +14 -26
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +20 -44
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +43 -97
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.h +10 -6
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSExperimental.h +3 -7
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSStable.h +0 -8
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +7 -13
- package/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +1 -0
- package/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm +49 -0
- package/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.cpp +4 -0
- package/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h +4 -0
- package/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp +2 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/React-NativeModulesApple.podspec +2 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h +4 -0
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +5 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +61 -4
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +0 -9
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +37 -139
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleWithJSIBindings.h +0 -3
- package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +6 -0
- package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/dom/NativeDOM.cpp +10 -4
- package/ReactCommon/react/nativemodule/dom/React-domnativemodule.podspec +2 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +25 -55
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -23
- package/ReactCommon/react/nativemodule/featureflags/React-featureflagsnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/idlecallbacks/React-idlecallbacksnativemodule.podspec +2 -1
- package/ReactCommon/react/nativemodule/intersectionobserver/React-intersectionobservernativemodule.podspec +2 -1
- package/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.cpp +4 -0
- package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +2 -1
- package/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec +1 -1
- package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h +1 -1
- package/ReactCommon/react/nativemodule/viewtransition/React-viewtransitionnativemodule.podspec +1 -1
- package/ReactCommon/react/nativemodule/webperformance/React-webperformancenativemodule.podspec +2 -1
- package/ReactCommon/react/networking/React-networking.podspec +1 -1
- package/ReactCommon/react/performance/cdpmetrics/React-performancecdpmetrics.podspec +1 -1
- package/ReactCommon/react/performance/timeline/React-performancetimeline.podspec +1 -1
- package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp +95 -63
- package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h +20 -1
- package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp +7 -10
- package/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.cpp +20 -1
- package/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.h +1 -0
- package/ReactCommon/react/renderer/animated/internal/primitives.h +1 -1
- package/ReactCommon/react/renderer/animated/nodes/InterpolationAnimatedNode.cpp +67 -6
- package/ReactCommon/react/renderer/animated/nodes/InterpolationAnimatedNode.h +12 -0
- package/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.cpp +25 -13
- package/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.h +7 -0
- package/ReactCommon/react/renderer/animated/tests/AnimationDriverTests.cpp +48 -0
- package/ReactCommon/react/renderer/animated/tests/DecayAnimationDriverTest.cpp +245 -0
- package/ReactCommon/react/renderer/animated/tests/ManagedPropsMountingOverrideTests.cpp +204 -0
- package/ReactCommon/react/renderer/animationbackend/AnimatedPropsRegistry.cpp +10 -1
- package/ReactCommon/react/renderer/animationbackend/AnimatedPropsRegistry.h +1 -0
- package/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp +17 -0
- package/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp +0 -2
- package/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +6 -2
- package/ReactCommon/react/renderer/attributedstring/TextAttributes.h +25 -1
- package/ReactCommon/react/renderer/attributedstring/conversions.h +29 -1
- package/ReactCommon/react/renderer/attributedstring/primitives.h +4 -2
- package/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp +73 -0
- package/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +6 -0
- package/ReactCommon/react/renderer/components/image/ImageProps.cpp +79 -126
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.cpp +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropShadowNode.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropState.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp +5 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.cpp +5 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticComponentDescriptor.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.cpp +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerAutomaticShadowNode.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/UnstableLegacyViewManagerInteropComponentDescriptor.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/platform/ios/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/platform/ios/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm +5 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/platform/ios/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h +4 -0
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/platform/ios/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm +5 -0
- package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp +235 -352
- package/ReactCommon/react/renderer/components/scrollview/platform/android/react/renderer/components/scrollview/HostPlatformScrollViewProps.cpp +30 -46
- package/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp +17 -27
- package/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +8 -10
- package/ReactCommon/react/renderer/components/text/BaseTextShadowNode.cpp +19 -0
- package/ReactCommon/react/renderer/components/text/TextEffectComponentDescriptor.h +17 -0
- package/ReactCommon/react/renderer/components/text/TextEffectProps.cpp +59 -0
- package/ReactCommon/react/renderer/components/text/TextEffectProps.h +30 -0
- package/{Libraries/Text/VirtualText/RCTVirtualTextView.mm → ReactCommon/react/renderer/components/text/TextEffectShadowNode.cpp} +4 -6
- package/ReactCommon/react/renderer/components/text/TextEffectShadowNode.h +26 -0
- package/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/HostPlatformParagraphProps.cpp +18 -28
- package/ReactCommon/react/renderer/components/text/tests/BaseTextShadowNodeTest.cpp +15 -0
- package/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +42 -50
- package/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +168 -754
- package/ReactCommon/react/renderer/components/view/AccessibilityProps.h +0 -9
- package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +248 -312
- package/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +0 -6
- package/ReactCommon/react/renderer/components/view/ViewShadowNode.h +2 -12
- package/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +73 -27
- package/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h +7 -9
- package/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +3 -11
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +82 -162
- package/ReactCommon/react/renderer/components/view/primitives.h +5 -0
- package/ReactCommon/react/renderer/components/view/propsConversions.h +74 -42
- package/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +5 -5
- package/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp +353 -6
- package/ReactCommon/react/renderer/consistency/React-rendererconsistency.podspec +1 -1
- package/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +41 -16
- package/ReactCommon/react/renderer/core/ConcreteShadowNode.h +19 -0
- package/ReactCommon/react/renderer/core/EventEmitter.cpp +20 -4
- package/ReactCommon/react/renderer/core/LayoutMetrics.h +3 -0
- package/ReactCommon/react/renderer/core/Props.cpp +8 -39
- package/ReactCommon/react/renderer/core/Props.h +63 -13
- package/ReactCommon/react/renderer/core/RawProps.cpp +20 -3
- package/ReactCommon/react/renderer/core/RawProps.h +44 -0
- package/ReactCommon/react/renderer/core/RawPropsKeyMap.cpp +11 -27
- package/ReactCommon/react/renderer/core/RawPropsKeyMap.h +3 -3
- package/ReactCommon/react/renderer/core/RawPropsParser.cpp +4 -6
- package/ReactCommon/react/renderer/core/RawPropsParser.h +3 -3
- package/ReactCommon/react/renderer/core/StateData.h +4 -4
- package/ReactCommon/react/renderer/core/propsConversions.h +3 -7
- package/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp +8 -0
- package/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp +7 -7
- package/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp +19 -19
- package/ReactCommon/react/renderer/core/tests/PropsConceptsTest.cpp +135 -0
- package/ReactCommon/react/renderer/core/tests/RawPropsTest.cpp +43 -53
- package/ReactCommon/react/renderer/css/React-renderercss.podspec +1 -1
- package/ReactCommon/react/renderer/debug/React-rendererdebug.podspec +1 -1
- package/ReactCommon/react/renderer/element/tests/ElementTest.cpp +3 -3
- package/ReactCommon/react/renderer/graphics/React-graphics.podspec +1 -1
- package/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/conversions.h +17 -0
- package/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec +1 -1
- package/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.mm +1 -1
- package/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp +123 -33
- package/ReactCommon/react/renderer/mapbuffer/MapBuffer.h +26 -14
- package/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp +96 -53
- package/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h +4 -0
- package/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp +96 -1
- package/ReactCommon/react/renderer/mounting/Differentiator.cpp +29 -318
- package/ReactCommon/react/renderer/mounting/ShadowTree.cpp +105 -33
- package/ReactCommon/react/renderer/mounting/ShadowTree.h +2 -0
- package/ReactCommon/react/renderer/mounting/internal/CullingContext.cpp +1 -1
- package/ReactCommon/react/renderer/mounting/tests/DifferentiatorUnflattenTest.cpp +11 -3
- package/ReactCommon/react/renderer/mounting/tests/OrderIndexTest.cpp +1 -1
- package/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp +15 -250
- package/ReactCommon/react/renderer/mounting/tests/ShadowTreeReactBranchingTest.cpp +141 -0
- package/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +1 -1
- package/ReactCommon/react/renderer/runtimescheduler/CMakeLists.txt +1 -0
- package/ReactCommon/react/renderer/runtimescheduler/React-runtimescheduler.podspec +2 -1
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +22 -2
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +13 -2
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp +13 -0
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h +9 -0
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +43 -5
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h +17 -1
- package/ReactCommon/react/renderer/runtimescheduler/Task.h +4 -0
- package/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +113 -8
- package/ReactCommon/react/renderer/scheduler/Scheduler.cpp +14 -6
- package/ReactCommon/react/renderer/scheduler/Scheduler.h +3 -2
- package/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp +1 -85
- package/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +0 -6
- package/ReactCommon/react/renderer/scheduler/tests/SchedulerDelegateInvalidationTest.cpp +671 -0
- package/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h +22 -5
- package/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp +4 -2
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +11 -0
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +65 -26
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm +1 -1
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +193 -1
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h +14 -2
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm +2 -1
- package/ReactCommon/react/renderer/textlayoutmanager/tests/TextLayoutManagerTest.cpp +86 -5
- package/ReactCommon/react/renderer/uimanager/UIManager.cpp +31 -41
- package/ReactCommon/react/renderer/uimanager/UIManager.h +2 -2
- package/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h +1 -1
- package/ReactCommon/react/renderer/uimanager/tests/FindShadowNodeByTagTest.cpp +1 -52
- package/ReactCommon/react/renderer/uimanager/tests/PointerEventsProcessorTest.cpp +4 -4
- package/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp +88 -39
- package/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h +12 -2
- package/ReactCommon/react/runtime/PlatformTimerRegistry.h +10 -0
- package/ReactCommon/react/runtime/React-RuntimeCore.podspec +1 -1
- package/ReactCommon/react/runtime/React-RuntimeHermes.podspec +1 -1
- package/ReactCommon/react/runtime/ReactInstance.cpp +79 -64
- package/ReactCommon/react/runtime/hermes/HermesInstance.cpp +0 -89
- package/ReactCommon/react/runtime/iostests/MainQueueCoordinatorTests.mm +99 -0
- package/ReactCommon/react/runtime/iostests/RCTInstanceTests.mm +244 -0
- package/ReactCommon/react/runtime/platform/ios/React-RuntimeApple.podspec +1 -1
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/ObjCTimerRegistry.h +1 -1
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +47 -30
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTJscInstance.mm +3 -2
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTPerformanceLoggerUtils.mm +3 -2
- package/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +27 -3
- package/ReactCommon/react/runtime/tests/cxx/RuntimeExecutorShutdownTest.cpp +155 -0
- package/ReactCommon/react/timing/React-timing.podspec +1 -1
- package/ReactCommon/react/utils/React-utils.podspec +1 -1
- package/ReactCommon/react/utils/Telemetry.h +0 -13
- package/ReactCommon/react/utils/tests/Base64Tests.cpp +36 -0
- package/ReactCommon/reactperflogger/React-perflogger.podspec +1 -1
- package/ReactCommon/reactperflogger/reactperflogger/ReactPerfettoLogger.cpp +0 -1
- package/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec +1 -1
- package/ReactCommon/runtimeexecutor/platform/ios/ReactCommon/RuntimeExecutorSyncUIThreadUtils.mm +21 -38
- package/ReactCommon/yoga/Yoga.podspec +2 -2
- package/ReactCommon/yoga/yoga/YGEnums.cpp +2 -0
- package/ReactCommon/yoga/yoga/YGEnums.h +1 -0
- package/ReactCommon/yoga/yoga/YGNode.cpp +27 -0
- package/ReactCommon/yoga/yoga/YGNode.h +69 -0
- package/ReactCommon/yoga/yoga/YGNodeLayout.h +0 -2
- package/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +283 -10
- package/ReactCommon/yoga/yoga/config/Config.h +1 -1
- package/ReactCommon/yoga/yoga/enums/Errata.h +1 -0
- package/ReactCommon/yoga/yoga/node/LayoutResults.h +8 -0
- package/ReactCommon/yoga/yoga/node/Node.cpp +32 -0
- package/ReactCommon/yoga/yoga/node/Node.h +33 -0
- package/changes.json +6 -14
- package/cli.js +3 -182
- package/flow/bom.js.flow +42 -42
- package/flow/cssom.js.flow +21 -21
- package/flow/dom.js.flow +128 -128
- package/flow/global.js +6 -0
- package/gradle/libs.versions.toml +7 -5
- package/index.js +53 -86
- package/index.js.flow +53 -23
- package/package.json +47 -66
- package/react-native.config.js +82 -1
- package/scripts/cocoapods/fabric.rb +1 -1
- package/scripts/cocoapods/jsengine.rb +1 -1
- package/scripts/cocoapods/new_architecture.rb +1 -1
- package/scripts/cocoapods/rncore.rb +36 -78
- package/scripts/cocoapods/rncore_facades.rb +232 -0
- package/scripts/cocoapods/rndependencies.rb +83 -16
- package/scripts/cocoapods/rndeps_facades.rb +193 -0
- package/scripts/cocoapods/spm.rb +79 -12
- package/scripts/cocoapods/utils.rb +7 -9
- package/scripts/codegen/generate-artifacts-executor/generateSchemaInfos.js +0 -1
- package/scripts/codegen/templates/Package.swift.spm-template +97 -0
- package/scripts/codegen/templates/ReactAppDependencyProvider.podspec.template +1 -1
- package/scripts/codegen/templates/ReactCodegen.podspec.template +2 -2
- package/scripts/hermes/hermes-utils.js +27 -58
- package/scripts/ios-configure-glog.sh +1 -1
- package/scripts/react-native-xcode.sh +20 -0
- package/scripts/react_native_pods.rb +71 -21
- package/scripts/react_native_pods_utils/script_phases.sh +4 -3
- package/scripts/replace-rncore-version.js +75 -88
- package/scripts/setup-apple-spm.js +1283 -0
- package/scripts/spm/autolinking-plugins.js +411 -0
- package/scripts/spm/download-spm-artifacts.js +1467 -0
- package/scripts/spm/expand-spm-dependencies.js +435 -0
- package/scripts/spm/flavored-frameworks.js +1008 -0
- package/scripts/spm/generate-spm-autolinking-config.js +221 -0
- package/scripts/spm/generate-spm-autolinking.js +2005 -0
- package/scripts/spm/generate-spm-package.js +314 -0
- package/scripts/spm/generate-spm-xcodeproj.js +2790 -0
- package/scripts/spm/read-podspec.js +695 -0
- package/scripts/spm/scaffold-package-swift.js +1247 -0
- package/scripts/spm/spm-pbxproj.js +784 -0
- package/scripts/spm/spm-types.js +546 -0
- package/scripts/spm/spm-utils.js +760 -0
- package/scripts/spm/sync-spm-autolinking.js +160 -0
- package/sdks/.hermesv1version +1 -1
- package/sdks/hermes-engine/hermes-engine.podspec +9 -39
- package/sdks/hermes-engine/hermes-utils.rb +19 -73
- package/sdks/hermes-engine/utils/replace_hermes_version.js +18 -4
- package/sdks/hermes-engine/version.properties +1 -2
- package/settings.gradle.kts +0 -43
- package/src/asset-registry.js +29 -0
- package/src/private/animated/NativeAnimatedHelper.js +45 -21
- package/src/private/assets/AssetRegistry.js +52 -0
- package/src/private/{specs_DEPRECATED/components → components/activityindicator/specs}/ActivityIndicatorViewNativeComponent.js +5 -5
- package/src/private/{specs_DEPRECATED/components → components/debuggingoverlay/specs}/DebuggingOverlayNativeComponent.js +8 -8
- package/src/private/{specs_DEPRECATED/components → components/drawerlayoutandroid/specs}/AndroidDrawerLayoutNativeComponent.js +8 -8
- package/src/private/{specs_DEPRECATED/components → components/inputaccessoryview/specs}/RCTInputAccessoryViewNativeComponent.js +4 -4
- package/src/private/{specs_DEPRECATED/components → components/modal/specs}/RCTModalHostViewNativeComponent.js +4 -9
- package/src/private/{specs_DEPRECATED/components → components/progressbarandroid/specs}/ProgressBarAndroidNativeComponent.js +5 -5
- package/src/private/{specs_DEPRECATED/components → components/refreshcontrol/specs}/AndroidSwipeRefreshLayoutNativeComponent.js +7 -7
- package/src/private/{specs_DEPRECATED/components → components/refreshcontrol/specs}/PullToRefreshViewNativeComponent.js +7 -7
- package/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js +2 -2
- package/src/private/{specs_DEPRECATED/components → components/safeareaview/specs}/RCTSafeAreaViewNativeComponent.js +3 -3
- package/src/private/components/scrollview/HScrollViewNativeComponents.js +1 -1
- package/src/private/{specs_DEPRECATED/components → components/scrollview/specs}/AndroidHorizontalScrollContentViewNativeComponent.js +3 -3
- package/src/private/{specs_DEPRECATED/components → components/switch/specs}/AndroidSwitchNativeComponent.js +7 -7
- package/src/private/{specs_DEPRECATED/components → components/switch/specs}/SwitchNativeComponent.js +10 -7
- package/src/private/{specs_DEPRECATED/components → components/unimplementedview/specs}/UnimplementedNativeViewNativeComponent.js +4 -4
- package/src/private/components/virtualcollection/Virtual.js +5 -5
- package/src/private/components/virtualcollection/VirtualCollectionView.js +2 -6
- package/src/private/components/virtualcollection/column/VirtualColumn.js +1 -1
- package/src/private/components/virtualcollection/row/VirtualRow.js +1 -1
- package/src/private/devsupport/devmenu/elementinspector/Inspector.js +3 -1
- package/src/private/devsupport/devmenu/specs/NativeDevMenu.js +4 -4
- package/src/private/devsupport/rndevtools/specs/NativeReactDevToolsRuntimeSettingsModule.js +4 -2
- package/src/private/devsupport/rndevtools/specs/NativeReactDevToolsSettingsManager.js +2 -2
- package/src/private/featureflags/ReactNativeFeatureFlags.js +46 -70
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +88 -94
- package/src/private/renderer/errorhandling/ErrorHandlers.js +2 -2
- package/src/private/renderer/events/ReactNativeResponder.js +49 -4
- package/src/private/renderer/events/ResponderTouchHistoryStore.js +11 -2
- package/src/private/renderer/events/dispatchNativeEvent.js +71 -36
- package/src/private/setup/setUpDOM.js +19 -9
- package/src/private/setup/setUpIntersectionObserver.js +7 -0
- package/src/private/setup/setUpMutationObserver.js +3 -1
- package/src/private/specs_DEPRECATED/modules/NativeAccessibilityInfo.js +9 -9
- package/src/private/specs_DEPRECATED/modules/NativeAccessibilityManager.js +24 -24
- package/src/private/specs_DEPRECATED/modules/NativeActionSheetManager.js +28 -28
- package/src/private/specs_DEPRECATED/modules/NativeAlertManager.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js +45 -25
- package/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js +44 -24
- package/src/private/specs_DEPRECATED/modules/NativeAppState.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeAppearance.js +8 -6
- package/src/private/specs_DEPRECATED/modules/NativeBlobModule.js +7 -7
- package/src/private/specs_DEPRECATED/modules/NativeClipboard.js +3 -3
- package/src/private/specs_DEPRECATED/modules/NativeDevLoadingView.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeDevSettings.js +11 -11
- package/src/private/specs_DEPRECATED/modules/NativeDeviceEventManager.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeDeviceInfo.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeDialogManagerAndroid.js +7 -7
- package/src/private/specs_DEPRECATED/modules/NativeExceptionsManager.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeFileReaderModule.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeFrameRateLogger.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeHeadlessJsTaskSupport.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeI18nManager.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeImageEditor.js +13 -13
- package/src/private/specs_DEPRECATED/modules/NativeImageLoaderAndroid.js +9 -6
- package/src/private/specs_DEPRECATED/modules/NativeImageLoaderIOS.js +6 -6
- package/src/private/specs_DEPRECATED/modules/NativeImageStoreAndroid.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeImageStoreIOS.js +8 -5
- package/src/private/specs_DEPRECATED/modules/NativeIntentAndroid.js +5 -5
- package/src/private/specs_DEPRECATED/modules/NativeJSCHeapCapture.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeKeyboardObserver.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeLinkingManager.js +6 -6
- package/src/private/specs_DEPRECATED/modules/NativeLogBox.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeModalManager.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeNetworkingAndroid.js +5 -5
- package/src/private/specs_DEPRECATED/modules/NativeNetworkingIOS.js +6 -6
- package/src/private/specs_DEPRECATED/modules/NativePermissionsAndroid.js +6 -4
- package/src/private/specs_DEPRECATED/modules/NativePlatformConstantsAndroid.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativePlatformConstantsIOS.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS.js +35 -31
- package/src/private/specs_DEPRECATED/modules/NativeRedBox.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeSampleTurboModule.js +24 -24
- package/src/private/specs_DEPRECATED/modules/NativeSegmentFetcher.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeSettingsManager.js +3 -3
- package/src/private/specs_DEPRECATED/modules/NativeShareModule.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeSoundManager.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeSourceCode.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerAndroid.js +5 -17
- package/src/private/specs_DEPRECATED/modules/NativeStatusBarManagerIOS.js +10 -15
- package/src/private/specs_DEPRECATED/modules/NativeTiming.js +3 -3
- package/src/private/specs_DEPRECATED/modules/NativeToastAndroid.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeUIManager.js +35 -22
- package/src/private/specs_DEPRECATED/modules/NativeVibration.js +4 -4
- package/src/private/specs_DEPRECATED/modules/NativeWebSocketModule.js +7 -7
- package/src/private/types/HostInstance.js +38 -80
- package/src/private/viewtransition/specs/NativeViewTransition.js +6 -4
- package/src/private/webapis/dom/abort-api/AbortController.js +92 -0
- package/src/private/webapis/dom/abort-api/AbortSignal.js +243 -0
- package/src/private/webapis/dom/events/CustomEvent.js +1 -1
- package/src/private/webapis/dom/events/Event.js +12 -12
- package/src/private/webapis/dom/events/EventTarget.js +146 -37
- package/src/private/webapis/dom/events/internals/EventInternals.js +36 -0
- package/src/private/webapis/dom/events/internals/EventTargetInternals.js +38 -3
- package/src/private/webapis/dom/nodes/ReactNativeDocument.js +11 -0
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +105 -4
- package/src/private/webapis/dom/nodes/ReadOnlyCharacterData.js +11 -0
- package/src/private/webapis/dom/nodes/ReadOnlyElement.js +9 -0
- package/src/private/webapis/dom/nodes/ReadOnlyNode.js +34 -7
- package/src/private/webapis/dom/nodes/ReadOnlyText.js +33 -0
- package/src/private/webapis/dom/nodes/specs/NativeDOM.js +46 -42
- package/src/private/webapis/dom/oldstylecollections/HTMLCollection.js +12 -0
- package/src/private/webapis/dom/oldstylecollections/HTMLCollection.js.flow +4 -2
- package/src/private/webapis/dom/oldstylecollections/NodeList.js +10 -0
- package/src/private/webapis/dom/oldstylecollections/NodeList.js.flow +4 -3
- package/src/private/webapis/errors/DOMException.js +50 -50
- package/src/private/webapis/geometry/DOMRectList.js +12 -0
- package/src/private/webapis/geometry/DOMRectList.js.flow +3 -1
- package/src/private/webapis/html/events/MessageEvent.js +3 -3
- package/src/private/webapis/idlecallbacks/specs/NativeIdleCallbacks.js +2 -2
- package/src/private/webapis/intersectionobserver/IntersectionObserverEntry.js +13 -0
- package/src/private/webapis/intersectionobserver/internals/IntersectionObserverManager.js +3 -7
- package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +5 -5
- package/src/private/webapis/microtasks/specs/NativeMicrotasks.js +1 -1
- package/src/private/webapis/mutationobserver/MutationObserver.js +7 -7
- package/src/private/webapis/mutationobserver/MutationRecord.js +12 -0
- package/src/private/webapis/mutationobserver/internals/MutationObserverManager.js +5 -7
- package/src/private/webapis/mutationobserver/specs/NativeMutationObserver.js +5 -5
- package/src/private/webapis/performance/EventTiming.js +3 -3
- package/src/private/webapis/performance/PerformanceEntry.js +3 -3
- package/src/private/webapis/performance/PerformanceObserver.js +4 -4
- package/src/private/webapis/performance/ResourceTiming.js +13 -13
- package/src/private/webapis/performance/UserTiming.js +3 -3
- package/src/private/webapis/performance/internals/Utilities.js +1 -1
- package/src/private/webapis/performance/specs/NativePerformance.js +26 -20
- package/src/private/webapis/utils/ArrayLikeUtils.js +1 -1
- package/src/private/webapis/websockets/events/CloseEvent.js +3 -3
- package/src/private/webapis/xhr/events/ProgressEvent.js +3 -3
- package/src/react-private-interface.js +145 -0
- package/src/react-private-interface.js.flow +48 -0
- package/src/setup-env.js +22 -0
- package/src/types/globals.d.ts +35 -3
- package/src/unstable-internals-do-not-use.d.ts +214 -0
- package/src/unstable-internals-do-not-use.js +76 -0
- package/third-party-podspecs/RCT-Folly.podspec +1 -1
- package/third-party-podspecs/ReactNativeDependencies.podspec +3 -3
- package/third-party-podspecs/glog.podspec +1 -1
- package/types/index.d.ts +0 -1
- package/types/public/DeprecatedPropertiesAlias.d.ts +0 -4
- package/types/public/ReactNativeTypes.d.ts +6 -4
- package/types_generated/Libraries/ActionSheetIOS/ActionSheetIOS.d.ts +26 -31
- package/types_generated/Libraries/Alert/Alert.d.ts +44 -7
- package/types_generated/Libraries/Animated/AnimatedEvent.d.ts +2 -2
- package/types_generated/Libraries/Animated/AnimatedExports.d.ts +2 -2
- package/types_generated/Libraries/Animated/AnimatedImplementation.d.ts +108 -4
- package/types_generated/Libraries/Animated/Easing.d.ts +5 -4
- package/types_generated/Libraries/Animated/animations/Animation.d.ts +7 -7
- package/types_generated/Libraries/Animated/animations/DecayAnimation.d.ts +5 -5
- package/types_generated/Libraries/Animated/animations/SpringAnimation.d.ts +49 -49
- package/types_generated/Libraries/Animated/animations/TimingAnimation.d.ts +13 -13
- package/types_generated/Libraries/Animated/components/AnimatedFlatList.d.ts +3 -3
- package/types_generated/Libraries/Animated/components/AnimatedScrollView.d.ts +2 -2
- package/types_generated/Libraries/Animated/components/AnimatedSectionList.d.ts +3 -3
- package/types_generated/Libraries/Animated/createAnimatedComponent.d.ts +4 -4
- package/types_generated/Libraries/Animated/nodes/AnimatedColor.d.ts +2 -2
- package/types_generated/Libraries/Animated/nodes/AnimatedInterpolation.d.ts +9 -9
- package/types_generated/Libraries/Animated/nodes/AnimatedNode.d.ts +6 -3
- package/types_generated/Libraries/Animated/nodes/AnimatedValue.d.ts +3 -3
- package/types_generated/Libraries/AppState/AppState.d.ts +41 -22
- package/types_generated/Libraries/BatchedBridge/NativeModules.d.ts +8 -1
- package/types_generated/Libraries/Blob/BlobTypes.d.ts +4 -4
- package/types_generated/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts +37 -46
- package/types_generated/Libraries/Components/ActivityIndicator/ActivityIndicator.d.ts +92 -43
- package/types_generated/Libraries/Components/Button.d.ts +118 -197
- package/types_generated/Libraries/Components/Clipboard/Clipboard.d.ts +6 -1
- package/types_generated/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidTypes.d.ts +44 -63
- package/types_generated/Libraries/Components/Keyboard/Keyboard.d.ts +30 -61
- package/types_generated/Libraries/Components/Keyboard/KeyboardAvoidingView.d.ts +30 -21
- package/types_generated/Libraries/Components/Pressable/Pressable.d.ts +41 -17
- package/types_generated/Libraries/Components/Pressable/useAndroidRippleForView.d.ts +6 -6
- package/types_generated/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.d.ts +5 -5
- package/types_generated/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidTypes.d.ts +18 -1
- package/types_generated/Libraries/Components/RefreshControl/RefreshControl.d.ts +35 -52
- package/types_generated/Libraries/Components/SafeAreaView/SafeAreaView.d.ts +9 -11
- package/types_generated/Libraries/Components/ScrollView/ScrollView.d.ts +212 -88
- package/types_generated/Libraries/Components/ScrollView/ScrollViewStickyHeader.d.ts +4 -4
- package/types_generated/Libraries/Components/StatusBar/StatusBar.d.ts +29 -62
- package/types_generated/Libraries/Components/Switch/Switch.d.ts +75 -70
- package/types_generated/Libraries/Components/TextInput/InputAccessoryView.d.ts +16 -65
- package/types_generated/Libraries/Components/TextInput/TextInput.d.ts +118 -3
- package/types_generated/Libraries/Components/TextInput/TextInput.flow.d.ts +24 -9
- package/types_generated/Libraries/Components/ToastAndroid/ToastAndroid.d.ts +18 -18
- package/types_generated/Libraries/Components/Touchable/TouchableHighlight.d.ts +24 -13
- package/types_generated/Libraries/Components/Touchable/TouchableNativeFeedback.d.ts +27 -64
- package/types_generated/Libraries/Components/Touchable/TouchableOpacity.d.ts +18 -6
- package/types_generated/Libraries/Components/Touchable/TouchableWithoutFeedback.d.ts +28 -28
- package/types_generated/Libraries/Components/View/View.d.ts +13 -9
- package/types_generated/Libraries/Components/View/ViewAccessibility.d.ts +31 -20
- package/types_generated/Libraries/Components/View/ViewNativeComponent.d.ts +1 -2
- package/types_generated/Libraries/Components/View/ViewPropTypes.d.ts +75 -24
- package/types_generated/Libraries/Core/ExtendedError.d.ts +10 -10
- package/types_generated/Libraries/EventEmitter/NativeEventEmitter.d.ts +34 -1
- package/types_generated/Libraries/EventEmitter/RCTNativeAppEventEmitter.d.ts +4 -1
- package/types_generated/Libraries/Image/AssetSourceResolver.d.ts +2 -13
- package/types_generated/Libraries/Image/ImageBackground.d.ts +33 -22
- package/types_generated/Libraries/Image/ImageProps.d.ts +201 -251
- package/types_generated/Libraries/Image/ImageTypes.flow.d.ts +6 -5
- package/types_generated/Libraries/Interaction/PanResponder.d.ts +103 -97
- package/types_generated/Libraries/LayoutAnimation/LayoutAnimation.d.ts +18 -7
- package/types_generated/Libraries/Linking/Linking.d.ts +28 -20
- package/types_generated/Libraries/Lists/FlatList.d.ts +17 -18
- package/types_generated/Libraries/Lists/SectionList.d.ts +10 -5
- package/types_generated/Libraries/Lists/VirtualizedList.d.ts +3 -1
- package/types_generated/Libraries/Lists/VirtualizedSectionList.d.ts +3 -1
- package/types_generated/Libraries/LogBox/Data/LogBoxData.d.ts +2 -2
- package/types_generated/Libraries/LogBox/Data/LogBoxLog.d.ts +2 -2
- package/types_generated/Libraries/LogBox/Data/parseLogBoxLog.d.ts +2 -2
- package/types_generated/Libraries/LogBox/LogBox.d.ts +4 -1
- package/types_generated/Libraries/Modal/Modal.d.ts +70 -35
- package/types_generated/Libraries/Network/FormData.d.ts +5 -5
- package/types_generated/Libraries/Performance/Systrace.d.ts +11 -1
- package/types_generated/Libraries/PermissionsAndroid/PermissionsAndroid.d.ts +31 -21
- package/types_generated/Libraries/Pressability/Pressability.d.ts +5 -5
- package/types_generated/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts +15 -11
- package/types_generated/Libraries/ReactNative/AppRegistry.flow.d.ts +5 -5
- package/types_generated/Libraries/ReactNative/AppRegistryImpl.d.ts +56 -9
- package/types_generated/Libraries/ReactNative/I18nManager.d.ts +20 -1
- package/types_generated/Libraries/ReactNative/IPerformanceLogger.flow.d.ts +5 -5
- package/types_generated/Libraries/ReactPrivate/ReactNativePrivateInterface.d.ts +6 -22
- package/types_generated/Libraries/Renderer/shims/ReactNativeTypes.d.ts +34 -34
- package/types_generated/Libraries/Share/Share.d.ts +36 -39
- package/types_generated/Libraries/StyleSheet/PlatformColorValueTypes.d.ts +7 -1
- package/types_generated/Libraries/StyleSheet/PlatformColorValueTypesIOS.d.ts +3 -3
- package/types_generated/Libraries/StyleSheet/StyleSheetTypes.d.ts +202 -181
- package/types_generated/Libraries/StyleSheet/private/_TransformStyle.d.ts +3 -3
- package/types_generated/Libraries/Text/Text.d.ts +10 -6
- package/types_generated/Libraries/Text/TextProps.d.ts +57 -102
- package/types_generated/Libraries/TurboModule/RCTExport.d.ts +2 -2
- package/types_generated/Libraries/Types/CoreEventTypes.d.ts +14 -8
- package/types_generated/Libraries/Utilities/Appearance.d.ts +25 -13
- package/types_generated/Libraries/Utilities/BackHandler.d.ts +17 -1
- package/types_generated/Libraries/Utilities/DevSettings.d.ts +9 -2
- package/types_generated/Libraries/Utilities/Dimensions.d.ts +19 -13
- package/types_generated/Libraries/Utilities/PixelRatio.d.ts +6 -3
- package/types_generated/Libraries/Utilities/Platform.d.ts +5 -1
- package/types_generated/Libraries/Utilities/PlatformTypes.d.ts +65 -6
- package/types_generated/Libraries/Utilities/codegenNativeComponent.d.ts +5 -5
- package/types_generated/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.d.ts +2 -2
- package/types_generated/Libraries/Utilities/differ/deepDiffer.d.ts +2 -2
- package/types_generated/Libraries/Utilities/useColorScheme.d.ts +12 -2
- package/types_generated/Libraries/Utilities/useWindowDimensions.d.ts +7 -1
- package/types_generated/Libraries/Vibration/Vibration.d.ts +14 -6
- package/types_generated/index.d.ts +31 -25
- package/types_generated/src/private/assets/AssetRegistry.d.ts +42 -0
- package/types_generated/src/private/components/virtualcollection/VirtualCollectionView.d.ts +5 -5
- package/types_generated/src/private/components/virtualcollection/column/VirtualColumn.d.ts +3 -3
- package/types_generated/src/private/components/virtualcollection/row/VirtualRow.d.ts +3 -3
- package/types_generated/src/private/components/virtualview/VirtualView.d.ts +7 -7
- package/types_generated/src/private/components/virtualview/VirtualViewExperimentalNativeComponent.d.ts +5 -5
- package/types_generated/src/private/components/virtualview/VirtualViewNativeComponent.d.ts +5 -5
- package/types_generated/src/private/renderer/events/dispatchNativeEvent.d.ts +26 -0
- package/types_generated/src/private/specs_DEPRECATED/modules/NativeAppearance.d.ts +6 -5
- package/types_generated/src/private/specs_DEPRECATED/modules/NativeDeviceInfo.d.ts +7 -7
- package/types_generated/src/private/specs_DEPRECATED/modules/NativeExceptionsManager.d.ts +5 -5
- package/types_generated/src/private/specs_DEPRECATED/modules/NativeUIManager.d.ts +8 -8
- package/types_generated/src/private/types/HostComponent.d.ts +3 -3
- package/types_generated/src/private/types/HostInstance.d.ts +39 -74
- package/types_generated/src/private/webapis/dom/events/CustomEvent.d.ts +2 -2
- package/types_generated/src/private/webapis/dom/events/Event.d.ts +4 -4
- package/types_generated/src/private/webapis/dom/events/EventTarget.d.ts +8 -8
- package/types_generated/src/private/webapis/dom/nodes/ReactNativeDocument.d.ts +3 -1
- package/types_generated/src/private/webapis/dom/nodes/ReactNativeElement.d.ts +57 -4
- package/types_generated/src/private/webapis/dom/nodes/ReadOnlyCharacterData.d.ts +3 -1
- package/types_generated/src/private/webapis/dom/nodes/ReadOnlyElement.d.ts +3 -1
- package/types_generated/src/private/webapis/dom/nodes/ReadOnlyNode.d.ts +4 -2
- package/types_generated/src/private/webapis/dom/nodes/ReadOnlyText.d.ts +3 -1
- package/types_generated/src/private/webapis/dom/nodes/specs/NativeDOM.d.ts +3 -3
- package/types_generated/src/private/webapis/dom/oldstylecollections/HTMLCollection.d.ts +3 -1
- package/types_generated/src/private/webapis/dom/oldstylecollections/NodeList.d.ts +3 -1
- package/types_generated/src/react-private-interface.d.ts +33 -0
- package/Libraries/AppDelegate/RCTArchConfiguratorProtocol.h +0 -38
- package/Libraries/Image/AssetRegistry.js +0 -14
- package/Libraries/Image/RCTImageShadowView.h +0 -17
- package/Libraries/Image/RCTImageShadowView.mm +0 -28
- package/Libraries/Image/RCTImageView.h +0 -32
- package/Libraries/Image/RCTImageView.mm +0 -508
- package/Libraries/Image/RCTImageViewManager.h +0 -17
- package/Libraries/Image/RCTImageViewManager.mm +0 -115
- package/Libraries/Interaction/InteractionManager.d.ts +0 -87
- package/Libraries/Interaction/InteractionManager.js +0 -189
- package/Libraries/Text/BaseText/RCTBaseTextShadowView.h +0 -35
- package/Libraries/Text/BaseText/RCTBaseTextShadowView.mm +0 -162
- package/Libraries/Text/BaseText/RCTBaseTextViewManager.h +0 -21
- package/Libraries/Text/BaseText/RCTBaseTextViewManager.mm +0 -64
- package/Libraries/Text/RCTTextAttributes.h +0 -107
- package/Libraries/Text/RCTTextAttributes.mm +0 -358
- package/Libraries/Text/RawText/RCTRawTextShadowView.h +0 -23
- package/Libraries/Text/RawText/RCTRawTextShadowView.mm +0 -38
- package/Libraries/Text/RawText/RCTRawTextViewManager.h +0 -21
- package/Libraries/Text/RawText/RCTRawTextViewManager.mm +0 -32
- package/Libraries/Text/Text/RCTTextShadowView.h +0 -33
- package/Libraries/Text/Text/RCTTextShadowView.mm +0 -469
- package/Libraries/Text/Text/RCTTextView.h +0 -34
- package/Libraries/Text/Text/RCTTextView.mm +0 -298
- package/Libraries/Text/Text/RCTTextViewManager.h +0 -19
- package/Libraries/Text/Text/RCTTextViewManager.mm +0 -97
- package/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputView.h +0 -21
- package/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputView.mm +0 -67
- package/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.h +0 -21
- package/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.mm +0 -28
- package/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h +0 -30
- package/Libraries/Text/TextInput/RCTBaseTextInputShadowView.mm +0 -367
- package/Libraries/Text/TextInput/RCTBaseTextInputView.h +0 -68
- package/Libraries/Text/TextInput/RCTBaseTextInputView.mm +0 -849
- package/Libraries/Text/TextInput/RCTBaseTextInputViewManager.h +0 -17
- package/Libraries/Text/TextInput/RCTBaseTextInputViewManager.mm +0 -181
- package/Libraries/Text/TextInput/RCTInputAccessoryShadowView.h +0 -17
- package/Libraries/Text/TextInput/RCTInputAccessoryShadowView.mm +0 -24
- package/Libraries/Text/TextInput/RCTInputAccessoryView.h +0 -22
- package/Libraries/Text/TextInput/RCTInputAccessoryView.mm +0 -82
- package/Libraries/Text/TextInput/RCTInputAccessoryViewContent.h +0 -17
- package/Libraries/Text/TextInput/RCTInputAccessoryViewContent.mm +0 -78
- package/Libraries/Text/TextInput/RCTInputAccessoryViewManager.h +0 -17
- package/Libraries/Text/TextInput/RCTInputAccessoryViewManager.mm +0 -33
- package/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputView.h +0 -21
- package/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputView.mm +0 -43
- package/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.h +0 -21
- package/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.mm +0 -35
- package/Libraries/Text/VirtualText/RCTVirtualTextShadowView.h +0 -17
- package/Libraries/Text/VirtualText/RCTVirtualTextShadowView.mm +0 -42
- package/Libraries/Text/VirtualText/RCTVirtualTextView.h +0 -28
- package/Libraries/Text/VirtualText/RCTVirtualTextViewManager.h +0 -17
- package/Libraries/Text/VirtualText/RCTVirtualTextViewManager.mm +0 -30
- package/Libraries/Utilities/SceneTracker.js +0 -42
- package/Libraries/Wrapper/Example/RCTWrapperExampleView.h +0 -21
- package/Libraries/Wrapper/Example/RCTWrapperExampleView.m +0 -57
- package/Libraries/Wrapper/Example/RCTWrapperExampleViewController.h +0 -21
- package/Libraries/Wrapper/Example/RCTWrapperExampleViewController.m +0 -27
- package/Libraries/Wrapper/Example/RCTWrapperReactRootViewController.h +0 -25
- package/Libraries/Wrapper/Example/RCTWrapperReactRootViewController.m +0 -50
- package/Libraries/Wrapper/Example/RCTWrapperReactRootViewManager.h +0 -23
- package/Libraries/Wrapper/Example/RCTWrapperReactRootViewManager.m +0 -35
- package/Libraries/Wrapper/RCTWrapper.h +0 -73
- package/Libraries/Wrapper/RCTWrapperShadowView.h +0 -27
- package/Libraries/Wrapper/RCTWrapperShadowView.m +0 -138
- package/Libraries/Wrapper/RCTWrapperView.h +0 -42
- package/Libraries/Wrapper/RCTWrapperView.m +0 -99
- package/Libraries/Wrapper/RCTWrapperViewControllerHostingView.h +0 -30
- package/Libraries/Wrapper/RCTWrapperViewControllerHostingView.m +0 -137
- package/Libraries/Wrapper/RCTWrapperViewManager.h +0 -25
- package/Libraries/Wrapper/RCTWrapperViewManager.m +0 -31
- package/React/Base/RCTRootContentView.h +0 -43
- package/React/Base/RCTRootContentView.m +0 -111
- package/React/Base/RCTRootViewInternal.h +0 -28
- package/React/CxxBridge/RCTCxxBridge.mm +0 -1572
- package/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.h +0 -25
- package/React/CxxBridge/RCTJSIExecutorRuntimeInstaller.mm +0 -34
- package/React/CxxBridge/RCTObjcExecutor.h +0 -34
- package/React/CxxBridge/RCTObjcExecutor.mm +0 -150
- package/React/CxxLogUtils/RCTDefaultCxxLogFunction.mm +0 -34
- package/React/CxxModule/DispatchMessageQueueThread.h +0 -50
- package/React/CxxModule/RCTCxxMethod.h +0 -17
- package/React/CxxModule/RCTCxxMethod.mm +0 -147
- package/React/CxxModule/RCTNativeModule.h +0 -34
- package/React/CxxModule/RCTNativeModule.mm +0 -241
- package/React/Fabric/RCTSurfacePresenterBridgeAdapter.mm +0 -205
- package/React/Tests/Text/RCTTextAttributesTest.mm +0 -49
- package/React/Views/RCTActivityIndicatorView.h +0 -16
- package/React/Views/RCTActivityIndicatorView.m +0 -26
- package/React/Views/RCTActivityIndicatorViewManager.h +0 -23
- package/React/Views/RCTActivityIndicatorViewManager.m +0 -65
- package/React/Views/RCTDebuggingOverlayManager.h +0 -17
- package/React/Views/RCTDebuggingOverlayManager.m +0 -68
- package/React/Views/RCTModalHostView.h +0 -64
- package/React/Views/RCTModalHostView.m +0 -264
- package/React/Views/RCTModalHostViewController.m +0 -74
- package/React/Views/RCTModalHostViewManager.m +0 -131
- package/React/Views/RCTModalManager.h +0 -22
- package/React/Views/RCTModalManager.m +0 -46
- package/React/Views/RCTRootShadowView.h +0 -35
- package/React/Views/RCTRootShadowView.m +0 -53
- package/React/Views/RCTShadowView+Internal.h +0 -18
- package/React/Views/RCTShadowView+Internal.m +0 -23
- package/React/Views/RCTSwitch.h +0 -22
- package/React/Views/RCTSwitch.m +0 -24
- package/React/Views/RCTSwitchManager.h +0 -17
- package/React/Views/RCTSwitchManager.m +0 -70
- package/React/Views/RefreshControl/RCTRefreshControl.h +0 -24
- package/React/Views/RefreshControl/RCTRefreshControl.m +0 -230
- package/React/Views/RefreshControl/RCTRefreshControlManager.h +0 -17
- package/React/Views/RefreshControl/RCTRefreshControlManager.m +0 -47
- package/React/Views/SafeAreaView/RCTSafeAreaShadowView.h +0 -21
- package/React/Views/SafeAreaView/RCTSafeAreaShadowView.m +0 -57
- package/React/Views/SafeAreaView/RCTSafeAreaView.h +0 -27
- package/React/Views/SafeAreaView/RCTSafeAreaView.m +0 -79
- package/React/Views/SafeAreaView/RCTSafeAreaViewLocalData.h +0 -25
- package/React/Views/SafeAreaView/RCTSafeAreaViewLocalData.m +0 -25
- package/React/Views/SafeAreaView/RCTSafeAreaViewManager.h +0 -21
- package/React/Views/SafeAreaView/RCTSafeAreaViewManager.m +0 -32
- package/React/Views/ScrollView/RCTScrollContentShadowView.h +0 -19
- package/React/Views/ScrollView/RCTScrollContentShadowView.m +0 -35
- package/React/Views/ScrollView/RCTScrollContentView.h +0 -19
- package/React/Views/ScrollView/RCTScrollContentView.m +0 -36
- package/React/Views/ScrollView/RCTScrollContentViewManager.h +0 -17
- package/React/Views/ScrollView/RCTScrollContentViewManager.m +0 -31
- package/React/Views/ScrollView/RCTScrollView.m +0 -1168
- package/React/Views/ScrollView/RCTScrollViewManager.h +0 -25
- package/React/Views/ScrollView/RCTScrollViewManager.m +0 -202
- package/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +0 -251
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/BridgeReactContext.java +0 -315
- package/ReactAndroid/src/main/java/com/facebook/react/common/ClearableSynchronizedPool.kt +0 -51
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/AnimationBackendChoreographer.kt +0 -89
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +0 -736
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +0 -221
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactShadowNode.java +0 -399
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactZIndexedViewGroup.kt +0 -35
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +0 -346
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +0 -666
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +0 -147
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupDrawingOrderHelper.kt +0 -113
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java +0 -614
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +0 -1838
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactNestedScrollView.java +0 -1646
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +0 -1638
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaAlign.java +0 -51
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaBoxSizing.java +0 -33
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaDimension.java +0 -33
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaDisplay.java +0 -37
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaEdge.java +0 -47
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.java +0 -41
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java +0 -33
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaFlexDirection.java +0 -37
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaGridTrackType.java +0 -39
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaGutter.java +0 -35
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaJustify.java +0 -49
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaLogLevel.java +0 -45
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaMeasureMode.java +0 -35
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java +0 -928
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeType.java +0 -33
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaOverflow.java +0 -35
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaPositionType.java +0 -35
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaUnit.java +0 -43
- package/ReactAndroid/src/main/java/com/facebook/yoga/YogaWrap.java +0 -35
- package/ReactAndroid/src/main/jni/react/fabric/JAnimationBackendChoreographer.cpp +0 -23
- package/ReactAndroid/src/main/jni/react/fabric/JAnimationBackendChoreographer.h +0 -37
- package/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +0 -135
- package/ReactCommon/cxxreact/JSIndexedRAMBundle.h +0 -72
- package/ReactCommon/hermes/inspector-modern/chrome/ConnectionDemux.cpp +0 -143
- package/ReactCommon/hermes/inspector-modern/chrome/ConnectionDemux.h +0 -55
- package/ReactCommon/hermes/inspector-modern/chrome/Registration.cpp +0 -78
- package/ReactCommon/hermes/inspector-modern/chrome/Registration.h +0 -39
- package/ReactCommon/hermes/inspector-modern/chrome/tests/ConnectionDemuxTests.cpp +0 -148
- package/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java +0 -168
- package/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp +0 -416
- package/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h +0 -31
- package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h +0 -134
- package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm +0 -290
- package/ReactCommon/react/renderer/core/RawPropsKey.cpp +0 -62
- package/ReactCommon/react/renderer/core/RawPropsKey.h +0 -39
- package/ReactCommon/react/renderer/mounting/internal/DiffMap.h +0 -170
- package/ReactCommon/react/renderer/mounting/internal/LongestIncreasingSubsequence.h +0 -95
- package/ReactCommon/react/renderer/mounting/internal/TinyMap.h +0 -147
- package/ReactCommon/react/renderer/mounting/tests/LongestIncreasingSubsequenceTest.cpp +0 -154
- package/interface.js +0 -21
- package/jest-preset.js +0 -26
- package/rn-get-polyfills.js +0 -13
- package/sdks/.hermesversion +0 -1
- package/src/private/components/virtualcollection/debug/FlingItemOverlay.js +0 -13
- package/types/tsconfig.json +0 -15
- package/types_generated/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.d.ts +0 -14
- package/types_generated/Libraries/Components/ScrollView/ScrollViewNativeComponent.d.ts +0 -21
- package/types_generated/Libraries/Components/ScrollView/ScrollViewNativeComponentType.d.ts +0 -134
- package/types_generated/Libraries/Components/Switch/AndroidSwitchNativeComponent.d.ts +0 -14
- package/types_generated/Libraries/Components/Switch/SwitchNativeComponent.d.ts +0 -14
- package/types_generated/Libraries/Components/Touchable/Touchable.d.ts +0 -262
- package/types_generated/Libraries/Interaction/InteractionManager.d.ts +0 -117
- package/types_generated/Libraries/NativeModules/specs/NativeDialogManagerAndroid.d.ts +0 -17
- package/types_generated/src/private/specs_DEPRECATED/components/AndroidSwitchNativeComponent.d.ts +0 -53
- package/types_generated/src/private/specs_DEPRECATED/components/ProgressBarAndroidNativeComponent.d.ts +0 -36
- package/types_generated/src/private/specs_DEPRECATED/components/SwitchNativeComponent.d.ts +0 -51
- package/types_generated/src/private/specs_DEPRECATED/modules/NativeDialogManagerAndroid.d.ts +0 -37
- package/types_generated/tsconfig.test.json +0 -16
- /package/ReactCommon/{cxxreact → react/utils}/MoveWrapper.h +0 -0
|
@@ -0,0 +1,2790 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* generate-spm-xcodeproj.js – Surgical, in-place Swift Package Manager
|
|
15
|
+
* integration toolkit for an existing `<App>.xcodeproj`.
|
|
16
|
+
*
|
|
17
|
+
* `injectSpmIntoExistingXcodeproj` adds the SPM package references, React build
|
|
18
|
+
* settings, the "Sync SPM Autolinking" build phase, and a scheme pre-action to
|
|
19
|
+
* a user's existing project — purely additively, recording every edit in a
|
|
20
|
+
* `.spm-injected.json` marker. `removeSpmInjection` is the exact inverse (used
|
|
21
|
+
* by `spm deinit`). Consumed as a library by setup-apple-spm.js; not a CLI.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const {readFlavoredFrameworksManifest} = require('./flavored-frameworks');
|
|
25
|
+
const {parseConfigCommandJson} = require('./generate-spm-autolinking-config');
|
|
26
|
+
const {
|
|
27
|
+
addArrayMembers,
|
|
28
|
+
addArrayStringValues,
|
|
29
|
+
commentSafe,
|
|
30
|
+
ensureScalarField,
|
|
31
|
+
findApplicationTargets,
|
|
32
|
+
findField,
|
|
33
|
+
findObjectByUuid,
|
|
34
|
+
findProjectObject,
|
|
35
|
+
insertObjectsIntoSection,
|
|
36
|
+
namespacedUUID,
|
|
37
|
+
quoteIfNeeded,
|
|
38
|
+
removeArrayMembersByUuid,
|
|
39
|
+
removeArrayStringValues,
|
|
40
|
+
removeDanglingJavaScriptCoreRef,
|
|
41
|
+
removeEmptyPodsGroup,
|
|
42
|
+
removeField,
|
|
43
|
+
removeObjectByUuid,
|
|
44
|
+
serializeEntry,
|
|
45
|
+
setScalarField,
|
|
46
|
+
uuidComment,
|
|
47
|
+
} = require('./spm-pbxproj');
|
|
48
|
+
const {
|
|
49
|
+
AUTOLINKED_PACKAGE_NAME,
|
|
50
|
+
REACT_CODEGEN_APP_PRODUCTS,
|
|
51
|
+
REACT_CODEGEN_PACKAGE_NAME,
|
|
52
|
+
REACT_NATIVE_PACKAGE_NAME,
|
|
53
|
+
REACT_NATIVE_PRODUCTS,
|
|
54
|
+
isValidScriptPhaseId,
|
|
55
|
+
isValidScriptPhaseName,
|
|
56
|
+
makeLogger,
|
|
57
|
+
remotePackageConfig,
|
|
58
|
+
} = require('./spm-utils');
|
|
59
|
+
const fs = require('fs');
|
|
60
|
+
const path = require('path');
|
|
61
|
+
|
|
62
|
+
/*:: import type {
|
|
63
|
+
FlavoredFrameworkManifestEntry,
|
|
64
|
+
PluginScriptPhase,
|
|
65
|
+
XcframeworkSlice,
|
|
66
|
+
} from './spm-types'; */
|
|
67
|
+
|
|
68
|
+
const {log} = makeLogger('generate-spm-xcodeproj');
|
|
69
|
+
|
|
70
|
+
// Sidecar inside a USER-OWNED xcodeproj that SPM packages were injected into in
|
|
71
|
+
// place. Records the host project's root UUID + every edit so `spm deinit`
|
|
72
|
+
// (removeSpmInjection) can surgically revert and re-runs stay idempotent.
|
|
73
|
+
const SPM_INJECTED_MARKER = '.spm-injected.json';
|
|
74
|
+
|
|
75
|
+
// Manifest of plugin-contributed sources that must COMPILE INTO THE APP TARGET
|
|
76
|
+
// (e.g. Expo's ExpoModulesProvider.swift — an `@objc` class only reaches the
|
|
77
|
+
// ObjC classlist, and so is discoverable via NSClassFromString, when it
|
|
78
|
+
// compiles into the app target, NOT the static Autolinked aggregate). Written
|
|
79
|
+
// by generate-spm-autolinking.js (the plugin merge) BEFORE setupXcodeproj runs
|
|
80
|
+
// on both `add` and `update`, so the injector reads it synchronously. Path is
|
|
81
|
+
// relative to the app root (== SRCROOT / the .xcodeproj's dir).
|
|
82
|
+
const SPM_GENERATED_SOURCES_MANIFEST = path.join(
|
|
83
|
+
'build',
|
|
84
|
+
'generated',
|
|
85
|
+
'autolinking',
|
|
86
|
+
'.spm-plugin-generated-sources.json',
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Manifest of plugin-contributed build-time shell phases for the app target —
|
|
90
|
+
// SwiftPM has no `script_phase`, so a framework that must generate content into
|
|
91
|
+
// the app bundle (expo-constants' `EXConstants.bundle/app.config`) declares one
|
|
92
|
+
// through the plugin contract.
|
|
93
|
+
const SPM_SCRIPT_PHASES_MANIFEST = path.join(
|
|
94
|
+
'build',
|
|
95
|
+
'generated',
|
|
96
|
+
'autolinking',
|
|
97
|
+
'.spm-plugin-script-phases.json',
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// The single navigator group all injected generated sources are parented under
|
|
101
|
+
// (created on first use). Its namespacedUUID id + display name.
|
|
102
|
+
const SPM_GENERATED_SOURCES_GROUP_ID = 'SPMGeneratedSources';
|
|
103
|
+
const SPM_GENERATED_SOURCES_GROUP_NAME = 'SPM Generated Sources';
|
|
104
|
+
|
|
105
|
+
// pbxproj `lastKnownFileType` per source extension. v1 plugins emit Swift only;
|
|
106
|
+
// .m/.mm are mapped as future-proofing (the plugin contract permits ObjC/ObjC++
|
|
107
|
+
// sources). An unmapped extension is skipped with a loud log.
|
|
108
|
+
const GENERATED_SOURCE_FILE_TYPES /*: {[string]: string} */ = {
|
|
109
|
+
'.swift': 'sourcecode.swift',
|
|
110
|
+
'.m': 'sourcecode.c.objc',
|
|
111
|
+
'.mm': 'sourcecode.cpp.objcpp',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Maps each SPM product to its sub-package path (relative to app root).
|
|
115
|
+
// The xcodeproj must reference each sub-package directly so Xcode can
|
|
116
|
+
// resolve the product dependencies — SPM doesn't expose transitive products.
|
|
117
|
+
const SPM_PRODUCT_PACKAGES /*: Array<{product: string, packagePath: string, packageName: string}> */ =
|
|
118
|
+
[
|
|
119
|
+
...REACT_NATIVE_PRODUCTS.map(product => ({
|
|
120
|
+
product,
|
|
121
|
+
packagePath: 'build/xcframeworks',
|
|
122
|
+
packageName: REACT_NATIVE_PACKAGE_NAME,
|
|
123
|
+
})),
|
|
124
|
+
{
|
|
125
|
+
product: AUTOLINKED_PACKAGE_NAME,
|
|
126
|
+
packagePath: 'build/generated/autolinking',
|
|
127
|
+
packageName: AUTOLINKED_PACKAGE_NAME,
|
|
128
|
+
},
|
|
129
|
+
...REACT_CODEGEN_APP_PRODUCTS.map(product => ({
|
|
130
|
+
product,
|
|
131
|
+
packagePath: 'build/generated/ios',
|
|
132
|
+
packageName: REACT_CODEGEN_PACKAGE_NAME,
|
|
133
|
+
})),
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
/*::
|
|
137
|
+
type RemoteCfg = {url: string, version: string, identity: string};
|
|
138
|
+
// Precise record of the build-setting edits injection made to ONE build config,
|
|
139
|
+
// so deinit can reverse exactly those (and nothing the user already had).
|
|
140
|
+
type BuildSettingChange = {
|
|
141
|
+
configUuid: string,
|
|
142
|
+
createdArrayKeys: Array<string>,
|
|
143
|
+
appendedArrayValues: {[string]: Array<string>},
|
|
144
|
+
createdScalars: Array<string>,
|
|
145
|
+
// Scalars whose pre-injection value was replaced (key → original raw
|
|
146
|
+
// value), e.g. a ${PODS_ROOT}-anchored REACT_NATIVE_PATH that dangles once
|
|
147
|
+
// CocoaPods is deintegrated. Deinit restores the original.
|
|
148
|
+
replacedScalars?: {[string]: string},
|
|
149
|
+
// Array settings that existed as a SCALAR and were promoted to a `( … )`
|
|
150
|
+
// array (key → the pre-injection raw value text, quotes included). Deinit
|
|
151
|
+
// restores that value verbatim; removing the injected members would leave
|
|
152
|
+
// the promoted array and its `"$(inherited)"` seed behind.
|
|
153
|
+
promotedArrayScalars?: {[string]: string},
|
|
154
|
+
};
|
|
155
|
+
// An array field injection CREATED (rather than appended to a pre-existing
|
|
156
|
+
// one), so deinit removes the whole field and lands byte-identical.
|
|
157
|
+
type CreatedArrayField = {container: 'project' | 'target', key: string};
|
|
158
|
+
// A plugin-contributed source, normalized for pbxproj emission. `path` is
|
|
159
|
+
// SRCROOT-relative when under the app root, else absolute; `sourceTree` is the
|
|
160
|
+
// matching pbxproj token ('SOURCE_ROOT' or '"<absolute>"').
|
|
161
|
+
type GeneratedSource = {path: string, name: string, sourceTree: string, fileType: string};
|
|
162
|
+
type SpmGraph = {
|
|
163
|
+
uniquePackages: Array<{packagePath: string, packageName: string}>,
|
|
164
|
+
localPkgRefs: Array<{uuid: string, packagePath: string, comment: string}>,
|
|
165
|
+
remotePkgRef: ?{uuid: string, url: string, version: string, identity: string, comment: string},
|
|
166
|
+
products: Array<{product: string, depUuid: string, buildFileUuid: string, pkgRefUuid: string, refComment: string}>,
|
|
167
|
+
};
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Resolve the SPM dependency graph (package references + product
|
|
172
|
+
* dependencies + their frameworks build files) from SPM_PRODUCT_PACKAGES.
|
|
173
|
+
* `mkUuid(section, id)` supplies UUIDs, seeded with the host project's root
|
|
174
|
+
* UUID so injected IDs are stable across re-runs and collision-safe.
|
|
175
|
+
*/
|
|
176
|
+
function buildSpmDependencyGraph(
|
|
177
|
+
mkUuid /*: (section: string, id: string) => string */,
|
|
178
|
+
remote /*: ?RemoteCfg */,
|
|
179
|
+
) /*: SpmGraph */ {
|
|
180
|
+
// Remote mode: ReactNative-family products move to the remote package.
|
|
181
|
+
const productPackages = SPM_PRODUCT_PACKAGES.map(e =>
|
|
182
|
+
remote != null && e.packagePath === 'build/xcframeworks'
|
|
183
|
+
? {...e, packagePath: 'REMOTE', packageName: remote.identity}
|
|
184
|
+
: e,
|
|
185
|
+
);
|
|
186
|
+
const uniquePackages = Array.from(
|
|
187
|
+
new Map(
|
|
188
|
+
productPackages
|
|
189
|
+
.filter(e => e.packagePath !== 'REMOTE')
|
|
190
|
+
.map(e => [
|
|
191
|
+
e.packagePath,
|
|
192
|
+
{packagePath: e.packagePath, packageName: e.packageName},
|
|
193
|
+
]),
|
|
194
|
+
).values(),
|
|
195
|
+
);
|
|
196
|
+
const localPkgRefs = uniquePackages.map(pkg => ({
|
|
197
|
+
uuid: mkUuid('XCLocalSwiftPackageReference', pkg.packagePath),
|
|
198
|
+
packagePath: pkg.packagePath,
|
|
199
|
+
comment: `XCLocalSwiftPackageReference "${pkg.packagePath}"`,
|
|
200
|
+
}));
|
|
201
|
+
const remotePkgRef =
|
|
202
|
+
remote != null
|
|
203
|
+
? {
|
|
204
|
+
uuid: mkUuid('XCRemoteSwiftPackageReference', remote.url),
|
|
205
|
+
url: remote.url,
|
|
206
|
+
version: remote.version,
|
|
207
|
+
identity: remote.identity,
|
|
208
|
+
comment: `XCRemoteSwiftPackageReference "${remote.identity}"`,
|
|
209
|
+
}
|
|
210
|
+
: null;
|
|
211
|
+
const localByPath = new Map(localPkgRefs.map(r => [r.packagePath, r]));
|
|
212
|
+
const products = productPackages.map(entry => {
|
|
213
|
+
const {product, packagePath} = entry;
|
|
214
|
+
const isRemote = packagePath === 'REMOTE' && remotePkgRef != null;
|
|
215
|
+
const pkgRefUuid = isRemote
|
|
216
|
+
? // $FlowFixMe[incompatible-use] guarded by isRemote
|
|
217
|
+
remotePkgRef.uuid
|
|
218
|
+
: // $FlowFixMe[incompatible-use] every non-REMOTE path is in localByPath
|
|
219
|
+
localByPath.get(packagePath).uuid;
|
|
220
|
+
const refComment = isRemote
|
|
221
|
+
? // $FlowFixMe[incompatible-use] guarded by isRemote
|
|
222
|
+
`XCRemoteSwiftPackageReference "${remotePkgRef.identity}"`
|
|
223
|
+
: `XCLocalSwiftPackageReference "${packagePath}"`;
|
|
224
|
+
return {
|
|
225
|
+
product,
|
|
226
|
+
depUuid: mkUuid('XCSwiftPackageProductDependency', product),
|
|
227
|
+
buildFileUuid: mkUuid('PBXBuildFile', `spm:${product}`),
|
|
228
|
+
pkgRefUuid,
|
|
229
|
+
refComment,
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
return {uniquePackages, localPkgRefs, remotePkgRef, products};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Render the SPM graph into pbxproj section entry objects the in-place injector
|
|
237
|
+
* splices into an existing project.
|
|
238
|
+
*/
|
|
239
|
+
/*:: type PbxEntryT = {uuid: string, comment: string, fields: {[string]: string}}; */
|
|
240
|
+
|
|
241
|
+
function spmGraphToEntries(
|
|
242
|
+
graph /*: SpmGraph */,
|
|
243
|
+
) /*: {localRefs: Array<PbxEntryT>, remoteRef: ?PbxEntryT, productDeps: Array<PbxEntryT>, buildFiles: Array<PbxEntryT>} */ {
|
|
244
|
+
const localRefs /*: Array<PbxEntryT> */ = graph.localPkgRefs.map(ref => ({
|
|
245
|
+
uuid: ref.uuid,
|
|
246
|
+
comment: ref.comment,
|
|
247
|
+
fields: {
|
|
248
|
+
isa: 'XCLocalSwiftPackageReference',
|
|
249
|
+
relativePath: quoteIfNeeded(ref.packagePath),
|
|
250
|
+
},
|
|
251
|
+
}));
|
|
252
|
+
const remote = graph.remotePkgRef;
|
|
253
|
+
const remoteRef /*: ?PbxEntryT */ =
|
|
254
|
+
remote != null
|
|
255
|
+
? {
|
|
256
|
+
uuid: remote.uuid,
|
|
257
|
+
comment: remote.comment,
|
|
258
|
+
fields: {
|
|
259
|
+
isa: 'XCRemoteSwiftPackageReference',
|
|
260
|
+
repositoryURL: quoteIfNeeded(remote.url),
|
|
261
|
+
requirement: `{\n\t\t\t\tkind = exactVersion;\n\t\t\t\tversion = "${remote.version}";\n\t\t\t}`,
|
|
262
|
+
},
|
|
263
|
+
}
|
|
264
|
+
: null;
|
|
265
|
+
const productDeps /*: Array<PbxEntryT> */ = graph.products.map(p => ({
|
|
266
|
+
uuid: p.depUuid,
|
|
267
|
+
comment: p.product,
|
|
268
|
+
fields: {
|
|
269
|
+
isa: 'XCSwiftPackageProductDependency',
|
|
270
|
+
package: `${p.pkgRefUuid} /* ${p.refComment} */`,
|
|
271
|
+
productName: quoteIfNeeded(p.product),
|
|
272
|
+
},
|
|
273
|
+
}));
|
|
274
|
+
const buildFiles /*: Array<PbxEntryT> */ = graph.products.map(p => ({
|
|
275
|
+
uuid: p.buildFileUuid,
|
|
276
|
+
comment: `${p.product} in Frameworks`,
|
|
277
|
+
fields: {
|
|
278
|
+
isa: 'PBXBuildFile',
|
|
279
|
+
productRef: `${p.depUuid} /* ${p.product} */`,
|
|
280
|
+
},
|
|
281
|
+
}));
|
|
282
|
+
return {localRefs, remoteRef, productDeps, buildFiles};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Build a PBXShellScriptBuildPhase entry. `inputPaths`/`outputPaths` accept
|
|
287
|
+
* either a plain path array or an already-serialized pbxproj list.
|
|
288
|
+
* `alwaysOutOfDate` emits Xcode's own `alwaysOutOfDate = 1;` (unquoted, right
|
|
289
|
+
* after `isa`, so a project Xcode rewrites stays diff-free) and is omitted
|
|
290
|
+
* entirely when false. `comment` overrides the cosmetic `/* … */` label, which
|
|
291
|
+
* otherwise derives from `name`.
|
|
292
|
+
*/
|
|
293
|
+
function shellScriptPhase(
|
|
294
|
+
phaseUUID /*: string */,
|
|
295
|
+
name /*: string */,
|
|
296
|
+
script /*: string */,
|
|
297
|
+
options /*: {inputPaths?: ?(string | ReadonlyArray<string>), outputPaths?: ?(string | ReadonlyArray<string>), alwaysOutOfDate?: ?boolean, comment?: string} */ = {},
|
|
298
|
+
) /*: {uuid: string, comment: string, fields: {[string]: string}} */ {
|
|
299
|
+
const empty = '(\n\t\t\t)';
|
|
300
|
+
const pathList = (
|
|
301
|
+
value /*: ?(string | ReadonlyArray<string>) */,
|
|
302
|
+
) /*: string */ => {
|
|
303
|
+
if (value == null) {
|
|
304
|
+
return empty;
|
|
305
|
+
}
|
|
306
|
+
return typeof value === 'string' ? value : pbxPathList(value);
|
|
307
|
+
};
|
|
308
|
+
return {
|
|
309
|
+
uuid: phaseUUID,
|
|
310
|
+
comment: options.comment ?? name,
|
|
311
|
+
fields: {
|
|
312
|
+
isa: 'PBXShellScriptBuildPhase',
|
|
313
|
+
...(options.alwaysOutOfDate === true ? {alwaysOutOfDate: '1'} : {}),
|
|
314
|
+
buildActionMask: '2147483647',
|
|
315
|
+
files: empty,
|
|
316
|
+
inputFileListPaths: empty,
|
|
317
|
+
inputPaths: pathList(options.inputPaths),
|
|
318
|
+
name: quoteIfNeeded(name),
|
|
319
|
+
outputFileListPaths: empty,
|
|
320
|
+
outputPaths: pathList(options.outputPaths),
|
|
321
|
+
runOnlyForDeploymentPostprocessing: '0',
|
|
322
|
+
shellPath: '/bin/sh',
|
|
323
|
+
shellScript: quoteIfNeeded(script),
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function frameworkSettingPrefix(id /*: string */) /*: string */ {
|
|
329
|
+
return `RN_SPM_${id.replace(/[^A-Za-z0-9]/g, '_').toUpperCase()}`;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function flavorForBuildConfiguration(
|
|
333
|
+
configurationName /*: string */,
|
|
334
|
+
) /*: 'debug' | 'release' */ {
|
|
335
|
+
const lower = configurationName.toLowerCase();
|
|
336
|
+
return lower.includes('debug') || lower.includes('development')
|
|
337
|
+
? 'debug'
|
|
338
|
+
: 'release';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function buildConfigurationName(
|
|
342
|
+
text /*: string */,
|
|
343
|
+
configUuid /*: string */,
|
|
344
|
+
) /*: string */ {
|
|
345
|
+
const config = findObjectByUuid(text, configUuid);
|
|
346
|
+
const name = config != null ? findField(text, config, 'name') : null;
|
|
347
|
+
if (name == null) {
|
|
348
|
+
throw new Error(`pbxproj: build configuration ${configUuid} has no name`);
|
|
349
|
+
}
|
|
350
|
+
return name.value.replace(/^"|"$/g, '');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function frameworkConditionalSettings(
|
|
354
|
+
frameworks /*: ReadonlyArray<FlavoredFrameworkManifestEntry> */,
|
|
355
|
+
) /*: Array<{key: string, value: string}> */ {
|
|
356
|
+
const settings /*: Array<{key: string, value: string}> */ = [];
|
|
357
|
+
for (const framework of frameworks) {
|
|
358
|
+
const prefix = frameworkSettingPrefix(framework.id);
|
|
359
|
+
const bySdk /*: Map<string, Array<XcframeworkSlice>> */ = new Map();
|
|
360
|
+
// The injected target is an Apple mobile/Catalyst application. Native
|
|
361
|
+
// macOS slices share `sdk=macosx*` with Catalyst and cannot be
|
|
362
|
+
// distinguished by an XCBuildConfiguration condition, so use the Catalyst
|
|
363
|
+
// slice and leave native-mac packaging out of this iOS integration.
|
|
364
|
+
for (const slice of framework.slices.filter(
|
|
365
|
+
candidate => candidate.platform !== 'macos',
|
|
366
|
+
)) {
|
|
367
|
+
const existing = bySdk.get(slice.sdk) ?? [];
|
|
368
|
+
existing.push(slice);
|
|
369
|
+
bySdk.set(slice.sdk, existing);
|
|
370
|
+
}
|
|
371
|
+
for (const [sdk, slices] of bySdk) {
|
|
372
|
+
const emit = (slice /*: XcframeworkSlice */, condition /*: string */) => {
|
|
373
|
+
const root =
|
|
374
|
+
`$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/` +
|
|
375
|
+
`${framework.artifactRelativePath}/${slice.libraryIdentifier}`;
|
|
376
|
+
settings.push(
|
|
377
|
+
{
|
|
378
|
+
key: quoteIfNeeded(`${prefix}_FRAMEWORK${condition}`),
|
|
379
|
+
value: quoteIfNeeded(`${root}/${slice.libraryPath}`),
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
key: quoteIfNeeded(`${prefix}_BINARY${condition}`),
|
|
383
|
+
value: quoteIfNeeded(`${root}/${slice.binaryPath}`),
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
key: quoteIfNeeded(`${prefix}_SEARCH_PATH${condition}`),
|
|
387
|
+
value: quoteIfNeeded(root),
|
|
388
|
+
},
|
|
389
|
+
);
|
|
390
|
+
};
|
|
391
|
+
if (slices.length === 1) {
|
|
392
|
+
emit(slices[0], `[sdk=${sdk}]`);
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const seenArchitectures /*: Set<string> */ = new Set();
|
|
396
|
+
for (const slice of slices) {
|
|
397
|
+
for (const architecture of slice.architectures) {
|
|
398
|
+
if (seenArchitectures.has(architecture)) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
`${framework.frameworkName} has ambiguous ${sdk}/${architecture} slices`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
seenArchitectures.add(architecture);
|
|
404
|
+
emit(slice, `[sdk=${sdk}][arch=${architecture}]`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return settings;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function frameworkArrayBuildSettings(
|
|
413
|
+
frameworks /*: ReadonlyArray<FlavoredFrameworkManifestEntry> */,
|
|
414
|
+
) /*: Array<{key: string, values: Array<string>}> */ {
|
|
415
|
+
return [
|
|
416
|
+
{
|
|
417
|
+
key: 'OTHER_LDFLAGS',
|
|
418
|
+
values: [
|
|
419
|
+
'"-ObjC"',
|
|
420
|
+
...frameworks.map(
|
|
421
|
+
framework => `"$(${frameworkSettingPrefix(framework.id)}_BINARY)"`,
|
|
422
|
+
),
|
|
423
|
+
],
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
key: 'FRAMEWORK_SEARCH_PATHS',
|
|
427
|
+
values: frameworks.map(
|
|
428
|
+
framework => `"$(${frameworkSettingPrefix(framework.id)}_SEARCH_PATH)"`,
|
|
429
|
+
),
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
key: 'LD_RUNPATH_SEARCH_PATHS',
|
|
433
|
+
values: ['"@executable_path/Frameworks"'],
|
|
434
|
+
},
|
|
435
|
+
];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function pbxPathList(paths /*: ReadonlyArray<string> */) /*: string */ {
|
|
439
|
+
if (paths.length === 0) {
|
|
440
|
+
return '(\n\t\t\t)';
|
|
441
|
+
}
|
|
442
|
+
return `(\n${paths
|
|
443
|
+
.map(value => `\t\t\t\t${quoteIfNeeded(value)},\n`)
|
|
444
|
+
.join('')}\t\t\t)`;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function buildEmbedFrameworksScript(
|
|
448
|
+
frameworks /*: ReadonlyArray<FlavoredFrameworkManifestEntry> */,
|
|
449
|
+
) /*: string */ {
|
|
450
|
+
const validations = frameworks
|
|
451
|
+
.map(framework => {
|
|
452
|
+
const variable = `${frameworkSettingPrefix(framework.id)}_FRAMEWORK`;
|
|
453
|
+
return `validate_framework "\${${variable}:-}" "${framework.frameworkName}.framework"`;
|
|
454
|
+
})
|
|
455
|
+
.join('\n');
|
|
456
|
+
const copies = frameworks
|
|
457
|
+
.map(framework => {
|
|
458
|
+
const variable = `${frameworkSettingPrefix(framework.id)}_FRAMEWORK`;
|
|
459
|
+
return `copy_and_sign "\${${variable}:-}" "${framework.frameworkName}.framework"`;
|
|
460
|
+
})
|
|
461
|
+
.join('\n');
|
|
462
|
+
return `set -euo pipefail
|
|
463
|
+
|
|
464
|
+
destination="$TARGET_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH"
|
|
465
|
+
mkdir -p "$destination"
|
|
466
|
+
|
|
467
|
+
validate_framework() {
|
|
468
|
+
source="$1"
|
|
469
|
+
name="$2"
|
|
470
|
+
if [ -z "$source" ] || [ ! -d "$source" ]; then
|
|
471
|
+
echo "error: React Native SwiftPM framework '$name' is unavailable for configuration '$CONFIGURATION' and SDK '$SDK_NAME': $source"
|
|
472
|
+
exit 1
|
|
473
|
+
fi
|
|
474
|
+
binary="\${name%.framework}"
|
|
475
|
+
if [ ! -e "$source/$binary" ] && [ ! -e "$source/Versions/Current/$binary" ]; then
|
|
476
|
+
echo "error: React Native SwiftPM framework '$name' is invalid for configuration '$CONFIGURATION': expected $source/$binary or $source/Versions/Current/$binary"
|
|
477
|
+
exit 1
|
|
478
|
+
fi
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
copy_and_sign() {
|
|
482
|
+
source="$1"
|
|
483
|
+
name="$2"
|
|
484
|
+
/usr/bin/rsync -a --delete "$source/" "$destination/$name/"
|
|
485
|
+
if [ "\${CODE_SIGNING_ALLOWED:-YES}" != "NO" ]; then
|
|
486
|
+
identity="\${EXPANDED_CODE_SIGN_IDENTITY:--}"
|
|
487
|
+
if [ "$identity" = "-" ]; then
|
|
488
|
+
/usr/bin/codesign --force --sign - --timestamp=none --preserve-metadata=identifier,entitlements,flags "$destination/$name"
|
|
489
|
+
else
|
|
490
|
+
/usr/bin/codesign --force --sign "$identity" --preserve-metadata=identifier,entitlements,flags "$destination/$name"
|
|
491
|
+
fi
|
|
492
|
+
fi
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
${validations}
|
|
496
|
+
${copies}
|
|
497
|
+
`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* The app target's `buildPhases` members, in the order the file lists them.
|
|
502
|
+
* Line-leading UUIDs only: a member's trailing comment carries a plugin-supplied
|
|
503
|
+
* phase name, and one that happens to look like a UUID would otherwise read as an
|
|
504
|
+
* extra member — leaving the actual order permanently at odds with the declared
|
|
505
|
+
* one, and offering a non-member as a re-seating anchor.
|
|
506
|
+
*/
|
|
507
|
+
function buildPhaseOrder(
|
|
508
|
+
text /*: string */,
|
|
509
|
+
target /*: {bodyOpen: number, bodyClose: number, ...} */,
|
|
510
|
+
) /*: Array<string> */ {
|
|
511
|
+
const field = findField(text, target, 'buildPhases');
|
|
512
|
+
if (field == null) {
|
|
513
|
+
return [];
|
|
514
|
+
}
|
|
515
|
+
return [...field.value.matchAll(/^[\t ]*([0-9A-Fa-f]{24})\b/gm)].map(
|
|
516
|
+
m => m[1],
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Rewrite the trailing comment Xcode keeps beside a UUID — on the object's own
|
|
522
|
+
* definition line and on every array-member line referencing it. Xcode
|
|
523
|
+
* normalizes those comments on its next write, so leaving a stale one behind
|
|
524
|
+
* (after a plugin renames a phase) plants a spurious diff in the user's repo.
|
|
525
|
+
* No-op when the comment already reads `comment`.
|
|
526
|
+
*/
|
|
527
|
+
function setUuidComment(
|
|
528
|
+
text /*: string */,
|
|
529
|
+
uuid /*: string */,
|
|
530
|
+
comment /*: string */,
|
|
531
|
+
) /*: string */ {
|
|
532
|
+
return text.replace(
|
|
533
|
+
new RegExp(`(\\n[\\t ]*${uuid})(?: /\\* [^\\n]*? \\*/)?( = \\{|,)`, 'g'),
|
|
534
|
+
(_match, head, tail) => `${head}${uuidComment(comment)}${tail}`,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/*:: type SeatedPhase = {uuid: string, comment: string, position: 'beforeCompile' | 'end'}; */
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Seat the plugin phases in the order the manifest declares: `beforeCompile`
|
|
542
|
+
* ones directly after the Sync SPM Autolinking phase (which stays first — it
|
|
543
|
+
* regenerates the content everything else reads) and always before Sources,
|
|
544
|
+
* `end` ones at the true end of `buildPhases`, after the app's own JS-bundle
|
|
545
|
+
* phase. The other members keep their relative order.
|
|
546
|
+
*
|
|
547
|
+
* `beforeCompile` is anchored on Sources, not merely on the sync phase: RN never
|
|
548
|
+
* re-seats its own sync phase, so a user who drags it below Sources would
|
|
549
|
+
* otherwise have every `beforeCompile` phase seated after compilation — the one
|
|
550
|
+
* thing the position promises not to do. Without a Sources phase the sync phase
|
|
551
|
+
* is the anchor.
|
|
552
|
+
*
|
|
553
|
+
* Rewrites the membership lines ONLY when the actual order differs from that,
|
|
554
|
+
* which is what keeps an unchanged sync byte-identical — `addBuildPhaseAfter`
|
|
555
|
+
* and `addArrayMembers` both short-circuit on a UUID that is already a member,
|
|
556
|
+
* so re-placing has to be driven from here. A phase a user dragged elsewhere in
|
|
557
|
+
* Xcode is therefore moved back: the declared position wins.
|
|
558
|
+
*/
|
|
559
|
+
function seatScriptPhases(
|
|
560
|
+
input /*: string */,
|
|
561
|
+
targetUuid /*: string */,
|
|
562
|
+
syncPhaseUuid /*: string */,
|
|
563
|
+
phases /*: ReadonlyArray<SeatedPhase> */,
|
|
564
|
+
sourcesPhaseUuid /*: ?string */,
|
|
565
|
+
) /*: string */ {
|
|
566
|
+
const pluginUuids = new Set(phases.map(p => p.uuid));
|
|
567
|
+
const actual = buildPhaseOrder(
|
|
568
|
+
input,
|
|
569
|
+
findApplicationTargetByUuid(input, targetUuid),
|
|
570
|
+
);
|
|
571
|
+
const others = actual.filter(uuid => !pluginUuids.has(uuid));
|
|
572
|
+
const beforeCompile = phases.filter(p => p.position === 'beforeCompile');
|
|
573
|
+
const atEnd = phases.filter(p => p.position !== 'beforeCompile');
|
|
574
|
+
const sourcesAt =
|
|
575
|
+
sourcesPhaseUuid != null ? others.indexOf(sourcesPhaseUuid) : -1;
|
|
576
|
+
const afterSyncAt = others.indexOf(syncPhaseUuid) + 1;
|
|
577
|
+
// 0 — no sync phase member, or Sources ahead of it — makes the beforeCompile
|
|
578
|
+
// phases lead the array, matching addArrayMembers' prepend fallback below.
|
|
579
|
+
const insertAt =
|
|
580
|
+
sourcesAt >= 0 ? Math.min(afterSyncAt, sourcesAt) : afterSyncAt;
|
|
581
|
+
const desired = [
|
|
582
|
+
...others.slice(0, insertAt),
|
|
583
|
+
...beforeCompile.map(p => p.uuid),
|
|
584
|
+
...others.slice(insertAt),
|
|
585
|
+
...atEnd.map(p => p.uuid),
|
|
586
|
+
];
|
|
587
|
+
if (
|
|
588
|
+
desired.length === actual.length &&
|
|
589
|
+
desired.every((uuid, i) => uuid === actual[i])
|
|
590
|
+
) {
|
|
591
|
+
return input;
|
|
592
|
+
}
|
|
593
|
+
// File-wide removal is safe for a shell-phase UUID: it appears on its own
|
|
594
|
+
// definition line (which ends `= {`, never matched) and on `buildPhases`
|
|
595
|
+
// member lines. The uncovered case is a user who copied the same phase object
|
|
596
|
+
// into a SECOND target's buildPhases — it is stripped there too.
|
|
597
|
+
let text = removeArrayMembersByUuid(input, [...pluginUuids]);
|
|
598
|
+
const target = () => findApplicationTargetByUuid(text, targetUuid);
|
|
599
|
+
let anchor = insertAt > 0 ? others[insertAt - 1] : null;
|
|
600
|
+
for (const member of beforeCompile) {
|
|
601
|
+
text =
|
|
602
|
+
anchor == null
|
|
603
|
+
? addArrayMembers(text, target(), 'buildPhases', [member], {
|
|
604
|
+
prepend: true,
|
|
605
|
+
})
|
|
606
|
+
: addBuildPhaseAfter(text, target(), anchor, member);
|
|
607
|
+
anchor = member.uuid;
|
|
608
|
+
}
|
|
609
|
+
for (const member of atEnd) {
|
|
610
|
+
text = addArrayMembers(text, target(), 'buildPhases', [member]);
|
|
611
|
+
}
|
|
612
|
+
return text;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function addBuildPhaseAfter(
|
|
616
|
+
text /*: string */,
|
|
617
|
+
target /*: {bodyOpen: number, bodyClose: number, ...} */,
|
|
618
|
+
afterUuid /*: string */,
|
|
619
|
+
member /*: {uuid: string, comment: string, ...} */,
|
|
620
|
+
) /*: string */ {
|
|
621
|
+
const field = findField(text, target, 'buildPhases');
|
|
622
|
+
if (field == null || field.value.includes(member.uuid)) {
|
|
623
|
+
return text;
|
|
624
|
+
}
|
|
625
|
+
const after = new RegExp(`(^|\\n)([\\t ]*)${afterUuid}\\b[^\\n]*,`).exec(
|
|
626
|
+
field.value,
|
|
627
|
+
);
|
|
628
|
+
if (after == null) {
|
|
629
|
+
return addArrayMembers(text, target, 'buildPhases', [member]);
|
|
630
|
+
}
|
|
631
|
+
const absoluteStart = field.valueStart + after.index;
|
|
632
|
+
const lineEnd = text.indexOf('\n', absoluteStart + after[0].length);
|
|
633
|
+
const indent = after[2];
|
|
634
|
+
const line = `\n${indent}${member.uuid}${uuidComment(member.comment)},`;
|
|
635
|
+
return text.slice(0, lineEnd) + line + text.slice(lineEnd);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// The node + react-native-dir resolution preamble shared by the sync build
|
|
639
|
+
// phase and scheme pre-action. Both dispatch DIRECTLY into react-native's
|
|
640
|
+
// scripts rather than through 'npx react-native' — that CLI requires
|
|
641
|
+
// @react-native-community/cli (absent in e.g. Expo apps), so it would exit
|
|
642
|
+
// non-zero and the failure would be silently swallowed.
|
|
643
|
+
function nodeAndRnDirPreamble(reactNativePath /*: string */) /*: string */ {
|
|
644
|
+
return `set -euo pipefail
|
|
645
|
+
|
|
646
|
+
# ---------------------------------------------------------------------------
|
|
647
|
+
# Resolve a node binary and the react-native package dir at BUILD TIME.
|
|
648
|
+
# ---------------------------------------------------------------------------
|
|
649
|
+
NODE_BINARY="\${NODE_BINARY:-}"
|
|
650
|
+
if [ -z "$NODE_BINARY" ]; then
|
|
651
|
+
# Source RN's standard app-local node-path files. They reference vars that
|
|
652
|
+
# may be unset and may return non-zero, so relax nounset AND errexit while
|
|
653
|
+
# sourcing — a buggy user .xcode.env must degrade to PATH-based node
|
|
654
|
+
# resolution below, not silently abort every build.
|
|
655
|
+
set +eu
|
|
656
|
+
if [ -f "$SRCROOT/.xcode.env" ]; then
|
|
657
|
+
. "$SRCROOT/.xcode.env"
|
|
658
|
+
fi
|
|
659
|
+
if [ -f "$SRCROOT/.xcode.env.local" ]; then
|
|
660
|
+
. "$SRCROOT/.xcode.env.local"
|
|
661
|
+
fi
|
|
662
|
+
set -eu
|
|
663
|
+
NODE_BINARY="\${NODE_BINARY:-}"
|
|
664
|
+
fi
|
|
665
|
+
if [ -z "$NODE_BINARY" ]; then
|
|
666
|
+
NODE_BINARY="$(command -v node 2>/dev/null || true)"
|
|
667
|
+
fi
|
|
668
|
+
|
|
669
|
+
# Resolve react-native's dir FROM THE APP (require.resolve), not a
|
|
670
|
+
# generation-time baked path — the baked path goes stale in pnpm / hoisted
|
|
671
|
+
# stores. Fall back to the baked path if resolution fails or the resolved dir
|
|
672
|
+
# has no setup-apple-spm.js.
|
|
673
|
+
RN_DIR=""
|
|
674
|
+
if [ -n "$NODE_BINARY" ]; then
|
|
675
|
+
RN_DIR="$(cd "$SRCROOT" && "$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json'))" 2>/dev/null || true)"
|
|
676
|
+
fi
|
|
677
|
+
if [ -z "$RN_DIR" ] || [ ! -f "$RN_DIR/scripts/setup-apple-spm.js" ]; then
|
|
678
|
+
RN_DIR="${reactNativePath}"
|
|
679
|
+
fi`;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Shared: the STALE-input check + conditional codegen/autolinking sync dispatch.
|
|
683
|
+
// Runtime framework slots are never touched here; add/update owns them.
|
|
684
|
+
function syncStaleCheckAndDispatch() /*: string */ {
|
|
685
|
+
return `STAMP="$SRCROOT/build/generated/autolinking/.spm-sync-stamp"
|
|
686
|
+
STALE=0
|
|
687
|
+
|
|
688
|
+
# Find project root (where package.json lives — may be an ancestor of SRCROOT)
|
|
689
|
+
PROJECT_ROOT="$SRCROOT"
|
|
690
|
+
while [ "$PROJECT_ROOT" != "/" ] && [ ! -f "$PROJECT_ROOT/package.json" ]; do
|
|
691
|
+
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
692
|
+
done
|
|
693
|
+
if [ ! -f "$PROJECT_ROOT/package.json" ]; then
|
|
694
|
+
PROJECT_ROOT="$SRCROOT"
|
|
695
|
+
fi
|
|
696
|
+
|
|
697
|
+
# Check 1: dependency inputs (covers app projects after any package manager install)
|
|
698
|
+
for INPUT in \\
|
|
699
|
+
"$PROJECT_ROOT/package.json" \\
|
|
700
|
+
"$PROJECT_ROOT/react-native.config.js"; do
|
|
701
|
+
if [ -f "$INPUT" ] && [ "$INPUT" -nt "$STAMP" ]; then
|
|
702
|
+
STALE=1
|
|
703
|
+
break
|
|
704
|
+
fi
|
|
705
|
+
done
|
|
706
|
+
|
|
707
|
+
# Check workspace lockfiles and package-manager metadata. These cover package
|
|
708
|
+
# managers that do not reliably bump node_modules mtimes, and Yarn PnP projects
|
|
709
|
+
# that do not have node_modules at all.
|
|
710
|
+
if [ "$STALE" -eq 0 ]; then
|
|
711
|
+
DIR="$PROJECT_ROOT"
|
|
712
|
+
while [ "$DIR" != "/" ]; do
|
|
713
|
+
for INPUT in \\
|
|
714
|
+
"$DIR/package-lock.json" \\
|
|
715
|
+
"$DIR/npm-shrinkwrap.json" \\
|
|
716
|
+
"$DIR/yarn.lock" \\
|
|
717
|
+
"$DIR/pnpm-lock.yaml" \\
|
|
718
|
+
"$DIR/bun.lock" \\
|
|
719
|
+
"$DIR/bun.lockb" \\
|
|
720
|
+
"$DIR/.pnp.cjs" \\
|
|
721
|
+
"$DIR/.pnp.loader.mjs"; do
|
|
722
|
+
if [ -f "$INPUT" ] && [ "$INPUT" -nt "$STAMP" ]; then
|
|
723
|
+
STALE=1
|
|
724
|
+
break
|
|
725
|
+
fi
|
|
726
|
+
done
|
|
727
|
+
if [ "$STALE" -eq 1 ]; then
|
|
728
|
+
break
|
|
729
|
+
fi
|
|
730
|
+
DIR="$(dirname "$DIR")"
|
|
731
|
+
done
|
|
732
|
+
fi
|
|
733
|
+
|
|
734
|
+
# Check node_modules mtime. In monorepos, node_modules may be hoisted to any
|
|
735
|
+
# ancestor between the app package and the workspace root.
|
|
736
|
+
if [ "$STALE" -eq 0 ]; then
|
|
737
|
+
DIR="$PROJECT_ROOT"
|
|
738
|
+
while [ "$DIR" != "/" ]; do
|
|
739
|
+
NM_DIR="$DIR/node_modules"
|
|
740
|
+
if [ -d "$NM_DIR" ] && [ "$NM_DIR" -nt "$STAMP" ]; then
|
|
741
|
+
STALE=1
|
|
742
|
+
break
|
|
743
|
+
fi
|
|
744
|
+
DIR="$(dirname "$DIR")"
|
|
745
|
+
done
|
|
746
|
+
fi
|
|
747
|
+
|
|
748
|
+
# Also check the app root directly when SRCROOT is not the package root.
|
|
749
|
+
if [ "$STALE" -eq 0 ] && [ "$SRCROOT" != "$PROJECT_ROOT" ]; then
|
|
750
|
+
if [ -d "$SRCROOT/node_modules" ] && [ "$SRCROOT/node_modules" -nt "$STAMP" ]; then
|
|
751
|
+
STALE=1
|
|
752
|
+
fi
|
|
753
|
+
fi
|
|
754
|
+
|
|
755
|
+
# Check 1.5: watched paths (mixed dirs AND files). Dirs catch add/remove of
|
|
756
|
+
# source files in spm.modules and autolinked deps (dir mtime updates on both);
|
|
757
|
+
# files catch edits to a dep's checked-in Package.swift / plugin manifests that
|
|
758
|
+
# would not bump any parent dir mtime. A path that has VANISHED (renamed/moved
|
|
759
|
+
# module root) forces a re-sync so the autolinker surfaces the real, actionable
|
|
760
|
+
# config error rather than the build failing later on dangling-symlink noise.
|
|
761
|
+
WATCH_FILE="$SRCROOT/build/generated/autolinking/.spm-sync-watch-paths"
|
|
762
|
+
if [ "$STALE" -eq 0 ] && [ -f "$WATCH_FILE" ]; then
|
|
763
|
+
while IFS= read -r P; do
|
|
764
|
+
[ -z "$P" ] && continue
|
|
765
|
+
if [ -d "$P" ]; then
|
|
766
|
+
if [ -n "$(find "$P" -newer "$STAMP" -print -quit 2>/dev/null)" ]; then
|
|
767
|
+
STALE=1
|
|
768
|
+
break
|
|
769
|
+
fi
|
|
770
|
+
elif [ -f "$P" ]; then
|
|
771
|
+
if [ "$P" -nt "$STAMP" ]; then
|
|
772
|
+
STALE=1
|
|
773
|
+
break
|
|
774
|
+
fi
|
|
775
|
+
else
|
|
776
|
+
STALE=1
|
|
777
|
+
break
|
|
778
|
+
fi
|
|
779
|
+
done < "$WATCH_FILE"
|
|
780
|
+
fi
|
|
781
|
+
|
|
782
|
+
# Check 2: codegen spec files changed via git (covers monorepo after git pull)
|
|
783
|
+
if [ "$STALE" -eq 0 ] && [ -f "$STAMP" ]; then
|
|
784
|
+
STAMP_TIME=$(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0)
|
|
785
|
+
LATEST_SPEC_COMMIT=$(git -C "$SRCROOT" log -1 --format=%ct -- '*.js' '*.ts' 2>/dev/null || echo 0)
|
|
786
|
+
if [ "$LATEST_SPEC_COMMIT" -gt "$STAMP_TIME" ]; then
|
|
787
|
+
STALE=1
|
|
788
|
+
fi
|
|
789
|
+
fi
|
|
790
|
+
|
|
791
|
+
if [ ! -f "$STAMP" ]; then
|
|
792
|
+
STALE=1
|
|
793
|
+
fi
|
|
794
|
+
|
|
795
|
+
# Re-sync codegen + autolinking when a dependency input changed. Runtime
|
|
796
|
+
# framework slots and Xcode linker settings are only changed by spm update.
|
|
797
|
+
if [ "$STALE" -eq 1 ]; then
|
|
798
|
+
echo "SPM sync inputs changed — re-syncing (codegen + autolinking)..."
|
|
799
|
+
|
|
800
|
+
WITH_ENVIRONMENT="$RN_DIR/scripts/xcode/with-environment.sh"
|
|
801
|
+
|
|
802
|
+
if [ -f "$WITH_ENVIRONMENT" ]; then
|
|
803
|
+
# with-environment.sh references PODS_ROOT and $1, which may be unset.
|
|
804
|
+
# Temporarily disable nounset to avoid failures when sourcing.
|
|
805
|
+
export PODS_ROOT="\${PODS_ROOT:-$SRCROOT}"
|
|
806
|
+
set +u
|
|
807
|
+
. "$WITH_ENVIRONMENT"
|
|
808
|
+
set -u
|
|
809
|
+
fi
|
|
810
|
+
|
|
811
|
+
cd "$SRCROOT"
|
|
812
|
+
# \`|| RC=$?\` so a non-zero exit is CAPTURED rather than aborting the phase
|
|
813
|
+
# under \`set -e\` — the whole point is to branch on the code below (2 = fail
|
|
814
|
+
# the build with a scaffold hint; other non-zero = warn but don't break).
|
|
815
|
+
RC=0
|
|
816
|
+
if [ -n "$NODE_BINARY" ] && [ -f "$RN_DIR/scripts/setup-apple-spm.js" ]; then
|
|
817
|
+
# Direct, dependency-free dispatch (no \`npx react-native\`, which needs
|
|
818
|
+
# @react-native-community/cli).
|
|
819
|
+
"$NODE_BINARY" "$RN_DIR/scripts/setup-apple-spm.js" sync || RC=$?
|
|
820
|
+
elif command -v npx >/dev/null 2>&1; then
|
|
821
|
+
npx react-native spm sync || RC=$?
|
|
822
|
+
else
|
|
823
|
+
echo "warning: node/npx not found — skipping SPM sync"
|
|
824
|
+
fi
|
|
825
|
+
if [ "$RC" -eq 2 ]; then
|
|
826
|
+
# Exit 2 = an autolinked community dependency has no Package.swift. The
|
|
827
|
+
# autolinker already printed an \`error:\` line per dep (so Xcode shows them
|
|
828
|
+
# and the fix). Fail the build — the developer must run
|
|
829
|
+
# \`npx react-native spm scaffold\` from a terminal to generate the manifest.
|
|
830
|
+
exit 1
|
|
831
|
+
elif [ "$RC" -ne 0 ]; then
|
|
832
|
+
echo "warning: SPM sync failed — build may use stale codegen/autolinking"
|
|
833
|
+
fi
|
|
834
|
+
fi
|
|
835
|
+
`;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Scheme pre-action: re-run codegen + autolinking before package resolution.
|
|
839
|
+
function buildSchemePreActionScript(
|
|
840
|
+
reactNativePath /*: string */,
|
|
841
|
+
) /*: string */ {
|
|
842
|
+
return `${nodeAndRnDirPreamble(reactNativePath)}
|
|
843
|
+
|
|
844
|
+
${syncStaleCheckAndDispatch()}
|
|
845
|
+
`;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// The in-target phase is only an autolinking safety net. Runtime framework
|
|
849
|
+
// selection is expressed entirely through build settings and the independent
|
|
850
|
+
// Embed React Native Flavored Frameworks phase.
|
|
851
|
+
function buildSyncAutolinkingScript(
|
|
852
|
+
reactNativePath /*: string */,
|
|
853
|
+
) /*: string */ {
|
|
854
|
+
return `${nodeAndRnDirPreamble(reactNativePath)}
|
|
855
|
+
|
|
856
|
+
${syncStaleCheckAndDispatch()}
|
|
857
|
+
`;
|
|
858
|
+
}
|
|
859
|
+
// XML-attribute escape (the five named entities). The sync script uses `>`
|
|
860
|
+
// and `&` for redirection and bg/and chains, plus `<` for heredocs and
|
|
861
|
+
// comparisons — all of which break Xcode's scheme parser if left raw.
|
|
862
|
+
function escapeXmlAttribute(s /*: string */) /*: string */ {
|
|
863
|
+
return s
|
|
864
|
+
.replace(/&/g, '&')
|
|
865
|
+
.replace(/</g, '<')
|
|
866
|
+
.replace(/>/g, '>')
|
|
867
|
+
.replace(/"/g, '"')
|
|
868
|
+
.replace(/'/g, ''');
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// The inverse of escapeXmlAttribute. `&` is expanded LAST so an entity that
|
|
872
|
+
// was itself escaped (`<` → `&lt;`) round-trips back to its own text
|
|
873
|
+
// rather than to `<`.
|
|
874
|
+
function unescapeXmlAttribute(s /*: string */) /*: string */ {
|
|
875
|
+
return s
|
|
876
|
+
.replace(/</g, '<')
|
|
877
|
+
.replace(/>/g, '>')
|
|
878
|
+
.replace(/"/g, '"')
|
|
879
|
+
.replace(/'/g, "'")
|
|
880
|
+
.replace(/&/g, '&');
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function generateXcscheme(
|
|
884
|
+
appName /*: string */,
|
|
885
|
+
targetUUID /*: string */,
|
|
886
|
+
projName /*: string */,
|
|
887
|
+
syncScript /*: string */,
|
|
888
|
+
) /*: string */ {
|
|
889
|
+
const escapedSync = escapeXmlAttribute(syncScript);
|
|
890
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
891
|
+
<Scheme
|
|
892
|
+
LastUpgradeVersion = "1600"
|
|
893
|
+
version = "1.7">
|
|
894
|
+
<BuildAction
|
|
895
|
+
parallelizeBuildables = "YES"
|
|
896
|
+
buildImplicitDependencies = "YES">
|
|
897
|
+
<PreActions>
|
|
898
|
+
<ExecutionAction
|
|
899
|
+
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
|
900
|
+
<ActionContent
|
|
901
|
+
title = "Sync SPM Autolinking"
|
|
902
|
+
scriptText = "${escapedSync}">
|
|
903
|
+
<EnvironmentBuildable>
|
|
904
|
+
<BuildableReference
|
|
905
|
+
BuildableIdentifier = "primary"
|
|
906
|
+
BlueprintIdentifier = "${targetUUID}"
|
|
907
|
+
BuildableName = "${appName}.app"
|
|
908
|
+
BlueprintName = "${appName}"
|
|
909
|
+
ReferencedContainer = "container:${projName}.xcodeproj">
|
|
910
|
+
</BuildableReference>
|
|
911
|
+
</EnvironmentBuildable>
|
|
912
|
+
</ActionContent>
|
|
913
|
+
</ExecutionAction>
|
|
914
|
+
</PreActions>
|
|
915
|
+
<BuildActionEntries>
|
|
916
|
+
<BuildActionEntry
|
|
917
|
+
buildForTesting = "YES"
|
|
918
|
+
buildForRunning = "YES"
|
|
919
|
+
buildForProfiling = "YES"
|
|
920
|
+
buildForArchiving = "YES"
|
|
921
|
+
buildForAnalyzing = "YES">
|
|
922
|
+
<BuildableReference
|
|
923
|
+
BuildableIdentifier = "primary"
|
|
924
|
+
BlueprintIdentifier = "${targetUUID}"
|
|
925
|
+
BuildableName = "${appName}.app"
|
|
926
|
+
BlueprintName = "${appName}"
|
|
927
|
+
ReferencedContainer = "container:${projName}.xcodeproj">
|
|
928
|
+
</BuildableReference>
|
|
929
|
+
</BuildActionEntry>
|
|
930
|
+
</BuildActionEntries>
|
|
931
|
+
</BuildAction>
|
|
932
|
+
<TestAction
|
|
933
|
+
buildConfiguration = "Debug"
|
|
934
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
935
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
936
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
937
|
+
shouldAutocreateTestPlan = "YES">
|
|
938
|
+
</TestAction>
|
|
939
|
+
<LaunchAction
|
|
940
|
+
buildConfiguration = "Debug"
|
|
941
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
942
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
943
|
+
launchStyle = "0"
|
|
944
|
+
useCustomWorkingDirectory = "NO"
|
|
945
|
+
ignoresPersistentStateOnLaunch = "NO"
|
|
946
|
+
debugDocumentVersioning = "YES"
|
|
947
|
+
debugServiceExtension = "internal"
|
|
948
|
+
allowLocationSimulation = "YES">
|
|
949
|
+
<BuildableProductRunnable
|
|
950
|
+
runnableDebuggingMode = "0">
|
|
951
|
+
<BuildableReference
|
|
952
|
+
BuildableIdentifier = "primary"
|
|
953
|
+
BlueprintIdentifier = "${targetUUID}"
|
|
954
|
+
BuildableName = "${appName}.app"
|
|
955
|
+
BlueprintName = "${appName}"
|
|
956
|
+
ReferencedContainer = "container:${projName}.xcodeproj">
|
|
957
|
+
</BuildableReference>
|
|
958
|
+
</BuildableProductRunnable>
|
|
959
|
+
</LaunchAction>
|
|
960
|
+
<ProfileAction
|
|
961
|
+
buildConfiguration = "Release"
|
|
962
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
963
|
+
savedToolIdentifier = ""
|
|
964
|
+
useCustomWorkingDirectory = "NO"
|
|
965
|
+
debugDocumentVersioning = "YES">
|
|
966
|
+
<BuildableProductRunnable
|
|
967
|
+
runnableDebuggingMode = "0">
|
|
968
|
+
<BuildableReference
|
|
969
|
+
BuildableIdentifier = "primary"
|
|
970
|
+
BlueprintIdentifier = "${targetUUID}"
|
|
971
|
+
BuildableName = "${appName}.app"
|
|
972
|
+
BlueprintName = "${appName}"
|
|
973
|
+
ReferencedContainer = "container:${projName}.xcodeproj">
|
|
974
|
+
</BuildableReference>
|
|
975
|
+
</BuildableProductRunnable>
|
|
976
|
+
</ProfileAction>
|
|
977
|
+
<AnalyzeAction
|
|
978
|
+
buildConfiguration = "Debug">
|
|
979
|
+
</AnalyzeAction>
|
|
980
|
+
<ArchiveAction
|
|
981
|
+
buildConfiguration = "Release"
|
|
982
|
+
revealArchiveInOrganizer = "YES">
|
|
983
|
+
</ArchiveAction>
|
|
984
|
+
</Scheme>
|
|
985
|
+
`;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// When the xcodeproj is generated, the referenced SPM package directories
|
|
989
|
+
// (build/xcframeworks, autolinked, build/generated/ios) may not exist yet.
|
|
990
|
+
// Xcode resolves packages before any build phase runs, so we write minimal
|
|
991
|
+
// stub Package.swift files to let resolution succeed. The real generators
|
|
992
|
+
// (sync-spm-autolinking.js) overwrite these during the first build.
|
|
993
|
+
|
|
994
|
+
/*::
|
|
995
|
+
type StubPackageDef = {
|
|
996
|
+
packageName: string,
|
|
997
|
+
products: Array<string>,
|
|
998
|
+
};
|
|
999
|
+
*/
|
|
1000
|
+
|
|
1001
|
+
function generateStubPackageSwift(def /*: StubPackageDef */) /*: string */ {
|
|
1002
|
+
const {packageName, products} = def;
|
|
1003
|
+
const stubTarget = `${packageName.replace(/[^a-zA-Z0-9]/g, '')}Stub`;
|
|
1004
|
+
const productLines = products
|
|
1005
|
+
.map(p => ` .library(name: "${p}", targets: ["${stubTarget}"]),`)
|
|
1006
|
+
.join('\n');
|
|
1007
|
+
return `// swift-tools-version: 5.9
|
|
1008
|
+
// GENERATED STUB — will be overwritten by sync-spm-autolinking.js during build.
|
|
1009
|
+
import PackageDescription
|
|
1010
|
+
|
|
1011
|
+
let package = Package(
|
|
1012
|
+
name: "${packageName}",
|
|
1013
|
+
products: [
|
|
1014
|
+
${productLines}
|
|
1015
|
+
],
|
|
1016
|
+
targets: [
|
|
1017
|
+
.target(name: "${stubTarget}", path: "_stub", sources: ["Stub.swift"]),
|
|
1018
|
+
]
|
|
1019
|
+
)
|
|
1020
|
+
`;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Ensures each referenced SPM sub-package directory has a valid Package.swift
|
|
1025
|
+
* so Xcode can resolve packages before any build phase runs.
|
|
1026
|
+
* Skips directories that already contain a Package.swift (from a previous build).
|
|
1027
|
+
*/
|
|
1028
|
+
function ensureStubPackages(appRoot /*: string */) /*: void */ {
|
|
1029
|
+
// Derive stub definitions from SPM_PRODUCT_PACKAGES
|
|
1030
|
+
const byPath = new Map /*:: <string, StubPackageDef> */();
|
|
1031
|
+
for (const entry of SPM_PRODUCT_PACKAGES) {
|
|
1032
|
+
const existing = byPath.get(entry.packagePath);
|
|
1033
|
+
if (existing != null) {
|
|
1034
|
+
existing.products.push(entry.product);
|
|
1035
|
+
} else {
|
|
1036
|
+
byPath.set(entry.packagePath, {
|
|
1037
|
+
packageName: entry.packageName,
|
|
1038
|
+
products: [entry.product],
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
for (const [relPath, def] of byPath) {
|
|
1044
|
+
const pkgDir = path.join(appRoot, relPath);
|
|
1045
|
+
const pkgSwiftPath = path.join(pkgDir, 'Package.swift');
|
|
1046
|
+
|
|
1047
|
+
if (fs.existsSync(pkgSwiftPath)) {
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
fs.mkdirSync(pkgDir, {recursive: true});
|
|
1052
|
+
fs.writeFileSync(pkgSwiftPath, generateStubPackageSwift(def), 'utf8');
|
|
1053
|
+
|
|
1054
|
+
// Create minimal stub source file required by SPM
|
|
1055
|
+
const stubDir = path.join(pkgDir, '_stub');
|
|
1056
|
+
fs.mkdirSync(stubDir, {recursive: true});
|
|
1057
|
+
const stubSwift = path.join(stubDir, 'Stub.swift');
|
|
1058
|
+
if (!fs.existsSync(stubSwift)) {
|
|
1059
|
+
fs.writeFileSync(
|
|
1060
|
+
stubSwift,
|
|
1061
|
+
'// Placeholder — replaced during first build.\n',
|
|
1062
|
+
'utf8',
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
log(`Wrote stub Package.swift: ${relPath}/Package.swift`);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// ---------------------------------------------------------------------------
|
|
1071
|
+
// In-place injection: add SPM packages to a user's EXISTING xcodeproj.
|
|
1072
|
+
//
|
|
1073
|
+
// This never creates a target or scans sources — it splices the SPM dependency
|
|
1074
|
+
// graph, the React build settings, and the sync build phase / scheme pre-action
|
|
1075
|
+
// into the project the user already owns, leaving everything else
|
|
1076
|
+
// byte-identical. The whole `spm add` / `spm update` xcodeproj strategy, so
|
|
1077
|
+
// hand-tuned signing / capabilities / extra targets survive. Fails loud (the
|
|
1078
|
+
// caller surfaces the error) when the project is CocoaPods-integrated or its
|
|
1079
|
+
// shape can't be safely anchored.
|
|
1080
|
+
// ---------------------------------------------------------------------------
|
|
1081
|
+
|
|
1082
|
+
// The React build settings the app target needs to compile against the SPM
|
|
1083
|
+
// products.
|
|
1084
|
+
const INJECTED_ARRAY_SETTINGS = [
|
|
1085
|
+
{
|
|
1086
|
+
key: 'HEADER_SEARCH_PATHS',
|
|
1087
|
+
values: ['"$(SRCROOT)/build/generated/autolinking/headers"'],
|
|
1088
|
+
},
|
|
1089
|
+
];
|
|
1090
|
+
|
|
1091
|
+
// Array build settings injected only into debug-flavored configurations.
|
|
1092
|
+
//
|
|
1093
|
+
// Swift's `#if DEBUG` is gated by SWIFT_ACTIVE_COMPILATION_CONDITIONS, NOT by
|
|
1094
|
+
// GCC_PREPROCESSOR_DEFINITIONS (which only reaches C/ObjC/C++). The app
|
|
1095
|
+
// template does not commit the setting: CocoaPods injects it at `pod install`
|
|
1096
|
+
// time (react_native_post_install → set_build_setting
|
|
1097
|
+
// SWIFT_ACTIVE_COMPILATION_CONDITIONS = ["$(inherited)", "DEBUG"] on Debug).
|
|
1098
|
+
// An SPM app never runs CocoaPods, so without this `#if DEBUG` is false even
|
|
1099
|
+
// in a Debug build — AppDelegate.swift's `bundleURL()` skips the Metro URL,
|
|
1100
|
+
// falls back to a main.jsbundle that a Debug build never produced, and the app
|
|
1101
|
+
// dies at launch with "No script url provided … unsanitizedScriptURLString =
|
|
1102
|
+
// (null)" while Metro is running right there.
|
|
1103
|
+
//
|
|
1104
|
+
// Paired with RN_SPM_FLAVOR via flavorForBuildConfiguration, so a config that
|
|
1105
|
+
// links the debug xcframeworks also compiles its Swift with DEBUG.
|
|
1106
|
+
const DEBUG_ARRAY_SETTINGS = [
|
|
1107
|
+
{key: 'SWIFT_ACTIVE_COMPILATION_CONDITIONS', values: ['DEBUG']},
|
|
1108
|
+
];
|
|
1109
|
+
|
|
1110
|
+
/** The XCBuildConfiguration UUIDs of a target (via its buildConfigurationList). */
|
|
1111
|
+
function targetBuildConfigUuids(
|
|
1112
|
+
text /*: string */,
|
|
1113
|
+
targetObj /*: {bodyOpen: number, bodyClose: number, ...} */,
|
|
1114
|
+
) /*: Array<string> */ {
|
|
1115
|
+
const listField = findField(text, targetObj, 'buildConfigurationList');
|
|
1116
|
+
if (listField == null) {
|
|
1117
|
+
return [];
|
|
1118
|
+
}
|
|
1119
|
+
const listMatch = listField.value.match(/[0-9A-Fa-f]{24}/);
|
|
1120
|
+
if (listMatch == null) {
|
|
1121
|
+
return [];
|
|
1122
|
+
}
|
|
1123
|
+
const listObj = findObjectByUuid(text, listMatch[0]);
|
|
1124
|
+
if (listObj == null) {
|
|
1125
|
+
return [];
|
|
1126
|
+
}
|
|
1127
|
+
const configs = findField(text, listObj, 'buildConfigurations');
|
|
1128
|
+
if (configs == null) {
|
|
1129
|
+
return [];
|
|
1130
|
+
}
|
|
1131
|
+
const matches = configs.value.match(/[0-9A-Fa-f]{24}/g);
|
|
1132
|
+
return matches != null ? Array.from(matches) : [];
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/** True when a build config layers a CocoaPods `Pods-*.xcconfig`. */
|
|
1136
|
+
function configUsesPods(
|
|
1137
|
+
text /*: string */,
|
|
1138
|
+
configUuid /*: string */,
|
|
1139
|
+
) /*: boolean */ {
|
|
1140
|
+
const obj = findObjectByUuid(text, configUuid);
|
|
1141
|
+
if (obj == null) {
|
|
1142
|
+
return false;
|
|
1143
|
+
}
|
|
1144
|
+
const base = findField(text, obj, 'baseConfigurationReference');
|
|
1145
|
+
return base != null && /Pods[-/]/.test(base.value);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Inspect an existing pbxproj and decide whether it can be injected. Returns
|
|
1150
|
+
* the chosen app target + its config/frameworks anchors, or a refusal reason
|
|
1151
|
+
* the caller surfaces (fail-loud).
|
|
1152
|
+
*/
|
|
1153
|
+
function planInjection(text /*: string */, opts /*: {appName?: ?string} */) /*:
|
|
1154
|
+
| {ok: true, rootUuid: string, target: {uuid: string, name: string, bodyOpen: number, bodyClose: number}, configUuids: Array<string>, frameworksPhaseUuid: string, sourcesPhaseUuid: ?string}
|
|
1155
|
+
| {ok: false, reason: string} */ {
|
|
1156
|
+
const project = findProjectObject(text);
|
|
1157
|
+
if (project == null) {
|
|
1158
|
+
return {ok: false, reason: 'no PBXProject object found'};
|
|
1159
|
+
}
|
|
1160
|
+
const apps = findApplicationTargets(text);
|
|
1161
|
+
if (apps.length === 0) {
|
|
1162
|
+
return {ok: false, reason: 'no application target found'};
|
|
1163
|
+
}
|
|
1164
|
+
let target;
|
|
1165
|
+
if (apps.length === 1) {
|
|
1166
|
+
target = apps[0];
|
|
1167
|
+
} else {
|
|
1168
|
+
const appName = opts.appName;
|
|
1169
|
+
if (appName == null) {
|
|
1170
|
+
return {
|
|
1171
|
+
ok: false,
|
|
1172
|
+
reason: `multiple application targets (${apps
|
|
1173
|
+
.map(a => a.name)
|
|
1174
|
+
.join(', ')}); pass --app-name to disambiguate`,
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
target = apps.find(a => a.name === appName);
|
|
1178
|
+
if (target == null) {
|
|
1179
|
+
return {
|
|
1180
|
+
ok: false,
|
|
1181
|
+
reason: `no application target named "${appName}"`,
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
const configUuids = targetBuildConfigUuids(text, target);
|
|
1186
|
+
if (configUuids.length === 0) {
|
|
1187
|
+
return {ok: false, reason: 'could not resolve target build configurations'};
|
|
1188
|
+
}
|
|
1189
|
+
if (configUuids.some(c => configUsesPods(text, c))) {
|
|
1190
|
+
return {
|
|
1191
|
+
ok: false,
|
|
1192
|
+
reason:
|
|
1193
|
+
'target uses CocoaPods (Pods-*.xcconfig) — in-place injection only ' +
|
|
1194
|
+
'supports SPM-only targets',
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
// The target's own Frameworks build phase (where product build files link).
|
|
1198
|
+
const buildPhases = findField(text, target, 'buildPhases');
|
|
1199
|
+
const phaseUuids =
|
|
1200
|
+
buildPhases != null
|
|
1201
|
+
? (buildPhases.value.match(/[0-9A-Fa-f]{24}/g) ?? [])
|
|
1202
|
+
: [];
|
|
1203
|
+
let frameworksPhaseUuid = null;
|
|
1204
|
+
// Also capture the Sources phase — plugin generated sources compile into it
|
|
1205
|
+
// (see injectSpmIntoPbxproj step 8). Nullable: a target may legitimately
|
|
1206
|
+
// lack one, in which case generated-source wiring is skipped (not fatal).
|
|
1207
|
+
let sourcesPhaseUuid = null;
|
|
1208
|
+
for (const pu of phaseUuids) {
|
|
1209
|
+
const po = findObjectByUuid(text, pu);
|
|
1210
|
+
if (po == null) {
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
const isa = findField(text, po, 'isa');
|
|
1214
|
+
if (isa == null) {
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
if (
|
|
1218
|
+
frameworksPhaseUuid == null &&
|
|
1219
|
+
/PBXFrameworksBuildPhase/.test(isa.value)
|
|
1220
|
+
) {
|
|
1221
|
+
frameworksPhaseUuid = pu;
|
|
1222
|
+
} else if (
|
|
1223
|
+
sourcesPhaseUuid == null &&
|
|
1224
|
+
/PBXSourcesBuildPhase/.test(isa.value)
|
|
1225
|
+
) {
|
|
1226
|
+
sourcesPhaseUuid = pu;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
if (frameworksPhaseUuid == null) {
|
|
1230
|
+
return {ok: false, reason: 'target has no Frameworks build phase'};
|
|
1231
|
+
}
|
|
1232
|
+
return {
|
|
1233
|
+
ok: true,
|
|
1234
|
+
rootUuid: project.uuid,
|
|
1235
|
+
target,
|
|
1236
|
+
configUuids,
|
|
1237
|
+
frameworksPhaseUuid,
|
|
1238
|
+
sourcesPhaseUuid,
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* Splice the SPM dependency graph + React build settings + sync build phase
|
|
1244
|
+
* into `text` and return the modified pbxproj. Pure string transform (no I/O),
|
|
1245
|
+
* idempotent: objects already present (by UUID) and array members / settings
|
|
1246
|
+
* already applied are skipped, so a second run is a no-op.
|
|
1247
|
+
*/
|
|
1248
|
+
function injectSpmIntoPbxproj(
|
|
1249
|
+
input /*: string */,
|
|
1250
|
+
plan /*: {rootUuid: string, targetUuid: string, configUuids: Array<string>, frameworksPhaseUuid: string, sourcesPhaseUuid?: ?string} */,
|
|
1251
|
+
reactNativePath /*: string */,
|
|
1252
|
+
remote /*: ?RemoteCfg */,
|
|
1253
|
+
hermesCliPath /*: ?string */ = null,
|
|
1254
|
+
generatedSources /*: ReadonlyArray<GeneratedSource> */ = [],
|
|
1255
|
+
flavoredFrameworks /*: ReadonlyArray<FlavoredFrameworkManifestEntry> */ = [],
|
|
1256
|
+
scriptPhases /*: ReadonlyArray<PluginScriptPhase> */ = [],
|
|
1257
|
+
) /*: {text: string, injectedUuids: Array<string>, createdArrayFields: Array<CreatedArrayField>, buildSettingChanges: Array<BuildSettingChange>, generatedSourceUuids: {[string]: Array<string>}, scriptPhaseUuids: {[string]: string}} */ {
|
|
1258
|
+
let text = input;
|
|
1259
|
+
const mkUuid = (section /*: string */, id /*: string */) =>
|
|
1260
|
+
namespacedUUID(plan.rootUuid, section, id);
|
|
1261
|
+
const graph = buildSpmDependencyGraph(mkUuid, remote);
|
|
1262
|
+
const entries = spmGraphToEntries(graph);
|
|
1263
|
+
const injectedUuids /*: Array<string> */ = [];
|
|
1264
|
+
|
|
1265
|
+
// 1. Insert the new objects (skip any UUID already present — idempotency).
|
|
1266
|
+
const insertObjects = (
|
|
1267
|
+
sectionName /*: string */,
|
|
1268
|
+
objs /*: ReadonlyArray<{readonly uuid: string, readonly comment?: ?string, readonly fields: {readonly [string]: string}, ...}> */,
|
|
1269
|
+
) => {
|
|
1270
|
+
const fresh = objs.filter(o => !text.includes(o.uuid));
|
|
1271
|
+
for (const o of objs) {
|
|
1272
|
+
injectedUuids.push(o.uuid);
|
|
1273
|
+
}
|
|
1274
|
+
if (fresh.length === 0) {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
text = insertObjectsIntoSection(
|
|
1278
|
+
text,
|
|
1279
|
+
sectionName,
|
|
1280
|
+
fresh.map(serializeEntry).join('\n'),
|
|
1281
|
+
);
|
|
1282
|
+
};
|
|
1283
|
+
insertObjects('XCLocalSwiftPackageReference', entries.localRefs);
|
|
1284
|
+
if (entries.remoteRef != null) {
|
|
1285
|
+
insertObjects('XCRemoteSwiftPackageReference', [entries.remoteRef]);
|
|
1286
|
+
}
|
|
1287
|
+
insertObjects('XCSwiftPackageProductDependency', entries.productDeps);
|
|
1288
|
+
insertObjects('PBXBuildFile', entries.buildFiles);
|
|
1289
|
+
|
|
1290
|
+
const createdArrayFields /*: Array<CreatedArrayField> */ = [];
|
|
1291
|
+
|
|
1292
|
+
// 2. packageReferences on the PBXProject.
|
|
1293
|
+
const pkgRefMembers = [
|
|
1294
|
+
...(graph.remotePkgRef != null
|
|
1295
|
+
? [{uuid: graph.remotePkgRef.uuid, comment: graph.remotePkgRef.comment}]
|
|
1296
|
+
: []),
|
|
1297
|
+
...graph.localPkgRefs.map(r => ({uuid: r.uuid, comment: r.comment})),
|
|
1298
|
+
];
|
|
1299
|
+
const project = findProjectObject(text);
|
|
1300
|
+
if (project != null) {
|
|
1301
|
+
if (findField(text, project, 'packageReferences') == null) {
|
|
1302
|
+
createdArrayFields.push({container: 'project', key: 'packageReferences'});
|
|
1303
|
+
}
|
|
1304
|
+
text = addArrayMembers(text, project, 'packageReferences', pkgRefMembers);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// 3. packageProductDependencies on the app target.
|
|
1308
|
+
const productMembers = graph.products.map(p => ({
|
|
1309
|
+
uuid: p.depUuid,
|
|
1310
|
+
comment: p.product,
|
|
1311
|
+
}));
|
|
1312
|
+
if (
|
|
1313
|
+
findField(
|
|
1314
|
+
text,
|
|
1315
|
+
findApplicationTargetByUuid(text, plan.targetUuid),
|
|
1316
|
+
'packageProductDependencies',
|
|
1317
|
+
) == null
|
|
1318
|
+
) {
|
|
1319
|
+
createdArrayFields.push({
|
|
1320
|
+
container: 'target',
|
|
1321
|
+
key: 'packageProductDependencies',
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
text = addArrayMembers(
|
|
1325
|
+
text,
|
|
1326
|
+
findApplicationTargetByUuid(text, plan.targetUuid),
|
|
1327
|
+
'packageProductDependencies',
|
|
1328
|
+
productMembers,
|
|
1329
|
+
);
|
|
1330
|
+
|
|
1331
|
+
// 4. product build files into the target's Frameworks phase.
|
|
1332
|
+
const phase = findObjectByUuid(text, plan.frameworksPhaseUuid);
|
|
1333
|
+
if (phase != null) {
|
|
1334
|
+
text = addArrayMembers(
|
|
1335
|
+
text,
|
|
1336
|
+
phase,
|
|
1337
|
+
'files',
|
|
1338
|
+
graph.products.map(p => ({
|
|
1339
|
+
uuid: p.buildFileUuid,
|
|
1340
|
+
comment: `${p.product} in Frameworks`,
|
|
1341
|
+
})),
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
// 5. React build settings into every build config (Debug + Release).
|
|
1346
|
+
const buildSettingChanges /*: Array<BuildSettingChange> */ = [];
|
|
1347
|
+
for (const configUuid of plan.configUuids) {
|
|
1348
|
+
const merged = mergeReactBuildSettings(
|
|
1349
|
+
text,
|
|
1350
|
+
configUuid,
|
|
1351
|
+
buildConfigurationName(text, configUuid),
|
|
1352
|
+
reactNativePath,
|
|
1353
|
+
hermesCliPath,
|
|
1354
|
+
flavoredFrameworks,
|
|
1355
|
+
);
|
|
1356
|
+
text = merged.text;
|
|
1357
|
+
buildSettingChanges.push(merged.change);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// 6. The Sync SPM Autolinking build phase (safety net; the scheme pre-action
|
|
1361
|
+
// is what fires before SPM resolution). Prepended so it runs before
|
|
1362
|
+
// Sources. We do NOT add a JS-bundle phase — an existing app already
|
|
1363
|
+
// bundles JS via its own phase.
|
|
1364
|
+
const syncScript = buildSyncAutolinkingScript(reactNativePath);
|
|
1365
|
+
const syncPhaseUuid = mkUuid('PBXShellScriptBuildPhase', 'SyncAutolinking');
|
|
1366
|
+
if (!text.includes(syncPhaseUuid)) {
|
|
1367
|
+
text = insertObjectsIntoSection(
|
|
1368
|
+
text,
|
|
1369
|
+
'PBXShellScriptBuildPhase',
|
|
1370
|
+
serializeEntry(
|
|
1371
|
+
shellScriptPhase(syncPhaseUuid, 'Sync SPM Autolinking', syncScript),
|
|
1372
|
+
),
|
|
1373
|
+
);
|
|
1374
|
+
} else {
|
|
1375
|
+
// Already injected on a prior run — the phase object owns its
|
|
1376
|
+
// shellScript, so refresh it in place (same quoting used at creation) in
|
|
1377
|
+
// case the generated script changed since. Byte-identical when it
|
|
1378
|
+
// didn't; field order and every other byte of the phase are untouched.
|
|
1379
|
+
const existingPhase = findObjectByUuid(text, syncPhaseUuid);
|
|
1380
|
+
if (existingPhase != null) {
|
|
1381
|
+
text = setScalarField(
|
|
1382
|
+
text,
|
|
1383
|
+
existingPhase,
|
|
1384
|
+
'shellScript',
|
|
1385
|
+
quoteIfNeeded(syncScript),
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
injectedUuids.push(syncPhaseUuid);
|
|
1390
|
+
text = addArrayMembers(
|
|
1391
|
+
text,
|
|
1392
|
+
findApplicationTargetByUuid(text, plan.targetUuid),
|
|
1393
|
+
'buildPhases',
|
|
1394
|
+
[{uuid: syncPhaseUuid, comment: 'Sync SPM Autolinking'}],
|
|
1395
|
+
{prepend: true},
|
|
1396
|
+
);
|
|
1397
|
+
|
|
1398
|
+
// 7. The sole writer of flavored frameworks under the final app bundle.
|
|
1399
|
+
// SwiftPM owns only invariant header/source products, so no implicit SPM
|
|
1400
|
+
// embed task competes with this phase.
|
|
1401
|
+
const embedPhaseUuid = mkUuid(
|
|
1402
|
+
'PBXShellScriptBuildPhase',
|
|
1403
|
+
'EmbedFlavoredFrameworks',
|
|
1404
|
+
);
|
|
1405
|
+
const embedScript = buildEmbedFrameworksScript(flavoredFrameworks);
|
|
1406
|
+
const embedInputs = [
|
|
1407
|
+
'$(SRCROOT)/build/xcframeworks/.artifact-stamp',
|
|
1408
|
+
...flavoredFrameworks.map(
|
|
1409
|
+
framework => `$(${frameworkSettingPrefix(framework.id)}_FRAMEWORK)`,
|
|
1410
|
+
),
|
|
1411
|
+
];
|
|
1412
|
+
const embedOutputs = flavoredFrameworks.map(
|
|
1413
|
+
framework =>
|
|
1414
|
+
`$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/${framework.frameworkName}.framework`,
|
|
1415
|
+
);
|
|
1416
|
+
const embedEntry = shellScriptPhase(
|
|
1417
|
+
embedPhaseUuid,
|
|
1418
|
+
'Embed React Native Flavored Frameworks',
|
|
1419
|
+
embedScript,
|
|
1420
|
+
{
|
|
1421
|
+
inputPaths: pbxPathList(embedInputs),
|
|
1422
|
+
outputPaths: pbxPathList(embedOutputs),
|
|
1423
|
+
},
|
|
1424
|
+
);
|
|
1425
|
+
if (!text.includes(embedPhaseUuid)) {
|
|
1426
|
+
text = insertObjectsIntoSection(
|
|
1427
|
+
text,
|
|
1428
|
+
'PBXShellScriptBuildPhase',
|
|
1429
|
+
serializeEntry(embedEntry),
|
|
1430
|
+
);
|
|
1431
|
+
} else {
|
|
1432
|
+
const existingPhase = findObjectByUuid(text, embedPhaseUuid);
|
|
1433
|
+
if (existingPhase != null) {
|
|
1434
|
+
for (const key of ['shellScript', 'inputPaths', 'outputPaths']) {
|
|
1435
|
+
const current = findObjectByUuid(text, embedPhaseUuid);
|
|
1436
|
+
if (current != null) {
|
|
1437
|
+
text = setScalarField(text, current, key, embedEntry.fields[key]);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
injectedUuids.push(embedPhaseUuid);
|
|
1443
|
+
text = addBuildPhaseAfter(
|
|
1444
|
+
text,
|
|
1445
|
+
findApplicationTargetByUuid(text, plan.targetUuid),
|
|
1446
|
+
plan.frameworksPhaseUuid,
|
|
1447
|
+
{
|
|
1448
|
+
uuid: embedPhaseUuid,
|
|
1449
|
+
comment: 'Embed React Native Flavored Frameworks',
|
|
1450
|
+
},
|
|
1451
|
+
);
|
|
1452
|
+
|
|
1453
|
+
// 8. Plugin generated sources compiled INTO THE APP TARGET (e.g. Expo's
|
|
1454
|
+
// ExpoModulesProvider.swift). An `@objc` class only reaches the ObjC
|
|
1455
|
+
// classlist — required for NSClassFromString discovery — when it compiles
|
|
1456
|
+
// into the app target, not the static Autolinked aggregate. Each source
|
|
1457
|
+
// gets a PBXFileReference + PBXBuildFile + a Sources-phase entry, parented
|
|
1458
|
+
// under a single "SPM Generated Sources" group. Every UUID is keyed on the
|
|
1459
|
+
// normalized path (deterministic → idempotent) and recorded so `deinit`
|
|
1460
|
+
// reverts it and `update` reconciles it (removal is done by the caller,
|
|
1461
|
+
// which owns the prior marker; emission here is purely additive).
|
|
1462
|
+
const generatedSourceUuids /*: {[string]: Array<string>} */ = {};
|
|
1463
|
+
const sourcesPhaseUuid = plan.sourcesPhaseUuid;
|
|
1464
|
+
if (generatedSources.length > 0) {
|
|
1465
|
+
if (sourcesPhaseUuid == null) {
|
|
1466
|
+
log(
|
|
1467
|
+
'warning: the app target has no Sources build phase — cannot compile ' +
|
|
1468
|
+
`${generatedSources.length} SPM plugin generated source(s) into the ` +
|
|
1469
|
+
'app target; skipping. Any @objc classes they define will not be ' +
|
|
1470
|
+
'discoverable via NSClassFromString.',
|
|
1471
|
+
);
|
|
1472
|
+
} else {
|
|
1473
|
+
const fileRefs = [];
|
|
1474
|
+
const buildFiles = [];
|
|
1475
|
+
const sourcesMembers = [];
|
|
1476
|
+
const groupChildren = [];
|
|
1477
|
+
for (const src of generatedSources) {
|
|
1478
|
+
const fileRefUuid = mkUuid('PBXFileReference', `gensrc:${src.path}`);
|
|
1479
|
+
const buildFileUuid = mkUuid('PBXBuildFile', `gensrc:${src.path}`);
|
|
1480
|
+
generatedSourceUuids[src.path] = [fileRefUuid, buildFileUuid];
|
|
1481
|
+
// The name/path VALUES stay verbatim (escaped) — only the cosmetic
|
|
1482
|
+
// comments are normalized, falling back to the normalized path (the
|
|
1483
|
+
// ledger key) and then to no comment at all, which is well-formed.
|
|
1484
|
+
const label = commentSafe(src.name) || commentSafe(src.path);
|
|
1485
|
+
const inSources = label === '' ? '' : `${label} in Sources`;
|
|
1486
|
+
fileRefs.push({
|
|
1487
|
+
uuid: fileRefUuid,
|
|
1488
|
+
comment: label,
|
|
1489
|
+
fields: {
|
|
1490
|
+
isa: 'PBXFileReference',
|
|
1491
|
+
lastKnownFileType: src.fileType,
|
|
1492
|
+
name: quoteIfNeeded(src.name),
|
|
1493
|
+
path: quoteIfNeeded(src.path),
|
|
1494
|
+
sourceTree: src.sourceTree,
|
|
1495
|
+
},
|
|
1496
|
+
});
|
|
1497
|
+
buildFiles.push({
|
|
1498
|
+
uuid: buildFileUuid,
|
|
1499
|
+
comment: inSources,
|
|
1500
|
+
fields: {
|
|
1501
|
+
isa: 'PBXBuildFile',
|
|
1502
|
+
fileRef: `${fileRefUuid}${uuidComment(label)}`,
|
|
1503
|
+
},
|
|
1504
|
+
});
|
|
1505
|
+
sourcesMembers.push({uuid: buildFileUuid, comment: inSources});
|
|
1506
|
+
groupChildren.push({uuid: fileRefUuid, comment: label});
|
|
1507
|
+
}
|
|
1508
|
+
insertObjects('PBXFileReference', fileRefs);
|
|
1509
|
+
insertObjects('PBXBuildFile', buildFiles);
|
|
1510
|
+
|
|
1511
|
+
// Compile membership — the actual reason these are wired into the app.
|
|
1512
|
+
const sourcesPhase = findObjectByUuid(text, sourcesPhaseUuid);
|
|
1513
|
+
if (sourcesPhase != null) {
|
|
1514
|
+
text = addArrayMembers(text, sourcesPhase, 'files', sourcesMembers);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
// The "SPM Generated Sources" group (created on first use, then reused).
|
|
1518
|
+
// Insert with empty children so the ONE population path (addArrayMembers)
|
|
1519
|
+
// handles both create and reconcile, keeping formatting identical.
|
|
1520
|
+
const groupUuid = mkUuid('PBXGroup', SPM_GENERATED_SOURCES_GROUP_ID);
|
|
1521
|
+
if (!text.includes(groupUuid)) {
|
|
1522
|
+
text = insertObjectsIntoSection(
|
|
1523
|
+
text,
|
|
1524
|
+
'PBXGroup',
|
|
1525
|
+
serializeEntry({
|
|
1526
|
+
uuid: groupUuid,
|
|
1527
|
+
comment: SPM_GENERATED_SOURCES_GROUP_NAME,
|
|
1528
|
+
fields: {
|
|
1529
|
+
isa: 'PBXGroup',
|
|
1530
|
+
children: '(\n\t\t\t)',
|
|
1531
|
+
name: quoteIfNeeded(SPM_GENERATED_SOURCES_GROUP_NAME),
|
|
1532
|
+
sourceTree: '"<group>"',
|
|
1533
|
+
},
|
|
1534
|
+
}),
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
injectedUuids.push(groupUuid);
|
|
1538
|
+
const groupObj = findObjectByUuid(text, groupUuid);
|
|
1539
|
+
if (groupObj != null) {
|
|
1540
|
+
text = addArrayMembers(text, groupObj, 'children', groupChildren);
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
// Parent the group under the project's main group (idempotent). Appends
|
|
1544
|
+
// to a pre-existing children array, so no createdArrayField is recorded —
|
|
1545
|
+
// deinit removes the group's membership via removeArrayMembersByUuid and
|
|
1546
|
+
// the group object itself via removeObjectByUuid (groupUuid is injected).
|
|
1547
|
+
const proj = findProjectObject(text);
|
|
1548
|
+
const mainGroupField =
|
|
1549
|
+
proj != null ? findField(text, proj, 'mainGroup') : null;
|
|
1550
|
+
const mainGroupMatch =
|
|
1551
|
+
mainGroupField != null
|
|
1552
|
+
? mainGroupField.value.match(/[0-9A-Fa-f]{24}/)
|
|
1553
|
+
: null;
|
|
1554
|
+
const mainGroupObj =
|
|
1555
|
+
mainGroupMatch != null
|
|
1556
|
+
? findObjectByUuid(text, mainGroupMatch[0])
|
|
1557
|
+
: null;
|
|
1558
|
+
if (mainGroupObj != null) {
|
|
1559
|
+
text = addArrayMembers(text, mainGroupObj, 'children', [
|
|
1560
|
+
{uuid: groupUuid, comment: SPM_GENERATED_SOURCES_GROUP_NAME},
|
|
1561
|
+
]);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
// 9. Plugin-declared build phases (SwiftPM has no `script_phase`). Each
|
|
1567
|
+
// phase's UUID is keyed on its plugin id, so re-runs refresh in place and
|
|
1568
|
+
// `deinit` reverses it.
|
|
1569
|
+
const scriptPhaseUuids /*: {[string]: string} */ = {};
|
|
1570
|
+
if (scriptPhases.length > 0) {
|
|
1571
|
+
const seated /*: Array<SeatedPhase> */ = [];
|
|
1572
|
+
for (const scriptPhase of scriptPhases) {
|
|
1573
|
+
const uuid = mkUuid(
|
|
1574
|
+
'PBXShellScriptBuildPhase',
|
|
1575
|
+
`plugin:${scriptPhase.id}`,
|
|
1576
|
+
);
|
|
1577
|
+
scriptPhaseUuids[scriptPhase.id] = uuid;
|
|
1578
|
+
// The full name goes into the `name` field (escaped) — that is what Xcode
|
|
1579
|
+
// displays. The cosmetic comments get it normalized, falling back to the
|
|
1580
|
+
// normalized id and then to no comment at all, which is well-formed. The
|
|
1581
|
+
// fallback is sanitized rather than trusted to the id charset, so widening
|
|
1582
|
+
// that charset can never reach a comment.
|
|
1583
|
+
const comment =
|
|
1584
|
+
commentSafe(scriptPhase.name) || commentSafe(scriptPhase.id);
|
|
1585
|
+
const entry = shellScriptPhase(
|
|
1586
|
+
uuid,
|
|
1587
|
+
scriptPhase.name,
|
|
1588
|
+
scriptPhase.script,
|
|
1589
|
+
{
|
|
1590
|
+
inputPaths: scriptPhase.inputPaths,
|
|
1591
|
+
outputPaths: scriptPhase.outputPaths,
|
|
1592
|
+
alwaysOutOfDate: scriptPhase.alwaysOutOfDate,
|
|
1593
|
+
comment,
|
|
1594
|
+
},
|
|
1595
|
+
);
|
|
1596
|
+
if (!text.includes(uuid)) {
|
|
1597
|
+
text = insertObjectsIntoSection(
|
|
1598
|
+
text,
|
|
1599
|
+
'PBXShellScriptBuildPhase',
|
|
1600
|
+
serializeEntry(entry),
|
|
1601
|
+
);
|
|
1602
|
+
} else {
|
|
1603
|
+
// Rewrite the fields we own unconditionally — byte-identical when the
|
|
1604
|
+
// plugin's declaration hasn't changed, so no content hashing is needed.
|
|
1605
|
+
// Each write shifts offsets, hence the re-lookup per field.
|
|
1606
|
+
for (const key of [
|
|
1607
|
+
'name',
|
|
1608
|
+
'shellScript',
|
|
1609
|
+
'inputPaths',
|
|
1610
|
+
'outputPaths',
|
|
1611
|
+
]) {
|
|
1612
|
+
const current = findObjectByUuid(text, uuid);
|
|
1613
|
+
if (current != null) {
|
|
1614
|
+
text = setScalarField(text, current, key, entry.fields[key]);
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
// Flipping alwaysOutOfDate back off means REMOVING the field —
|
|
1618
|
+
// setScalarField would only ever write a value.
|
|
1619
|
+
const current = findObjectByUuid(text, uuid);
|
|
1620
|
+
if (current != null) {
|
|
1621
|
+
text =
|
|
1622
|
+
scriptPhase.alwaysOutOfDate === true
|
|
1623
|
+
? setScalarField(text, current, 'alwaysOutOfDate', '1')
|
|
1624
|
+
: removeField(text, current, 'alwaysOutOfDate');
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
injectedUuids.push(uuid);
|
|
1628
|
+
text = setUuidComment(text, uuid, comment);
|
|
1629
|
+
seated.push({uuid, comment, position: scriptPhase.position});
|
|
1630
|
+
}
|
|
1631
|
+
text = seatScriptPhases(
|
|
1632
|
+
text,
|
|
1633
|
+
plan.targetUuid,
|
|
1634
|
+
syncPhaseUuid,
|
|
1635
|
+
seated,
|
|
1636
|
+
sourcesPhaseUuid,
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return {
|
|
1641
|
+
text,
|
|
1642
|
+
injectedUuids,
|
|
1643
|
+
createdArrayFields,
|
|
1644
|
+
buildSettingChanges,
|
|
1645
|
+
generatedSourceUuids,
|
|
1646
|
+
scriptPhaseUuids,
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
/** Re-locate an application target by UUID against the current text. */
|
|
1651
|
+
function findApplicationTargetByUuid(
|
|
1652
|
+
text /*: string */,
|
|
1653
|
+
targetUuid /*: string */,
|
|
1654
|
+
) /*: {uuid: string, bodyOpen: number, bodyClose: number} */ {
|
|
1655
|
+
const obj = findObjectByUuid(text, targetUuid);
|
|
1656
|
+
if (obj == null) {
|
|
1657
|
+
throw new Error(`pbxproj: app target ${targetUuid} disappeared mid-edit`);
|
|
1658
|
+
}
|
|
1659
|
+
return obj;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
/**
|
|
1663
|
+
* Merge the React build settings into one XCBuildConfiguration's dict. Returns
|
|
1664
|
+
* the modified text plus a precise record of what was actually added — so
|
|
1665
|
+
* `deinit` (removeSpmInjection) can reverse exactly these edits, never touching
|
|
1666
|
+
* a value the user already had (key insight: ensureScalarField/
|
|
1667
|
+
* addArrayStringValues are no-ops / dedupe when a value is already present).
|
|
1668
|
+
*/
|
|
1669
|
+
/**
|
|
1670
|
+
* Resolves the host `hermesc` from the `hermes-compiler` npm package and returns
|
|
1671
|
+
* its ABSOLUTE path as the HERMES_CLI_PATH value, or null when it can't be found
|
|
1672
|
+
* (e.g. USE_HERMES=false apps without the package). require.resolve (anchored at
|
|
1673
|
+
* reactNativeRoot) follows Node's lookup, so a hoisted monorepo layout — where
|
|
1674
|
+
* hermes-compiler sits in the workspace-root node_modules, NOT next to
|
|
1675
|
+
* react-native — resolves correctly.
|
|
1676
|
+
*
|
|
1677
|
+
* The value is intentionally ABSOLUTE, not `$(REACT_NATIVE_PATH)/../...`: when
|
|
1678
|
+
* react-native is a symlink (the monorepo default, and common in real apps), a
|
|
1679
|
+
* `..` after it resolves — kernel-side — to the symlink TARGET's parent, not the
|
|
1680
|
+
* node_modules dir, so the relative form points at a non-existent
|
|
1681
|
+
* `<rn-target>/../hermes-compiler`. An absolute path sidesteps that entirely
|
|
1682
|
+
* (and matches how the CocoaPods hermes-engine pod sets HERMES_CLI_PATH). It is
|
|
1683
|
+
* regenerated on every `spm add`, so machine-specificity is a non-issue.
|
|
1684
|
+
*/
|
|
1685
|
+
function resolveHermesCliPathSetting(
|
|
1686
|
+
reactNativeRoot /*: string */,
|
|
1687
|
+
) /*: ?string */ {
|
|
1688
|
+
try {
|
|
1689
|
+
const pkg = require.resolve('hermes-compiler/package.json', {
|
|
1690
|
+
paths: [reactNativeRoot],
|
|
1691
|
+
});
|
|
1692
|
+
const hermesc = path.join(
|
|
1693
|
+
path.dirname(pkg),
|
|
1694
|
+
'hermesc',
|
|
1695
|
+
'osx-bin',
|
|
1696
|
+
'hermesc',
|
|
1697
|
+
);
|
|
1698
|
+
return fs.existsSync(hermesc) ? hermesc : null;
|
|
1699
|
+
} catch {
|
|
1700
|
+
return null;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
/** Strip the surrounding plist quotes from a build-setting token, if any. */
|
|
1705
|
+
function unquotePlist(s /*: string */) /*: string */ {
|
|
1706
|
+
return s.replace(/^"/, '').replace(/"$/, '');
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/**
|
|
1710
|
+
* The individual values a build setting already carries, unquoted — for both
|
|
1711
|
+
* shapes a pbxproj uses: the array form Xcode writes for a multi-value setting
|
|
1712
|
+
* (`("$(inherited)", DEBUG)`) and the scalar form the app template and
|
|
1713
|
+
* hand-edits use (`"$(inherited) DEBUG"`). Membership, not substring: the
|
|
1714
|
+
* latter would read `MY_DEBUG_FLAG` as `DEBUG` already being set and silently
|
|
1715
|
+
* skip the injection.
|
|
1716
|
+
*/
|
|
1717
|
+
function buildSettingValueTokens(value /*: string */) /*: Set<string> */ {
|
|
1718
|
+
return new Set(
|
|
1719
|
+
value
|
|
1720
|
+
.split(/[\s,()]+/)
|
|
1721
|
+
.filter(Boolean)
|
|
1722
|
+
.map(unquotePlist),
|
|
1723
|
+
);
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
function mergeReactBuildSettings(
|
|
1727
|
+
input /*: string */,
|
|
1728
|
+
configUuid /*: string */,
|
|
1729
|
+
configurationName /*: string */,
|
|
1730
|
+
reactNativePath /*: string */,
|
|
1731
|
+
hermesCliPath /*: ?string */ = null,
|
|
1732
|
+
flavoredFrameworks /*: ReadonlyArray<FlavoredFrameworkManifestEntry> */ = [],
|
|
1733
|
+
) /*: {text: string, change: BuildSettingChange} */ {
|
|
1734
|
+
let text = input;
|
|
1735
|
+
const scalars = [
|
|
1736
|
+
{key: 'CLANG_CXX_LANGUAGE_STANDARD', value: '"c++20"'},
|
|
1737
|
+
{key: 'REACT_NATIVE_PATH', value: quoteIfNeeded(reactNativePath)},
|
|
1738
|
+
// Under SwiftPM there is no hermes-engine pod, so react-native-xcode.sh's
|
|
1739
|
+
// fallback ($PODS_ROOT/hermes-engine/destroot/bin/hermesc) resolves to a
|
|
1740
|
+
// non-existent "/hermes-engine/..." and the Release JS→Hermes bundling
|
|
1741
|
+
// fails. Point HERMES_CLI_PATH at the hermes-compiler npm package's host
|
|
1742
|
+
// hermesc (an ABSOLUTE path resolved by the caller — see
|
|
1743
|
+
// resolveHermesCliPathSetting). react-native-xcode.sh honors an already-set
|
|
1744
|
+
// HERMES_CLI_PATH before its pod fallback; ensureScalarField leaves any
|
|
1745
|
+
// user-provided value untouched.
|
|
1746
|
+
...(hermesCliPath != null
|
|
1747
|
+
? [{key: 'HERMES_CLI_PATH', value: quoteIfNeeded(hermesCliPath)}]
|
|
1748
|
+
: []),
|
|
1749
|
+
];
|
|
1750
|
+
// Re-locate the buildSettings dict before each edit (offsets shift).
|
|
1751
|
+
const dict = () => {
|
|
1752
|
+
const cfg = findObjectByUuid(text, configUuid);
|
|
1753
|
+
if (cfg == null) {
|
|
1754
|
+
return null;
|
|
1755
|
+
}
|
|
1756
|
+
const bs = findField(text, cfg, 'buildSettings');
|
|
1757
|
+
if (bs == null) {
|
|
1758
|
+
return null;
|
|
1759
|
+
}
|
|
1760
|
+
return {
|
|
1761
|
+
uuid: configUuid,
|
|
1762
|
+
bodyOpen: bs.valueStart,
|
|
1763
|
+
bodyClose: bs.tokenEnd - 1,
|
|
1764
|
+
};
|
|
1765
|
+
};
|
|
1766
|
+
const createdArrayKeys /*: Array<string> */ = [];
|
|
1767
|
+
const appendedArrayValues /*: {[string]: Array<string>} */ = {};
|
|
1768
|
+
const promotedArrayScalars /*: {[string]: string} */ = {};
|
|
1769
|
+
const createdScalars /*: Array<string> */ = [];
|
|
1770
|
+
const arraySettings = [
|
|
1771
|
+
...INJECTED_ARRAY_SETTINGS,
|
|
1772
|
+
...(flavorForBuildConfiguration(configurationName) === 'debug'
|
|
1773
|
+
? DEBUG_ARRAY_SETTINGS
|
|
1774
|
+
: []),
|
|
1775
|
+
...frameworkArrayBuildSettings(flavoredFrameworks),
|
|
1776
|
+
];
|
|
1777
|
+
for (const {key, values} of arraySettings) {
|
|
1778
|
+
const d = dict();
|
|
1779
|
+
if (d == null) {
|
|
1780
|
+
continue;
|
|
1781
|
+
}
|
|
1782
|
+
const existing = findField(text, d, key);
|
|
1783
|
+
// Non-null only for a scalar addArrayStringValues would promote to an array
|
|
1784
|
+
// (same array-vs-scalar test it uses). Kept RAW: findField's token for a
|
|
1785
|
+
// bare scalar ends at the `;`, so it carries any whitespace before it, and
|
|
1786
|
+
// deinit has to write those bytes back verbatim.
|
|
1787
|
+
const priorScalar =
|
|
1788
|
+
existing != null && !existing.value.trimStart().startsWith('(')
|
|
1789
|
+
? existing.value
|
|
1790
|
+
: null;
|
|
1791
|
+
if (existing == null) {
|
|
1792
|
+
createdArrayKeys.push(key);
|
|
1793
|
+
} else {
|
|
1794
|
+
const present = buildSettingValueTokens(existing.value);
|
|
1795
|
+
const fresh = values.filter(v => !present.has(unquotePlist(v)));
|
|
1796
|
+
if (fresh.length === 0) {
|
|
1797
|
+
// Nothing to add. Skip addArrayStringValues entirely: its dedupe is by
|
|
1798
|
+
// EXACT array member, so a value the user carries in the scalar form
|
|
1799
|
+
// (`SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"`) would
|
|
1800
|
+
// otherwise be promoted to an array and re-appended — an edit `deinit`
|
|
1801
|
+
// has no record of and so could never reverse.
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
if (priorScalar == null) {
|
|
1805
|
+
appendedArrayValues[key] = fresh;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
const beforeAdd = text;
|
|
1809
|
+
text = addArrayStringValues(text, d, key, values);
|
|
1810
|
+
// Record only a promotion that actually happened: addArrayStringValues
|
|
1811
|
+
// no-ops when `values` is empty or every value is already a member, and a
|
|
1812
|
+
// recorded-but-untouched field would have deinit clobber whatever the user
|
|
1813
|
+
// has there by then. Restoring the scalar subsumes removing the injected
|
|
1814
|
+
// members, so the two records stay mutually exclusive per key.
|
|
1815
|
+
if (priorScalar != null && text !== beforeAdd) {
|
|
1816
|
+
promotedArrayScalars[key] = priorScalar;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
const replacedScalars /*: {[string]: string} */ = {};
|
|
1820
|
+
for (const {key, value} of scalars) {
|
|
1821
|
+
const d = dict();
|
|
1822
|
+
if (d == null) {
|
|
1823
|
+
continue;
|
|
1824
|
+
}
|
|
1825
|
+
const existing = findField(text, d, key);
|
|
1826
|
+
if (existing == null) {
|
|
1827
|
+
createdScalars.push(key);
|
|
1828
|
+
} else if (
|
|
1829
|
+
key === 'REACT_NATIVE_PATH' &&
|
|
1830
|
+
existing.value.includes('PODS_ROOT')
|
|
1831
|
+
) {
|
|
1832
|
+
// A ${PODS_ROOT}-anchored REACT_NATIVE_PATH (the CocoaPods template
|
|
1833
|
+
// default) dangles once CocoaPods is deintegrated: PODS_ROOT resolves
|
|
1834
|
+
// empty at build time, so the Bundle React Native code and images
|
|
1835
|
+
// phase looks for "/../…/scripts/xcode/with-environment.sh". Replace
|
|
1836
|
+
// it with the SPM-computed path, recording the original for deinit.
|
|
1837
|
+
replacedScalars[key] = existing.value;
|
|
1838
|
+
text = removeField(text, d, key);
|
|
1839
|
+
const d2 = dict();
|
|
1840
|
+
if (d2 == null) {
|
|
1841
|
+
continue;
|
|
1842
|
+
}
|
|
1843
|
+
text = ensureScalarField(text, d2, key, value);
|
|
1844
|
+
continue;
|
|
1845
|
+
}
|
|
1846
|
+
text = ensureScalarField(text, d, key, value);
|
|
1847
|
+
}
|
|
1848
|
+
const ownedScalars = [
|
|
1849
|
+
{
|
|
1850
|
+
key: 'RN_SPM_FLAVOR',
|
|
1851
|
+
value: flavorForBuildConfiguration(configurationName),
|
|
1852
|
+
},
|
|
1853
|
+
...frameworkConditionalSettings(flavoredFrameworks),
|
|
1854
|
+
];
|
|
1855
|
+
for (const {key, value} of ownedScalars) {
|
|
1856
|
+
const d = dict();
|
|
1857
|
+
if (d == null) {
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
const existing = findField(text, d, key);
|
|
1861
|
+
if (existing == null) {
|
|
1862
|
+
createdScalars.push(key);
|
|
1863
|
+
} else if (existing.value !== value) {
|
|
1864
|
+
replacedScalars[key] = existing.value;
|
|
1865
|
+
}
|
|
1866
|
+
text = setScalarField(text, d, key, value);
|
|
1867
|
+
}
|
|
1868
|
+
return {
|
|
1869
|
+
text,
|
|
1870
|
+
change: {
|
|
1871
|
+
configUuid,
|
|
1872
|
+
createdArrayKeys,
|
|
1873
|
+
appendedArrayValues,
|
|
1874
|
+
createdScalars,
|
|
1875
|
+
replacedScalars,
|
|
1876
|
+
...(Object.keys(promotedArrayScalars).length > 0
|
|
1877
|
+
? {promotedArrayScalars}
|
|
1878
|
+
: {}),
|
|
1879
|
+
},
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
// Write only when content changed (avoids spurious Xcode reloads / git churn).
|
|
1884
|
+
function writeIfChanged(
|
|
1885
|
+
filePath /*: string */,
|
|
1886
|
+
content /*: string */,
|
|
1887
|
+
) /*: boolean */ {
|
|
1888
|
+
fs.mkdirSync(path.dirname(filePath), {recursive: true});
|
|
1889
|
+
try {
|
|
1890
|
+
if (fs.readFileSync(filePath, 'utf8') === content) {
|
|
1891
|
+
return false;
|
|
1892
|
+
}
|
|
1893
|
+
} catch {
|
|
1894
|
+
/* file doesn't exist yet */
|
|
1895
|
+
}
|
|
1896
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
1897
|
+
return true;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* Add the "Sync SPM Autolinking" pre-action to an existing scheme's
|
|
1902
|
+
* BuildAction, reusing the scheme's own primary BuildableReference. Returns
|
|
1903
|
+
* the XML unchanged when the pre-action is already present.
|
|
1904
|
+
*/
|
|
1905
|
+
function addPreActionToScheme(
|
|
1906
|
+
xml /*: string */,
|
|
1907
|
+
targetUuid /*: string */,
|
|
1908
|
+
syncScript /*: string */,
|
|
1909
|
+
) /*: string */ {
|
|
1910
|
+
const titleIdx = xml.indexOf('title = "Sync SPM Autolinking"');
|
|
1911
|
+
if (titleIdx >= 0) {
|
|
1912
|
+
// Already injected on a prior run — refresh a possibly-stale scriptText
|
|
1913
|
+
// in place (same escaping used at creation) rather than leaving it
|
|
1914
|
+
// forever. Splice by index (not a regex/string replace) since the script
|
|
1915
|
+
// itself may contain `$`-sequences that String.replace's replacement-
|
|
1916
|
+
// pattern syntax would otherwise misinterpret. Byte-identical when the
|
|
1917
|
+
// script is unchanged; every other byte of the scheme is untouched.
|
|
1918
|
+
const scriptTextMarker = 'scriptText = "';
|
|
1919
|
+
const stIdx = xml.indexOf(scriptTextMarker, titleIdx);
|
|
1920
|
+
if (stIdx < 0) {
|
|
1921
|
+
return xml; // malformed — leave untouched rather than guess
|
|
1922
|
+
}
|
|
1923
|
+
const valueStart = stIdx + scriptTextMarker.length;
|
|
1924
|
+
// escapeXmlAttribute maps a literal `"` to `"`, so the attribute
|
|
1925
|
+
// value itself never contains one — the next `"` is always the closing
|
|
1926
|
+
// delimiter.
|
|
1927
|
+
const valueEnd = xml.indexOf('"', valueStart);
|
|
1928
|
+
return (
|
|
1929
|
+
xml.slice(0, valueStart) +
|
|
1930
|
+
escapeXmlAttribute(syncScript) +
|
|
1931
|
+
xml.slice(valueEnd)
|
|
1932
|
+
);
|
|
1933
|
+
}
|
|
1934
|
+
const refMatch = xml.match(
|
|
1935
|
+
new RegExp(
|
|
1936
|
+
`<BuildableReference\\b[^>]*BlueprintIdentifier = "${targetUuid}"[^>]*>`,
|
|
1937
|
+
),
|
|
1938
|
+
);
|
|
1939
|
+
const attr = (name /*: string */) => {
|
|
1940
|
+
const m =
|
|
1941
|
+
refMatch != null
|
|
1942
|
+
? refMatch[0].match(new RegExp(`${name} = "([^"]*)"`))
|
|
1943
|
+
: null;
|
|
1944
|
+
return m != null ? m[1] : '';
|
|
1945
|
+
};
|
|
1946
|
+
const cleanRef =
|
|
1947
|
+
`<BuildableReference\n` +
|
|
1948
|
+
` BuildableIdentifier = "primary"\n` +
|
|
1949
|
+
` BlueprintIdentifier = "${targetUuid}"\n` +
|
|
1950
|
+
` BuildableName = "${attr('BuildableName')}"\n` +
|
|
1951
|
+
` BlueprintName = "${attr('BlueprintName')}"\n` +
|
|
1952
|
+
` ReferencedContainer = "${attr('ReferencedContainer')}">\n` +
|
|
1953
|
+
` </BuildableReference>`;
|
|
1954
|
+
const executionAction =
|
|
1955
|
+
` <ExecutionAction\n` +
|
|
1956
|
+
` ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">\n` +
|
|
1957
|
+
` <ActionContent\n` +
|
|
1958
|
+
` title = "Sync SPM Autolinking"\n` +
|
|
1959
|
+
` scriptText = "${escapeXmlAttribute(syncScript)}">\n` +
|
|
1960
|
+
` <EnvironmentBuildable>\n` +
|
|
1961
|
+
` ${cleanRef}\n` +
|
|
1962
|
+
` </EnvironmentBuildable>\n` +
|
|
1963
|
+
` </ActionContent>\n` +
|
|
1964
|
+
` </ExecutionAction>`;
|
|
1965
|
+
|
|
1966
|
+
if (/<PreActions>/.test(xml)) {
|
|
1967
|
+
return xml.replace(
|
|
1968
|
+
'</PreActions>',
|
|
1969
|
+
`${executionAction}\n </PreActions>`,
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
const openEnd = xml.indexOf('>', xml.indexOf('<BuildAction'));
|
|
1973
|
+
if (openEnd < 0) {
|
|
1974
|
+
return xml; // no BuildAction — leave the scheme untouched
|
|
1975
|
+
}
|
|
1976
|
+
const block = `\n <PreActions>\n${executionAction}\n </PreActions>`;
|
|
1977
|
+
return xml.slice(0, openEnd + 1) + block + xml.slice(openEnd + 1);
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
/**
|
|
1981
|
+
* Ensure the app target's shared scheme runs the sync pre-action before SPM
|
|
1982
|
+
* resolution. Updates the scheme that builds the target if one exists,
|
|
1983
|
+
* otherwise creates a fresh shared scheme. Returns 'updated' | 'created' |
|
|
1984
|
+
* 'unchanged'.
|
|
1985
|
+
*/
|
|
1986
|
+
function injectOrCreateScheme(
|
|
1987
|
+
xcodeprojDir /*: string */,
|
|
1988
|
+
opts /*: {appName: string, targetUuid: string, projName: string, syncScript: string} */,
|
|
1989
|
+
) /*: {status: 'updated' | 'unchanged' | 'created', file: string} */ {
|
|
1990
|
+
const schemesDir = path.join(xcodeprojDir, 'xcshareddata', 'xcschemes');
|
|
1991
|
+
let schemeFiles /*: Array<string> */ = [];
|
|
1992
|
+
try {
|
|
1993
|
+
schemeFiles = fs
|
|
1994
|
+
.readdirSync(schemesDir)
|
|
1995
|
+
.filter(f => f.endsWith('.xcscheme'));
|
|
1996
|
+
} catch {
|
|
1997
|
+
/* no shared schemes dir yet */
|
|
1998
|
+
}
|
|
1999
|
+
for (const f of schemeFiles) {
|
|
2000
|
+
const p = path.join(schemesDir, f);
|
|
2001
|
+
const xml = fs.readFileSync(p, 'utf8');
|
|
2002
|
+
if (xml.includes(`BlueprintIdentifier = "${opts.targetUuid}"`)) {
|
|
2003
|
+
const updated = addPreActionToScheme(
|
|
2004
|
+
xml,
|
|
2005
|
+
opts.targetUuid,
|
|
2006
|
+
opts.syncScript,
|
|
2007
|
+
);
|
|
2008
|
+
return {
|
|
2009
|
+
status: writeIfChanged(p, updated) ? 'updated' : 'unchanged',
|
|
2010
|
+
file: f,
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
const file = `${opts.appName}.xcscheme`;
|
|
2015
|
+
const xml = generateXcscheme(
|
|
2016
|
+
opts.appName,
|
|
2017
|
+
opts.targetUuid,
|
|
2018
|
+
opts.projName,
|
|
2019
|
+
opts.syncScript,
|
|
2020
|
+
);
|
|
2021
|
+
writeIfChanged(path.join(schemesDir, file), xml);
|
|
2022
|
+
return {status: 'created', file};
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
/**
|
|
2026
|
+
* Strip the empty `Pods` group `pod deintegrate` leaves in the navigator.
|
|
2027
|
+
* Called by `add --deintegrate` after deintegration so the converted project is
|
|
2028
|
+
* visually clean. No-op when absent or when the group still has children.
|
|
2029
|
+
*/
|
|
2030
|
+
function cleanupLeftoverPodsGroup(xcodeprojPath /*: string */) /*: boolean */ {
|
|
2031
|
+
const pbxprojPath = path.join(xcodeprojPath, 'project.pbxproj');
|
|
2032
|
+
if (!fs.existsSync(pbxprojPath)) {
|
|
2033
|
+
return false;
|
|
2034
|
+
}
|
|
2035
|
+
const original = fs.readFileSync(pbxprojPath, 'utf8');
|
|
2036
|
+
const cleaned = removeEmptyPodsGroup(original);
|
|
2037
|
+
return cleaned !== original ? writeIfChanged(pbxprojPath, cleaned) : false;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
/**
|
|
2041
|
+
* Strip the dangling `JavaScriptCore.framework` file reference the community
|
|
2042
|
+
* template has carried since RN 0.60 (navigator-only, meaningless under
|
|
2043
|
+
* Hermes) — see `removeDanglingJavaScriptCoreRef` for the full rationale and
|
|
2044
|
+
* the safety gate that leaves a still-linked reference untouched. No-op when
|
|
2045
|
+
* absent or when the pbxproj is missing.
|
|
2046
|
+
*/
|
|
2047
|
+
function cleanupDanglingJavaScriptCoreRef(
|
|
2048
|
+
xcodeprojPath /*: string */,
|
|
2049
|
+
) /*: boolean */ {
|
|
2050
|
+
const pbxprojPath = path.join(xcodeprojPath, 'project.pbxproj');
|
|
2051
|
+
if (!fs.existsSync(pbxprojPath)) {
|
|
2052
|
+
return false;
|
|
2053
|
+
}
|
|
2054
|
+
const original = fs.readFileSync(pbxprojPath, 'utf8');
|
|
2055
|
+
const cleaned = removeDanglingJavaScriptCoreRef(original);
|
|
2056
|
+
return cleaned !== original ? writeIfChanged(pbxprojPath, cleaned) : false;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
/**
|
|
2060
|
+
* Normalize one plugin generated-source path into the fields a PBXFileReference
|
|
2061
|
+
* needs. Stores an SRCROOT-relative path (`sourceTree = SOURCE_ROOT`) when the
|
|
2062
|
+
* source lives under the app root — the typical case (build/generated/…) — and
|
|
2063
|
+
* an absolute path (`sourceTree = "<absolute>"`) otherwise. Returns null (with a
|
|
2064
|
+
* loud log) for an extension the pbxproj can't compile.
|
|
2065
|
+
*/
|
|
2066
|
+
function normalizeGeneratedSource(
|
|
2067
|
+
appRoot /*: string */,
|
|
2068
|
+
srcPath /*: string */,
|
|
2069
|
+
) /*: ?GeneratedSource */ {
|
|
2070
|
+
const ext = path.extname(srcPath).toLowerCase();
|
|
2071
|
+
const fileType = GENERATED_SOURCE_FILE_TYPES[ext];
|
|
2072
|
+
if (fileType == null) {
|
|
2073
|
+
log(
|
|
2074
|
+
`warning: unsupported generated-source extension "${ext}" for ` +
|
|
2075
|
+
`${srcPath}; skipping (SPM plugin sources must be .swift/.m/.mm).`,
|
|
2076
|
+
);
|
|
2077
|
+
return null;
|
|
2078
|
+
}
|
|
2079
|
+
const abs = path.isAbsolute(srcPath)
|
|
2080
|
+
? srcPath
|
|
2081
|
+
: path.resolve(appRoot, srcPath);
|
|
2082
|
+
const rel = path.relative(appRoot, abs);
|
|
2083
|
+
const underAppRoot =
|
|
2084
|
+
rel !== '' &&
|
|
2085
|
+
rel !== '..' &&
|
|
2086
|
+
!rel.startsWith('..' + path.sep) &&
|
|
2087
|
+
!path.isAbsolute(rel);
|
|
2088
|
+
return {
|
|
2089
|
+
path: underAppRoot ? rel : abs,
|
|
2090
|
+
name: path.basename(abs),
|
|
2091
|
+
sourceTree: underAppRoot ? 'SOURCE_ROOT' : '"<absolute>"',
|
|
2092
|
+
fileType,
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
/**
|
|
2097
|
+
* Read + normalize the plugin generated-sources manifest at
|
|
2098
|
+
* `<appRoot>/build/generated/autolinking/.spm-plugin-generated-sources.json`.
|
|
2099
|
+
* Absent, empty, or malformed → `[]` (the feature stays inert for non-plugin
|
|
2100
|
+
* apps and never breaks injection). The file need not exist yet at inject time:
|
|
2101
|
+
* the build-time sync regenerates it before compile, and a PBXFileReference to a
|
|
2102
|
+
* not-yet-created path is valid.
|
|
2103
|
+
*/
|
|
2104
|
+
function readGeneratedSourcesManifest(
|
|
2105
|
+
appRoot /*: string */,
|
|
2106
|
+
) /*: Array<GeneratedSource> */ {
|
|
2107
|
+
const manifestPath = path.join(appRoot, SPM_GENERATED_SOURCES_MANIFEST);
|
|
2108
|
+
let raw /*: string */ = '';
|
|
2109
|
+
try {
|
|
2110
|
+
raw = fs.readFileSync(manifestPath, 'utf8');
|
|
2111
|
+
} catch {
|
|
2112
|
+
return [];
|
|
2113
|
+
}
|
|
2114
|
+
let entries /*: unknown */ = null;
|
|
2115
|
+
try {
|
|
2116
|
+
entries = JSON.parse(raw);
|
|
2117
|
+
} catch {
|
|
2118
|
+
log(
|
|
2119
|
+
`warning: could not parse ${SPM_GENERATED_SOURCES_MANIFEST}; ` +
|
|
2120
|
+
'skipping generated sources.',
|
|
2121
|
+
);
|
|
2122
|
+
return [];
|
|
2123
|
+
}
|
|
2124
|
+
if (!Array.isArray(entries)) {
|
|
2125
|
+
return [];
|
|
2126
|
+
}
|
|
2127
|
+
const out /*: Array<GeneratedSource> */ = [];
|
|
2128
|
+
for (const entry of entries) {
|
|
2129
|
+
if (
|
|
2130
|
+
entry == null ||
|
|
2131
|
+
typeof entry !== 'object' ||
|
|
2132
|
+
typeof entry.path !== 'string'
|
|
2133
|
+
) {
|
|
2134
|
+
continue;
|
|
2135
|
+
}
|
|
2136
|
+
const normalized = normalizeGeneratedSource(appRoot, entry.path);
|
|
2137
|
+
// Dedupe by normalized path — a duplicate manifest entry would otherwise
|
|
2138
|
+
// double-insert identical-UUID pbxproj objects.
|
|
2139
|
+
if (normalized != null && !out.some(s => s.path === normalized.path)) {
|
|
2140
|
+
out.push(normalized);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
return out;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
const nonEmptyStrings = (value /*: unknown */) /*: ?Array<string> */ =>
|
|
2147
|
+
Array.isArray(value)
|
|
2148
|
+
? value.filter(p => typeof p === 'string' && p.length > 0)
|
|
2149
|
+
: null;
|
|
2150
|
+
|
|
2151
|
+
/**
|
|
2152
|
+
* Read the plugin script-phases manifest at
|
|
2153
|
+
* `<appRoot>/build/generated/autolinking/.spm-plugin-script-phases.json`.
|
|
2154
|
+
* Absent, unparseable, or malformed → `[]`. Lenient by design even though the
|
|
2155
|
+
* plugin contract validates these entries fatally at invoke time: the sidecar
|
|
2156
|
+
* legitimately does not exist yet on a first `spm add`, and a stale or
|
|
2157
|
+
* hand-edited file must not break injection. This reader is the ONLY gate on
|
|
2158
|
+
* such a file, so it applies the same id/name rules (from spm-utils) that
|
|
2159
|
+
* invokePlugins enforces fatally.
|
|
2160
|
+
*/
|
|
2161
|
+
function readScriptPhasesManifest(
|
|
2162
|
+
appRoot /*: string */,
|
|
2163
|
+
) /*: Array<PluginScriptPhase> */ {
|
|
2164
|
+
const manifestPath = path.join(appRoot, SPM_SCRIPT_PHASES_MANIFEST);
|
|
2165
|
+
let raw /*: string */ = '';
|
|
2166
|
+
try {
|
|
2167
|
+
raw = fs.readFileSync(manifestPath, 'utf8');
|
|
2168
|
+
} catch {
|
|
2169
|
+
return [];
|
|
2170
|
+
}
|
|
2171
|
+
let entries /*: unknown */ = null;
|
|
2172
|
+
try {
|
|
2173
|
+
entries = JSON.parse(raw);
|
|
2174
|
+
} catch {
|
|
2175
|
+
log(
|
|
2176
|
+
`warning: could not parse ${SPM_SCRIPT_PHASES_MANIFEST}; ` +
|
|
2177
|
+
'skipping script phases.',
|
|
2178
|
+
);
|
|
2179
|
+
return [];
|
|
2180
|
+
}
|
|
2181
|
+
if (!Array.isArray(entries)) {
|
|
2182
|
+
return [];
|
|
2183
|
+
}
|
|
2184
|
+
const out /*: Array<PluginScriptPhase> */ = [];
|
|
2185
|
+
for (const entry of entries) {
|
|
2186
|
+
if (
|
|
2187
|
+
entry == null ||
|
|
2188
|
+
typeof entry !== 'object' ||
|
|
2189
|
+
!isValidScriptPhaseId(entry.id) ||
|
|
2190
|
+
!isValidScriptPhaseName(entry.name) ||
|
|
2191
|
+
typeof entry.script !== 'string' ||
|
|
2192
|
+
entry.script.length === 0 ||
|
|
2193
|
+
// An unknown position is a malformed entry, not something to coerce: it
|
|
2194
|
+
// would silently run somewhere the plugin didn't ask for.
|
|
2195
|
+
(entry.position != null &&
|
|
2196
|
+
entry.position !== 'beforeCompile' &&
|
|
2197
|
+
entry.position !== 'end') ||
|
|
2198
|
+
// Dedupe by id — the id seeds the phase's UUID, so a duplicate would
|
|
2199
|
+
// insert two objects with identical UUIDs.
|
|
2200
|
+
out.some(phase => phase.id === entry.id)
|
|
2201
|
+
) {
|
|
2202
|
+
continue;
|
|
2203
|
+
}
|
|
2204
|
+
const phase /*: PluginScriptPhase */ = {
|
|
2205
|
+
id: entry.id,
|
|
2206
|
+
name: entry.name,
|
|
2207
|
+
script: entry.script,
|
|
2208
|
+
position: entry.position ?? 'end',
|
|
2209
|
+
};
|
|
2210
|
+
const inputPaths = nonEmptyStrings(entry.inputPaths);
|
|
2211
|
+
const outputPaths = nonEmptyStrings(entry.outputPaths);
|
|
2212
|
+
if (inputPaths != null) {
|
|
2213
|
+
phase.inputPaths = inputPaths;
|
|
2214
|
+
}
|
|
2215
|
+
if (outputPaths != null) {
|
|
2216
|
+
phase.outputPaths = outputPaths;
|
|
2217
|
+
}
|
|
2218
|
+
if (typeof entry.alwaysOutOfDate === 'boolean') {
|
|
2219
|
+
phase.alwaysOutOfDate = entry.alwaysOutOfDate;
|
|
2220
|
+
}
|
|
2221
|
+
out.push(phase);
|
|
2222
|
+
}
|
|
2223
|
+
return out;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
/**
|
|
2227
|
+
* Read the `.spm-injected.json` marker of a previously-injected project, or
|
|
2228
|
+
* null when absent/unreadable. Used to reconcile generated sources on `update`
|
|
2229
|
+
* and to read back a pinned `artifactsVersionOverride` (see below).
|
|
2230
|
+
*/
|
|
2231
|
+
function readMarker(
|
|
2232
|
+
xcodeprojPath /*: string */,
|
|
2233
|
+
) /*: ?{generatedSources?: {[string]: Array<string>}, scriptPhases?: {[string]: string}, artifactsVersionOverride?: ?string, configCommand?: ?Array<string>, buildSettingChanges?: Array<BuildSettingChange>, createdArrayFields?: Array<CreatedArrayField>, scheme?: {file?: ?string, created?: ?boolean}, ...} */ {
|
|
2234
|
+
const markerPath = path.join(xcodeprojPath, SPM_INJECTED_MARKER);
|
|
2235
|
+
try {
|
|
2236
|
+
// $FlowFixMe[incompatible-return] JSON.parse returns any
|
|
2237
|
+
return JSON.parse(fs.readFileSync(markerPath, 'utf8'));
|
|
2238
|
+
} catch {
|
|
2239
|
+
return null;
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// Returns the `*.xcodeproj` under `appRoot` carrying a `.spm-injected.json`
|
|
2244
|
+
// marker (the user-owned project SPM packages were injected into in place),
|
|
2245
|
+
// or null when none has been injected yet. Pure fs reads — safe for the
|
|
2246
|
+
// marker readers below, and for callers that only locate the project (setup-
|
|
2247
|
+
// apple-spm.js's action defaulting and `deinit`), to call without exercising
|
|
2248
|
+
// any pbxproj-editing machinery.
|
|
2249
|
+
function findInjectedXcodeproj(appRoot /*: string */) /*: string | null */ {
|
|
2250
|
+
let entries /*: Array<{name: string, isDirectory(): boolean}> */ = [];
|
|
2251
|
+
try {
|
|
2252
|
+
// $FlowFixMe[incompatible-type] Dirent typing
|
|
2253
|
+
entries = fs.readdirSync(appRoot, {withFileTypes: true});
|
|
2254
|
+
} catch {
|
|
2255
|
+
return null;
|
|
2256
|
+
}
|
|
2257
|
+
for (const entry of entries) {
|
|
2258
|
+
if (!entry.isDirectory()) continue;
|
|
2259
|
+
// $FlowFixMe[incompatible-type] Dirent.name is string|Buffer in Flow stubs
|
|
2260
|
+
const name /*: string */ = entry.name;
|
|
2261
|
+
if (!name.endsWith('.xcodeproj')) continue;
|
|
2262
|
+
if (fs.existsSync(path.join(appRoot, name, SPM_INJECTED_MARKER))) {
|
|
2263
|
+
return path.join(appRoot, name);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return null;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
/**
|
|
2270
|
+
* Read the `artifactsVersionOverride` a previous `spm add --version` / `spm
|
|
2271
|
+
* update --version` pinned into the injected xcodeproj's `.spm-injected.json`
|
|
2272
|
+
* marker (see the field's doc comment in injectSpmIntoExistingXcodeproj
|
|
2273
|
+
* below), or null when no project is injected yet, no override is pinned, or
|
|
2274
|
+
* the marker can't be read (never throws). Pure fs reads — setup-apple-spm.js's
|
|
2275
|
+
* determineVersion prefers the pinned version over the one derived from
|
|
2276
|
+
* node_modules/react-native/package.json, so a later flagless `add`/`update`
|
|
2277
|
+
* (and `download`) stays on the SAME artifact slot the explicit `--version`
|
|
2278
|
+
* selected.
|
|
2279
|
+
*/
|
|
2280
|
+
function readArtifactsVersionOverride(appRoot /*: string */) /*: ?string */ {
|
|
2281
|
+
const xcodeprojPath = findInjectedXcodeproj(appRoot);
|
|
2282
|
+
if (xcodeprojPath == null) {
|
|
2283
|
+
return null;
|
|
2284
|
+
}
|
|
2285
|
+
const override = readMarker(xcodeprojPath)?.artifactsVersionOverride;
|
|
2286
|
+
return typeof override === 'string' && override.length > 0 ? override : null;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
/**
|
|
2290
|
+
* Read the autolinking config command a previous `spm add`/`update` pinned into
|
|
2291
|
+
* the injected xcodeproj's `.spm-injected.json` marker, or null when nothing
|
|
2292
|
+
* usable is pinned. Pure fs reads, like readArtifactsVersionOverride above, but
|
|
2293
|
+
* this one IS wired: setup-apple-spm.js's resolveExplicitConfigCommand reads it
|
|
2294
|
+
* on add/update/scaffold and on the build-time `sync`. Re-validated through the
|
|
2295
|
+
* same parseConfigCommandJson the flag goes through, and never throws, so a
|
|
2296
|
+
* hand-edited marker degrades to the env-var/default command instead of
|
|
2297
|
+
* injecting a bogus argv into the build.
|
|
2298
|
+
*/
|
|
2299
|
+
function readPinnedConfigCommand(appRoot /*: string */) /*: ?Array<string> */ {
|
|
2300
|
+
const xcodeprojPath = findInjectedXcodeproj(appRoot);
|
|
2301
|
+
if (xcodeprojPath == null) {
|
|
2302
|
+
return null;
|
|
2303
|
+
}
|
|
2304
|
+
const pinned = readMarker(xcodeprojPath)?.configCommand;
|
|
2305
|
+
if (pinned == null) {
|
|
2306
|
+
return null;
|
|
2307
|
+
}
|
|
2308
|
+
try {
|
|
2309
|
+
return parseConfigCommandJson(JSON.stringify(pinned), SPM_INJECTED_MARKER);
|
|
2310
|
+
} catch {
|
|
2311
|
+
return null;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
/**
|
|
2316
|
+
* Union the array fields RN has created across syncs, deduped by container+key.
|
|
2317
|
+
*
|
|
2318
|
+
* THE CANONICAL STATEMENT of why anything RN created is recorded stickily (the
|
|
2319
|
+
* marker's `scheme.created` carries it forward for the same reason): a re-sync
|
|
2320
|
+
* re-injects from a baseline with only the BUILD SETTINGS reversed, so it finds
|
|
2321
|
+
* whatever the first run created already there and reports creating nothing. Once
|
|
2322
|
+
* RN has created something, that fact has to be carried forward, or the new
|
|
2323
|
+
* marker forgets it and `deinit` leaves an empty `packageReferences` /
|
|
2324
|
+
* `packageProductDependencies` behind and the generated scheme on disk.
|
|
2325
|
+
*
|
|
2326
|
+
* The record licenses removal; it does not order it. `deinit` still checks that
|
|
2327
|
+
* what it is about to remove is RN's (see its step 1 and isGeneratedScheme), so
|
|
2328
|
+
* carrying forward a field the user has since taken over — or deleted by hand —
|
|
2329
|
+
* is safe.
|
|
2330
|
+
*/
|
|
2331
|
+
function mergeCreatedArrayFields(
|
|
2332
|
+
previous /*: ReadonlyArray<CreatedArrayField> */,
|
|
2333
|
+
current /*: ReadonlyArray<CreatedArrayField> */,
|
|
2334
|
+
) /*: Array<CreatedArrayField> */ {
|
|
2335
|
+
const merged = [...previous];
|
|
2336
|
+
for (const field of current) {
|
|
2337
|
+
if (
|
|
2338
|
+
!merged.some(
|
|
2339
|
+
seen => seen.container === field.container && seen.key === field.key,
|
|
2340
|
+
)
|
|
2341
|
+
) {
|
|
2342
|
+
merged.push(field);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
return merged;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
/**
|
|
2349
|
+
* Add SPM packages to a user's EXISTING xcodeproj in place. Returns
|
|
2350
|
+
* {status: 'injected', target} on success, or {status: 'refused', reason}
|
|
2351
|
+
* when the project can't be safely edited (caller surfaces it; fail-loud).
|
|
2352
|
+
*/
|
|
2353
|
+
function injectSpmIntoExistingXcodeproj(
|
|
2354
|
+
opts /*: {appRoot: string, reactNativeRoot: string, xcodeprojPath: string, appName?: ?string, artifactsVersionOverride?: ?string, configCommand?: ?Array<string>} */,
|
|
2355
|
+
) /*: {status: 'injected', target: string} | {status: 'refused', reason: string} */ {
|
|
2356
|
+
const {appRoot, reactNativeRoot, xcodeprojPath} = opts;
|
|
2357
|
+
const pbxprojPath = path.join(xcodeprojPath, 'project.pbxproj');
|
|
2358
|
+
if (!fs.existsSync(pbxprojPath)) {
|
|
2359
|
+
return {
|
|
2360
|
+
status: 'refused',
|
|
2361
|
+
reason: `no project.pbxproj at ${xcodeprojPath}`,
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
const original = fs.readFileSync(pbxprojPath, 'utf8');
|
|
2365
|
+
const plan = planInjection(original, {appName: opts.appName});
|
|
2366
|
+
if (!plan.ok) {
|
|
2367
|
+
return {status: 'refused', reason: plan.reason};
|
|
2368
|
+
}
|
|
2369
|
+
const reactNativePath = path.relative(appRoot, reactNativeRoot);
|
|
2370
|
+
const remote = remotePackageConfig(appRoot);
|
|
2371
|
+
const hermesCliPath = resolveHermesCliPathSetting(reactNativeRoot);
|
|
2372
|
+
const generatedSources = readGeneratedSourcesManifest(appRoot);
|
|
2373
|
+
const scriptPhases = readScriptPhasesManifest(appRoot);
|
|
2374
|
+
const flavoredFrameworks = readFlavoredFrameworksManifest(appRoot).frameworks;
|
|
2375
|
+
|
|
2376
|
+
const prevMarker = readMarker(xcodeprojPath);
|
|
2377
|
+
|
|
2378
|
+
// Reconcile generated sources injected on a PRIOR run that are no longer in
|
|
2379
|
+
// the manifest (a plugin's entry was dropped, or the plugin was removed).
|
|
2380
|
+
// Diff the marker's `generatedSources` map against the current manifest and
|
|
2381
|
+
// delete only the stale UUIDs — the additive injection below re-emits (and
|
|
2382
|
+
// idempotently skips) everything that remains, so an unchanged run stays
|
|
2383
|
+
// byte-identical. deinit needs none of this: the removed objects live in
|
|
2384
|
+
// `injectedUuids`.
|
|
2385
|
+
const prevGeneratedSources /*: {[string]: Array<string>} */ =
|
|
2386
|
+
prevMarker?.generatedSources ?? {};
|
|
2387
|
+
const currentPaths = new Set(generatedSources.map(s => s.path));
|
|
2388
|
+
const staleUuids /*: Array<string> */ = [];
|
|
2389
|
+
for (const p of Object.keys(prevGeneratedSources)) {
|
|
2390
|
+
if (!currentPaths.has(p)) {
|
|
2391
|
+
staleUuids.push(...prevGeneratedSources[p]);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
// When the last generated source is gone, retire the now-empty group too.
|
|
2395
|
+
if (
|
|
2396
|
+
generatedSources.length === 0 &&
|
|
2397
|
+
Object.keys(prevGeneratedSources).length > 0
|
|
2398
|
+
) {
|
|
2399
|
+
staleUuids.push(
|
|
2400
|
+
namespacedUUID(plan.rootUuid, 'PBXGroup', SPM_GENERATED_SOURCES_GROUP_ID),
|
|
2401
|
+
);
|
|
2402
|
+
}
|
|
2403
|
+
// Same reconciliation for script phases, keyed on the plugin-supplied id.
|
|
2404
|
+
const prevScriptPhases /*: {[string]: string} */ =
|
|
2405
|
+
prevMarker?.scriptPhases ?? {};
|
|
2406
|
+
const currentPhaseIds = new Set(scriptPhases.map(p => p.id));
|
|
2407
|
+
for (const id of Object.keys(prevScriptPhases)) {
|
|
2408
|
+
if (!currentPhaseIds.has(id)) {
|
|
2409
|
+
staleUuids.push(prevScriptPhases[id]);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
// Re-apply generated settings from a clean recorded baseline. This removes
|
|
2413
|
+
// linker entries for plugin frameworks that disappeared and keeps the new
|
|
2414
|
+
// marker a complete inverse after an idempotent update.
|
|
2415
|
+
let base = removeRecordedBuildSettings(
|
|
2416
|
+
original,
|
|
2417
|
+
prevMarker?.buildSettingChanges ?? [],
|
|
2418
|
+
);
|
|
2419
|
+
if (staleUuids.length > 0) {
|
|
2420
|
+
base = removeArrayMembersByUuid(base, staleUuids);
|
|
2421
|
+
for (const u of staleUuids) {
|
|
2422
|
+
base = removeObjectByUuid(base, u);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
const {
|
|
2427
|
+
text,
|
|
2428
|
+
injectedUuids,
|
|
2429
|
+
createdArrayFields,
|
|
2430
|
+
buildSettingChanges,
|
|
2431
|
+
generatedSourceUuids,
|
|
2432
|
+
scriptPhaseUuids,
|
|
2433
|
+
} = injectSpmIntoPbxproj(
|
|
2434
|
+
base,
|
|
2435
|
+
{
|
|
2436
|
+
rootUuid: plan.rootUuid,
|
|
2437
|
+
targetUuid: plan.target.uuid,
|
|
2438
|
+
configUuids: plan.configUuids,
|
|
2439
|
+
frameworksPhaseUuid: plan.frameworksPhaseUuid,
|
|
2440
|
+
sourcesPhaseUuid: plan.sourcesPhaseUuid,
|
|
2441
|
+
},
|
|
2442
|
+
reactNativePath,
|
|
2443
|
+
remote,
|
|
2444
|
+
hermesCliPath,
|
|
2445
|
+
generatedSources,
|
|
2446
|
+
flavoredFrameworks,
|
|
2447
|
+
scriptPhases,
|
|
2448
|
+
);
|
|
2449
|
+
|
|
2450
|
+
const changed = writeIfChanged(pbxprojPath, text);
|
|
2451
|
+
log(
|
|
2452
|
+
changed
|
|
2453
|
+
? `Injected SPM packages into ${path.relative(appRoot, pbxprojPath)}`
|
|
2454
|
+
: `${path.relative(appRoot, pbxprojPath)} already up to date`,
|
|
2455
|
+
);
|
|
2456
|
+
|
|
2457
|
+
const projName = path.basename(xcodeprojPath, '.xcodeproj');
|
|
2458
|
+
const schemeResult = injectOrCreateScheme(xcodeprojPath, {
|
|
2459
|
+
appName: plan.target.name,
|
|
2460
|
+
targetUuid: plan.target.uuid,
|
|
2461
|
+
projName,
|
|
2462
|
+
// The scheme pre-action is SYNC-ONLY (no flavor swap). A pre-action swap
|
|
2463
|
+
// could win its race and mask a mismatch from the in-target detector.
|
|
2464
|
+
syncScript: buildSchemePreActionScript(reactNativePath),
|
|
2465
|
+
});
|
|
2466
|
+
log(`Scheme sync pre-action: ${schemeResult.status}`);
|
|
2467
|
+
|
|
2468
|
+
// The RN version this app's xcframework artifact-cache slot should be
|
|
2469
|
+
// pinned to, when `add`/`update` was given an EXPLICIT `--version` — SETS
|
|
2470
|
+
// the pin. Omitting `--version` (opts.artifactsVersionOverride is null)
|
|
2471
|
+
// PRESERVES whatever was recorded on a prior run, since it's an
|
|
2472
|
+
// intentional pin, not something to silently re-derive from
|
|
2473
|
+
// node_modules/react-native/package.json. There is no "clear" verb yet;
|
|
2474
|
+
// `deinit` (removeSpmInjection) drops the whole marker, including this
|
|
2475
|
+
// field. Read back by readArtifactsVersionOverride (above) so a later
|
|
2476
|
+
// flagless `add`/`update`/`download` resolves to the SAME slot, even on a
|
|
2477
|
+
// version-mismatched setup.
|
|
2478
|
+
const artifactsVersionOverride =
|
|
2479
|
+
opts.artifactsVersionOverride ??
|
|
2480
|
+
prevMarker?.artifactsVersionOverride ??
|
|
2481
|
+
null;
|
|
2482
|
+
|
|
2483
|
+
// Same set-or-preserve contract as the version pin above, for the autolinking
|
|
2484
|
+
// config command `add`/`update` resolved (`--config-command` or
|
|
2485
|
+
// RCT_SPM_AUTOLINKING_CONFIG_COMMAND) — the build-time sync sees neither the
|
|
2486
|
+
// flag nor the developer's shell environment, so without the pin it
|
|
2487
|
+
// re-derives autolinking.json with the default @react-native-community/cli
|
|
2488
|
+
// command and breaks apps that replace it. Read back by
|
|
2489
|
+
// readPinnedConfigCommand (above). No "clear" verb yet either; `deinit` drops
|
|
2490
|
+
// the whole marker, this field with it.
|
|
2491
|
+
const configCommand = opts.configCommand ?? prevMarker?.configCommand ?? null;
|
|
2492
|
+
|
|
2493
|
+
// Marker: idempotency signal + the exact, reversible record of every edit so
|
|
2494
|
+
// `deinit` (removeSpmInjection) can undo precisely what was added.
|
|
2495
|
+
writeIfChanged(
|
|
2496
|
+
path.join(xcodeprojPath, SPM_INJECTED_MARKER),
|
|
2497
|
+
JSON.stringify(
|
|
2498
|
+
{
|
|
2499
|
+
rootUuid: plan.rootUuid,
|
|
2500
|
+
target: plan.target.name,
|
|
2501
|
+
targetUuid: plan.target.uuid,
|
|
2502
|
+
injectedUuids: Array.from(new Set(injectedUuids)).sort(),
|
|
2503
|
+
createdArrayFields: mergeCreatedArrayFields(
|
|
2504
|
+
prevMarker?.createdArrayFields ?? [],
|
|
2505
|
+
createdArrayFields,
|
|
2506
|
+
),
|
|
2507
|
+
buildSettingChanges,
|
|
2508
|
+
// Normalized path → [fileRefUuid, buildFileUuid]. Read back on the next
|
|
2509
|
+
// `update` to reconcile away entries that left the manifest.
|
|
2510
|
+
generatedSources: generatedSourceUuids,
|
|
2511
|
+
// Plugin phase id → its PBXShellScriptBuildPhase UUID, reconciled the
|
|
2512
|
+
// same way.
|
|
2513
|
+
scriptPhases: scriptPhaseUuids,
|
|
2514
|
+
artifactsVersionOverride,
|
|
2515
|
+
configCommand,
|
|
2516
|
+
scheme: {
|
|
2517
|
+
file: schemeResult.file,
|
|
2518
|
+
// Sticky — see mergeCreatedArrayFields for why a later sync cannot
|
|
2519
|
+
// observe this for itself.
|
|
2520
|
+
created:
|
|
2521
|
+
schemeResult.status === 'created' ||
|
|
2522
|
+
prevMarker?.scheme?.created === true,
|
|
2523
|
+
},
|
|
2524
|
+
},
|
|
2525
|
+
null,
|
|
2526
|
+
2,
|
|
2527
|
+
) + '\n',
|
|
2528
|
+
);
|
|
2529
|
+
|
|
2530
|
+
ensureStubPackages(appRoot);
|
|
2531
|
+
return {status: 'injected', target: plan.target.name};
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
/** The sync pre-action's script, unescaped, or null when the scheme has none. */
|
|
2535
|
+
function schemePreActionScript(xml /*: string */) /*: ?string */ {
|
|
2536
|
+
const titleIdx = xml.indexOf('title = "Sync SPM Autolinking"');
|
|
2537
|
+
if (titleIdx < 0) {
|
|
2538
|
+
return null;
|
|
2539
|
+
}
|
|
2540
|
+
const marker = 'scriptText = "';
|
|
2541
|
+
const start = xml.indexOf(marker, titleIdx);
|
|
2542
|
+
if (start < 0) {
|
|
2543
|
+
return null;
|
|
2544
|
+
}
|
|
2545
|
+
const valueStart = start + marker.length;
|
|
2546
|
+
// escapeXmlAttribute maps a literal `"` to `"`, so the next `"` is always
|
|
2547
|
+
// the closing delimiter.
|
|
2548
|
+
const valueEnd = xml.indexOf('"', valueStart);
|
|
2549
|
+
return valueEnd < 0
|
|
2550
|
+
? null
|
|
2551
|
+
: unescapeXmlAttribute(xml.slice(valueStart, valueEnd));
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
/**
|
|
2555
|
+
* Whether `xml` is still, byte for byte, the scheme RN generates for this target
|
|
2556
|
+
* — everything but the pre-action's script, which RN rewrites in place on every
|
|
2557
|
+
* sync and which varies with the app's react-native path, so it cannot be part of
|
|
2558
|
+
* an ownership test.
|
|
2559
|
+
*
|
|
2560
|
+
* `deinit` deletes a scheme the marker says RN created only while this holds. A
|
|
2561
|
+
* user may replace a generated scheme with one of their own under the same name
|
|
2562
|
+
* (same target, so `injectOrCreateScheme` finds and updates it, and the created
|
|
2563
|
+
* record stays), and destroying that is unrecoverable where leaving a scheme
|
|
2564
|
+
* behind is not — so the harmless way of being wrong wins: a generated scheme the
|
|
2565
|
+
* user has since edited leaks, minus its pre-action.
|
|
2566
|
+
*/
|
|
2567
|
+
function isGeneratedScheme(
|
|
2568
|
+
xml /*: string */,
|
|
2569
|
+
appName /*: string */,
|
|
2570
|
+
targetUuid /*: string */,
|
|
2571
|
+
projName /*: string */,
|
|
2572
|
+
) /*: boolean */ {
|
|
2573
|
+
const script = schemePreActionScript(xml);
|
|
2574
|
+
return (
|
|
2575
|
+
script != null &&
|
|
2576
|
+
xml === generateXcscheme(appName, targetUuid, projName, script)
|
|
2577
|
+
);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
/**
|
|
2581
|
+
* Remove the "Sync SPM Autolinking" pre-action that addPreActionToScheme added
|
|
2582
|
+
* to a scheme, and drop the `<PreActions>` wrapper if it is left empty (the
|
|
2583
|
+
* byte-identical inverse for the common case where injection created it).
|
|
2584
|
+
*/
|
|
2585
|
+
function removePreActionFromScheme(xml /*: string */) /*: string */ {
|
|
2586
|
+
const withoutAction = xml.replace(
|
|
2587
|
+
/[ \t]*<ExecutionAction\b(?:(?!<\/ExecutionAction>)[\s\S])*?title = "Sync SPM Autolinking"(?:(?!<\/ExecutionAction>)[\s\S])*?<\/ExecutionAction>\n?/,
|
|
2588
|
+
'',
|
|
2589
|
+
);
|
|
2590
|
+
return withoutAction.replace(/\n[ \t]*<PreActions>\s*<\/PreActions>/, '');
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function removeRecordedBuildSettings(
|
|
2594
|
+
input /*: string */,
|
|
2595
|
+
changes /*: ReadonlyArray<BuildSettingChange> */,
|
|
2596
|
+
) /*: string */ {
|
|
2597
|
+
let text = input;
|
|
2598
|
+
for (const change of changes) {
|
|
2599
|
+
const dict = () => {
|
|
2600
|
+
const config = findObjectByUuid(text, change.configUuid);
|
|
2601
|
+
if (config == null) {
|
|
2602
|
+
return null;
|
|
2603
|
+
}
|
|
2604
|
+
const buildSettings = findField(text, config, 'buildSettings');
|
|
2605
|
+
if (buildSettings == null) {
|
|
2606
|
+
return null;
|
|
2607
|
+
}
|
|
2608
|
+
return {
|
|
2609
|
+
uuid: change.configUuid,
|
|
2610
|
+
bodyOpen: buildSettings.valueStart,
|
|
2611
|
+
bodyClose: buildSettings.tokenEnd - 1,
|
|
2612
|
+
};
|
|
2613
|
+
};
|
|
2614
|
+
for (const key of Object.keys(change.appendedArrayValues ?? {})) {
|
|
2615
|
+
const current = dict();
|
|
2616
|
+
if (current != null) {
|
|
2617
|
+
text = removeArrayStringValues(
|
|
2618
|
+
text,
|
|
2619
|
+
current,
|
|
2620
|
+
key,
|
|
2621
|
+
change.appendedArrayValues[key],
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
const promotedArrayScalars /*: {[string]: string} */ =
|
|
2626
|
+
change.promotedArrayScalars ?? {};
|
|
2627
|
+
for (const key of Object.keys(promotedArrayScalars)) {
|
|
2628
|
+
const current = dict();
|
|
2629
|
+
const originalValue = promotedArrayScalars[key];
|
|
2630
|
+
// A field that is gone was deleted by the user after injection; restoring
|
|
2631
|
+
// it would resurrect it, at the top of the dict, matching neither state.
|
|
2632
|
+
if (
|
|
2633
|
+
current != null &&
|
|
2634
|
+
typeof originalValue === 'string' &&
|
|
2635
|
+
findField(text, current, key) != null
|
|
2636
|
+
) {
|
|
2637
|
+
// Rewriting the whole value is what makes the promotion reversible at
|
|
2638
|
+
// all — its members and its `"$(inherited)"` seed are indistinguishable
|
|
2639
|
+
// from the user's own once folded together. The tradeoff: members the
|
|
2640
|
+
// user hand-added to the promoted array afterwards are discarded.
|
|
2641
|
+
text = setScalarField(text, current, key, originalValue);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
for (const key of change.createdArrayKeys ?? []) {
|
|
2645
|
+
const current = dict();
|
|
2646
|
+
if (current != null) {
|
|
2647
|
+
text = removeField(text, current, key);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
for (const key of change.createdScalars ?? []) {
|
|
2651
|
+
const current = dict();
|
|
2652
|
+
if (current != null) {
|
|
2653
|
+
text = removeField(text, current, key);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
const replacedScalars /*: {[string]: string} */ =
|
|
2657
|
+
change.replacedScalars ?? {};
|
|
2658
|
+
for (const key of Object.keys(replacedScalars)) {
|
|
2659
|
+
const current = dict();
|
|
2660
|
+
if (current != null) {
|
|
2661
|
+
text = removeField(text, current, key);
|
|
2662
|
+
const replacement = dict();
|
|
2663
|
+
if (replacement != null) {
|
|
2664
|
+
const originalValue = replacedScalars[key];
|
|
2665
|
+
if (typeof originalValue === 'string') {
|
|
2666
|
+
text = ensureScalarField(text, replacement, key, originalValue);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return text;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
/**
|
|
2676
|
+
* The exact inverse of `add` (injectSpmIntoExistingXcodeproj): using the
|
|
2677
|
+
* `.spm-injected.json` marker's precise record of every edit, remove only what
|
|
2678
|
+
* injection added — leaving any other (user) edits made afterwards intact. No
|
|
2679
|
+
* `git checkout`, no prompt. Returns {status:'absent'} when the project was
|
|
2680
|
+
* never injected.
|
|
2681
|
+
*/
|
|
2682
|
+
function removeSpmInjection(
|
|
2683
|
+
opts /*: {appRoot: string, xcodeprojPath: string} */,
|
|
2684
|
+
) /*: {status: 'removed', target: string} | {status: 'absent'} */ {
|
|
2685
|
+
const {appRoot, xcodeprojPath} = opts;
|
|
2686
|
+
const markerPath = path.join(xcodeprojPath, SPM_INJECTED_MARKER);
|
|
2687
|
+
if (!fs.existsSync(markerPath)) {
|
|
2688
|
+
return {status: 'absent'};
|
|
2689
|
+
}
|
|
2690
|
+
// $FlowFixMe[incompatible-type] JSON.parse returns any
|
|
2691
|
+
const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
|
|
2692
|
+
const pbxprojPath = path.join(xcodeprojPath, 'project.pbxproj');
|
|
2693
|
+
let text = fs.readFileSync(pbxprojPath, 'utf8');
|
|
2694
|
+
|
|
2695
|
+
const injectedUuids /*: Array<string> */ = marker.injectedUuids ?? [];
|
|
2696
|
+
|
|
2697
|
+
// 1. Drop our array members, then the array fields we created (now empty),
|
|
2698
|
+
// then the injected object definitions.
|
|
2699
|
+
text = removeArrayMembersByUuid(text, injectedUuids);
|
|
2700
|
+
for (const f of marker.createdArrayFields ?? []) {
|
|
2701
|
+
const obj =
|
|
2702
|
+
f.container === 'project'
|
|
2703
|
+
? findProjectObject(text)
|
|
2704
|
+
: findObjectByUuid(text, marker.targetUuid);
|
|
2705
|
+
if (obj == null) {
|
|
2706
|
+
continue;
|
|
2707
|
+
}
|
|
2708
|
+
// The record says the field did not exist before RN created it, which is
|
|
2709
|
+
// necessary but not sufficient: anything still in it after our own members
|
|
2710
|
+
// are gone is the user's (their own SPM package, added to the same field),
|
|
2711
|
+
// and dropping the field would orphan it.
|
|
2712
|
+
const field = findField(text, obj, f.key);
|
|
2713
|
+
if (field != null && /^\(\s*\)$/.test(field.value)) {
|
|
2714
|
+
text = removeField(text, obj, f.key);
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
for (const uuid of injectedUuids) {
|
|
2718
|
+
text = removeObjectByUuid(text, uuid);
|
|
2719
|
+
}
|
|
2720
|
+
// Drop any section that injection created and we just emptied (e.g.
|
|
2721
|
+
// XCLocalSwiftPackageReference) — a well-formed pbxproj never carries an
|
|
2722
|
+
// empty `/* Begin X */ /* End X */` section, so this lands byte-identical.
|
|
2723
|
+
text = text.replace(
|
|
2724
|
+
/\/\* Begin (\w+) section \*\/\n\/\* End \1 section \*\/\n\n/g,
|
|
2725
|
+
'',
|
|
2726
|
+
);
|
|
2727
|
+
|
|
2728
|
+
// 2. Reverse the per-config build-setting edits (only what we added).
|
|
2729
|
+
text = removeRecordedBuildSettings(text, marker.buildSettingChanges ?? []);
|
|
2730
|
+
writeIfChanged(pbxprojPath, text);
|
|
2731
|
+
log(`Removed SPM injection from ${path.relative(appRoot, pbxprojPath)}`);
|
|
2732
|
+
|
|
2733
|
+
// 3. Scheme: delete it if injection created it AND still owns its contents,
|
|
2734
|
+
// else strip the pre-action and leave the file (see isGeneratedScheme).
|
|
2735
|
+
const scheme = marker.scheme;
|
|
2736
|
+
if (scheme != null && scheme.file != null) {
|
|
2737
|
+
const schemePath = path.join(
|
|
2738
|
+
xcodeprojPath,
|
|
2739
|
+
'xcshareddata',
|
|
2740
|
+
'xcschemes',
|
|
2741
|
+
scheme.file,
|
|
2742
|
+
);
|
|
2743
|
+
if (fs.existsSync(schemePath)) {
|
|
2744
|
+
const xml = fs.readFileSync(schemePath, 'utf8');
|
|
2745
|
+
const ours =
|
|
2746
|
+
scheme.created === true &&
|
|
2747
|
+
isGeneratedScheme(
|
|
2748
|
+
xml,
|
|
2749
|
+
marker.target,
|
|
2750
|
+
marker.targetUuid,
|
|
2751
|
+
path.basename(xcodeprojPath, '.xcodeproj'),
|
|
2752
|
+
);
|
|
2753
|
+
if (ours) {
|
|
2754
|
+
fs.rmSync(schemePath, {force: true});
|
|
2755
|
+
} else {
|
|
2756
|
+
writeIfChanged(schemePath, removePreActionFromScheme(xml));
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
// 4. Drop the marker — the project is no longer SPM-injected.
|
|
2762
|
+
fs.rmSync(markerPath, {force: true});
|
|
2763
|
+
return {status: 'removed', target: marker.target};
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
module.exports = {
|
|
2767
|
+
generateXcscheme,
|
|
2768
|
+
buildSyncAutolinkingScript,
|
|
2769
|
+
buildSchemePreActionScript,
|
|
2770
|
+
buildEmbedFrameworksScript,
|
|
2771
|
+
flavorForBuildConfiguration,
|
|
2772
|
+
frameworkConditionalSettings,
|
|
2773
|
+
ensureStubPackages,
|
|
2774
|
+
buildSpmDependencyGraph,
|
|
2775
|
+
spmGraphToEntries,
|
|
2776
|
+
buildPhaseOrder,
|
|
2777
|
+
planInjection,
|
|
2778
|
+
injectSpmIntoPbxproj,
|
|
2779
|
+
injectSpmIntoExistingXcodeproj,
|
|
2780
|
+
removeSpmInjection,
|
|
2781
|
+
cleanupLeftoverPodsGroup,
|
|
2782
|
+
cleanupDanglingJavaScriptCoreRef,
|
|
2783
|
+
addPreActionToScheme,
|
|
2784
|
+
removePreActionFromScheme,
|
|
2785
|
+
findInjectedXcodeproj,
|
|
2786
|
+
readArtifactsVersionOverride,
|
|
2787
|
+
readPinnedConfigCommand,
|
|
2788
|
+
readScriptPhasesManifest,
|
|
2789
|
+
SPM_INJECTED_MARKER,
|
|
2790
|
+
};
|