diff --git a/packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts b/packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts index 044a873..d845892 100644 --- a/packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts +++ b/packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts @@ -139,6 +139,18 @@ describe('differential parity', () => { expect(normalize(boost.props)).toEqual(normalize(wrapper.props)); }); + it('Text: static userSelect overrides selectable from a later spread', async () => { + const jsx = + 'hello'; + const preamble = 'const _b0 = false;\nconst _s0 = { selectable: true };'; + const boost = await captureBoost(os, jsx, preamble); + expect(boost.optimized).toBe(true); + if (!boost.optimized) throw new Error('expected Text static userSelect spread case to optimize'); + const wrapper = await captureWrapper(os, jsx, preamble); + expect(boost.which).toEqual(wrapper.which); + expect(normalize(boost.props)).toEqual(normalize(wrapper.props)); + }); + it.each(VIEW_CASES)('View: %s', async (jsx) => { const boost = await captureBoost(os, jsx); expect(boost.optimized).toBe(!BAILED_VIEW_CASES.has(jsx)); diff --git a/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select-overrides-selectable/output.js b/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select-overrides-selectable/output.js index 2805b73..8b67b2b 100644 --- a/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select-overrides-selectable/output.js +++ b/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select-overrides-selectable/output.js @@ -4,11 +4,11 @@ import { } from 'react-native-boost/runtime'; import { Text } from 'react-native'; <_NativeText - selectable={true} style={{ color: 'red', }} allowFontScaling={true} ellipsizeMode={'tail'} + selectable={true} accessible={_getDefaultTextAccessible()} />; diff --git a/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select/output.js b/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select/output.js index 3b74f74..e2213da 100644 --- a/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select/output.js +++ b/packages/react-native-boost/src/plugin/optimizers/text/__tests__/fixtures/static-style-user-select/output.js @@ -4,11 +4,11 @@ import { } from 'react-native-boost/runtime'; import { Text } from 'react-native'; <_NativeText - selectable={false} style={{ color: 'red', }} allowFontScaling={true} ellipsizeMode={'tail'} + selectable={false} accessible={_getDefaultTextAccessible()} />; diff --git a/packages/react-native-boost/src/plugin/optimizers/text/index.ts b/packages/react-native-boost/src/plugin/optimizers/text/index.ts index 789fa62..6ee8566 100644 --- a/packages/react-native-boost/src/plugin/optimizers/text/index.ts +++ b/packages/react-native-boost/src/plugin/optimizers/text/index.ts @@ -427,16 +427,16 @@ function processProps( // ============================================ // 4. Assemble the final attribute list // ============================================ - // `styleSpread` (the runtime `processTextStyle` call) is emitted AFTER the direct attributes so a - // `userSelect`-derived `selectable` it computes at runtime overrides a direct `selectable`, mirroring - // `Text`'s late `userSelect` override. `selectionColorSpread` writes a disjoint key (`selectionColor`), - // so its position is free — it leads for readability. + // `selectableAttribute` and `styleSpread` are emitted AFTER the remaining attributes so style-derived + // `userSelect` overrides direct or spread-carried `selectable`, mirroring `Text`'s late override. + // `selectionColorSpread` writes a disjoint key (`selectionColor`), so its position is free — it leads + // for readability. path.node.attributes = [ selectionColorSpread, accessibilitySpread, - selectableAttribute, staticStyleAttribute, ...remainingAttributes, + selectableAttribute, styleSpread, accessibleAttribute, ].filter((attribute): attribute is t.JSXAttribute | t.JSXSpreadAttribute => attribute !== undefined);