diff --git a/patches/react-native-reanimated+4.5.1.patch b/patches/react-native-reanimated+4.5.1.patch new file mode 100644 index 0000000000..b1d3218add --- /dev/null +++ b/patches/react-native-reanimated+4.5.1.patch @@ -0,0 +1,35 @@ +diff --git a/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt b/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +index 48e3771..0fba1af 100644 +--- a/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt ++++ b/node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +@@ -245,6 +245,15 @@ open class NativeProxy { + }.apply { isAccessible = true } + } + ++ // Backport of https://github.com/software-mansion/react-native-reanimated/pull/10435 ++ // (shipped in Reanimated 4.7.1). The reflective updatePropsSynchronously path skips RN's ++ // view-existence guard, so a tag that unmounted with buffered updates throws ++ // RetryableMountingLayerException on every event dispatch and Log.w printed the full stack ++ // on the UI thread inside the draw pass. Remove once the installed Reanimated includes the fix. ++ private val getViewExistsMethod by lazy { ++ runCatching { mountingManager.javaClass.getMethod("getViewExists", Int::class.javaPrimitiveType) }.getOrNull() ++ } ++ + @DoNotStrip + fun synchronouslyUpdateUIProps( + intBuffer: IntArray, +@@ -253,9 +262,13 @@ open class NativeProxy { + SynchronousPropsBufferParser.parse(intBuffer, doubleBuffer) { viewTag, props -> + if (BuildConfig.IS_REACT_NATIVE_86_OR_NEWER) { + try { ++ // The props stay in the registry, and the commit hook applies them to the shadow tree. ++ if (getViewExistsMethod?.invoke(mountingManager, viewTag) == false) { ++ return@parse ++ } + updatePropsSynchronouslyMethod.invoke(mountingManager, viewTag, props) + } catch (e: Exception) { +- Log.w("Reanimated", "synchronouslyUpdateUIProps failed for tag $viewTag", e) ++ Log.w("Reanimated", "synchronouslyUpdateUIProps failed for tag $viewTag: ${e.cause ?: e}") + } + } else { + mFabricUIManager.synchronouslyUpdateViewOnUIThread(viewTag, props) diff --git a/scripts/postinstall-patches.mjs b/scripts/postinstall-patches.mjs index d82af94788..b009be9841 100644 --- a/scripts/postinstall-patches.mjs +++ b/scripts/postinstall-patches.mjs @@ -25,6 +25,14 @@ const patchedPackages = [ nodeModulesPath: "node_modules/react-native-unistyles", patchPrefix: "react-native-unistyles+", }, + // Backport of https://github.com/software-mansion/react-native-reanimated/pull/10435 + // (Reanimated 4.7.1): skip synchronous Android prop updates for unmounted view tags + // instead of throwing and printing a full stack trace on the UI thread per tag per event. + // Remove when the installed Reanimated is >= 4.7.1. + { + nodeModulesPath: "node_modules/react-native-reanimated", + patchPrefix: "react-native-reanimated+", + }, { nodeModulesPath: "node_modules/react-native-draggable-flatlist", patchPrefix: "react-native-draggable-flatlist+",