New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 820067 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Mar 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 2
Type: Bug



Sign in to add a comment

Selection is moved after removing part of the text on 'compositionend' event in which composition takes place

Reported by k.krz...@cksource.com, Mar 8 2018

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36

Steps to reproduce the problem:
1. Create contenteditable element with HTML like `<p>Foo<strong>Bar</strong></p>`.
2. Create a `compositionend` listener attached to editable, which will remove first few characters from `<strong>` text node on composition end.
3. Put caret like `<p>Foo<strong>Bar^</strong></p>`.
4. Start and end composition which will result in inserting some text.

If this scenario is not obvious to understand check below codepen in which it can be easily reproduced: https://codepen.io/f1ames/pen/EEYjKg?editors=1010

What is the expected behavior?
After removing some characters on `compositionend` event from text node in which selection is present, selection does not change.

What went wrong?
After removing some characters on `compositionend` event from text node in which selection is present, selection moves right (by the same amount of characters which was removed).

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 64.0.3282.167  Channel: stable
OS Version: OS X 10.11.6
Flash Version: 

## Observations

When text data is removed via `CharacterData.replaceData` or `CharacterData.deleteData` it works in other browsers (FF, Safari) and selection is not moved, but fails, as described, in Chrome.

When text is removed by replacing whole text node data like `textNode.data = textNode.data.substr( 7 );` it fails on Chrome as described above. In other browsers selection is moved to the beginning of the text node.

Deferring (`setTimeout( ..., 0 )`) the text removal inside `compositionend` listener, results in Chrome behaving like other browsers using `textNode.data = textNode.data.substr( 7 );` - selection moves to the beginning of the text node.

Selection movement looks async, manually setting selection after text removal has no effect.

When instead of `compositionend`, listening to `keyup` (so just plain typing), Chrome moves selection to the beginning of text node when using `textNode.data = textNode.data.substr( 7 );` and works fine with `CharacterData.*` methods.

The original issue is related to removing zero-width spaces from text node after composition ends, however it seems it also happens with printable characters.
 
Chrome - Mar-08-2018 14-27-02.gif
830 KB View Download
Firefox - Mar-08-2018 14-27-35.gif
467 KB View Download
Safari - Mar-08-2018 14-28-16.gif
439 KB View Download
I think this is the same issue we fixed in  crbug.com/737395 . Can you please verify that the issue does not occur in Chrome 65 (which just started getting rolled out this week)?
Labels: Needs-Triage-M64
Cc: rlanday@chromium.org vamshi.kommuri@chromium.org
Labels: Triaged-ET Needs-Feedback
Thanks for filing the issue!

@Reporter: As per comment#1 could you please check the same issue on upcoming latest stable version where issue seems to be fixed and let us know it's behaviour. From  crbug.com/737395   cc'ing  "rlanday".
That's great news! Checked on newest Chrome (Version 65.0.3325.146 (Official Build) (64-bit)) and yes, it is fixed (for cases mentioned in original description), but only partially.

I still found 3 cases in which it can be reproduced, the set up is the same, but now listening and removing characters on `compositionstart/update` (check attached gifs showing how it behaves with Spanish accent and macOS accent panel) it is still reproducible.

The above is, let's say, not that big issue, since with this events you know composition takes place so it is easier to determine if text node can be manipulated, still an issue IMHO.

However, there is a serious issue with macOS accent panel. When listening to and manipulating text node on `keyup` (which in case of accent panel may be called before composition events so you are unable to determine that composition will take place), the caret looks like it is not moved, but character in composition is inserted in the wrong place (check out the 3rd attached gif and codepen - https://codepen.io/f1ames/pen/pLoyrM?editors=1010).


compositionstart_spanish - Mar-09-2018 11-15-05.gif
574 KB View Download
compositionstart_macosaccent - Mar-09-2018 11-16-17.gif
923 KB View Download
keyup_macosaccent - Mar-09-2018 11-56-58.gif
615 KB View Download
Project Member

Comment 5 by sheriffbot@chromium.org, Mar 9 2018

Labels: -Needs-Feedback
Thank you for providing more feedback. Adding the requester to the cc list.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Status: Available (was: Unconfirmed)
compositionstart and compositionupdate are fired before we actually perform the DOM edit requested by the IME. So if you change the text in that time frame, you’re kind of asking for trouble since the IME’s about to perform an edit but you’ve just changed the text it’s expecting. Performing edits in response to input or compositionend should be safe as of M65.

I’m having a hard time reproducing the behavior you’re describing on macOS. I think keyup is fired *after* compositionupdate in every scenario I’ve tested:
https://w3c.github.io/uievents/tools/key-event-viewer.html

Can you please provide more detail?

What you’re describing though seems to be the result of an implementation detail with how composition edits are implemented. When an IME wants to change the text in the current composition, we first select the composition range, then let the IME overwrite it, then take this new selection range and convert it back to a composition range. I’m not sure it’s safe to change this since some developers apparently depend on this behavior to get the composition range (see discussion on  https://crbug.com/812674 ).
> compositionstart and compositionupdate are fired before we actually perform the DOM edit requested by the IME. So if you change the text in that time frame, you’re kind of asking for trouble since the IME’s about to perform an edit but you’ve just changed the text it’s expecting.

I can agree to some extent, but in all cases in this issue the part of the text which is removed does not contain selection. Selection is placed in the part which is not touched so it should be safe. In different scenarios, when you have selection inside text, removing some part of the text before/after does not affect selection in any way I suppose, so why it happens in this case?
Plus even for `compositionstart/update` it works fine in Firefox and Safari.

As for the third case, te reproduce this scenario you have to press `a` first, then accent panel will appear, the release `a` (this will trigger `keyup`). And the pressing `left/right arrow` will trigger `compositionstart`. I attached two more gifs which shows this behaviour. 
Mar-09-2018 17-41-30.gif
4.7 MB View Download
Mar-09-2018 17-43-35.gif
6.6 MB View Download
> I can agree to some extent, but in all cases in this issue the part of the text which is removed does not contain selection. Selection is placed in the part which is not touched so it should be safe. In different scenarios, when you have selection inside text, removing some part of the text before/after does not affect selection in any way I suppose, so why it happens in this case?

I told you why it works this way. We could potentially change the implementation, but I’m not sure what the point would really be, and it might break other web apps. You’re essentially moving the composition range when you move the selection. If you move the selection here, the IME is going to overwrite it anyway after it updates the composition, so there’s really no point.

> As for the third case, te reproduce this scenario you have to press `a` first, then accent panel will appear, the release `a` (this will trigger `keyup`). And the pressing `left/right arrow` will trigger `compositionstart`. I attached two more gifs which shows this behaviour. 

It’s not interesting to me that it’s possible to have a keyup event, and then later, have an IME open a composition from a separate action. That’s a fairly trivial observation. From Chrome’s perspective, it should be perfectly safe to change the text in between those two operations. It might possibly confuse the accent panel, but we can’t really do anything about that. Your test case seems messed up in Safari too.
When I say “the IME is going to overwrite [the selection] anyway after it updates the composition,” this is because our implementation is heavily influenced by the need to properly support text input on Android.

Two of the methods used for inputting text on Android:

setComposingText():
https://developer.android.com/reference/android/view/inputmethod/InputConnection.html#setComposingText(java.lang.CharSequence,%20int)

commitText();
https://developer.android.com/reference/android/view/inputmethod/InputConnection.html#commitText(java.lang.CharSequence,%20int)

provide a selection offset together with the new text. So from our perspective, there’s no good way to support changing the selection in the middle of an IME command. You should wait until either the input or compositionend events.
Thank you for clarification. So (more or less) the the position where text during/after composition is inserted, is based on text/offset of the node before composition starts (or collected on `compositionstart` event).

This makes sense and I agree that fiddling with text/selection in the text node in which composition takes place is asking for trouble. Thanks to `composition*` events is easy to distinguish such situations, so we may prevent any manipulation during composition. This is fine.

However, I'm still worried about 3rd case with MacOS accent panel, where removing part of the text on `keyup` which takes place before `compositionstart` (as composition is fired on arrows navigation through panel) also affects the composition as explained in my previous comment. Do you have any thoughts on that? Is it the same case or the cause is different here?
I agree it's not ideal, but I think this is between you and Apple. We can't predict in Chrome that the accent panel is going to open any more than you can. I think they're sort of persisting state in a way we can't keep track of.
Status: WontFix (was: Available)

Sign in to add a comment