Skip to content

chore(morph): reinforce morph mechanism#72

Merged
yzuyr merged 2 commits into
mainfrom
chore/ilha-reinforce-morph
Jul 18, 2026
Merged

chore(morph): reinforce morph mechanism#72
yzuyr merged 2 commits into
mainfrom
chore/ilha-reinforce-morph

Conversation

@yzuyr

@yzuyr yzuyr commented Jul 18, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Bug Fixes
    • Preserved focus, cursor/selection, and layout/input subtrees during in-place updates and navigation.
    • Improved keyed slot reconciliation (including shrink/leave transitions) to avoid unintended removals.
    • Synced <select> live selection without clobbering user choice, including keyed option reorders.
    • Preserved controller-owned attributes via data-morph-preserve and added dev warnings for updates that may replace stateful elements (iframe/video/audio/canvas).
    • Avoided unnecessary DOM changes when output is unchanged.
  • Documentation
    • Expanded the guide with identity-sensitive keying guidance and data-morph-preserve examples.
  • Chores
    • Bumped package versions across the ecosystem and templates.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8129d576-2dd1-422f-893f-6ad2fe430e75

📥 Commits

Reviewing files that changed from the base of the PR and between fa576f2 and 7e1018b.

📒 Files selected for processing (2)
  • packages/ilha/src/index.test.ts
  • packages/ilha/src/index.ts

📝 Walkthrough

Walkthrough

The island runtime hardens DOM morphing with keyed slot reconciliation, focus and form-state preservation, transition guards, and identical-output fast paths. Regression tests, render documentation, and package version requirements are updated accordingly.

Changes

Morph engine hardening

Layer / File(s) Summary
Morph reconciliation contracts
packages/ilha/src/index.ts
Adds preserved-attribute handling, data-key and slot-based identity matching, destructive replacement warnings, and leaving-slot safeguards.
Focus and form synchronization
packages/ilha/src/index.ts
Synchronizes template-driven <select> state and restores input, selection, and contenteditable state after morphing.
Render fast path and slot rehoming
packages/ilha/src/index.ts
Tracks rendered output, skips identical markup morphs while updating slot props, and adjusts slot teardown and rehoming during list changes.
Regression coverage and release alignment
packages/ilha/src/index.test.ts, packages/router/src/inplace-update.test.ts, apps/website/src/pages/(content)/guide/island/render.mdx, packages/*/package.json, apps/website/package.json, templates/*/package.json
Adds regression coverage for slot stability, forms, preserved attributes, transitions, identical output, and warnings; documents the new morph contracts and updates package versions and requirements.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant IslandRenderEffect
  participant applyMorph
  participant morphChildren
  participant DOM
  participant MountedSlot
  IslandRenderEffect->>IslandRenderEffect: compare output with lastRendered
  IslandRenderEffect->>MountedSlot: update props when output is identical
  IslandRenderEffect->>applyMorph: reconcile changed output
  applyMorph->>morphChildren: morph the wrapped host
  morphChildren->>DOM: preserve focus, form state, and keyed nodes
  morphChildren->>MountedSlot: retain, rehome, or replace slot hosts
Loading

Possibly related PRs

  • ilhajs/ilha#23: Related keyed slot marker and slot-id reconciliation changes.
  • ilhajs/ilha#61: Related handling of reused slot ids and island remounting.
  • ilhajs/ilha#68: Related keyed morph reconciliation and live form-state synchronization.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main focus on strengthening the morph engine and reconciliation behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/ilha-reinforce-morph

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ilha/src/index.ts`:
- Around line 3562-3573: The list reconciliation logic around listShrunk and
teardownMountedSlot currently remounts every surviving positional slot whenever
the total slot count decreases. Track the actual positional divergence caused by
the removed slot(s), and tear down only p: slots at or after that affected
position; preserve earlier positional slots and their state, effects, DOM, and
focus.
- Around line 600-619: Update restoreFocusAfterMorph so document.activeElement
=== active does not return before restoring selection or contenteditable ranges.
Only skip the focus() call when the element is already active, while continuing
to apply the selection and range restoration logic for connected elements.
- Around line 525-533: Update the select-option state tracking around
syncAttributes and morphChildren to preserve each option’s pre-morph selected
state by option identity rather than array index. Compare each resulting option
against its corresponding original option identity, and only run the o.selected
reset loop when an option’s selected attribute state actually changed; keyed
reorders without attribute changes must preserve the user’s live selection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6c892942-86d5-4678-a938-3d75fc49a567

📥 Commits

Reviewing files that changed from the base of the PR and between 2073a67 and fa576f2.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • apps/website/package.json
  • apps/website/src/pages/(content)/guide/island/render.mdx
  • packages/ilha/package.json
  • packages/ilha/src/index.test.ts
  • packages/ilha/src/index.ts
  • packages/router/package.json
  • packages/router/src/inplace-update.test.ts
  • packages/store/package.json
  • templates/elysia/package.json
  • templates/hono/package.json
  • templates/nitro/package.json
  • templates/vite/package.json

Comment thread packages/ilha/src/index.ts Outdated
Comment thread packages/ilha/src/index.ts
Comment thread packages/ilha/src/index.ts Outdated
@yzuyr
yzuyr merged commit ae816a3 into main Jul 18, 2026
5 checks passed
@yzuyr
yzuyr deleted the chore/ilha-reinforce-morph branch July 18, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant