Skip to content

Fix Text parity fuzz edge cases#75

Merged
mfkrause merged 2 commits into
kuatsu:mainfrom
adamivancza:codex/text-fuzz-72-74
Jul 6, 2026
Merged

Fix Text parity fuzz edge cases#75
mfkrause merged 2 commits into
kuatsu:mainfrom
adamivancza:codex/text-fuzz-72-74

Conversation

@adamivancza

@adamivancza adamivancza commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #72
Fixes #74

Summary

  • normalize style: null as host-equivalent to absent style in parity comparisons
  • make static style.userSelect clobber direct selectable even when the value maps to undefined
  • add deterministic parity cases for both fuzz findings

Validation

  • parity test suite
  • parity fuzz gate
  • Text optimizer tests
  • typecheck
  • format

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of text styles so null and unknown selectable states are treated more consistently.
    • Better preserves the last applicable style value when multiple style objects are combined.
    • Updated text rendering behavior to avoid dropping or misapplying selectable-related props in edge cases.

@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

@adamivancza is attempting to deploy a commit to the Kuatsu Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 03428934-eb06-423e-9a9f-8ec43cc06cf4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Rewrites the style-based userSelect/selectable extraction to return a structured result with stricter static resolution checks, updates the Text optimizer to use this structured result, and adjusts parity test normalization/cases to handle style={null} and invalid userSelect values.

Changes

Selectable Extraction and Parity Fixes

Layer / File(s) Summary
Selectable extraction contract rewrite
packages/react-native-boost/src/plugin/utils/common/attributes.ts
extractSelectableAndUpdateStyle now flattens style candidates, bails when the last userSelect value is nullish or non-static, and returns a SelectableExtraction object instead of a plain boolean; userSelect removal is now conditional on passing these checks.
Text optimizer selectable wiring
packages/react-native-boost/src/plugin/optimizers/text/index.ts
processProps consumes selectable.value from the new structured result and emits selectable={undefined} when the value is explicitly undefined, instead of always emitting a boolean literal.
Parity normalization and test cases
packages/react-native-boost/src/plugin/__tests__/parity/normalize.ts, packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts
normalize now deletes style when it's null; new TEXT_CASES entries cover style={null} with adjustsFontSizeToFit={false}, and userSelect: "xyz" combined with selectable={true}.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Poem

A style of null, once tossed away,
Now lingers gently, come what may.
userSelect's whims, both real and "xyz",
Now rightly clobber selectable's plea.
Hop hop hooray, the parity's tight! 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the Text parity fuzz fix.
Linked Issues check ✅ Passed The changes normalize style: null and make userSelect override selectable, matching the linked issues' requirements.
Out of Scope Changes check ✅ Passed All edits stay within Text parity normalization, optimizer logic, and targeted tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/react-native-boost/src/plugin/optimizers/text/index.ts`:
- Line 339: The `selectable` prop generation currently emits an identifier for
`undefined`, which can be shadowed by a local binding. Update the `selectable`
handling in the text optimizer logic to emit an unshadowable undefined value
using the existing AST helper pattern instead of `t.identifier('undefined')`,
while keeping the boolean literal path unchanged. Use the surrounding
`selectable.value` expression in
`packages/react-native-boost/src/plugin/optimizers/text/index.ts` to locate the
fix.

In `@packages/react-native-boost/src/plugin/utils/common/attributes.ts`:
- Around line 431-452: The style-userSelect extraction in attributes.ts is too
optimistic when `styleExpr` contains mixed or unresolved entries, which can
cause the computed selectable value to be overridden by later flattened styles.
Update the logic around the candidate collection and `processTextStyle` handling
so it bails out to runtime whenever the style array includes dynamic elements,
spreads, or any unresolved nested entries rather than only handling fully static
object arrays. Keep the fix localized to the `collect` flow and the final
`last`/`removeUserSelectProperties` decision so `selectable` is only derived
when RN flatten order can be preserved safely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89981b52-bafa-49f9-8ec4-c85d566c5e15

📥 Commits

Reviewing files that changed from the base of the PR and between c823949 and 2270285.

📒 Files selected for processing (4)
  • packages/react-native-boost/src/plugin/__tests__/parity/normalize.ts
  • packages/react-native-boost/src/plugin/__tests__/parity/parity.test.ts
  • packages/react-native-boost/src/plugin/optimizers/text/index.ts
  • packages/react-native-boost/src/plugin/utils/common/attributes.ts

Comment thread packages/react-native-boost/src/plugin/optimizers/text/index.ts Outdated
Comment thread packages/react-native-boost/src/plugin/utils/common/attributes.ts
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-native-boost-docs Ready Ready Preview, Comment Jul 6, 2026 4:08pm

@mfkrause mfkrause merged commit cc94e0e into kuatsu:main Jul 6, 2026
6 of 7 checks passed
@mfkrause

mfkrause commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Appreciated! :)

@adamivancza adamivancza deleted the codex/text-fuzz-72-74 branch July 7, 2026 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Text: invalid userSelect style value fails to clobber a direct selectable prop Text: style={null} is dropped instead of passed through

2 participants