-
-
Notifications
You must be signed in to change notification settings - Fork 9k
fix(runtime-core): correctly propagate placeholder for async component #14177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughFixes Suspense element ordering issue when using v-for with wrapper components around async components. Introduces a helper function to resolve actual elements from unresolved async component sub-trees during anchor calculation in patch operations, extending the fallback chain for proper element positioning. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 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 |
Size ReportBundles
Usages
|
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
| if (root === vnode) { | ||
| ;(vnode = parent.vnode).el = el | ||
| if (root.placeholder) { | ||
| vnode.placeholder = root.placeholder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should cause a memory leak, leading to the placeholder referencing a detached DOM node. Because when Suspense resolves, we only clear the placeholder of the async component. see
| vnode.placeholder = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The correct approach should be to attempt to locate the placeholder on anchorVNode.component.subTree here
core/packages/runtime-core/src/renderer.ts
Line 1999 in 44ee438
| anchorVNode.el || anchorVNode.placeholder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your guidance. I’ve made the changes accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/runtime-core/src/renderer.ts (1)
2423-2429: Add defensive null check forsubTree.While
subTreeshould always be set aftersetupComponent, consider adding a defensive check to prevent potential runtime errors in edge cases (e.g., error handling, invalid component states):Apply this diff to make the function more robust:
const getSubTreeElement = (vnode: VNode): RendererNode | null => { let current = vnode - while (current.component) { + while (current.component && current.component.subTree) { current = current.component.subTree } return current.el || current.placeholder }This ensures we won't attempt to traverse into components with uninitialized subtrees.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/runtime-core/src/renderer.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/runtime-core/src/renderer.ts (2)
packages/runtime-core/src/vnode.ts (1)
VNode(160-257)packages/runtime-core/src/index.ts (2)
VNode(250-250)RendererNode(306-306)
🔇 Additional comments (1)
packages/runtime-core/src/renderer.ts (1)
1999-2001: LGTM! Anchor fallback chain correctly handles wrapper components.The extended fallback chain properly resolves the anchor element when async components are wrapped by other components. The progression from
el→placeholder→getSubTreeElement()ensures correct element ordering in Suspense scenarios with v-for.
| while (current.component) { | ||
| current = current.component.subTree | ||
| } | ||
| return current.el || current.placeholder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to get current.el here; if el has a value, then anchorVNode.el must also have a value.
Just need to get current.placeholder.
This implementation isn't quite right either; we shouldn't keep searching down the subTree but should early return as soon as we find the placeholder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, but I perfer https://github.com/vuejs/core/pull/14182/files
fix #14173
Summary by CodeRabbit
Tests
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.