Replace [start, end) of a text field with textas a user edit — the browser records it on the
element's own undo stack, and a native input event fires so a controlled React input picks it up.
Any programmatic edit that goes around this (assigning .value, or pushing new text through React's
controlled value) is invisible to the browser's undo history — and worse, assigning .valueclears it. So a feature that rewrites the field's text on the user's behalf (paste-insert, the
formula editor's F9) has to go through here, or the very next ctrl+Z does nothing (or something
older and more surprising). This is the same undo stack the input-clipboard injector's undo/redo
drive, which is what makes them one coherent history rather than two.
execCommand is deprecated but is still the only API that writes to that history; setRangeText is
the fallback for anywhere it isn't honored (it edits correctly, it just isn't undoable).
Replace
[start, end)of a text field withtextas a user edit — the browser records it on the element's own undo stack, and a nativeinputevent fires so a controlled React input picks it up.Any programmatic edit that goes around this (assigning
.value, or pushing new text through React's controlledvalue) is invisible to the browser's undo history — and worse, assigning.valueclears it. So a feature that rewrites the field's text on the user's behalf (paste-insert, the formula editor's F9) has to go through here, or the very nextctrl+Zdoes nothing (or something older and more surprising). This is the same undo stack the input-clipboard injector'sundo/redodrive, which is what makes them one coherent history rather than two.execCommandis deprecated but is still the only API that writes to that history;setRangeTextis the fallback for anywhere it isn't honored (it edits correctly, it just isn't undoable).