fix: detect autofilled values on focus for controlled inputs #35719
+81
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Human View
Summary
Fixes #1159 — an 11-year-old bug where browser autofill breaks controlled components.
When browsers autofill form fields (saved passwords, address autocomplete, password managers), they may set the input value without firing
inputorchangeevents. This causes controlled components to have stale state — the user sees filled data but React state remains empty. On form submission, data is lost.Root Cause
React's
ChangeEventPlugindetects value changes viagetTargetInstForInputOrChangeEvent(), which only checks values wheninputorchangeDOM events fire. When browsers autofill without events (e.g., Chrome on iOS, some password managers), React never checks and never firesonChange.Fix
Add value change detection on
focusinevents for text inputs. Thefocusinevent is already registered as a dependency ofonChangebut was unused for modern browsers. When a user focuses an autofilled field, React now checks if the DOM value differs from its tracked value (viaupdateValueIfChanged()) and firesonChangeif so.This is safe because:
updateValueIfChanged()compares the value tracker with the actual DOM value — if they match, no event fires (zero false positives)focusinalready bubbles to the root and is captured by React's event delegationChange
1 function modified in
ChangeEventPlugin.js(+7 lines):Coverage
Known Limitations
Test Plan
ReactDOMInput-test.jsAI View (DCCE Protocol v1.0)
Metadata
AI Contribution Summary
Verification Steps Performed
Human Review Guidance
ChangeEventPlugin.js,ReactDOMInput-test.jsMade with M7 Cursor