-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Description
The editor can crash if the user is typing while other updates are being applied (for instance, applying remote user updates or automated edits). The user's typing triggers an onDOMSelectionChange call, but the selection update from this function is stale, which can cause the cursor to jump or crash the editor.
Recording
https://github.com/user-attachments/assets/a68453b1-df47-4324-a542-9313569958ca
Sandbox
https://codesandbox.io/s/slate-selection-change-repro-ztssmp
Steps
To reproduce the behavior:
- Go to https://codesandbox.io/s/slate-selection-change-repro-ztssmp
- In Chrome developer tools, under the Performance tab, enable CPU throttling. This approximates the behavior of a large document and makes the issue easier to repro, although it still occurs without throttling.
- Click the "Simulate ops" button, which repeatedly adds new elements to the middle of the document.
- Type continuously in the last line of the document
- A "Cannot resolve a DOM point from Slate point" error is triggered
Expectation
Basic concurrent updates shouldn't crash the editor. In the example posted, the user should be able to continue to type on the last line while new lines are added above.
Environment
- Slate Version: 0.103.0
- Operating System: Mac
- Browser: Chrome
Context
I suspect the root cause of this issue is a stale NODE_TO_INDEX weak map. Because that map is updated after nodes rerender, if the editor content changes and a selection event fires before a re-render, the map can be stale.
Looking at the code, the sequence of events is:
- A new line is inserted in the editor. React does not yet re-render
- The user's typing triggers the onDOMSelectionChange handler
- The handler attempts to convert the user's selected DOM node to a Slate range in toSlateRange, which calls findPath on the resulting Slate Node
- NODE_TO_INDEX is used to retrieve the path for the given node. However, because the editor has not yet re-rendered, this map is stale
- The resulting path to the node is wrong (Say, [2, 0] instead of [3, 0]) and an invalid selection is set. Downstream code that attempts to use this selection triggers a crash.