♻️ Share one walk and one attribute loop in component sync

Sync and the variant switch each copied attributes with a loop of
their own (update-attrs, update-attrs-on-switch), and direct and
inverse sync each walked the shape tree with a function of their own.

- One attribute loop, attr-operations, builds the redo and undo :set
  operations. It takes a policy per attribute, sync-attr-operations or
  switch-attr-operations, which gives the [attr value] pairs to set:
  the attribute, after the derived ones it resets (position data
  before a text content, the transforms before a rotation). The two
  callers keep only what differs: which attributes they carry and how
  they end (the switch sets the copy's new touched groups).
  text-change-value and switch-text-change-value are one function,
  text-content-with-overrides; each caller passes the override groups
  it carries.
- One walk, sync-shape-recursive: sync the pair, pair the children
  with compare-children, recurse, finish. Two direction maps hold what
  differs: direct-sync (main to copy: a normal sync or a reset) and
  inverse-sync (copy to main, update main). Each gives the pair's
  sync, the four compare-children callbacks, the work after the
  children, and the container of the main shape. What stays the same
  along a walk travels in one context map instead of eleven arguments.

No behavior change: the golden master and the suites are unchanged.

Benchmark (lower quantile, ms; baseline / now / ratio):
  deepest-edit-through-three-levels    35.2 /  36.0 / 1.02
  edit-through-a-chain-of-dependents   68.9 /  66.4 / 0.96
  library-update-into-copies           83.1 /  74.9 / 0.90
  main-edit-into-10-copies              1.8 /   1.5 / 0.82
  main-edit-into-100-copies            15.4 /  14.7 / 0.95
  main-edit-into-1000-copies          153.1 / 144.8 / 0.95
  variant-switch-into-copies           32.1 /  26.7 / 0.83

AI-assisted-by: claude-opus-5-5

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
alonso.torres 2026-10-14 01:00:16 +02:00
parent 717aa026ba
commit 66799e3d55

File diff suppressed because it is too large Load Diff