[diffs/edit] Programmatic edits join the undo timeline like local edits#987
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Design decision: edits applied through applyEdits are not a separate semantic class — a mixed programmatic/local sequence must behave exactly like the all-local sequence. Previously updateHistory=false skipped the EditStack entirely, so history entries carried stale offsets after any programmatic edit: undo could corrupt text, redo replayed at wrong positions, and exhaustion never restored the original document. TextDocument.applyResolvedEdits now always creates/coalesces/pushes an entry; the updateHistory flag only gates caller-supplied selection and undo-boundary metadata. Editor.applyEdits always tracks (its flag is kept but deprecated). Undo/redo replay is untouched — it always wrote through the private buffer path, so no recursion. Composition previews never touched the document and are unaffected. Flips the seven history-equivalence pins to permanent regression tests (assertions unchanged — they encode the all-tracked reference), rewrites the two old-model pins, and updates the one bypass-model test elsewhere in the suite plus the public docs. Pinned known-bug count: 32 -> 25. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5477a73 to
3ff5975
Compare
The pre-commit formatter globs cover js/ts but not .mdx, so the History section edit landed unformatted and failed root:format-check in CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97812b4aed
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| updateHistory ? selectionsBefore : undefined, | ||
| updateHistory ? selectionsAfter : undefined |
There was a problem hiding this comment.
Keep editor selections coherent for false-history undo
When Editor.applyEdits(..., false) is used while the editor has a caret, this now creates an undoable entry but strips both selection snapshots here. Undo/redo then returns undefined selections, so Editor.#applyChange leaves #selections in the coordinates from the other document version; for example inserting a line above the caret with updateHistory=false remaps the caret down, but undoing the now-undoable edit leaves it on the non-existent lower line and the next input/focus can act on stale coordinates. Since this commit makes these edits user-undoable, the editor still needs some selection remap/restoration path even when caller metadata is omitted.
Useful? React with 👍 / 👎.
What
Fixes the largest bug cluster from the editor-behavior audit (7 pinned bugs, one root cause): history entries were frozen while
applyEdits(..., updateHistory=false)bypassed the EditStack, so any programmatic edit left the stack holding stale offsets — undo corrupted text, redo replayed at wrong positions, and undo-to-exhaustion could never restore the original document.Design decision
Programmatic edits are not a separate semantic class: a mixed programmatic/local sequence must behave exactly like the same sequence applied all-locally. Concretely, after any sequence, undo-to-exhaustion restores the original text and redo-to-exhaustion the final text, with per-step states matching the all-local run.
How
TextDocument.applyResolvedEditsalways creates/coalesces/pushes an EditStack entry;updateHistorynow only gates caller-supplied selection + undo-boundary metadata on the entry. Redo clears on every recorded edit, tracked or not.Editor.applyEditsalways tracks; itsupdateHistoryparam is kept for API compatibility but deprecated.undo()/redo()always wrote through the private#applyResolvedEditsToBufferand are untouched; that private method is the only non-tracking door. History reset remains document rebuild with a fresh stack.compositionendcommits once through the tracked path) — verified end-to-end in review.Tests
applyEdits default does not record undo) and is flipped with a cross-reference.applyEditsexample + History section) — they described the old flag.Review notes
The riskiest surfaces were checked specifically: recursive recording via undo/redo replay, bypass leaking publicly, composition previews entering history, redo-clear semantics on the coalesce path, metadata-less entries in selection restore, and version-counter drift — all clean. Second PR of the failing-test burn-down (after #986).
🤖 Generated with Claude Code