Skip to content

Client-only minimal-order-apply: O(moved) reorders instead of O(n) #23

Description

@khusmann

Problem

The client irid-mutate handler applies order by lifting every listed child to the container tail in sequence:

msg.order.forEach(function (childId) { /* lift child range, insertBefore(frag, end) */ });

So a reorder that moves a single item still performs O(n) DOM moves. For large reorderable lists this is wasteful.

Fix (client-only)

No protocol or server change is needed — the client already has the full target order and the current child sequence. It can move only the out-of-place ranges using the keyed-reconciler / longest-increasing-subsequence trick, giving O(moved) reorders while preserving the declarative order contract:

  1. Map each id in msg.order to its current DOM position among the container's children.
  2. Compute the longest increasing subsequence of those positions — these children are already in relative order and need no move.
  3. Move only the children not in the LIS, into place.

Complexity / notes

  • Self-contained: lives in the order step of the irid-mutate handler in inst/js/irid.js. Server and wire payload unchanged.
  • Standard prior art (Vue / Snabbdom keyed reconcilers).
  • The fiddly part: irid children are comment-anchored [start..end] ranges, not single nodes, so the move logic operates on ranges and must read each child's current position. Needs dedicated tests for the range-move edge cases.

When

Gate on whether large reorderable lists are a real use case. Safely shippable on its own; was deliberately decoupled from the reconciler unification (#22).

Originally captured in the (now removed) dev/each-reconciler-unification-design.md §12.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions