Slate: Calling addMark in onDOMBeforeInput crashes Slate when selection is not collapsed

Created on 30 Mar 2020  路  2Comments  路  Source: ianstormtaylor/slate

Do you want to request a _feature_ or report a _bug_?

report a _bug_

What's the current behavior?

Slate: 0.57.1
Browser: Chrome 80
OS: Mac

Adding an editor.addMark call to an onDOMBeforeInput callback reliably crashes Slate when the selection is not collapsed. The error is Cannot resolve a DOM point from Slate point, but stepping though the code, I noticed that the selection does not appear to be deleted correctly before the new text is inserted. Maybe because the addMark calls setNode and splits the block for non-collapsed selections?

Here's a minimal reproduction of the issue:

https://codesandbox.io/s/little-rain-5089t

Select the first 'D', then type 'C' and it will crash.

In that example, after the insert_text command runs, editor.childen[0].children looks like

[{"text":"ABC"},{"text":"D","bold":true},{"text":"DEF"}]

having performed the following operations:

[
  {
    "type": "split_node",
    "path": [
      0,
      0
    ],
    "position": 3,
    "target": null,
    "properties": {}
  },
  {
    "type": "split_node",
    "path": [
      0,
      0
    ],
    "position": 2,
    "target": null,
    "properties": {}
  },
  {
    "type": "set_selection",
    "properties": {
      "focus": {
        "path": [
          0,
          2
        ],
        "offset": 0
      }
    },
    "newProperties": {
      "focus": {
        "path": [
          0,
          1
        ],
        "offset": 1
      }
    }
  },
  {
    "type": "set_node",
    "path": [
      0,
      1
    ],
    "properties": {},
    "newProperties": {
      "bold": true
    }
  },
  {
    "type": "set_selection",
    "properties": {
      "anchor": {
        "path": [
          0,
          1
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          1
        ],
        "offset": 1
      }
    },
    "newProperties": {
      "anchor": {
        "path": [
          0,
          0
        ],
        "offset": 2
      },
      "focus": {
        "path": [
          0,
          0
        ],
        "offset": 3
      }
    }
  },
  {
    "type": "remove_text",
    "path": [
      0,
      0
    ],
    "offset": 2,
    "text": ""    // <--- This looks like a bug.
  },
  {
    "type": "set_selection",
    "properties": {
      "anchor": {
        "path": [
          0,
          0
        ],
        "offset": 2
      }
    },
    "newProperties": {
      "anchor": {
        "path": [
          0,
          0
        ],
        "offset": 3
      }
    }
  },
  {
    "type": "insert_text",
    "path": [
      0,
      0
    ],
    "offset": 3,
    "text": "C"
  }
]

which demonstrates the text not being deleted correctly, and the mark applied to the wrong selection.

The crash eventually happens in the call to editor.onChange() within apply.

What's the expected behavior?

I believe the value after this input should look like:

[{"text":"AB"},{"text":"C","bold":true},{"text":"DEF"}]
bug discussion

All 2 comments

Chatted with @majelbstoat in slack. I'm not quite sure whether this is a bug or an unintended usage. As such, we'll leave this issue open and see if other folks run into similar problems.

For folks trying to achieve the same thing (put a mark on every character), I managed to do it with the following plugin:

  e.insertText = (text: string) => {
    const marks = Editor.marks(e)
    if (!marks?.mymark) {
      e.marks = {mymark: "whatever"}
    }
    insertText(text)
  }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ianstormtaylor picture ianstormtaylor  路  3Comments

bunterWolf picture bunterWolf  路  3Comments

ianstormtaylor picture ianstormtaylor  路  3Comments

adrianclay picture adrianclay  路  3Comments

ianstormtaylor picture ianstormtaylor  路  3Comments