From cf202547c96834968572b2d1a5113415d5c8e542 Mon Sep 17 00:00:00 2001
From: Dominik Henneke <dominik.henneke@nordeck.net>
Date: Tue, 28 Mar 2023 20:32:22 +0200
Subject: [PATCH] Restore deleted entries in a map

---
 src/structs/Item.js      |  2 +-
 tests/undo-redo.tests.js | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/src/structs/Item.js b/src/structs/Item.js
index 704dcd32..86c05915 100644
--- a/src/structs/Item.js
+++ b/src/structs/Item.js
@@ -200,7 +200,7 @@ export const redoItem = (transaction, item, redoitems, itemsToDelete, ignoreRemo
   } else {
     right = null
     if (item.right && !ignoreRemoteMapChanges) {
-      left = item
+      left = item.right
       // Iterate right while right is in itemsToDelete
       // If it is intended to delete right while item is redone, we can expect that item should replace right.
       while (left !== null && left.right !== null && isDeleted(itemsToDelete, left.right.id)) {
diff --git a/tests/undo-redo.tests.js b/tests/undo-redo.tests.js
index 3ee65d18..261eaffd 100644
--- a/tests/undo-redo.tests.js
+++ b/tests/undo-redo.tests.js
@@ -644,3 +644,43 @@ export const testSpecialDeletionCase = tc => {
   undoManager.undo()
   t.compareStrings(fragment.toString(), '<test a="1" b="2"></test>')
 }
+
+/**
+ * Deleted entries in a map should be restored on undo.
+ * 
+ * @see https://github.com/yjs/yjs/issues/500
+ * @param {t.TestCase} tc
+ */
+export const testUndoDeleteInMap = (tc) => {
+  const { map0 } = init(tc, { users: 3 })
+  const undoManager = new Y.UndoManager(map0, { captureTimeout: 0 })
+
+  map0.set('a', 'a')
+  map0.delete('a')
+  map0.set('a', 'b')
+  map0.delete('a')
+  map0.set('a', 'c')
+  map0.delete('a')
+  map0.set('a', 'd')
+
+  t.compare(map0.toJSON(), { a: 'd' })
+
+  undoManager.undo()
+  t.compare(map0.toJSON(), {})
+  
+  undoManager.undo()
+  t.compare(map0.toJSON(), { a: 'c' })
+  
+  undoManager.undo()
+  t.compare(map0.toJSON(), {})
+  
+  undoManager.undo()
+  t.compare(map0.toJSON(), { a: 'b' })
+  
+  undoManager.undo()
+  t.compare(map0.toJSON(), {})
+  
+  undoManager.undo()
+  t.compare(map0.toJSON(), { a: 'a' })
+};
+