Fix Cursor blot restoration and selection preservation #2354
+105
−37
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR refixes issue #1019 and de0d564.
Repros for bugs addressed:
aa
, click between the two A's, then do command-B, command-B, then typeb
. You should get a plainaba
with the cursor after theb
. Added a functional test for this.aa
, click between the two A's, then do command-B, typeb
, command-B, typec
. You should getabca
with a boldb
. Added a functional test for a case similar to this.asdfasdf
), click in the middle of it, then do command-B, command-B, and then click somewhere else in the text, before or after the first position. The text cursor should stay where you planted it (instead of e.g. jumping to the end of the line). This is equivalent to the unit test that was failing.Basically, to be correct,
cursor.restore
has to take a number of things into account:cursor.restore
may be a selection change from the user clicking in a different text node, such as that of an adjacent TextBlot, which may be optimized away. Therefore, selection preservation must operate even if the selection isn't in the Cursor blot's own textNode. This is the subject of repro 4 above. In this case, I also had to make sure that the return value ofcursor.restore
is always used by the caller!editor.update
, but for full correctness there mustn't be any case ofcursor.restore
that uses the Cursor blot's own textNode, mutated by the user, as part of the document (outside of the Cursor blot which is removed), because then the "hack path" ineditor.update
will think it has a green light and try to generate a delta based on the current value of the text node, which is not going to come out properly.The solution is for
cursor.restore
to optimize the surrounding text nodes on the spot and calculate an appropriate selection range if the old selection is anywhere in those text nodes.