fix(runtime-core): resolve $el for dev root comment fragment - #15313
fix(runtime-core): resolve $el for dev root comment fragment#15313oedumoreira wants to merge 1 commit into
Conversation
In dev mode, a leading comment before a component's single root element causes the compiler to wrap the root in a fragment flagged DEV_ROOT_FRAGMENT. $el (and template refs pointing at the component) resolved to the fragment's anchor node instead of the real rendered element, silently breaking any code relying on $el being an actual DOM element (measuring, focusing, third-party DOM integrations, etc). Resolve $el to the real single root via filterSingleRoot, the same utility already used to resolve attrs/scopeId fallthrough for this exact scenario in renderComponentRoot. Production builds are unaffected since dev comments are stripped from templates outside of dev. close vuejs#12680
|
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 includes up to 10 reviews per rolling hour; 9 remain after this review. 📝 WalkthroughWalkthroughDevelopment-mode ChangesDevelopment root fragment element resolution
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized change makes component references resolve to the actual root element for development-only comment fragments; no actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 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 |
edison1105
left a comment
There was a problem hiding this comment.
Thanks for working on this. The overall direction looks correct: DEV_ROOT_FRAGMENT is the right way to distinguish a comment-only pseudo-fragment from a real multi-root component, and resolving this in the public $el getter preserves the renderer's internal fragment-anchor semantics.
However, the current resolver stops at component boundaries. For example:
<!-- Inner.vue -->
<!-- comment -->
<div /><!-- Outer.vue -->
<Inner />Outer.subTree is the Inner component VNode, so getDevRootFragmentEl(Outer) falls back to Outer.vnode.el. That value follows the normal component host-element chain to Inner.vnode.el, which is still the DEV_ROOT_FRAGMENT anchor. As a result, Outer.$el remains an anchor instead of the <div>. The same issue remains when both Outer and Inner have root comments: resolving the outer fragment returns the Inner VNode's .el, which is still the inner fragment anchor.
Could we make the public-root resolver recursively treat both DEV_ROOT_FRAGMENT and single-root component VNodes as transparent layers, following vnode.component.subTree where applicable? Please also add a regression test for an outer component rendering an inner component whose root is comment + div; covering the case where both layers are DEV_ROOT_FRAGMENT would be useful as well.
One minor test-fidelity point: the compiler emits PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, so the hand-written test should preferably use that combination rather than DEV_ROOT_FRAGMENT alone.
close #12680
In dev mode, Vue preserves HTML comments written in a template. When a component's root is a single element preceded by a leading comment, e.g.: