Fix Undo manager sometimes generates wrong states when undoing #743
+92
−7
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.
Fixes: #736
Note: I made the PR against v13 branch because the unit tests in main were failing.
Describe the bug
Undo-manager over arrays sometimes generates a wrong result when undoing.
To Reproduce
Run the following jest test:
Expected behavior
Undo manager should be able to go back to the first initial state, 1,2,3, but it goest to a weird 1,2,7,3 state instead. This is the minimal amount of operations I could find that trigger this error.
Environment Information
Additional context
The problem with this kind of broken undo steps is that you never know exactly when they are going to trigger and it leaves you in a potentially corrupted state
Problem
When undoing array operations, the UndoManager would sometimes produce incorrect results. Specifically, when an item that was originally inserted as a single multi-value item (e.g., [6, 7]) was later split due to other operations, only part of it would be deleted during undo, leaving the document in a corrupted state.
Cause
In /src/utils/UndoManager.js, the popStackItem function was incorrectly handling split items:
Fix
Modified the code to iterate through each position in the original item's range and follow the redone chain for each position individually: