From 40c3be1732eb5b69d340bb34f732a72812d2f622 Mon Sep 17 00:00:00 2001
From: Kevin Jahns <kevin.jahns@pm.me>
Date: Sun, 21 Nov 2021 14:00:02 +0100
Subject: [PATCH] fix backwards edge case

---
 src/types/AbstractType.js | 37 +++++++++++++++++++++++++++----------
 src/utils/ListIterator.js |  7 ++++---
 2 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/src/types/AbstractType.js b/src/types/AbstractType.js
index 6e059721..91972316 100644
--- a/src/types/AbstractType.js
+++ b/src/types/AbstractType.js
@@ -54,7 +54,21 @@ export const useSearchMarker = (tr, yarray, index, f) => {
   if (createFreshMarker) {
     searchMarker.push(fsm)
   }
+  const diff = fsm.index - index
+  if (diff > 0) {
+    fsm.backward(tr, diff)
+  } else {
+    fsm.forward(tr, -diff)
+  }
   const result = f(fsm)
+  if (fsm.reachedEnd) {
+    fsm.reachedEnd = false
+    const nextItem = /** @type {Item} */ (fsm.nextItem)
+    if (nextItem.countable && !nextItem.deleted) {
+      fsm.index -= nextItem.length
+    }
+    fsm.rel = 0
+  }
   if (!createFreshMarker && fsm.nextItem !== prevItem) {
     // reused old marker and we moved to a different position
     prevItem.marker = false
@@ -76,22 +90,25 @@ export const useSearchMarker = (tr, yarray, index, f) => {
  *
  * This should be called before doing a deletion!
  *
- * @param {Transaction} tr
  * @param {Array<ListIterator>} searchMarker
  * @param {number} index
  * @param {number} len If insertion, len is positive. If deletion, len is negative.
+ * @param {ListIterator} origSearchMarker Do not update this searchmarker because it is the one we used to manipulate.
  */
-export const updateMarkerChanges = (tr, searchMarker, index, len) => {
+export const updateMarkerChanges = (searchMarker, index, len, origSearchMarker) => {
   for (let i = searchMarker.length - 1; i >= 0; i--) {
     const marker = searchMarker[i]
-    if (len > 0 && index === marker.index) {
-      // inserting at a marked position deletes the marked position because we can't do a simple transformation
-      // (we don't know whether to insert directly before or directly after the position)
-      searchMarker.splice(i, 1)
-      continue
-    }
-    if (index < marker.index) { // a simple index <= m.index check would actually suffice
-      marker.index = math.max(index, marker.index + len)
+    if (marker !== origSearchMarker) {
+      if (len > 0 && index === marker.index) {
+        // inserting at a marked position deletes the marked position because we can't do a simple transformation
+        // (we don't know whether to insert directly before or directly after the position)
+        searchMarker.splice(i, 1)
+        if (marker.nextItem) marker.nextItem.marker = false
+        continue
+      }
+      if (index < marker.index) { // a simple index <= m.index check would actually suffice
+        marker.index = math.max(index, marker.index + len)
+      }
     }
   }
 }
diff --git a/src/utils/ListIterator.js b/src/utils/ListIterator.js
index a38375cf..08d28e15 100644
--- a/src/utils/ListIterator.js
+++ b/src/utils/ListIterator.js
@@ -202,7 +202,7 @@ export class ListIterator {
       item = item.left
     }
     this.index -= len
-    this.nextItem = item
+    this.nextItem = item && item.right
     return this
   }
 
@@ -278,11 +278,12 @@ export class ListIterator {
       if (item && !this.reachedEnd && len > 0) {
         this.nextItem = item
         this.forward(tr, 0)
+        item = this.nextItem
       }
     }
     this.nextItem = item
     if (sm) {
-      updateMarkerChanges(tr, sm, this.index, -startLength + len)
+      updateMarkerChanges(sm, this.index, -startLength + len, this)
     }
   }
 
@@ -369,7 +370,7 @@ export class ListIterator {
       this.nextItem = right
     }
     if (sm) {
-      updateMarkerChanges(tr, sm, this.index, content.length)
+      updateMarkerChanges(sm, this.index, content.length, this)
     }
     this.index += content.length
   }