Skip to content

Fix controlled TextInput jumbling characters during autocorrect on Fabric#56658

Open
fkgozali wants to merge 1 commit intofacebook:mainfrom
fkgozali:export-D103123618
Open

Fix controlled TextInput jumbling characters during autocorrect on Fabric#56658
fkgozali wants to merge 1 commit intofacebook:mainfrom
fkgozali:export-D103123618

Conversation

@fkgozali
Copy link
Copy Markdown
Contributor

Summary:
On iOS Fabric, a controlled <TextInput> could silently drop characters when iOS autocorrect/IME composition was in flight, regressing the controlled-input "jumbled text" behavior that the TextInput-dynamicWidth-e2e.js regression test was designed to catch. The test had been left disabled on iOS Fabric configs because of this, masking the real product regression.

Root cause: RCTTextInputComponentView snapshots the backing field's typingAttributes once at view init time and uses that snapshot as the "insensitive attributes" set for RCTIsAttributedStringEffectivelySame — i.e. the set of UIKit-injected attributes the comparison should ignore so it doesn't trigger a destructive setAttributedText: on every keystroke. UIKit, however, injects additional typing attributes lazily after the field becomes first responder. Concretely, the init snapshot has {NSColor, NSParagraphStyle, NSFont}, but after focus the live typingAttributes also contains NSBackgroundColor (used for the marked-text highlight during composition/autocorrect) and the React Native event-emitter wrapping key. When iOS performs a multi-step text replacement (e.g. autocorrect substituting Thos -> This), characters in the backing string transiently carry these extra attributes. The comparison then incorrectly returns "different", we overwrite the backing field mid-replacement, and the in-flight text mutation is corrupted — exactly the original failure mode this code path was meant to prevent.

Fix: introduce _insensitiveTypingAttributes, which unions the init snapshot with the live typingAttributes at compare time. The init snapshot is preserved as a floor (in case UIKit later removes attributes it had during normal typing), and any attribute UIKit silently injects after focus is now correctly ignored by the comparison.

The fix is small, scoped to RCTTextInputComponentView.mm, and preserves the contract of RCTIsAttributedStringEffectivelySame: we only broaden the insensitive set, never narrow it.

Changelog:
[iOS][Fixed] - Fix controlled TextInput jumbling characters during autocorrect/IME composition on Fabric

Differential Revision: D103123618

…bric

Summary:
On iOS Fabric, a controlled `<TextInput>` could silently drop characters when iOS autocorrect/IME composition was in flight, regressing the controlled-input "jumbled text" behavior that the `TextInput-dynamicWidth-e2e.js` regression test was designed to catch. The test had been left disabled on iOS Fabric configs because of this, masking the real product regression.

Root cause: `RCTTextInputComponentView` snapshots the backing field's `typingAttributes` once at view init time and uses that snapshot as the "insensitive attributes" set for `RCTIsAttributedStringEffectivelySame` — i.e. the set of UIKit-injected attributes the comparison should ignore so it doesn't trigger a destructive `setAttributedText:` on every keystroke. UIKit, however, injects additional typing attributes lazily after the field becomes first responder. Concretely, the init snapshot has `{NSColor, NSParagraphStyle, NSFont}`, but after focus the live `typingAttributes` also contains `NSBackgroundColor` (used for the marked-text highlight during composition/autocorrect) and the React Native event-emitter wrapping key. When iOS performs a multi-step text replacement (e.g. autocorrect substituting `Thos` -> `This`), characters in the backing string transiently carry these extra attributes. The comparison then incorrectly returns "different", we overwrite the backing field mid-replacement, and the in-flight text mutation is corrupted — exactly the original failure mode this code path was meant to prevent.

Fix: introduce `_insensitiveTypingAttributes`, which unions the init snapshot with the live `typingAttributes` at compare time. The init snapshot is preserved as a floor (in case UIKit later removes attributes it had during normal typing), and any attribute UIKit silently injects after focus is now correctly ignored by the comparison.

The fix is small, scoped to `RCTTextInputComponentView.mm`, and preserves the contract of `RCTIsAttributedStringEffectivelySame`: we only broaden the insensitive set, never narrow it.

Changelog:
[iOS][Fixed] - Fix controlled TextInput jumbling characters during autocorrect/IME composition on Fabric

Differential Revision: D103123618
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 30, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Apr 30, 2026

@fkgozali has exported this pull request. If you are a Meta employee, you can view the originating Diff in D103123618.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant