1414
1515namespace facebook ::react {
1616
17+ // Derive accessibilityTraits from the resolved role and accessibilityState
18+ // members. This makes accessibilityTraits the single source of truth.
19+ // See: github.com/facebook/react-native/issues/57515
20+ static AccessibilityTraits deriveAccessibilityTraits (
21+ Role role,
22+ const std::string& accessibilityRole,
23+ const std::optional<AccessibilityState>& accessibilityState) {
24+ AccessibilityTraits traits = AccessibilityTraits::None;
25+ if (role != Role::None) {
26+ fromString (toString (role), traits);
27+ } else if (!accessibilityRole.empty ()) {
28+ fromString (accessibilityRole, traits);
29+ }
30+
31+ const auto state = accessibilityState.value_or (AccessibilityState{});
32+ if (state.selected ) {
33+ traits = traits | AccessibilityTraits::Selected;
34+ }
35+ if (state.disabled ) {
36+ traits = traits | AccessibilityTraits::NotEnabled;
37+ }
38+
39+ return traits;
40+ }
41+
1742AccessibilityProps::AccessibilityProps (
1843 const PropsParserContext& context,
1944 const AccessibilityProps& sourceProps,
@@ -146,19 +171,9 @@ AccessibilityProps::AccessibilityProps(
146171 ImportantForAccessibility::Auto)),
147172 testId(
148173 convertRawProp (context, rawProps, " testID" , sourceProps.testId, " " )) {
149- // It is a (severe!) perf deoptimization to request props out-of-order.
150- // Thus, since we need to request the same prop twice here
151- // (accessibilityRole) we "must" do them subsequently here to prevent
152- // a regression. It is reasonable to ask if the `at` function can be improved;
153- // it probably can, but this is a fairly rare edge-case that (1) is easy-ish
154- // to work around here, and (2) would require very careful work to address
155- // this case and not regress the more common cases.
156174 auto * accessibilityRoleValue = rawProps.at (" accessibilityRole" );
157175 auto * roleValue = rawProps.at (" role" );
158176
159- auto * precedentRoleValue =
160- roleValue != nullptr ? roleValue : accessibilityRoleValue;
161-
162177 if (accessibilityRoleValue == nullptr ||
163178 !accessibilityRoleValue->hasValue ()) {
164179 accessibilityRole = sourceProps.accessibilityRole ;
@@ -172,11 +187,8 @@ AccessibilityProps::AccessibilityProps(
172187 fromRawValue (context, *roleValue, role);
173188 }
174189
175- if (precedentRoleValue == nullptr || !precedentRoleValue->hasValue ()) {
176- accessibilityTraits = sourceProps.accessibilityTraits ;
177- } else {
178- fromRawValue (context, *precedentRoleValue, accessibilityTraits);
179- }
190+ accessibilityTraits =
191+ deriveAccessibilityTraits (role, accessibilityRole, accessibilityState);
180192}
181193
182194void AccessibilityProps::setProp (
@@ -188,7 +200,12 @@ void AccessibilityProps::setProp(
188200
189201 switch (hash) {
190202 RAW_SET_PROP_SWITCH_CASE_BASIC (accessible);
191- RAW_SET_PROP_SWITCH_CASE_BASIC (accessibilityState);
203+ case CONSTEXPR_RAW_PROPS_KEY_HASH (" accessibilityState" ): {
204+ fromRawValue (context, value, accessibilityState, defaults.accessibilityState );
205+ accessibilityTraits =
206+ deriveAccessibilityTraits (role, accessibilityRole, accessibilityState);
207+ return ;
208+ }
192209 RAW_SET_PROP_SWITCH_CASE_BASIC (accessibilityLabel);
193210 RAW_SET_PROP_SWITCH_CASE (
194211 accessibilityOrder, " experimental_accessibilityOrder" );
@@ -209,18 +226,21 @@ void AccessibilityProps::setProp(
209226 RAW_SET_PROP_SWITCH_CASE_BASIC (onAccessibilityEscape);
210227 RAW_SET_PROP_SWITCH_CASE_BASIC (onAccessibilityAction);
211228 RAW_SET_PROP_SWITCH_CASE_BASIC (importantForAccessibility);
212- RAW_SET_PROP_SWITCH_CASE_BASIC (role);
229+ case CONSTEXPR_RAW_PROPS_KEY_HASH (" role" ): {
230+ fromRawValue (context, value, role, defaults.role );
231+ accessibilityTraits =
232+ deriveAccessibilityTraits (role, accessibilityRole, accessibilityState);
233+ return ;
234+ }
213235 RAW_SET_PROP_SWITCH_CASE (testId, " testID" );
214236 case CONSTEXPR_RAW_PROPS_KEY_HASH (" accessibilityRole" ): {
215- AccessibilityTraits traits = AccessibilityTraits::None;
216237 std::string roleString;
217238 if (value.hasValue ()) {
218- fromRawValue (context, value, traits);
219239 fromRawValue (context, value, roleString);
220240 }
221-
222- accessibilityTraits = traits;
223241 accessibilityRole = roleString;
242+ accessibilityTraits =
243+ deriveAccessibilityTraits (role, accessibilityRole, accessibilityState);
224244 return ;
225245 }
226246 }
0 commit comments