From acfe2d76cfbca48e83f2f681b863ea27e9288e7d Mon Sep 17 00:00:00 2001 From: entelostre Date: Wed, 19 Aug 2026 13:14:45 +0300 Subject: [PATCH] Fix TextInput state revisions retaining their predecessor on Android Summary: #55719 added shadowViewFromShadowNode() to BaseTextInputShadowNode.h, nulling props/state on a fragment's parentShadowView so a text-input state revision does not retain the previous one. AndroidTextInputShadowNode is `final : public ConcreteViewShadowNode<...>` and builds its own fragment for the input's text value, so it never received that fix. ShadowView::state points at the AndroidTextInputState held when the fragment was built, and that fragment is stored into the next state by updateStateIfNeeded(), making revision N retain N-1. The chain grows one link per update and is destroyed by nested recursion, exhausting the native stack. Nothing reads Fragment::parentShadowView.props or .state - only tag, layoutMetrics and componentHandle are consumed - so clearing them is behaviour-preserving, including on the MapBuffer measurement path. Changelog: [Android] [Fixed] - Fix TextInput state revisions retaining their predecessor, causing a native stack overflow after many text updates --- .../androidtextinput/AndroidTextInputShadowNode.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp index 5a09063b9f34..94db00591406 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp @@ -190,6 +190,12 @@ AttributedString AndroidTextInputShadowNode::getAttributedString( // that effect. fragment.textAttributes.backgroundColor = clearColor(); fragment.parentShadowView = ShadowView(*this); + // Clearing `props` and `state` (which we don't use) allows avoiding + // retaining the previous state revision. Same rationale as + // `shadowViewFromShadowNode()` in `BaseTextInputShadowNode.h`, which this + // platform override does not inherit. + fragment.parentShadowView.props = nullptr; + fragment.parentShadowView.state = nullptr; attributedString.prependFragment(std::move(fragment)); }