Conversation
A cycle in head input sent walkResolver into infinite recursion, so the caller got a RangeError ten frames deep in unhead internals. The walk now tracks ancestors and throws an error naming the key the cycle entered through. Siblings may share a reference, so each object leaves the set when its subtree completes.
|
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 (2)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthrough
ChangesCircular head input detection
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This PR replaces an unhelpful recursion failure with a clear error for circular head input while preserving valid shared objects; no actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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 |
📦 Bundle Size
All bundles (14)
📦 Runtime Dependencies✅ No runtime dependency changes All packages (10)
Skipped optional dependencies (18)
Production dependencies only. Peer dependencies and Unhead workspace packages are excluded. Skipped optional dependencies are unavailable on the CI platform. ⚡ Performance (directional)
All benchmarks (25)
Baseline: main @ e69071e · 2026-08-22 · gzipped is the headline size metric · perf is directional (shared-runner, gated) |
🤖 READY · 95/100
|
🔗 Linked issue
found while integrating unhead 3.4 streaming into Nuxt (nuxt/nuxt#36120, nuxt/nuxt#36139)
📚 Description
A circular reference in head input sent
walkResolverinto infinite recursion. The caller receivedMaximum call stack size exceededten frames deep in unhead internals, with nothing pointing at the user's input as the fault.The walk now tracks ancestors in a
Setand throws:Sibling reuse stays legal: each object leaves the set when its subtree completes, so the same tag object may appear under two keys without a false positive. Structural sharing is untouched: unchanged input still returns the same reference.
Callers that already catch resolve failures keep working:
renderSSRHeadSuspenseChunkdrops the poisoned entry and rethrows,wrapStream's defaultflushChunkskips the patch, and the SSR render surfaces the clean message instead of aRangeError.📝 Notes
Setper top-level walk, allocated on first object entry; the static fast path still shares the whole treechildrenprop case from the same integration (renders as a literal attribute without the deprecations plugin) is already covered by thedeprecated-prop-childrenrule, so no change thereSummary by CodeRabbit