-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
selectionStart/selectionEnd behavior needs to be specified #2424
Comments
So here is a proposal for specific behavior:
This is what I tentatively plan to implement in Gecko. |
@cdumez @domenic @travisleithead Note that I haven't had a chance to test Edge, so maybe it's got sane behavior.... |
/cc @tkent-google
To be clear, this means leaving the text entry cursor alone, unless it would be outside the [0, newlength] range, in which case it gets clamped? |
Yes, exactly. Probably the same thing for selection too. So basically, adjust selectionStart/selectionEnd to min(currentValue,newLength). |
One other problem: it's not clear to me what should happen when the control is focused, or maybe "has been focused". In that case, setting defaultValue seems to put the cursor at the end of the value in browsers? Not sure which parts here are interoperable, exactly. |
I recently filed related issues:
This behavior is definitely a bug. Chrome doesn't update selection values for input/defaultValue change at all.
I agree if this is already interoperable.
Agree. This is defined and interoperable.
I think in many cases modifying a value sets the cursor at the end of the text. At least updating textarea/@DefaultValue sets it to the end in all major browsers. |
It's complicated. In particular there's ok interop for text controls that come from the parser, I think. But if you try to create one from script, you have to do the equivalent of setting .defaultValue, and suddenly implementations are all over the map per above.
Though #2412 is proposing changing it a bit, right?
Right, setting .value needs to do that per current spec. The question is about value changes that don't set .value but do change the value it returns. Most obviously, modifying the value via setRangeText or the user typing or whatnot obviously don't move the cursor. It's not clear how .defaultValue sets should behave. What about reset() calls? Direct mutations to the .nodeValue of a child of a textarea? Might be worth testing what UAs do in practice...
That's only sometimes true in Firefox. I'm pretty sure it's false if the textarea is display:none, for example, or not attached to a document... It's definitely false in Safari, unless I messed something up testing. See my first comment in this issue. |
As noted in https://bugzilla.mozilla.org/show_bug.cgi?id=1345293#c0 this is not necessarily true even in Chrome, depending on what "updating" means.... |
Once this is sorted out, should update the tests in https://hg.mozilla.org/mozilla-central/file/7b19a6386225/testing/web-platform/mozilla/tests/html/semantics/forms/textfieldselection/selection-value-interactions.html and move them to the shared wpt bits. |
I've posted #2437 and web-platform-tests/wpt#5147 around the first of these bugs, #2412, as that seems rather separable. But this and #2411 seem worth solving together; #2411 is largely a subset of the larger question posed here about what happens if the underlying value is changed, somehow. @bzbarsky's plan in #2424 (comment) still seems sound as a way forward, modulo the change in #2437 to not set selection to the end if the value is the same. However the big question for me is how to spec it. We could either have something vague, like "whenever the value changes, run these steps", or we could try to find all the places that update the value. We'll need to do the latter for tests anyway. So far what I've got are:
I guess from this perspective a vague "whenever the value changes" makes more sense. For textareas, there's also a difference between changing the element's value and its raw value. It seems like we only care about changes to value; e.g. if you set the raw value to |
You missed a few. Off the top of my head:
You'd think some of these would be covered by your list, but at least Blink has different behavior for
Right. I'm not sure how these interact with selection in practice. Is the selection in the raw value or in the value? |
Oh, and I think it's obvious that paste/cut should probably not modify selection/cursor stuff in any ways other than the obvious one.... But at this point it would merely sadden me, not surprise me, to discover that we have no interop there either... |
Sounds good. I'll try to add those to the test cases.
I imagine it should be on something with normalized line breaks (so value or API value) since you can't select the |
Don't they give different answers for the "did the value change?" question? In an ideal world, our definition of "value did not change" should probably be such that doing |
I can't see how. They are just two different ways of normalizing away line breaks. As far as I can see apiValue1 === apiValue2 iff value1 === value2. An example input where this is not true would be appreciated. |
No, that's not true. Here's a testcase:
The API values are different: one is Of course the only spec requirement here is that the Of course the other direction works too: if I have two textareas, one with |
I guess if you restrict to a single textarea, such that you can assume a particular value of the |
Thanks. I was indeed thinking one text area, but I guess even then it's not so simple. I think we should compare API values then. |
Comparing API values makes the most sense to me. |
This is a minor point from the larger issue of #2424.
This catches Safari and Chrome bugs noted in whatwg/html#2424
This is a minor point from the larger issue of #2424.
A related issue that comes very close to the above discussion but I don't think we ever explicitly touched on was noted by @bzbarsky in #2770: when setting the value to something smaller than the currently-selected range (e.g. setting the value to "ab" when selectionStart or selectionEnd are 3) the behavior is not interoperable. Also, dropping a reminder to myself in this thread to file bugs on browsers for #2770 at the same time as filing bugs for however we fix this. I think filing separate bugs will be a bit annoying since anyone fixing the two bugs will end up touching very similar code so we shouldn't make them do it twice. |
The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla.
The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla.
I might be able to help a bit here, but I'd personally prefer to see the spec patch first. I've never written tests for a standard so the more context and explicit instructions I have, the better :-) Should all those tests go into |
The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla.
The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla.
@emanchado (!) I strongly suspect that how you think makes sense will be just fine, but once you submit some you can ask for review on your PR and iterate from there. |
Ok, I have started looking into this (see emanchado/servo@181b375) but I have a bunch of questions:
|
Working directly with the upstream repository would be preferable to upstreaming them from Servo's copy. |
What we're trying to specify/test here is what happens to the selection bounds when the underlying value of a field changes under various "edge case" scenarios. What happens to the selection bounds when There are more edge cases listed in the links in @domenic's comment above:
I think that's fine. (Alternatively you could set
I don't think you can detect this, or need to. |
Disallow mutating the internals of TextInput The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20051) <!-- Reviewable:end -->
…rom jonleighton:prevent-invalid-selections); r=jdm The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla. Source-Repo: https://github.com/servo/servo Source-Revision: f6463c89d50b0ebc377bfe10bd0ffe0c59dd84ca --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : a8ee624291af3d58b8126cd067ea9f7292bfca6b
Ok, see different approach in the branch It's obviously incomplete, but I seem to be getting better results:
Comments welcome. If this looks good now, I'll keep going and will try to cover all the mentioned cases. |
The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla.
Previously the spec allowed this to be "up to platform conventions", but the web depends on it being at the beginning: see https://bugzilla.mozilla.org/show_bug.cgi?id=1337392. This also updates the spec to require resetting the cursor to the beginning after type changes. This is not currently interoperable, although it is the case in Edge and Gecko. This was brought up in the context of the larger issue of whatwg#2424.
Per the test case included as an example in the spec, this is more in line with browser behavior, and makes more sense. A similar conclusion was reached on related matters in whatwg#2424, and also in whatwg#2437.
…rom jonleighton:prevent-invalid-selections); r=jdm The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla. Source-Repo: https://github.com/servo/servo Source-Revision: f6463c89d50b0ebc377bfe10bd0ffe0c59dd84ca UltraBlame original commit: 9d5cf31fee15fe12d992bc4548c777e94be01664
…rom jonleighton:prevent-invalid-selections); r=jdm The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla. Source-Repo: https://github.com/servo/servo Source-Revision: f6463c89d50b0ebc377bfe10bd0ffe0c59dd84ca UltraBlame original commit: 9d5cf31fee15fe12d992bc4548c777e94be01664
…rom jonleighton:prevent-invalid-selections); r=jdm The TextInput::assert_ok_selection() method is meant to ensure that we are not getting into a state where a selection refers to a location in the control's contents which doesn't exist. However, before this change we could have a situation where the internals of the TextInput are changed by another part of the code, without using its public API. This could lead to us having an invalid selection. I did manage to trigger such a situation (see the test added in this commit) although it is quite contrived. There may be others that I didn't think of, and it's also possible that future changes could introduce new cases. (Including ones which trigger panics, if indexing is used on the assumption that the selection indices are always valid.) The current HTML specification doesn't explicitly say that selectionStart/End must remain within the length of the content, but that does seems to be the consensus reached in a discussion of this: whatwg/html#2424 The test case I've added here is currently undefined in the spec which is why I've added it in tests/wpt/mozilla. Source-Repo: https://github.com/servo/servo Source-Revision: f6463c89d50b0ebc377bfe10bd0ffe0c59dd84ca UltraBlame original commit: 9d5cf31fee15fe12d992bc4548c777e94be01664
Right now the spec is pretty much silent on how this stuff works, and as a result browsers have all sorts of behavior differences, both internally and across browsers. Some examples:
In Chrome,
var x = document.createElement(tag); x.defaultValue = "abc"; alert(x.selectionStart);
will alert 0 iftag
is"input"
but 3 iftag
is"textarea"
.In Safari,
var x = document.createElement("textarea"); x.defaultValue = "abc"; alert(x.selectionStart);
alerts 0. So dovar x = document.createElement("textarea"); document.body.appendChild(x); x.defaultValue = "abc"; alert(x.selectionStart);
andvar x = document.createElement("textarea"); x.selectionStart = x.selectionStart; x.defaultValue = "abc"; alert(x.selectionStart);
. Butvar x = document.createElement("textarea"); document.body.appendChild(x); x.selectionStart = x.selectionStart; x.defaultValue = "abc"; alert(x.selectionStart);
alerts 3.In Gecko... there are various inconsistencies, esp between textarea vs input, display:none vs non-display-none, etc. I'm fixing some of this stuff right now, so not sure it's worth going into the details, which are changing.
OK, what does the spec actually say? It says that setting the "value" IDL attribute of an input that is in "value" mode will move the text entry cursor (if there is one!) to the end of the text.
It also says that setting the "value" IDL attribute of textarea should do the same thing.
It says that UAs must "follow platform conventions to determine their initial state" for the text entry cursor and selection.
That's it. There's no indication of how this initial state should get modified when the value or default value changes...
The text was updated successfully, but these errors were encountered: