Skip to content

Commit 5964a19

Browse files
NickGerlemanmeta-codesync[bot]
authored andcommitted
Delete fixTextClippingAndroid15useBoundsForWidth() (#56282)
Summary: Pull Request resolved: #56282 Fixes #56185 Fixes #56186 Fixes #56187 Delete the `fixTextClippingAndroid15useBoundsForWidth()` feature flag and all code gated behind it. This flag was never shipped, and the new code path has been implicated in several bugs. The change removes: - The feature flag definition and all generated plumbing (C++, JNI, Kotlin, JS) - The visual-bounds-based width measurement path in `TextLayoutManager.kt` - The `setUseBoundsForWidth(true)` call in `buildLayout()` - The MobileConfig parameter (`react_fabric.fix_text_clipping_android_15_use_bounds_for_width`) - The Facebook Android and OSS Experimental overrides The old advance-based width logic is retained as the sole code path. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D98427218 fbshipit-source-id: 7c322353d9c0a0548386a486ecd4280b73a66872
1 parent aaa0684 commit 5964a19

23 files changed

+57
-240
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<61964fd9ddf11ed5c2848da3f4d0b490>>
7+
* @generated SignedSource<<c47da5069c3dfd7a287125bd0dfbc0c0>>
88
*/
99

1010
/**
@@ -384,12 +384,6 @@ public object ReactNativeFeatureFlags {
384384
@JvmStatic
385385
public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = accessor.fixMappingOfEventPrioritiesBetweenFabricAndReact()
386386

387-
/**
388-
* Fix text clipping starting in Android 15 due to usage of useBoundsForWidth
389-
*/
390-
@JvmStatic
391-
public fun fixTextClippingAndroid15useBoundsForWidth(): Boolean = accessor.fixTextClippingAndroid15useBoundsForWidth()
392-
393387
/**
394388
* Fix flex basis computation to not apply FitContent constraint in the main axis for non-measure container nodes, preventing unnecessary re-measurement in scroll containers.
395389
*/

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<4ce2605ff71e60b6096a211ff902e994>>
7+
* @generated SignedSource<<0d98c7f7d2762c248a9670a447b5a93e>>
88
*/
99

1010
/**
@@ -79,7 +79,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
7979
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
8080
private var fixFindShadowNodeByTagRaceConditionCache: Boolean? = null
8181
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
82-
private var fixTextClippingAndroid15useBoundsForWidthCache: Boolean? = null
8382
private var fixYogaFlexBasisFitContentInMainAxisCache: Boolean? = null
8483
private var fuseboxAssertSingleHostStateCache: Boolean? = null
8584
private var fuseboxEnabledReleaseCache: Boolean? = null
@@ -643,15 +642,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
643642
return cached
644643
}
645644

646-
override fun fixTextClippingAndroid15useBoundsForWidth(): Boolean {
647-
var cached = fixTextClippingAndroid15useBoundsForWidthCache
648-
if (cached == null) {
649-
cached = ReactNativeFeatureFlagsCxxInterop.fixTextClippingAndroid15useBoundsForWidth()
650-
fixTextClippingAndroid15useBoundsForWidthCache = cached
651-
}
652-
return cached
653-
}
654-
655645
override fun fixYogaFlexBasisFitContentInMainAxis(): Boolean {
656646
var cached = fixYogaFlexBasisFitContentInMainAxisCache
657647
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<5f3573c9983cb54c5df527a3053ebbae>>
7+
* @generated SignedSource<<01dbfbb85643951c562e2cf1725387ff>>
88
*/
99

1010
/**
@@ -146,8 +146,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
146146

147147
@DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
148148

149-
@DoNotStrip @JvmStatic public external fun fixTextClippingAndroid15useBoundsForWidth(): Boolean
150-
151149
@DoNotStrip @JvmStatic public external fun fixYogaFlexBasisFitContentInMainAxis(): Boolean
152150

153151
@DoNotStrip @JvmStatic public external fun fuseboxAssertSingleHostState(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<a822c8a92925244e2a302bd04f034fa0>>
7+
* @generated SignedSource<<79077f7e8b2a7d435ac44c0a31ab87cc>>
88
*/
99

1010
/**
@@ -141,8 +141,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
141141

142142
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
143143

144-
override fun fixTextClippingAndroid15useBoundsForWidth(): Boolean = false
145-
146144
override fun fixYogaFlexBasisFitContentInMainAxis(): Boolean = false
147145

148146
override fun fuseboxAssertSingleHostState(): Boolean = true

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<e211fdbb92579b05507ea84ae42f22ff>>
7+
* @generated SignedSource<<b6c95e5954a185b0ee8c0ae8dde4a74b>>
88
*/
99

1010
/**
@@ -83,7 +83,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
8383
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
8484
private var fixFindShadowNodeByTagRaceConditionCache: Boolean? = null
8585
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
86-
private var fixTextClippingAndroid15useBoundsForWidthCache: Boolean? = null
8786
private var fixYogaFlexBasisFitContentInMainAxisCache: Boolean? = null
8887
private var fuseboxAssertSingleHostStateCache: Boolean? = null
8988
private var fuseboxEnabledReleaseCache: Boolean? = null
@@ -706,16 +705,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
706705
return cached
707706
}
708707

709-
override fun fixTextClippingAndroid15useBoundsForWidth(): Boolean {
710-
var cached = fixTextClippingAndroid15useBoundsForWidthCache
711-
if (cached == null) {
712-
cached = currentProvider.fixTextClippingAndroid15useBoundsForWidth()
713-
accessedFeatureFlags.add("fixTextClippingAndroid15useBoundsForWidth")
714-
fixTextClippingAndroid15useBoundsForWidthCache = cached
715-
}
716-
return cached
717-
}
718-
719708
override fun fixYogaFlexBasisFitContentInMainAxis(): Boolean {
720709
var cached = fixYogaFlexBasisFitContentInMainAxisCache
721710
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<8531ce29d0e5362517d35559ebda623b>>
7+
* @generated SignedSource<<dffc5db0f80501f6246f9d6087c6fb4a>>
88
*/
99

1010
/**
@@ -27,7 +27,5 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
2727

2828
override fun enableSwiftUIBasedFilters(): Boolean = true
2929

30-
override fun fixTextClippingAndroid15useBoundsForWidth(): Boolean = true
31-
3230
override fun preventShadowTreeCommitExhaustion(): Boolean = true
3331
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<540700c0c0f3259a093a98ad639478ba>>
7+
* @generated SignedSource<<30a507b84b656705ee1abec794472d6b>>
88
*/
99

1010
/**
@@ -141,8 +141,6 @@ public interface ReactNativeFeatureFlagsProvider {
141141

142142
@DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean
143143

144-
@DoNotStrip public fun fixTextClippingAndroid15useBoundsForWidth(): Boolean
145-
146144
@DoNotStrip public fun fixYogaFlexBasisFitContentInMainAxis(): Boolean
147145

148146
@DoNotStrip public fun fuseboxAssertSingleHostState(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import com.facebook.react.uimanager.PixelUtil
3636
import com.facebook.react.uimanager.PixelUtil.dpToPx
3737
import com.facebook.react.uimanager.PixelUtil.pxToDp
3838
import com.facebook.react.uimanager.ReactAccessibilityDelegate
39-
import com.facebook.react.util.AndroidVersion.VERSION_CODE_VANILLA_ICE_CREAM
4039
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan
4140
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan
4241
import com.facebook.react.views.text.internal.span.CustomStyleSpan
@@ -634,63 +633,14 @@ internal object TextLayoutManager {
634633
)
635634
}
636635

637-
// Pre-Android 15: Use existing advance-based logic
638-
if (
639-
Build.VERSION.SDK_INT < VERSION_CODE_VANILLA_ICE_CREAM ||
640-
!ReactNativeFeatureFlags.fixTextClippingAndroid15useBoundsForWidth()
641-
) {
642-
val desiredWidth = ceil(Layout.getDesiredWidth(text, paint)).toInt()
643-
644-
val layoutWidth =
645-
when (widthYogaMeasureMode) {
646-
YogaMeasureMode.EXACTLY -> floor(width).toInt()
647-
YogaMeasureMode.AT_MOST -> min(desiredWidth, floor(width).toInt())
648-
else -> desiredWidth
649-
}
650-
return buildLayout(
651-
text,
652-
layoutWidth,
653-
includeFontPadding,
654-
textBreakStrategy,
655-
hyphenationFrequency,
656-
alignment,
657-
justificationMode,
658-
ellipsizeMode,
659-
maxNumberOfLines,
660-
paint,
661-
)
662-
}
663-
664-
// Android 15+: Need to account for visual bounds
665-
// Step 1: Create unconstrained layout to get visual bounds width
666-
val unconstrainedLayout =
667-
buildLayout(
668-
text,
669-
Int.MAX_VALUE / 2,
670-
includeFontPadding,
671-
textBreakStrategy,
672-
hyphenationFrequency,
673-
alignment,
674-
justificationMode,
675-
null,
676-
ReactConstants.UNSET,
677-
paint,
678-
)
679-
680-
// Calculate visual bounds width from unconstrained layout
681-
var desiredVisualWidth = 0f
682-
for (i in 0 until unconstrainedLayout.lineCount) {
683-
val lineWidth = unconstrainedLayout.getLineRight(i) - unconstrainedLayout.getLineLeft(i)
684-
desiredVisualWidth = max(desiredVisualWidth, lineWidth)
685-
}
636+
val desiredWidth = ceil(Layout.getDesiredWidth(text, paint)).toInt()
686637

687638
val layoutWidth =
688639
when (widthYogaMeasureMode) {
689-
YogaMeasureMode.AT_MOST -> min(ceil(desiredVisualWidth).toInt(), floor(width).toInt())
690-
else -> ceil(desiredVisualWidth).toInt()
640+
YogaMeasureMode.EXACTLY -> floor(width).toInt()
641+
YogaMeasureMode.AT_MOST -> min(desiredWidth, floor(width).toInt())
642+
else -> desiredWidth
691643
}
692-
693-
// Step 2: Create final layout with correct width
694644
return buildLayout(
695645
text,
696646
layoutWidth,
@@ -737,16 +687,6 @@ internal object TextLayoutManager {
737687
builder.setUseLineSpacingFromFallbacks(true)
738688
}
739689

740-
// setUseBoundsForWidth added in API 35 — use reflection to support internal targets that
741-
// compile against an SDK older than 35.
742-
// https://developer.android.com/reference/android/text/StaticLayout.Builder#setUseBoundsForWidth(boolean)
743-
if (
744-
Build.VERSION.SDK_INT >= VERSION_CODE_VANILLA_ICE_CREAM &&
745-
ReactNativeFeatureFlags.fixTextClippingAndroid15useBoundsForWidth()
746-
) {
747-
setUseBoundsForWidthMethod?.invoke(builder, true)
748-
}
749-
750690
return builder.build()
751691
}
752692

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<6c088ccf18868fc6e54d83c7483b6607>>
7+
* @generated SignedSource<<880f137911af6d2a9d383ebd68ddc300>>
88
*/
99

1010
/**
@@ -393,12 +393,6 @@ class ReactNativeFeatureFlagsJavaProvider
393393
return method(javaProvider_);
394394
}
395395

396-
bool fixTextClippingAndroid15useBoundsForWidth() override {
397-
static const auto method =
398-
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixTextClippingAndroid15useBoundsForWidth");
399-
return method(javaProvider_);
400-
}
401-
402396
bool fixYogaFlexBasisFitContentInMainAxis() override {
403397
static const auto method =
404398
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("fixYogaFlexBasisFitContentInMainAxis");
@@ -884,11 +878,6 @@ bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabri
884878
return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact();
885879
}
886880

887-
bool JReactNativeFeatureFlagsCxxInterop::fixTextClippingAndroid15useBoundsForWidth(
888-
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
889-
return ReactNativeFeatureFlags::fixTextClippingAndroid15useBoundsForWidth();
890-
}
891-
892881
bool JReactNativeFeatureFlagsCxxInterop::fixYogaFlexBasisFitContentInMainAxis(
893882
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
894883
return ReactNativeFeatureFlags::fixYogaFlexBasisFitContentInMainAxis();
@@ -1252,9 +1241,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
12521241
makeNativeMethod(
12531242
"fixMappingOfEventPrioritiesBetweenFabricAndReact",
12541243
JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact),
1255-
makeNativeMethod(
1256-
"fixTextClippingAndroid15useBoundsForWidth",
1257-
JReactNativeFeatureFlagsCxxInterop::fixTextClippingAndroid15useBoundsForWidth),
12581244
makeNativeMethod(
12591245
"fixYogaFlexBasisFitContentInMainAxis",
12601246
JReactNativeFeatureFlagsCxxInterop::fixYogaFlexBasisFitContentInMainAxis),

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<73cfe749b34b786e25b683c499889e48>>
7+
* @generated SignedSource<<906bda93de19c1836ce3df29e05db610>>
88
*/
99

1010
/**
@@ -207,9 +207,6 @@ class JReactNativeFeatureFlagsCxxInterop
207207
static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(
208208
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
209209

210-
static bool fixTextClippingAndroid15useBoundsForWidth(
211-
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
212-
213210
static bool fixYogaFlexBasisFitContentInMainAxis(
214211
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
215212

0 commit comments

Comments
 (0)