fix(runtime-vapor): delay teleport child init until target is available#14593
fix(runtime-vapor): delay teleport child init until target is available#14593edison1105 merged 2 commits intominorfrom
Conversation
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/compiler-vapor
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/runtime-vapor
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
Size ReportBundles
Usages
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/runtime-vapor/src/components/Teleport.ts`:
- Around line 126-145: The renderEffect body in initChildren must run with the
Teleport's owner instance set on every effect run; move or add a
setCurrentInstance(this.ownerInstance) call inside the renderEffect callback
(and restore the previous instance after the callback finishes) so that each
invocation of rawSlots!.default() sees the correct currentInstance; update the
corresponding restore to call setCurrentInstance(prevInstance) (or use the
returned prev value from setCurrentInstance) within the renderEffect finally
block to ensure currentInstance is restored on every rerun and that
createComponent and component.ts see the proper app/parent context.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8bf83dd7-a96e-4ec3-b587-2330b6aced15
📒 Files selected for processing (3)
packages/runtime-vapor/__tests__/components/Teleport.spec.tspackages/runtime-vapor/__tests__/hydration.spec.tspackages/runtime-vapor/src/components/Teleport.ts
| private initChildren(): void { | ||
| renderEffect(() => { | ||
| this.handleChildrenUpdate( | ||
| this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(), | ||
| ) | ||
| }) | ||
| this.bindChildren(this.nodes) | ||
| const prevInstance = setCurrentInstance(this.ownerInstance) | ||
| try { | ||
| this.childrenInitialized = true | ||
| renderEffect(() => { | ||
| const prevOwner = setCurrentSlotOwner(this.slotOwner) | ||
| const prevKeepAliveCtx = setCurrentKeepAliveCtx(this.keepAliveCtx) | ||
| try { | ||
| this.handleChildrenUpdate( | ||
| this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(), | ||
| ) | ||
| } finally { | ||
| setCurrentKeepAliveCtx(prevKeepAliveCtx) | ||
| setCurrentSlotOwner(prevOwner) | ||
| } | ||
| }) | ||
| this.bindChildren(this.nodes) | ||
| } finally { | ||
| setCurrentInstance(...prevInstance) | ||
| } |
There was a problem hiding this comment.
Restore currentInstance on every delayed-child rerun.
setCurrentInstance(this.ownerInstance) only wraps the initial renderEffect() registration. After the first late mount, later effect reruns call rawSlots.default() without re-entering the owner instance, and createComponent() then falls back to missing parent/app-context wiring. packages/runtime-vapor/src/component.ts reads currentInstance for that metadata, so a delayed teleport that later re-renders its slot root can recreate children under the wrong context.
🛠️ Proposed fix
private initChildren(): void {
const prevInstance = setCurrentInstance(this.ownerInstance)
try {
this.childrenInitialized = true
renderEffect(() => {
+ const prevEffectInstance = setCurrentInstance(this.ownerInstance)
const prevOwner = setCurrentSlotOwner(this.slotOwner)
const prevKeepAliveCtx = setCurrentKeepAliveCtx(this.keepAliveCtx)
try {
this.handleChildrenUpdate(
this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(),
)
} finally {
setCurrentKeepAliveCtx(prevKeepAliveCtx)
setCurrentSlotOwner(prevOwner)
+ setCurrentInstance(...prevEffectInstance)
}
})
this.bindChildren(this.nodes)
} finally {
setCurrentInstance(...prevInstance)
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/runtime-vapor/src/components/Teleport.ts` around lines 126 - 145,
The renderEffect body in initChildren must run with the Teleport's owner
instance set on every effect run; move or add a
setCurrentInstance(this.ownerInstance) call inside the renderEffect callback
(and restore the previous instance after the callback finishes) so that each
invocation of rawSlots!.default() sees the correct currentInstance; update the
corresponding restore to call setCurrentInstance(prevInstance) (or use the
returned prev value from setCurrentInstance) within the renderEffect finally
block to ensure currentInstance is restored on every rerun and that
createComponent and component.ts see the proper app/parent context.
Summary by CodeRabbit