Bug: Crash when select all and delete with only table in the editor
Copy-pasting/ Inserting a table into the editor and deleting it by selecting all crashes the editor.
Lexical version: v0.17.1
Steps To Reproduce
- By copy/paste
- Copy a table
- Ctrl + A in the lexical editor
- Paste
- Ctrl + A
- Press Del key
- By Inserting
- Insert table
- Remove everything before and after the table node
- Ctrl + A
- Press Del
The current behavior
Can see crashes
The expected behavior
To not crash and delete the table
I've tried both ways, but I'm not able to reproduce those crashes, tried with both - the current playground and a few commits ago locally.
Interesting - I can consistently reproduce the crash in the playground. After you inserted the table, did you remove the nodes before the table node?
The repro instructions for case 2 don't work for me, but it does work if there is nothing before and an empty paragraph after.
- Clear editor
- Insert table
- Press up to move cursor to paragraph before table
- Press delete to remove paragraph before table
- Press Ctrl-A to select all
- Press delete to crash
Appears to be a crash in RangeSelection.getNodes in isBefore. Could possibly be related to #6568 but the root cause is that by the time the DELETE_CHARACTER_COMMAND runs the table is already not connected (not sure yet what code is doing this) but since the DOM for it still exists it ends up getting selected along the way.
$deleteCellHandler is removing the table before the code runs. I think the root cause of the bug is really that table.remove() doesn't properly update the selection so it's likely the best fix is in $removeNode (perhaps $maybeMoveChildrenSelectionToParent)?
After doing a deeper dive it seems that the problem is that the implementation of deleteCharacter ends up applying the DOM selection to the current selection (via applyDOMRange in modify) after the node is already removed and chaos ensues because it ends up creating a selection where the anchor is not attached to the root anymore. It's a weird thing to do because at the point you call applyDOMRange the DOM and its selection might have no overlap at all with the document since reconciliation hasn't happened yet. Not exactly clear what the best fix would be, maybe @zurfyx has some insight because he has worked on some of this code (e.g. #3279).
In an ideal world I don't think we would want to call applyDOMRange in this flow at all, at least with the character granularity?
This is the playground URL I was using to repro the issue:
It doesn't preserve selection so you have to make the selection and then press delete but it makes setting it up a little quicker