WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
110742
selectionStart/selectionEnd return "obsolete" values when requested during "input" event
https://bugs.webkit.org/show_bug.cgi?id=110742
Summary
selectionStart/selectionEnd return "obsolete" values when requested during "i...
Eugene Klyuchnikov
Reported
2013-02-25 02:39:01 PST
Steps to reproduce: 1) Create input element 2) Attach "input" listener 3) Log input value and selectionStart/selectionEnd when event is fired Result: 1) After first key is typed (after focusing input control) value.length = selectionStart = selectionEnd = 1 (correct) 2) After consequent keys selectionStart = selectionEnd = value.length - 1 (incorrect) Expected result: typing resets selection, so if cursor is at the end of input, then we expect value.length = selectionStart = selectionEnd Note: after "Delete" is hit cursor position is reported correctly. But insert/replace behave the same way as typing. Analysis: we fire "input" event before selection is updated.
Attachments
Patch
(4.52 KB, patch)
2013-02-25 02:41 PST
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(5.59 KB, patch)
2013-03-01 03:19 PST
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(5.47 KB, patch)
2013-03-04 01:07 PST
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(5.79 KB, patch)
2013-03-11 05:18 PDT
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(6.41 KB, patch)
2013-04-09 02:31 PDT
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(8.75 KB, patch)
2013-05-30 06:32 PDT
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Patch
(8.75 KB, patch)
2013-05-30 07:32 PDT
,
Eugene Klyuchnikov
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from webkit-ews-15 for mac-mountainlion-wk2
(559.57 KB, application/zip)
2013-05-30 09:06 PDT
,
Build Bot
no flags
Details
Patch
(2.68 KB, patch)
2013-06-03 02:30 PDT
,
Eugene Klyuchnikov
rniwa
: review-
Details
Formatted Diff
Diff
Show Obsolete
(7)
View All
Add attachment
proposed patch, testcase, etc.
Eugene Klyuchnikov
Comment 1
2013-02-25 02:41:17 PST
Created
attachment 190024
[details]
Patch
Build Bot
Comment 2
2013-02-25 04:30:38 PST
Comment on
attachment 190024
[details]
Patch
Attachment 190024
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://queues.webkit.org/results/16749177
New failing tests: editing/selection/caret-after-keypress.html
Alexey Proskuryakov
Comment 3
2013-02-25 09:53:13 PST
What do other browsers do? Should the event be async? Cancellable?
Eugene Klyuchnikov
Comment 4
2013-02-25 21:38:50 PST
(In reply to
comment #3
)
> What do other browsers do? Should the event be async? Cancellable?
In MSDN it is said: Synchronous No; Bubbles No; Cancelable No In Mozilla Event reference it is said: Bubbles Yes; Cancelable No In current Firefox release selectionStart/selectionEnd is coherent with input content. In whatwg.org specs it is mentioned that firing event must be queued on input content change (so, implicitly, caret/selection during dispatching will be actual). Also several "input" events could be collapsed (to denote that user stopped typing).
Ryosuke Niwa
Comment 5
2013-02-27 01:11:09 PST
Comment on
attachment 190024
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=190024&action=review
I'm somewhat nervous about changing the timing of this event because of the way copy & paste uses webkitEditableContentChangedEvent and how alternative text controller may depends on events firing in advance but I can't think of bugs that this change will introduce off the top of my head.
> LayoutTests/editing/selection/caret-after-keypress-expected.txt:6 > +[] 0 0 > +[a] 1 1 > +[ab] 2 2
Instead of just logging values like this, can we use shouldBe and other functions in js-test-pre.js to make the test more explicit? As is, it's hard to tell when the test is passing or why these outputs ought to be correct.
Eugene Klyuchnikov
Comment 6
2013-02-28 02:33:59 PST
(In reply to
comment #5
)
> ...and how alternative text controller may depends on events firing in advance but I can't think of bugs that this change will introduce off the top of my head.
IMHO controller couldn't depend on receiving notification "in advance" because in other cases it receives notifications after selection is fixed (known cases are: first keypress after input is focused; user deleted char in input). As a best effort we could implement deferred "onInput" notifications...
Eugene Klyuchnikov
Comment 7
2013-03-01 03:07:06 PST
Comment on
attachment 190024
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=190024&action=review
>> LayoutTests/editing/selection/caret-after-keypress-expected.txt:6 >> +[ab] 2 2 > > Instead of just logging values like this, can we use shouldBe and other functions in js-test-pre.js to make the test more explicit? > As is, it's hard to tell when the test is passing or why these outputs ought to be correct.
Fixed.
Eugene Klyuchnikov
Comment 8
2013-03-01 03:19:28 PST
Created
attachment 190922
[details]
Patch
Ryosuke Niwa
Comment 9
2013-03-01 12:00:47 PST
Comment on
attachment 190922
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=190922&action=review
> LayoutTests/editing/selection/caret-after-keypress.html:46 > + test.addEventListener("input", step);
I really don't understand why we need to make this test asynchronous given that input event fires synchronously. We can run all the steps synchronously.
Eugene Klyuchnikov
Comment 10
2013-03-04 01:06:17 PST
(In reply to
comment #9
)
> I really don't understand why we need to make this test asynchronous given that input event fires synchronously. > We can run all the steps synchronously.
OK, I'll make test synchronous. But as I mentioned, in HTML5 spec it is not yet determined if "input" event is synchronous or asynchronous. So making test asynchronous shields us from details of implementation that could change.
Eugene Klyuchnikov
Comment 11
2013-03-04 01:07:20 PST
Created
attachment 191167
[details]
Patch
Ryosuke Niwa
Comment 12
2013-03-09 00:25:04 PST
Comment on
attachment 191167
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=191167&action=review
> LayoutTests/editing/selection/caret-after-keypress-expected.txt:12 > +PASS 0 > +PASS 1 > +PASS 2 > +PASS 3 > +PASS 4 > +PASS 5 > +PASS 6
I'm sorry but this output is not exactly helpful. It doesn't tell me what each test case is testing and why they're passing.
> LayoutTests/editing/selection/caret-after-keypress.html:27 > + assertEquals(test.value, output.join(""), "value"); > + assertEquals(test.selectionStart, output.length, "selectionStart"); > + assertEquals(test.selectionEnd, output.length, "selectionEnd");
It seems like all we need to do is to use shouldBe instead of assertEquals.
> LayoutTests/editing/selection/caret-after-keypress.html:28 > + testPassed("" + pass++);
This is going to output PASS regardless of whether tests have passed or not.
> LayoutTests/editing/selection/caret-after-keypress.html:34 > + var key = input.shift(); > + if (key === backSpace) > + output.pop(); > + else > + output.push(key);
This makes it really hard to understand what's happening in the test. I would have preferred to hard code the expected output instead. It's very important for tests to be obvious and self-evidently correct. Unfortunately, this test isn't so self-evident to me and I think we can do better.
Eugene Klyuchnikov
Comment 13
2013-03-11 05:12:27 PDT
Comment on
attachment 191167
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=191167&action=review
>> LayoutTests/editing/selection/caret-after-keypress.html:27 >> + assertEquals(test.selectionEnd, output.length, "selectionEnd"); > > It seems like all we need to do is to use shouldBe instead of assertEquals.
OK
>> LayoutTests/editing/selection/caret-after-keypress.html:28 >> + testPassed("" + pass++); > > This is going to output PASS regardless of whether tests have passed or not.
oops. fixed.
>> LayoutTests/editing/selection/caret-after-keypress.html:34 >> + output.push(key); > > This makes it really hard to understand what's happening in the test. I would have preferred to hard code the expected output instead. > It's very important for tests to be obvious and self-evidently correct. > Unfortunately, this test isn't so self-evident to me and I think we can do better.
Done
Eugene Klyuchnikov
Comment 14
2013-03-11 05:18:03 PDT
Created
attachment 192444
[details]
Patch
Eugene Klyuchnikov
Comment 15
2013-03-28 00:28:56 PDT
Comment on
attachment 192444
[details]
Patch Any news?
Ryosuke Niwa
Comment 16
2013-03-28 00:49:48 PDT
Comment on
attachment 192444
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=192444&action=review
> Source/WebCore/ChangeLog:3 > + [Editor] selectionStart/selectionEnd return "obsolete" values when requested during "input" event.
We don't prefix a bug with "[Editor]".
> Source/WebCore/ChangeLog:7 > +
This patch changes the timing at which webkitEditableContentChangedEvent is fired. You should explain why that results in "input" event being fired at the right time.
Ryosuke Niwa
Comment 17
2013-03-28 00:49:49 PDT
Comment on
attachment 192444
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=192444&action=review
> Source/WebCore/ChangeLog:3 > + [Editor] selectionStart/selectionEnd return "obsolete" values when requested during "input" event.
We don't prefix a bug with "[Editor]".
> Source/WebCore/ChangeLog:7 > +
This patch changes the timing at which webkitEditableContentChangedEvent is fired. You should explain why that results in "input" event being fired at the right time.
Eugene Klyuchnikov
Comment 18
2013-03-29 02:21:07 PDT
Analysis: after key-press there are 2 possibilities 1) We recently focused input, so new CompositeEditCommand is created and applied. 2) We have done some editing already, so insertion command is appended. Here are two scenarios in time/nesting cut. First (good) scenario. keypress event dispatching { textInput event dispatching { CompositeEditCommand::apply creates scope { Editor::appliedEditing invoked { dispatchEditableContentChangedEvents invoked { webkitEditableContentChanged dispatched { input event enqueued (because it is scoped event) } } * FrameSelection::setSelection invoked } } * input event is dispatched because scope is closed } } Second (bad) scenario. keypress event dispatching { textInput event dispatching { Editor::appliedEditing invoked { dispatchEditableContentChangedEvents invoked { webkitEditableContentChanged dispatched { * input event dispatched (no scope this time) } } * FrameSelection::setSelection invoked (too late) } } } So I see 3 possible solutions 1) Invoke dispatchEditableContentChangedEvents after setSelection (but you are right, this should be done for all 3 methods: applied/unapplied/reapplied editing). 2) Create scope in those 3 methods; actually this will save order of execution of webkitEditableContentChanged and setSelection and just pull out dispatching of input event. 3) Place more coarse scope (several stack levels up), but we can't predict how it will affect execution. Overall (2) solution looks like least invasive.
Ryosuke Niwa
Comment 19
2013-03-29 10:12:28 PDT
Why don't we have EditCommand in the stack in the second scenario?
Eugene Klyuchnikov
Comment 20
2013-04-01 00:32:17 PDT
As I said earlier 2 paths are "create composition" and "append to composition". Details. Both paths has common point: TypingCommand::insertText(document, text, selection, options, compositionType) Condition "if (lastTypingCommandIfStillOpenForTyping(...))" splits them. First (good) scenarion we create typing command, and then: TextInsertionBaseCommand::applyTextInsertionCommand applyCommand [CompositeEditCommand.cpp:170] * CompositeEditCommand::apply TypingCommand::doApply = TypingCommand::insertText = forEachLineInString [TextInsertionBaseCommand.h:61] = TypingCommandLineOperation::operator() = TypingCommand::insertTextRunWithoutNewlines = TypingCommand::typingAddedToOpenCommand = Editor::appliedEditing "*" is where scope create. Second scenario is shorter: it consists only of lines marked with "=". So the answer is: we do not apply command because we do not create one.
Eugene Klyuchnikov
Comment 21
2013-04-07 22:44:16 PDT
to Ryosuke Niwa: any thoughts how this should be fixed?
Ryosuke Niwa
Comment 22
2013-04-07 22:46:06 PDT
We should fix this but I don't think the patch posted here is correct.
Eugene Klyuchnikov
Comment 23
2013-04-08 04:59:00 PDT
(In reply to
comment #22
)
> We should fix this but I don't think the patch posted here is correct.
Surely. Earlier I've proposed 3 patch ideas. Personally I like this one: create EventQueueScope in 3 Editor methods: appliedEditing, unappliedEditing, reappliedEditing. This is least invasive solution, because it will affect only on time when "input" event is dispatched (in case it is fired). It is up to you to choose the best way to fix. Just post a comment with decision and I'll implement corresponding patch.
Ryosuke Niwa
Comment 24
2013-04-08 07:22:49 PDT
If we were to use the event scope to resolve this bug, I'd instantiate the scope object in TypingCommand::insertText and other static functions of TypingCommand since the event scope was invented to delay firing of mutation events. On the other hand, it's strange that the event scope is needed for correctness of ordering of events. Ordering of the events should be correct regardless of whether we define the scope or not.
Eugene Klyuchnikov
Comment 25
2013-04-08 09:20:32 PDT
(In reply to
comment #24
)
> If we were to use the event scope to resolve this bug, I'd instantiate the scope object in TypingCommand::insertText and other static functions of TypingCommand since the event scope was invented to delay firing of mutation events. > > On the other hand, it's strange that the event scope is needed for correctness of ordering of events. Ordering of the events should be correct regardless of whether we define the scope or not.
That is what we began with. I've proposed to move "setSelection" before "dispatchEvent". Because that is what expected by user. But it turned out that scoping could be an alternate solution. This solution looks in terms of "how alternative text controller may depends on events firing in advance". Summary. We have to care about 2 message types: "webkitEditableContentChanged" and "input". The later one is fired from the first. We are aimed to make "input" be dispatched after setSelection, but it not known how change of "webkitEditableContentChanged" firing time will affect different aspects of editing.
Ryosuke Niwa
Comment 26
2013-04-08 09:27:49 PDT
We need to look at each place we listen to webkitEditableContentChanged, and make sure that code still works when we change the order. I'm sorry I sound like blocking your patch but we need to verify the correctness regardless of which approach we take. And the burden of the proof is on each patch author. I can't, as a reviewer, tell you which approach is better, let alone correct.
Eugene Klyuchnikov
Comment 27
2013-04-09 01:56:32 PDT
(In reply to
comment #26
)
> We need to look at each place we listen to webkitEditableContentChanged, and make sure that code still works when we change the order. I'm sorry I sound like blocking your patch but we need to verify the correctness regardless of which approach we take. And the burden of the proof is on each patch author. I can't, as a reviewer, tell you which approach is better, let alone correct.
I quite agree with you =) But your expertise in the area is very valuable! I've checked: we have no explicit listeners of webkitEditableContentChanged, but some handlers process this message specifically. As I see none of work with selection. When Node dispatches "webkitEditableContentChanged" it create "input" event and dispatches it as scoped. So it is at least suggested that scope is placed. There are two distinct invocations of Editor::appliedEditing. One from composite command, other one from typing command. un-/re-appliedEditing is invoked only from composite command. To be honest, none of those calls are wrapped directly by scope. So, what I see: 1) commands do not care about "input" event at all, and it is implementation detail of editor, when to dispatch this event; 2) webkitEditableContentChanged dispatchers do not depend on selection As a result, I propose to swap setSelection and dispatch of event in aforementioned 3 methods. I'll upload patch soon.
Eugene Klyuchnikov
Comment 28
2013-04-09 02:31:26 PDT
Created
attachment 197012
[details]
Patch
Eugene Klyuchnikov
Comment 29
2013-05-30 06:32:10 PDT
Created
attachment 203349
[details]
Patch
Eugene Klyuchnikov
Comment 30
2013-05-30 07:32:11 PDT
Created
attachment 203355
[details]
Patch
Build Bot
Comment 31
2013-05-30 09:06:15 PDT
Comment on
attachment 203355
[details]
Patch
Attachment 203355
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-queues.appspot.com/results/661182
New failing tests: fast/dom/location-new-window-no-crash.html
Build Bot
Comment 32
2013-05-30 09:06:18 PDT
Created
attachment 203363
[details]
Archive of layout-test-results from webkit-ews-15 for mac-mountainlion-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: webkit-ews-15 Port: mac-mountainlion-wk2 Platform: Mac OS X 10.8.3
Ryosuke Niwa
Comment 33
2013-05-30 12:25:39 PDT
(In reply to
comment #27
)
> (In reply to
comment #26
) > > We need to look at each place we listen to webkitEditableContentChanged, and make sure that code still works when we change the order. I'm sorry I sound like blocking your patch but we need to verify the correctness regardless of which approach we take. And the burden of the proof is on each patch author. I can't, as a reviewer, tell you which approach is better, let alone correct. > > I quite agree with you =) But your expertise in the area is very valuable! > > I've checked: we have no explicit listeners of webkitEditableContentChanged, but some handlers process this message specifically. As I see none of work with selection. > > When Node dispatches "webkitEditableContentChanged" it create "input" event and dispatches it as scoped. So it is at least suggested that scope is placed. > > There are two distinct invocations of Editor::appliedEditing. One from composite command, other one from typing command. un-/re-appliedEditing is invoked only from composite command. To be honest, none of those calls are wrapped directly by scope. > > So, what I see: > 1) commands do not care about "input" event at all, and it is implementation detail of editor, when to dispatch this event; > 2) webkitEditableContentChanged dispatchers do not depend on selection > > As a result, I propose to swap setSelection and dispatch of event in aforementioned 3 methods.
Thanks for the investigation.
Eugene Klyuchnikov
Comment 34
2013-05-30 22:15:19 PDT
Committed
r151009
: <
http://trac.webkit.org/changeset/151009
>
Eugene Klyuchnikov
Comment 35
2013-06-03 02:30:36 PDT
Reopening to attach new patch.
Eugene Klyuchnikov
Comment 36
2013-06-03 02:30:41 PDT
Created
attachment 203563
[details]
Patch
Eugene Klyuchnikov
Comment 37
2013-06-03 02:52:46 PDT
Ooops. Attached to wrong bug. (In reply to
comment #36
)
> Created an attachment (id=203563) [details] > Patch
Alexey Proskuryakov
Comment 38
2013-06-03 08:53:21 PDT
Where should this patch be attached?
Bug 117070
?
Ryosuke Niwa
Comment 39
2013-06-03 09:35:19 PDT
Comment on
attachment 203563
[details]
Patch Please post this patch on a new bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug