From 1525c5f342d48eea19b30afad3110cddfc64c2ff Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 16 Jun 2023 06:15:07 -0700 Subject: [PATCH] Fix the issue that local reference overflows in Yoga 1 (#37929) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/37929 X-link: https://github.com/facebook/litho/pull/952 X-link: https://github.com/facebook/yoga/pull/1308 Long story in short, we're trying to fix an issue with Yoga that could potentially lead to an overflow in the JNI local reference table. Reviewed By: NickGerleman, astreet Differential Revision: D46653732 fbshipit-source-id: 0bc34bd5a819037c046c62b651e414b249cbdcb8 --- .../facebook/yoga/YogaExperimentalFeature.java | 4 +++- .../jni/first-party/yogajni/jni/YGJNIVanilla.cpp | 16 +++++++++++++--- .../ReactCommon/yoga/yoga/YGEnums.cpp | 2 ++ .../react-native/ReactCommon/yoga/yoga/YGEnums.h | 3 ++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java index 3532e45ec87..ba881370252 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaExperimentalFeature.java @@ -12,7 +12,8 @@ package com.facebook.yoga; public enum YogaExperimentalFeature { WEB_FLEX_BASIS(0), ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE(1), - FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN(2); + FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN(2), + FIX_JNILOCAL_REF_OVERFLOWS(3); private final int mIntValue; @@ -29,6 +30,7 @@ public enum YogaExperimentalFeature { case 0: return WEB_FLEX_BASIS; case 1: return ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE; case 2: return FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN; + case 3: return FIX_JNILOCAL_REF_OVERFLOWS; default: throw new IllegalArgumentException("Unknown enum value: " + value); } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp index 0a95d991976..1f0dd1c4a86 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNIVanilla.cpp @@ -280,7 +280,8 @@ static void YGTransferLayoutOutputsRecursive( JNIEnv* env, jobject thiz, YGNodeRef root, - void* layoutContext) { + void* layoutContext, + bool shouldCleanLocalRef) { if (!YGNodeGetHasNewLayout(root)) { return; } @@ -346,11 +347,16 @@ static void YGTransferLayoutOutputsRecursive( env->SetFloatArrayRegion(arrFinal.get(), 0, arrSize, arr); env->SetObjectField(obj.get(), arrField, arrFinal.get()); + if (shouldCleanLocalRef) { + objectClass.reset(); + arrFinal.reset(); + } + YGNodeSetHasNewLayout(root, false); for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { YGTransferLayoutOutputsRecursive( - env, thiz, YGNodeGetChild(root, i), layoutContext); + env, thiz, YGNodeGetChild(root, i), layoutContext, shouldCleanLocalRef); } } @@ -372,13 +378,17 @@ static void jni_YGNodeCalculateLayoutJNI( } const YGNodeRef root = _jlong2YGNodeRef(nativePointer); + const bool shouldCleanLocalRef = + root->getConfig()->isExperimentalFeatureEnabled( + YGExperimentalFeatureFixJNILocalRefOverflows); YGNodeCalculateLayoutWithContext( root, static_cast(width), static_cast(height), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)), layoutContext); - YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext); + YGTransferLayoutOutputsRecursive( + env, obj, root, layoutContext, shouldCleanLocalRef); } catch (const YogaJniException& jniException) { ScopedLocalRef throwable = jniException.getThrowable(); if (throwable.get()) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp index 96b424a3bfd..5753403ef6d 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.cpp @@ -109,6 +109,8 @@ const char* YGExperimentalFeatureToString(const YGExperimentalFeature value) { return "absolute-percentage-against-padding-edge"; case YGExperimentalFeatureFixAbsoluteTrailingColumnMargin: return "fix-absolute-trailing-column-margin"; + case YGExperimentalFeatureFixJNILocalRefOverflows: + return "fix-jnilocal-ref-overflows"; } return "unknown"; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h index 72146fe2798..990e3149773 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h +++ b/packages/react-native/ReactCommon/yoga/yoga/YGEnums.h @@ -66,7 +66,8 @@ YG_ENUM_SEQ_DECL( YGExperimentalFeature, YGExperimentalFeatureWebFlexBasis, YGExperimentalFeatureAbsolutePercentageAgainstPaddingEdge, - YGExperimentalFeatureFixAbsoluteTrailingColumnMargin) + YGExperimentalFeatureFixAbsoluteTrailingColumnMargin, + YGExperimentalFeatureFixJNILocalRefOverflows) YG_ENUM_SEQ_DECL( YGFlexDirection,