v2 editing model: optimistic commits + hold() gating + per-commit token#330
Merged
Conversation
Bundle size impact
|
| Format | Base raw | PR raw | Δ raw | Base gzip | PR gzip | Δ gzip |
|---|---|---|---|---|---|---|
| esm | 53.82 KB | 54.53 KB | 🔺 +724 B (+1.31%) | 18.86 KB | 19.47 KB | 🔺 +626 B (+3.24%) |
| cjs | 55.32 KB | 56.02 KB | 🔺 +715 B (+1.26%) | 18.94 KB | 19.53 KB | 🔺 +605 B (+3.12%) |
Measured from build/index.{cjs,esm}.js. Gzip at level 9.
CarlosNZ
commented
Jun 8, 2026
- Move OPTIMISTIC_DELAY_MS to the top of the file (alongside the type aliases) so the constant is easy to find. - Replace the if-cascade in eventForOp with a nested EVENT_FOR_OP map. Reads more cleanly and the event names become grep-able.
This was referenced Jun 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Reworks the editing/commit lifecycle so the window "submitted but not yet resolved" — while
onUpdateruns (a confirm dialog, a slow remote save) — is a first-class state. Previously the model had only two states (editing | not); that gap was patched out-of-band in #325 (committingPaths) and produced ~5 bugs that only showed up with a slow/deferredonUpdate(commit-after-cancel, double events, mode-blind close, stale suppression, double-submit). That patch was abandoned; this fixes the class by construction.Closes the design work tracked in #325.
The model
onUpdateruns in the background; a rejection (false/{ error }/ throw / rejected promise) reverts the change and surfaces the error. A slowonUpdatenever blocks the editor.hold().onUpdategets a second argument,{ hold }. Callinghold()(synchronously, before the firstawait) keeps the editor open and blocks the tree until the returnedrelease()is called — the path for confirmation dialogs / pre-commit validation.Event model
onEditEventis nowstart* → [submit*] → commit*, orstart* → cancel*, plusupdateSuccessful/updateErrorfor the background settlement of any committed change whoseonUpdateran. Renamesconfirm*→commit*and addssubmit*+ the two settlement events. A no-op confirm firescommitEdit(notcancelEdit).Engine bugs found + fixed while migrating the tests
dataRefstaleness — optimisticapplycallssetData, butdataRef.currentonly refreshed on the next render, so a synchronously-resolvingonUpdateran the revert against the pre-apply doc (add-revert threw). Fixed with acommitDocumenthelper that updates the ref synchronously.commit/settlement events rebuiltNodeDatafrom the now-mutated live doc →delete/renamedescribed a vanished node. Fixed with a frozen per-opBuiltCommit.nodeDatasnapshot.{ value }override wrote to the node path instead of replacing the whole document.[data]effect can't fire whendatadidn't change). AddedsettleEdit, guarded against clobbering an in-progress re-edit.reconcilenow returnsundefinedon token mismatch.onCommit.Tests
Migrated the §17 lifecycle + result-protocol suites to the optimistic model (reject = apply-then-revert, asserted via the net
setData; async paths usewaitFor; primitive/enum type-change is now local-then-commit). Added 4 regression tests pinning the hard guarantees:hold()+ tree-block → commit →updateSuccessful; concurrent optimistic commits where a late failure reverts only its node; re-edit-during-settlement; confirm-before-delete. Full suite green (364 passed, 2 todo);compile/lint/buildclean.Docs & demo
README gained an "Optimistic updates and gating (
hold)" section + a rewrittenonEditEvent; migration-guide §9/§10 updated; changeset added (json-edit-react: major). Demo: fixed theisEditingheuristic sosubmit*doesn't prematurely flip it.Draft — still open
1.30.1baseline. A forensic breakdown + a micro-trim pass are next, before this is marked ready.EditingModel-current.md/EditingModel-new.mdworking docs (at repo root) should be removed before merge.🤖 Generated with Claude Code