diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 947f15cc55f..7887d2f4f6e 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -130,6 +130,9 @@ class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, publi if (reactNativeConfig->getBool("react_fabric:enable_crash_on_missing_component_descriptor")) { _animationDriver->enableCrashOnMissingComponentDescriptor(); } + if (reactNativeConfig->getBool("react_fabric:enable_simulate_image_props_memory_access")) { + _animationDriver->enableSimulateImagePropsMemoryAccess(); + } _uiRunLoopObserver = toolbox.mainRunLoopObserverFactory(RunLoopObserver::Activity::BeforeWaiting, _layoutAnimationDelegateProxy); _uiRunLoopObserver->setDelegate(_layoutAnimationDelegateProxy.get()); diff --git a/ReactCommon/react/renderer/animations/BUCK b/ReactCommon/react/renderer/animations/BUCK index fbf1c6c6139..1998f8d9717 100644 --- a/ReactCommon/react/renderer/animations/BUCK +++ b/ReactCommon/react/renderer/animations/BUCK @@ -62,6 +62,7 @@ rn_xplat_cxx_library( react_native_xplat_target("react/debug:debug"), react_native_xplat_target("react/renderer/componentregistry:componentregistry"), react_native_xplat_target("react/renderer/components/view:view"), + react_native_xplat_target("react/renderer/components/image:image"), react_native_xplat_target("react/renderer/core:core"), react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("react/renderer/mounting:mounting"), diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 846085ed04d..d4676fb5c27 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( MountingTransaction::Number transactionNumber, TransactionTelemetry const &telemetry, ShadowViewMutationList mutations) const { + simulateImagePropsMemoryAccess(mutations); // Current time in milliseconds uint64_t now = now_(); @@ -1058,6 +1060,8 @@ LayoutAnimationKeyFrameManager::pullTransaction( } } + simulateImagePropsMemoryAccess(mutations); + return MountingTransaction{ surfaceId, transactionNumber, std::move(mutations), telemetry}; } @@ -1086,6 +1090,10 @@ void LayoutAnimationKeyFrameManager::enableCrashOnMissingComponentDescriptor() { crashOnMissingComponentDescriptor_ = true; } +void LayoutAnimationKeyFrameManager::enableSimulateImagePropsMemoryAccess() { + simulateImagePropsMemoryAccess_ = true; +} + #pragma mark - Protected bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView( @@ -1696,5 +1704,40 @@ void LayoutAnimationKeyFrameManager::deleteAnimationsForStoppedSurfaces() } } +void LayoutAnimationKeyFrameManager::simulateImagePropsMemoryAccess( + ShadowViewMutationList const &mutations) const { + if (!simulateImagePropsMemoryAccess_) { + return; + } + for (auto const &mutation : mutations) { + if (mutation.type != ShadowViewMutation::Type::Insert) { + continue; + } + if (strcmp(mutation.newChildShadowView.componentName, "Image") == 0) { + auto const &imageProps = *std::static_pointer_cast( + mutation.newChildShadowView.props); + int temp = 0; + switch (imageProps.resizeMode) { + case ImageResizeMode::Cover: + temp = 1; + break; + case ImageResizeMode::Contain: + temp = 2; + break; + case ImageResizeMode::Stretch: + temp = 3; + break; + case ImageResizeMode::Center: + temp = 4; + break; + case ImageResizeMode::Repeat: + temp = 5; + break; + } + (void)temp; + } + } +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h index 099c1c4dcaf..330b597827b 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h @@ -90,6 +90,8 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, void enableCrashOnMissingComponentDescriptor(); + void enableSimulateImagePropsMemoryAccess(); + protected: SharedComponentDescriptorRegistry componentDescriptorRegistry_; mutable better::optional currentAnimation_{}; @@ -157,6 +159,12 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, */ bool crashOnMissingComponentDescriptor_{false}; + /* + * Feature flag that enables simulation of memory access. This is a temporary + * flag to diagnose where crashes are coming from in LayoutAnimations on iOS. + */ + bool simulateImagePropsMemoryAccess_{false}; + // Function that returns current time in milliseconds std::function now_; @@ -180,6 +188,9 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, * Removes animations from `inflightAnimations_` for stopped surfaces. */ void deleteAnimationsForStoppedSurfaces() const; + + void simulateImagePropsMemoryAccess( + ShadowViewMutationList const &mutations) const; }; } // namespace react