Skip to content

fix(teleport): properly handling disabled teleport target anchor#14417

Merged
edison1105 merged 2 commits intomainfrom
edison/fix/14412
Feb 9, 2026
Merged

fix(teleport): properly handling disabled teleport target anchor#14417
edison1105 merged 2 commits intomainfrom
edison/fix/14412

Conversation

@edison1105
Copy link
Copy Markdown
Member

@edison1105 edison1105 commented Feb 5, 2026

close #14412

Summary by CodeRabbit

  • Bug Fixes

    • Fixed hydration/SSR mismatches for Teleport anchors so content stays consistent when toggling enabled/disabled states.
  • Refactor

    • Reworked Teleport anchor management and hydration flow for more reliable anchor insertion, CSS variable updates, and no-op compatibility in non-teleport scenarios.
  • Tests

    • Added an integration test covering disabled Teleport hydration and unmount behavior to prevent regressions.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

Introduces a lookahead hydration helper hydrateAnchor, centralizes anchor handling via an extended prepareAnchor(anchor?), and refactors both enabled and disabled Teleport hydration/update flows (including CSS var anchor derivation) to use these helpers and avoid propagating target start/anchor through call paths.

Changes

Cohort / File(s) Summary
Teleport hydration core
packages/runtime-core/src/components/Teleport.ts
Adds hydrateAnchor (lookahead anchor discovery), introduces hydrateDisabledTeleport usage, refactors enabled/disabled hydration paths to call hydrateAnchor and prepareAnchor(anchor?), removes direct propagation of targetStart/targetAnchor, and adjusts updateCssVars to derive anchors correctly.
Hydration tests
packages/runtime-core/__tests__/hydration.spec.ts
Adds integration test "Teleport unmount (disabled + full integration)" exercising client hydration and toggling of Teleport target and disabled states along with surrounding v-if.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client
participant Hydrator
participant Teleport
participant Renderer
participant DOM
Client->>Hydrator: start hydration
Hydrator->>Teleport: hydrate Teleport vnode
Teleport->>Hydrator: request anchor lookup
Hydrator->>Teleport: call hydrateAnchor(node)
Teleport->>Renderer: prepareAnchor(target, vnode, ..., anchor?)
Renderer->>DOM: insert/create anchors (start/anchor)
DOM-->>Renderer: anchors available
Renderer-->>Teleport: anchors set (targetStart/targetAnchor/_lpa)
Teleport->>Hydrator: continue hydrating children into anchors

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop and peer with lookahead sight,
I find the anchors hidden from light,
I stitch start and end with gentle care,
so teleports land exactly where. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing proper handling of disabled teleport target anchors during hydration.
Linked Issues check ✅ Passed The PR addresses issue #14412 by implementing hydration helpers and anchor management to fix node traversal errors in Teleport with conditional rendering.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing Teleport anchor handling during hydration and conditional rendering; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch edison/fix/14412

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 5, 2026

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 103 kB (+66 B) 39.1 kB (+15 B) 35.2 kB (-3 B)
vue.global.prod.js 162 kB (+66 B) 59.1 kB (+11 B) 52.6 kB (-35 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 47 kB 18.3 kB 16.8 kB
createApp 55.1 kB 21.4 kB 19.6 kB
createSSRApp 59.4 kB 23.2 kB 21.1 kB
defineCustomElement 60.8 kB 23.1 kB 21.1 kB
overall 69.5 kB 26.7 kB 24.3 kB

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Feb 5, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14417
npm i https://pkg.pr.new/@vue/compiler-core@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14417
npm i https://pkg.pr.new/@vue/compiler-dom@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14417
npm i https://pkg.pr.new/@vue/compiler-sfc@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14417
npm i https://pkg.pr.new/@vue/compiler-ssr@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14417
npm i https://pkg.pr.new/@vue/reactivity@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14417
npm i https://pkg.pr.new/@vue/runtime-core@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14417
npm i https://pkg.pr.new/@vue/runtime-dom@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14417
npm i https://pkg.pr.new/@vue/server-renderer@14417
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14417
npm i https://pkg.pr.new/@vue/shared@14417
yarn add https://pkg.pr.new/@vue/[email protected]

vue

pnpm add https://pkg.pr.new/vue@14417
npm i https://pkg.pr.new/vue@14417
yarn add https://pkg.pr.new/[email protected]

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14417
npm i https://pkg.pr.new/@vue/compat@14417
yarn add https://pkg.pr.new/@vue/[email protected]

commit: d62d5c9

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/runtime-core/src/components/Teleport.ts (1)

533-549: ⚠️ Potential issue | 🔴 Critical

Fix anchor parameter type to accept non-Element nodes.

prepareAnchor receives an insert function that accepts RendererNode (including non-Element nodes like Comment nodes used in hydration) as the anchor parameter, but declares the anchor parameter as RendererElement, which is too narrow.

Proposed fix
function prepareAnchor(
  target: RendererElement | null,
  vnode: TeleportVNode,
  createText: RendererOptions['createText'],
  insert: RendererOptions['insert'],
-  anchor: RendererElement | null = null,
+  anchor: RendererNode | null = null,
) {

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/runtime-core/src/components/Teleport.ts (1)

459-481: ⚠️ Potential issue | 🟡 Minor

Advance _lpa when anchors are synthesized.

When SSR anchors are missing, prepareAnchor creates new anchors but _lpa remains unset. With multiple teleports targeting the same element, the next hydration pass can restart at target.firstChild, leading to mismatched hydration/duplicate anchors. Consider advancing _lpa immediately after prepareAnchor in both branches.

Suggested fix (update _lpa after creating anchors)
-        if (!vnode.targetAnchor) {
-          prepareAnchor(
-            target,
-            vnode,
-            createText,
-            insert,
-            // if target is the same as the main view, insert anchors before current node
-            // to avoid hydrating mismatch
-            parentNode(node)! === target ? node : null,
-          )
-        }
+        if (!vnode.targetAnchor) {
+          const createdAnchor = prepareAnchor(
+            target,
+            vnode,
+            createText,
+            insert,
+            // if target is the same as the main view, insert anchors before current node
+            // to avoid hydrating mismatch
+            parentNode(node)! === target ? node : null,
+          )
+          ;(target as TeleportTargetElement)._lpa = nextSibling(
+            createdAnchor as Node,
+          )
+        }
...
-        if (!vnode.targetAnchor) {
-          prepareAnchor(target, vnode, createText, insert)
-        }
+        if (!vnode.targetAnchor) {
+          const createdAnchor = prepareAnchor(target, vnode, createText, insert)
+          ;(target as TeleportTargetElement)._lpa = nextSibling(
+            createdAnchor as Node,
+          )
+        }

@edison1105 edison1105 added scope: teleport 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged. labels Feb 5, 2026
@edison1105
Copy link
Copy Markdown
Member Author

/ecosystem-ci run

@vue-bot
Copy link
Copy Markdown
Contributor

vue-bot commented Feb 5, 2026

📝 Ran ecosystem CI: Open

suite result latest scheduled
vite-plugin-vue success success
language-tools success success
test-utils success success
pinia success success
vitepress success success
vue-macros success success
vue-i18n success success
nuxt success success
quasar success success
vuetify success success
router success success
radix-vue success success
primevue success success
vant success success
vueuse success success
vue-simple-compiler success success

@edison1105 edison1105 merged commit d7bcd85 into main Feb 9, 2026
16 checks passed
@edison1105 edison1105 deleted the edison/fix/14412 branch February 9, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged. scope: teleport

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Teleport bug on conditional rendering

2 participants