Skip to content

Commit a199655

Browse files
authored
fix(editor): preserve pending diff when bailToMark target doesn't exist (tldraw#8260)
`bailToMark()` (and `_undo` with `toMark`) would silently discard the pending diff when the target mark didn't exist in the undo stack. The pending diff was cleared at the start of `_undo` but never restored on early return, causing accumulated changes to be lost. Now the pending diff is restored if the mark is not found. Extracted from tldraw#8243. ### Change type - [x] `bugfix` ### Test plan 1. Call `bailToMark` with a non-existent mark ID after making changes 2. Verify the pending changes are preserved (not silently discarded) 3. Verify a subsequent `bailToMark` with a valid mark still works correctly - [x] Unit tests ### Release notes - Fix a bug where calling `bailToMark` with a non-existent mark ID could silently discard pending history changes. ### Code changes | Section | LOC change | | --------- | ---------- | | Core code | +7 / -2 | | Tests | +16 / -0 |
1 parent 32c4832 commit a199655

2 files changed

Lines changed: 23 additions & 2 deletions

File tree

packages/editor/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,22 @@ describe('HistoryManager error scenarios and edge cases', () => {
736736
expect(store.get(ids.a)!.value).toBe(originalValue)
737737
})
738738

739+
it('should preserve pending diff when mark is not found', () => {
740+
manager._mark('real-mark')
741+
store.update(ids.a, (s) => ({ ...s, value: 1 }))
742+
743+
// bail to a mark that doesn't exist
744+
manager.bailToMark('non-existent-mark')
745+
746+
// the pending diff should still be intact
747+
expect(store.get(ids.a)!.value).toBe(1)
748+
expect(manager.getNumUndos()).toBeGreaterThan(0)
749+
750+
// a subsequent bail to the real mark should still work
751+
manager.bailToMark('real-mark')
752+
expect(store.get(ids.a)!.value).toBe(0)
753+
})
754+
739755
it('should find mark correctly when it exists', () => {
740756
manager._mark('existing-mark')
741757
store.update(ids.a, (s) => ({ ...s, value: 1 }))

packages/editor/src/lib/editor/managers/HistoryManager/HistoryManager.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ export class HistoryManager<R extends UnknownRecord> {
172172
}
173173

174174
if (!didFindMark && toMark) {
175-
// whoops, we didn't find the mark we were looking for
176-
// don't do anything
175+
// we didn't find the mark we were looking for — restore state and bail
176+
this.pendingDiff.restore(pendingDiff)
177177
return this
178178
}
179179

@@ -338,6 +338,11 @@ class PendingDiff<R extends UnknownRecord> {
338338
return diff
339339
}
340340

341+
restore(diff: RecordsDiff<R>) {
342+
this.diff = diff
343+
this.isEmptyAtom.set(isRecordsDiffEmpty(diff))
344+
}
345+
341346
isEmpty() {
342347
return this.isEmptyAtom.get()
343348
}

0 commit comments

Comments
 (0)