Skip to content

PairNodesPlugin.appendTransaction crashes on undo/redo #124

Description

@lattln

Describe the bug

Undo (and redo) can throw an unhandled TypeError, leaving the editor in an inconsistent state.

Uncaught TypeError: Cannot read properties of undefined (reading 'nodeSize')
    at Fragment.nodesBetween        (prosemirror-model/dist/index.cjs:116:28)
    at Node.nodesBetween            (prosemirror-model/dist/index.cjs:935:19)
    at Plugin.appendTransaction     (@kerebron/extension-basic-editor/esm/pairing/PairNodesPlugin.js:23:37)
    at EditorState.applyTransaction (prosemirror-state/dist/index.js:808:54)
    at EditorState.apply            (prosemirror-state/dist/index.js:773:20)
    at CoreEditor.dispatchTransaction(@kerebron/editor/esm/CoreEditor.js:182:32)
    at EditorView.dispatch          (prosemirror-view/dist/index.js:5751:28)
    at Object.<anonymous>           (@kerebron/extension-basic-editor/esm/history/history.js:458:16)
    at Object.command               (@kerebron/editor/esm/commands/CommandManager.js:36:39)

To Reproduce

  1. Type Sample text, select all, apply several marks and block wraps in sequence (bold, blockquote, horizontal rule, alignment).
  2. Click Undo last change in the toolbar.
  3. Console throws the above; the undo does not apply.

Expected behavior

Undo/redo apply cleanly without throwing.

Root cause

PairNodesPlugin.appendTransaction (packages/extension-basic-editor/src/pairing/PairNodesPlugin.ts:~23) walks document positions derived from the pre-transaction doc against the post-transaction doc without bounds-checking or mapping them through tr.mapping. On undo the doc shrinks, so positions can exceed the new doc size and nodesBetween dereferences undefined.

Additional context — likely the same family of bug

During ordinary editing the console repeatedly logs:

NO NODE at 2
NO NODE at 3
NO NODE at 19

These appear whenever the doc shrinks (delete-all, replace-selection, table insert over a selected node).

Suggested fix

Clamp/map positions through tr.mapping and bounds-check against newState.doc.content.size before calling nodesBetween.


Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions