Skip to content

[web] Preserve active autofill form across text input configuration updates - #193269

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
simonpham:master
Oct 8, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:masterfrom
simonpham:master

Conversation

@simonpham

@simonpham simonpham commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #192102
Fixes #193267

Problem

Toggling TextField.obscureText on Web sends TextInput.updateConfig, which decodes a new EngineAutofillForm lacking an associated DOM form (formElement == null).

On blur (TextInput.clearClient), the web engine bypasses dormancy and tears down the active DOM input element. Refocusing the field leaves it unresponsive to keyboard events.

Solution

Preserve the active EngineAutofillForm across TextInput.updateConfig in DefaultTextEditingStrategy.applyConfiguration. This retains live DOM ownership so the form goes dormant on blur and wakes up cleanly on refocus.

Testing

Added engine unit tests in text_editing_test.dart for multi-field and single-field autofill forms, verifying dormancy and refocus reusability.

Issue Result
#192102: plain password field
Screen.Recording.2026-09-24.at.15.42.06.mov
#193267: password field with autofill hints
Screen.Recording.2026-09-24.at.15.42.42.mov

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • All existing and new tests are passing.

@github-actions github-actions Bot added a: text input Entering text in a text field or keyboard related problems engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team labels Sep 24, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the web text editing engine to preserve and reuse the active autofill form during configuration updates instead of replacing the DOM form. This is achieved by introducing updateFrameworkConfiguration on EngineAutofillForm and updating applyConfiguration in DefaultTextEditingStrategy to reuse the existing autofill group when identity properties match. Corresponding tests were added to verify this behavior. The review feedback suggests refactoring the duplicated identity checks into a helper method hasSameIdentity on EngineAutofillForm to improve maintainability.

@simonpham simonpham changed the title [web] Preserve autofill form across TextInput.updateConfig draft: [web] Preserve autofill form across TextInput.updateConfig Sep 24, 2026
@simonpham
simonpham marked this pull request as draft September 24, 2026 08:21
@simonpham simonpham changed the title draft: [web] Preserve autofill form across TextInput.updateConfig draft: [web] Restart text input connection when obscureText changes Sep 24, 2026
@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. and removed engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team labels Sep 24, 2026
@simonpham simonpham changed the title draft: [web] Restart text input connection when obscureText changes [web] Restart text input connection when obscureText changes Sep 24, 2026
@simonpham
simonpham marked this pull request as ready for review September 24, 2026 08:59

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request modifies EditableTextState to schedule a text input connection restart on web when obscureTextChanged is true, instead of updating the configuration. It also updates the corresponding tests in editable_text_test.dart to verify this behavior specifically on web while skipping the standard configuration update test on web. I have no feedback to provide.

@justinmc justinmc added the CICD Run CI/CD label Sep 24, 2026
justinmc
justinmc previously approved these changes Sep 24, 2026

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM 👍 . I tried this on my Mac using a composing Chinese Pinyin keyboard and I couldn't seem to find cause any bugs. Tapping to change obscureText while in the middle of composing just commits the text as-is, without converting to Chinese characters. This seems to be the same before before and after this PR.

@Renzo-Olivares Renzo-Olivares left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for digging into this @simonpham!

I think the fix belongs in the web engine rather than in EditableText. The root cause is that #182024 made the autofill <form> lazily created and reused across connections, but TextInput.updateConfig still decodes a brand new EngineAutofillForm with no DOM form and swaps it in for the live one. On the next blur, disable() sees formElement == null and removes the <input> instead of letting the form go dormant. If the form went dormant earlier, wakeUp then calls replaceWith on a detached element, so the new <input> never makes it into the DOM.

Because of that, restarting the connection for obscureText only covers one of the callers. I tried this branch in Chrome and the same dead field still reproduces when keyboardType or readOnly changes while the field is focused (focus, blur, focus, change the property, blur, focus, type). The viewId change and any third-party TextInputClient that calls TextInputConnection.updateConfig go through the same path.

@Renzo-Olivares Renzo-Olivares added the waiting for response The Flutter team cannot make further progress on this issue until the original reporter responds label Oct 1, 2026
@Renzo-Olivares

Copy link
Copy Markdown
Contributor

fyi @mdebbar @flutter-zl if y'all had any thoughts on the web diagnosis #193269 (review)

@simonpham

simonpham commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for digging into this @simonpham!

I think the fix belongs in the web engine rather than in EditableText. The root cause is that #182024 made the autofill <form> lazily created and reused across connections, but TextInput.updateConfig still decodes a brand new EngineAutofillForm with no DOM form and swaps it in for the live one. On the next blur, disable() sees formElement == null and removes the <input> instead of letting the form go dormant. If the form went dormant earlier, wakeUp then calls replaceWith on a detached element, so the new <input> never makes it into the DOM.

Because of that, restarting the connection for obscureText only covers one of the callers. I tried this branch in Chrome and the same dead field still reproduces when keyboardType or readOnly changes while the field is focused (focus, blur, focus, change the property, blur, focus, type). The viewId change and any third-party TextInputClient that calls TextInputConnection.updateConfig go through the same path.

Thanks for this insight. But your suggestion was my initial attempt to fix and it did not work. You can see the first commit of this PR (which later I force-pushed the right fix in the framework).
nevermind. Let me test with your suggested fix later and let you know.

@github-actions github-actions Bot removed the waiting for response The Flutter team cannot make further progress on this issue until the original reporter responds label Oct 2, 2026
@mdebbar

mdebbar commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

+1 I agree with @Renzo-Olivares's assessment to fixing this in the engine.

@mdebbar mdebbar added the CICD Run CI/CD label Oct 8, 2026
@mdebbar
mdebbar requested a review from Renzo-Olivares October 8, 2026 15:10

@Renzo-Olivares Renzo-Olivares left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, google testing failures need a rebase to fully verify. Analyzer failures seem unrelated.

…pdates

When TextInput.updateConfig arrives while an autofill form is active,
the newly decoded EngineAutofillForm has no associated DOM form.
Preserve the active form so that on blur/disable the form goes dormant
and remains reusable rather than incorrectly removing the live element.

Fixes flutter#192102
SemanticsTextEditingStrategy never sets _appendedToForm, so the check
skipped preserving the active autofill form in semantics mode. Rely on
the active group's formElement alone.
@Renzo-Olivares Renzo-Olivares added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 8, 2026
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 8, 2026
@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Oct 8, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Oct 8, 2026
Merged via the queue into flutter:master with commit 4c15b12 Oct 8, 2026
24 of 25 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 8, 2026
sero583 added a commit to sero583/flutter that referenced this pull request Oct 18, 2026
Resolves the conflicts with flutter#187108, flutter#190942 and flutter#193269, and reformats
the change for the Dart 3.13 formatter from flutter#192649.
suryaKommana2662 pushed a commit to suryaKommana2662/flutter that referenced this pull request Oct 29, 2026
…pdates (flutter#193269)

Fixes flutter#192102
Fixes flutter#193267

### Problem
Toggling `TextField.obscureText` on Web sends `TextInput.updateConfig`,
which decodes a new `EngineAutofillForm` lacking an associated DOM form
(`formElement == null`).

On blur (`TextInput.clearClient`), the web engine bypasses dormancy and
tears down the active DOM input element. Refocusing the field leaves it
unresponsive to keyboard events.

### Solution
Preserve the active `EngineAutofillForm` across `TextInput.updateConfig`
in `DefaultTextEditingStrategy.applyConfiguration`. This retains live
DOM ownership so the form goes dormant on blur and wakes up cleanly on
refocus.

### Testing
Added engine unit tests in `text_editing_test.dart` for multi-field and
single-field autofill forms, verifying dormancy and refocus reusability.

| Issue | Result |
| - | - |
| flutter#192102: plain password field |
https://github.com/user-attachments/assets/a8c98c15-7dbe-4d91-bf32-bbe90bfffc08
|
| flutter#193267: password field with autofill hints |
https://github.com/user-attachments/assets/7c57998f-4e80-42bc-bc3c-b7bdc49f27db
|

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: text input Entering text in a text field or keyboard related problems CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team

Projects

None yet

4 participants