Skip to content

[EditableText] Fix TextField crashed with composing and maxLength set#63754

Merged
fluttergithubbot merged 11 commits intoflutter:masterfrom
AlexV525:fix-ios-textfield-maxlength-crash
Aug 24, 2020
Merged

[EditableText] Fix TextField crashed with composing and maxLength set#63754
fluttergithubbot merged 11 commits intoflutter:masterfrom
AlexV525:fix-ios-textfield-maxlength-crash

Conversation

@AlexV525
Copy link
Member

@AlexV525 AlexV525 commented Aug 14, 2020

Description

This is a fix for EditableText and LengthLimitingTextInputFormatter, several behaviors updated.

  • _formatAndSetValue now detects the composing changes and update normally.
  • maxLength (LengthLimitingTextInputFormatter) 's constraint will be temporary lifted if the value is composing.
  • No more composing if the value reached constraint.

Without this fix, apps will crash if they triggered any strange composing delete. It happens from flutter 1.0.0 until now.

Before After
Kapture 2020-08-14 at 16 53 45 Kapture 2020-08-14 at 16 55 19

Related Issues

Resolves #63753
Resolves #35106
Resolves #25511

Tests

I added the following tests:

  • Length formatter will not cause crash while the TextEditingValue is composing in editable text test.
  • Validate form should return correct validation if the value is composing in form test.

Checklist

Before you create this PR, confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I signed the [CLA].
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

  • No, no existing tests failed, so this is not a breaking change.
  • Yes, this is a breaking change.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label Aug 14, 2020
@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@AlexV525
Copy link
Member Author

@googlebot I signed it!

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@cv692001
Copy link

Hey I am very new to contributing , I have read documentations but I am still confused that how to proceed

@goderbauer
Copy link
Member

Looks like this change is causing some tests to fail: https://cirrus-ci.com/task/4806069081866240. This can either mean you're breaking existing functionality or the tests need to be updated. Can you please take a look at those?

Also, in order to accept this PR you will have to write a test to ensure that we never regress and accidentally re-introduce the bug into our code base. Can you please add some tests?

/cc @justinmc

@AlexV525
Copy link
Member Author

Yeah I just forgot to put this into WIP.

@justinmc
Copy link
Contributor

@cv692001 I'm not sure if you're asking in relation to this PR, but if you're just asking about contributing in general, feel free to reach out to me via the contact info in my Github profile.

@AlexV525
Copy link
Member Author

@goderbauer @justinmc I have a question about using the tester to simulate the composing input.

I wrote something like this:

final EditableTextState state =
  tester.state<EditableTextState>(find.byType(EditableText));

state.updateEditingValue(const TextEditingValue(text: '111 1'));
expect(state.currentTextEditingValue.composing, TextRange.empty);

state.updateEditingValue(const TextEditingValue(text: '111 1', composing: TextRange(start: 2, end: 4)));
expect(state.currentTextEditingValue.composing, const TextRange(start: 2, end: 4));

state.updateEditingValue(const TextEditingValue(text: '111 11', composing: TextRange(start: 2, end: 5)));
expect(state.currentTextEditingValue.composing, const TextRange(start: 2, end: 5));

When I tried to add more text with composing like '111 11' (6 characters) it ends up nothing happened. How can I achieve the effect just like the real device's? (Like the screenshot below)
Kapture 2020-08-14 at 16 55 19

@AlexV525
Copy link
Member Author

Forget about it. I forgot that I run this on stable, now it works on the new one.

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this! I confirmed that this fixes the problem for me locally and that the test fails without the fix.

Just one small change on a comment.

I had noticed this problem previously in #35106 and I imagined that something like this behavior would be the best solution. I've added that issue to the description of this PR, because I think it fixes that too.

We should watch out for this causing any undesirable behavior in any existing Flutter apps. For example, with this PR, it's now possible to get an invalid value from a TextField using textFieldController.text. That may cause some Flutter apps to receive invalid values when they previously could not, if they're not checking the valid state of the form.

@justinmc
Copy link
Contributor

I worry that this is a problem too:

Screen Shot 2020-08-17 at 10 49 45 AM

Maybe we shouldn't count composing characters as part of the character limit? Would a native Chinese speaker expect the behavior in the screenshot, or should the character count be zero until the composing characters are committed?

@justinmc
Copy link
Contributor

CC @LongCatIsLooong

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

IMO we shouldn't specialize LengthLimitingTextInputFormatter. The fix should be applied to the implementation of that formatter if possible.

@justinmc it makes sense to me for the length of the text to transiently surpass the limit if there's composing text. The user should be able to input the same thing using IME as they can with copy paste. But I think this is going to be an issue if the user submits the text without finalizing the composing text.

Other input formatters (even third party ones) may have this issue too, @AlexV525 did you by any chance look into why it crashes?

@AlexV525
Copy link
Member Author

AlexV525 commented Aug 18, 2020

We should watch out for this causing any undesirable behavior in any existing Flutter apps. For example, with this PR, it's now possible to get an invalid value from a TextField using textFieldController.text. That may cause some Flutter apps to receive invalid values when they previously could not, if they're not checking the valid state of the form.

@justinmc I'll see if I can add a test to ensure it won't happened.

IMO we shouldn't specialize LengthLimitingTextInputFormatter. The fix should be applied to the implementation of that formatter if possible.

@LongCatIsLooong That make sense. But last night I was thinking about this, should we prevent all formatters update while composing?

Other input formatters (even third party ones) may have this issue too, @AlexV525 did you by any chance look into why it crashes?

Basically when the composing editing value is updated by the formatter, the composing TextRange's end is more than the length of the texts.

Let's go back to the crashing screenshot. Such as 12345 (with 5 composing TextRange(start: 3, end: 4)), then type 6, the value was updated to 12346 (with 6 composing). Since then the composing might be TextRange(start: 3, end: 5) which is more than the actual length. At this time, call delete and the substring is failed, and crashed.

@AlexV525
Copy link
Member Author

AlexV525 commented Aug 18, 2020

After a few hours of investigation, I found that it's hard to land this fix directly on the LengthLimitingTextInputFormatter. Here is a strange behavior I saw:

  1. Input aaaa, with the TextField displayed a a a.
  2. Input another 'a', now the value in _formatAndSetValue becomes a, which means it's been truncated or updated from the method _handleTextInputInvocation.
  3. Continuing input multiple a, then delete when it's over-sized, crashed again.

If we only release the constraint inside the LengthLimitingTextInputFormatter, value won't be truncated when the composing is end and I see no events related.

Maybe it's something with keyboard behavior and the only thing we can do is what we currently have done.

It's done.

@AlexV525
Copy link
Member Author

AlexV525 commented Aug 19, 2020

Now the changes are both landed on LengthLimitingTextInputFormatter and the _formatAndSetValue, to keep composing status unified.

@AlexV525
Copy link
Member Author

We should watch out for this causing any undesirable behavior in any existing Flutter apps. For example, with this PR, it's now possible to get an invalid value from a TextField using textFieldController.text. That may cause some Flutter apps to receive invalid values when they previously could not, if they're not checking the valid state of the form.

The last thing is about this concern. For me, technically, it should be the current value whether it's composing or not. I added a test about form validation when the value composing. Although it can return false if the composing value cannot pass the validator, we definitely should keep our eyes on related behaviors.

@AlexV525
Copy link
Member Author

I've updated the description for behavior changes.

@AlexV525 AlexV525 changed the title [TextField] Fix TextField crashed with composing and maxLength set [EditableText] Fix TextField crashed with composing and maxLength set Aug 21, 2020
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Just a quick grammar fix in a comment below.

It looks like Windows_tool_tests is failing, but it seems unrelated. I tried rerunning it, but if it doesn't pass, it might be necessary to update the branch with master.

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@AlexV525
Copy link
Member Author

Oops, seems run into a CLA issue, can you check this out? @justinmc

@AlexV525 AlexV525 force-pushed the fix-ios-textfield-maxlength-crash branch from 76bce4b to 4a750f5 Compare August 21, 2020 18:04
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@AlexV525 AlexV525 requested a review from justinmc August 21, 2020 18:40
@AlexV525
Copy link
Member Author

(knock knock...)

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍

This should be merged when the build is green. Thanks for all the work on this!

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

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

7 participants