Repository: ianstormtaylor/slate
File: packages/slate/src/transforms/text.ts (TypeScript)

Code before:
          (!Path.isCommon(path, start.path) && !Path.isCommon(path, end.path))
        ) {
          matches.push(entry)
          lastPath = path
        }
      }

      const pathRefs = Array.from(matches, ([, p]) => Editor.pathRef(editor, p))
      const startRef = Editor.pointRef(editor, start)
      const endRef = Editor.pointRef(editor, end)

      let removedText = ''

      if (!isSingleText && !startVoid) {
        const point = startRef.current!
        const [node] = Editor.leaf(editor, point)
        const { path } = point
        const { offset } = start
        const text = node.text.slice(offset)
        if (text.length > 0) {
          editor.apply({ type: 'remove_text', path, offset, text })
          removedText = text
        }
      }

      const middlePaths = pathRefs
        .reverse()
        .map(r => r.unref())
        .filter((r): r is Path => !!r)

      for (const p of middlePaths) {
        Transforms.removeNodes(editor, { at: p, voids })
      }

      if (!endVoid) {
        const point = endRef.current!
        const [node] = Editor.leaf(editor, point)
        const { path } = point
        const offset = isSingleText ? start.offset : 0
        const text = node.text.slice(offset, end.offset)
        if (text.length > 0) {
          editor.apply({ type: 'remove_text', path, offset, text })
          removedText = text
        }
      }

      if (
        !isSingleText &&
        isAcrossBlocks &&
        endRef.current &&
        startRef.current

Review comment (performance):
I think the idea of reversing the order of operation to remove without affecting `pathRefs` is a good one.

I'm curious why are we first creating an array using array functions and then using `for of`. What are the benefits of what you did here versus:

```ts
pathRefs
  .reverse()
  .map(r => r.unref())
  .filter((r): r is Path => r !== null) // note i would compare with null as per the unref interface
  .forEach(p => Transforms.removeNodes(editor, { at: p, voids })
```

Also, would it be possible to not use `pathRefs` at all given the fact that all `removeNodes` operations would work and the code before `removeNodes` doesn't seem to alter the tree. It is possible that not using `pathRefs` might be asking for trouble because something might get in between `matches` and `removeNodes` but seems like a possible performance gain (and performance gains are usually... less pretty).

Code after:
          (!Path.isCommon(path, start.path) && !Path.isCommon(path, end.path))
        ) {
          matches.push(entry)
          lastPath = path
        }
      }

      const pathRefs = Array.from(matches, ([, p]) => Editor.pathRef(editor, p))
      const startRef = Editor.pointRef(editor, start)
      const endRef = Editor.pointRef(editor, end)

      let removedText = ''

      if (!isSingleText && !startVoid) {
        const point = startRef.current!
        const [node] = Editor.leaf(editor, point)
        const { path } = point
        const { offset } = start
        const text = node.text.slice(offset)
        if (text.length > 0) {
          editor.apply({ type: 'remove_text', path, offset, text })
          removedText = text
        }
      }

      pathRefs
        .reverse()
        .map(r => r.unref())
        .filter((r): r is Path => r !== null)
        .forEach(p => Transforms.removeNodes(editor, { at: p, voids }))

      if (!endVoid) {
        const point = endRef.current!
        const [node] = Editor.leaf(editor, point)
        const { path } = point
        const offset = isSingleText ? start.offset : 0
        const text = node.text.slice(offset, end.offset)
        if (text.length > 0) {
          editor.apply({ type: 'remove_text', path, offset, text })
          removedText = text
        }
      }

      if (
        !isSingleText &&
        isAcrossBlocks &&
        endRef.current &&
        startRef.current
      ) {
        Transforms.mergeNodes(editor, {
          at: endRef.current,