Unify the Each reconciler's keyed/positional paths into one planner + executor - #22
Merged
Conversation
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.
Unifies the
Eachreconciler's keyed and positional paths into a single pure planner and one mode-agnostic executor.This PR landed in two stages on the branch:
The core insight
Positional
Eachis keyedEachwhose id is the row position. With ids as stable strings — the key in keyed mode,as.character(index)in positional mode — every mode difference collapses to set algebra overold_ids/new_ids.What changed (all in
mount.R)plan_reconcile(old_ids, new_ids, old_sigs, new_sigs)returnsremoved/added/kept, a derivedorder(orNULL), and abuild_indexmapping added ids to their positions. No session, nobuild_entry, no DOM messages.orderpolicy.orderis computed from the client's natural insert order (survivors in old order ++ added at the tail) and sent only when it differs fromnew_ids— no mode flag. This reproduces both modes' historical behavior and, as a free correct improvement, omitsorderon keyed tail-appends (smaller payloads). Noirid.js/ wire change required.run_reconcile_plan()does teardown → build →irid-mutate→ mount → reposition against a unified container. Thepos_rvguard makes kept-repositioning a no-op for positional entries.new_idscomputation (as.character(by(x))vsseq_along). Everything after is shared.current_idsvector.build_entrystays mode-aware — its late-bound-key vs captured-index value access is the identity model, not incidental duplication.Tests
Planner unit tests exercise the decision logic directly with plain data, including the derived
orderpolicy: append-no-order, reorder-order, mid-list-rebuild-order, keyed-tail-append-no-order, shrink-no-order, andbuild_index. The mount-based integration tests (the reconciler guardrail) pass untouched. 706 tests, 0 failures, plus a live browser check of the keyed reorder/focus path.Follow-up
The client currently applies
orderwith O(n) DOM moves; a client-only O(moved) optimization is tracked separately in #23 and deliberately decoupled from this change.