chore(ilha): reinforce island nesting#74
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughChangesIsland Slot Composition
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ParentIsland
participant emitIslandSlot
participant SSRMarkup
participant mountSlots
participant ChildIsland
ParentIsland->>emitIslandSlot: render nested child slot
emitIslandSlot->>SSRMarkup: write sanitized data-ilha-props
SSRMarkup->>mountSlots: provide slot marker and snapshot
mountSlots->>ChildIsland: revive props and mount child
ParentIsland->>ChildIsland: push updated props during rerender
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Checkov (3.3.8)apps/website/package.jsonTraceback (most recent call last): 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
packages/ilha/src/index.ts (2)
3655-3660: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGood fix, but this is now the third copy of the same "push props into mounted slots" loop.
This exact
for (const [id, entry] of mountedSlots) { const next = newSlotMap.get(id); if (next) entry.updateProps(next.props); }pattern already exists at the hydration path (around Lines 3626-3629) and the identical-output fast path (Lines 3683-3686). The fact that this PR had to add a missing instance here is itself evidence the duplication is a maintenance risk — a future change to one copy is likely to miss the others.♻️ Extract a shared helper
+function pushUpdatedProps( + mounted: Map<string, { updateProps: (p?: Record<string, unknown>) => void }>, + slotMap: IslandRenderCtx["slots"], +): void { + for (const [id, entry] of mounted) { + const next = slotMap.get(id); + if (next) entry.updateProps(next.props); + } +}Then replace all three loop sites with
pushUpdatedProps(mountedSlots, newSlotMap).🤖 Prompt for 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. In `@packages/ilha/src/index.ts` around lines 3655 - 3660, Extract the repeated mounted-slot prop update loop into a shared helper named pushUpdatedProps, accepting mountedSlots and newSlotMap and applying each matching entry’s props via updateProps. Replace the existing loops in the hydration path, this slot-set-stable path, and the identical-output fast path with calls to the helper, preserving their current behavior.
323-343: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winNo cycle guard in
encodeSlotPropValue— a circular prop causes stack overflow instead of a clean error.
encodeSlotPropValuerecurses into arrays/objects with no visited-set tracking. A circular reference in a prop (a real possibility — self-referencing tree nodes, DOM/element refs, etc.) will recurse indefinitely untilRangeError: Maximum call stack size exceeded, crashing the SSR render for that page rather than surfacing a predictable error.♻️ Add a cycle guard
-function encodeSlotPropValue(value: unknown): unknown { +function encodeSlotPropValue(value: unknown, seen: WeakSet<object> = new WeakSet()): unknown { if (value == null) return value; if (typeof value === "function" || typeof value === "symbol") return undefined; if (typeof value !== "object") return value; if (isRawHtmlValue(value)) return { __ilha: "raw", value: value.value }; + if (seen.has(value)) return undefined; + seen.add(value); if (Array.isArray(value)) { - return value.map((item) => encodeSlotPropValue(item)).filter((item) => item !== undefined); + return value.map((item) => encodeSlotPropValue(item, seen)).filter((item) => item !== undefined); } if (Object.getPrototypeOf(value) !== Object.prototype) return undefined; const obj = value as Record<string, unknown>; const encoded: Record<string, unknown> = {}; for (const key of Object.keys(obj)) { - const next = encodeSlotPropValue(obj[key]); + const next = encodeSlotPropValue(obj[key], seen); if (next !== undefined || obj[key] === null) encoded[key] = next as unknown; } return encoded; }🤖 Prompt for 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. In `@packages/ilha/src/index.ts` around lines 323 - 343, Update encodeSlotPropValue to track visited arrays and plain objects during recursive encoding and detect circular references before descending. On a repeated reference, surface a predictable error instead of recursing until stack overflow, while preserving existing handling for raw HTML, unsupported values, and non-cyclic structures.
🤖 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 `@apps/website/package.json`:
- Around line 14-18: Update the `@ilha/store` dependency in the apps/website
package manifest from ^0.7.6 to ^0.7.7, leaving the surrounding dependencies
unchanged.
In `@packages/ilha/src/index.ts`:
- Around line 3317-3319: Update the parsed persisted-props handling around
reviveSlotProps so non-object values are validated or safely handled before
revival, preventing reviveSlotProps from receiving invalid input while
preserving valid object props behavior.
- Line 4161: Update the auto-discovery path in mountAll so reviveSlotProps
safely handles malformed parsed values that are not objects before assigning to
props, matching the input validation used by reviveSlotProps’s definition while
preserving valid object revival.
- Around line 3071-3073: Update the parsed-props handling in mount() so
reviveSlotProps is called only when parsed is a non-null object; skip or safely
handle null and primitive JSON values without throwing, while preserving revival
for valid object payloads.
- Around line 345-396: Restrict the legacy conversion in reviveLegacyChildren to
objects matching the exact legacy blob shape, rather than any object containing
a string value; preserve objects with sibling fields as ordinary data and only
pass the exact blob to makeRawHtml. Apply the same shape check in both the
single-child and array-child branches.
In `@packages/router/src/layout-nested-children.test.ts`:
- Around line 37-40: Correct the escaping character class in slotPropsFromSsr so
slotId.replace properly escapes all regex metacharacters, including the closing
bracket, without trailing garbage; match the established pattern used by the
nesting-stress helper.
---
Nitpick comments:
In `@packages/ilha/src/index.ts`:
- Around line 3655-3660: Extract the repeated mounted-slot prop update loop into
a shared helper named pushUpdatedProps, accepting mountedSlots and newSlotMap
and applying each matching entry’s props via updateProps. Replace the existing
loops in the hydration path, this slot-set-stable path, and the identical-output
fast path with calls to the helper, preserving their current behavior.
- Around line 323-343: Update encodeSlotPropValue to track visited arrays and
plain objects during recursive encoding and detect circular references before
descending. On a repeated reference, surface a predictable error instead of
recursing until stack overflow, while preserving existing handling for raw HTML,
unsupported values, and non-cyclic structures.
🪄 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: 30155b0a-73f8-4e80-9067-f431062ee1c9
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (15)
apps/website/package.jsonpackages/ilha/README.mdpackages/ilha/package.jsonpackages/ilha/src/index.test.tspackages/ilha/src/index.tspackages/ilha/src/jsx-runtime.test.tsxpackages/ilha/src/nesting-stress.test.tspackages/router/README.mdpackages/router/package.jsonpackages/router/src/layout-nested-children.test.tspackages/store/package.jsontemplates/elysia/package.jsontemplates/hono/package.jsontemplates/nitro/package.jsontemplates/vite/package.json
Summary by CodeRabbit