Skip to content

Commit a4733b1

Browse files
aravi365meta-codesync[bot]
authored andcommitted
Fix crash when accessibilityRole="tabbar" is used on Android (#57915)
Summary: Fixes #57890. `tabbar` is part of the public `AccessibilityRole` union in both Flow and TypeScript, with nothing marking it iOS-only, and on iOS it maps to `UIAccessibilityTraitTabBar`. On Android the `AccessibilityRole` enum has no `TABBAR` entry, so `fromValue()` throws `IllegalArgumentException` from `BaseViewManager.setAccessibilityRole` during `createViewInstance` and the app crashes on mount. It is the only value in the union Android fails to resolve. This adds `TABBAR` to the enum and maps it to `android.view.View` in `getValue`, next to `TAB` and `TABLIST`, which likewise have no dedicated Android widget. `getValue` is an exhaustive `when` with no `else`, so the second hunk is required for the enum addition to compile. `setRole` already has an `else` branch, so no `roleDescription` is set for the new value. That looks right to me, since Android has no tab bar concept to announce, but happy to add a string resource if you'd prefer one. ## Changelog: [ANDROID] [FIXED] - Fix crash when `accessibilityRole="tabbar"` is used on Android Pull Request resolved: #57915 Test Plan: Added a unit test to `ReactAccessibilityDelegateTest` asserting that `fromValue("tabbar")` resolves to `TABBAR` and maps to `android.view.View` rather than throwing. Repro from the issue: ```jsx <View accessibilityRole="tabbar"> <Text>hello</Text> </View> ``` Before: crashes on mount on Android with `Invalid accessibility role value: tabbar`. After: renders as a plain view, matching iOS, where roles without a UIKit trait fall back rather than raising. I have not run the Android suite locally, relying on CI for that. Reviewed By: christophpurrer Differential Revision: D115730694 Pulled By: Abbondanzo fbshipit-source-id: ab0ac7987aa0fa0a4015a08514b8d83cfaa0323c
1 parent aa96fa6 commit a4733b1

3 files changed

Lines changed: 12 additions & 0 deletions

File tree

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3630,6 +3630,7 @@ public final class com/facebook/react/uimanager/ReactAccessibilityDelegate$Acces
36303630
public static final field SUMMARY Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
36313631
public static final field SWITCH Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
36323632
public static final field TAB Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
3633+
public static final field TABBAR Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
36333634
public static final field TABLIST Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
36343635
public static final field TEXT Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;
36353636
public static final field TIMER Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole;

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ public open class ReactAccessibilityDelegate( // The View this delegate is attac
437437
SPINBUTTON,
438438
SWITCH,
439439
TAB,
440+
TABBAR,
440441
TABLIST,
441442
TIMER,
442443
LIST,
@@ -491,6 +492,7 @@ public open class ReactAccessibilityDelegate( // The View this delegate is attac
491492
RADIOGROUP,
492493
SCROLLBAR,
493494
TAB,
495+
TABBAR,
494496
TABLIST,
495497
TIMER,
496498
TOOLBAR -> "android.view.View"

packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactAccessibilityDelegateTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ class ReactAccessibilityDelegateTest {
347347
assertThat(view.getTag(R.id.accessibility_state_expanded)).isEqualTo(true)
348348
}
349349

350+
@Test
351+
fun testAccessibilityRole_fromValue_tabbar_resolvesInsteadOfThrowing() {
352+
val role = ReactAccessibilityDelegate.AccessibilityRole.fromValue("tabbar")
353+
354+
assertThat(role).isEqualTo(ReactAccessibilityDelegate.AccessibilityRole.TABBAR)
355+
assertThat(ReactAccessibilityDelegate.AccessibilityRole.getValue(role))
356+
.isEqualTo("android.view.View")
357+
}
358+
350359
@Test
351360
fun testPerformAccessibilityAction_collapseAction_fromAccessibilityActions() {
352361
val accessibilityActions = JavaOnlyArray()

0 commit comments

Comments
 (0)