Skip to content

fix(runtime-vapor): guard VaporSlot when vnode.vs is undefined#14779

Merged
edison1105 merged 2 commits intovuejs:minorfrom
miguelrk:fix/vapor-slot-vs-undefined
May 6, 2026
Merged

fix(runtime-vapor): guard VaporSlot when vnode.vs is undefined#14779
edison1105 merged 2 commits intovuejs:minorfrom
miguelrk:fix/vapor-slot-vs-undefined

Conversation

@miguelrk
Copy link
Copy Markdown

@miguelrk miguelrk commented May 5, 2026

Fixes a runtime error when Vapor/VDOM interop leaves VaporSlot vnodes without vapor slot metadata (vnode.vs / missing slot function), e.g. when using VDOM component libraries (Nuxt UI) from Vapor parents (nuxt/ui#6395).

  • Return an empty block from renderVaporSlot when vnode.vs or vnode.vs.slot is missing, before resolving interop slot state
  • Remount the slot when either side of an update lacks vs or the slot function changes
  • Add regression test

Made with Cursor

Summary by CodeRabbit

  • Bug Fixes

    • Improved slot component handling stability during updates.
    • Fixed potential issues when slot state information is missing.
    • Enhanced slot remounting detection for accurate updates.
  • Tests

    • Added regression test coverage for slot component behavior.

Vapor/VDOM interop could leave slot vnodes without vapor slot metadata,
causing renderVaporSlot to throw when destructuring vnode.vs.

- Return empty block when vnode.vs.slot is missing
- Remount slot when either side lacks vs or slot fn changes
- Add regression test (nuxt/ui #6395)

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8519102e-7194-4fe4-b908-8e6644dc7993

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 5, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14779
npm i https://pkg.pr.new/@vue/compiler-core@14779
yarn add https://pkg.pr.new/@vue/compiler-core@14779.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14779
npm i https://pkg.pr.new/@vue/compiler-dom@14779
yarn add https://pkg.pr.new/@vue/compiler-dom@14779.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14779
npm i https://pkg.pr.new/@vue/compiler-sfc@14779
yarn add https://pkg.pr.new/@vue/compiler-sfc@14779.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14779
npm i https://pkg.pr.new/@vue/compiler-ssr@14779
yarn add https://pkg.pr.new/@vue/compiler-ssr@14779.tgz

@vue/compiler-vapor

pnpm add https://pkg.pr.new/@vue/compiler-vapor@14779
npm i https://pkg.pr.new/@vue/compiler-vapor@14779
yarn add https://pkg.pr.new/@vue/compiler-vapor@14779.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14779
npm i https://pkg.pr.new/@vue/reactivity@14779
yarn add https://pkg.pr.new/@vue/reactivity@14779.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14779
npm i https://pkg.pr.new/@vue/runtime-core@14779
yarn add https://pkg.pr.new/@vue/runtime-core@14779.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14779
npm i https://pkg.pr.new/@vue/runtime-dom@14779
yarn add https://pkg.pr.new/@vue/runtime-dom@14779.tgz

@vue/runtime-vapor

pnpm add https://pkg.pr.new/@vue/runtime-vapor@14779
npm i https://pkg.pr.new/@vue/runtime-vapor@14779
yarn add https://pkg.pr.new/@vue/runtime-vapor@14779.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14779
npm i https://pkg.pr.new/@vue/server-renderer@14779
yarn add https://pkg.pr.new/@vue/server-renderer@14779.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14779
npm i https://pkg.pr.new/@vue/shared@14779
yarn add https://pkg.pr.new/@vue/shared@14779.tgz

vue

pnpm add https://pkg.pr.new/vue@14779
npm i https://pkg.pr.new/vue@14779
yarn add https://pkg.pr.new/vue@14779.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14779
npm i https://pkg.pr.new/@vue/compat@14779
yarn add https://pkg.pr.new/@vue/compat@14779.tgz

commit: bfbc7cc

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Size Report

Bundles

File Size Gzip Brotli
compiler-dom.global.prod.js 86.4 kB 30.3 kB 26.6 kB
runtime-dom.global.prod.js 113 kB 42.4 kB 38 kB
vue.global.prod.js 172 kB 62.2 kB 55.5 kB

Usages

Name Size Gzip Brotli
createApp (CAPI only) 51.3 kB 20 kB 18.3 kB
createApp 60.4 kB 23.3 kB 21.2 kB
createApp + vaporInteropPlugin 101 kB (+75 B) 36.2 kB (+30 B) 32.8 kB (-30 B)
createVaporApp 27.3 kB 10.6 kB 9.73 kB
createSSRApp 64.9 kB 25.1 kB 22.8 kB
createVaporSSRApp 33.3 kB 12.7 kB 11.6 kB
defineCustomElement 67 kB 25.3 kB 23 kB
defineVaporCustomElement 40 kB 14.2 kB 13.1 kB
overall 75.4 kB 28.7 kB 26.1 kB

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.

🧹 Nitpick comments (1)
packages/runtime-vapor/__tests__/vdomInterop.spec.ts (1)

3645-3668: ⚡ Quick win

Reactive update errors aren't surfaced to the test runner — add an errorHandler check.

Vue routes component re-render errors through app.config.errorHandler rather than throwing them into the test's async context. As written, if the update path (triggered by tick.value++) causes an error, the test still passes because await nextTick() resolves normally and root.childNodes.length > 0 is satisfied by the anchor text node.

🛡️ Suggested fix to make the update-path regression detectable
     const root = document.createElement('div')
     const app = createApp(App)
     app.use(vaporInteropPlugin)
+    const errorHandler = vi.fn()
+    app.config.errorHandler = errorHandler

     expect(() => app.mount(root)).not.toThrow()

     tick.value++
     await nextTick()
     expect(root.childNodes.length).toBeGreaterThan(0)
+    expect(errorHandler).not.toHaveBeenCalled()
+    app.unmount()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/runtime-vapor/__tests__/vdomInterop.spec.ts` around lines 3645 -
3668, The test mounts App and advances reactive state but misses errors routed
through Vue's app.config.errorHandler; update the test to set
app.config.errorHandler to a handler that fails the test (e.g., capture and
rethrow or store and throw after nextTick) before calling app.mount(root) so any
errors during the update path (triggered by tick.value++ / nextTick) are
surfaced; reference the test block that defines tick, App (which returns
createVNode(VaporSlot, {})), app.use(vaporInteropPlugin), app.mount(root) and
nextTick to locate where to install the errorHandler.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/runtime-vapor/__tests__/vdomInterop.spec.ts`:
- Around line 3645-3668: The test mounts App and advances reactive state but
misses errors routed through Vue's app.config.errorHandler; update the test to
set app.config.errorHandler to a handler that fails the test (e.g., capture and
rethrow or store and throw after nextTick) before calling app.mount(root) so any
errors during the update path (triggered by tick.value++ / nextTick) are
surfaced; reference the test block that defines tick, App (which returns
createVNode(VaporSlot, {})), app.use(vaporInteropPlugin), app.mount(root) and
nextTick to locate where to install the errorHandler.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d00f98d-e1bf-4e41-aa82-7627ba086dbd

📥 Commits

Reviewing files that changed from the base of the PR and between 9c7c610 and a4f3461.

📒 Files selected for processing (2)
  • packages/runtime-vapor/__tests__/vdomInterop.spec.ts
  • packages/runtime-vapor/src/vdomInterop.ts

@edison1105 edison1105 added the scope: vapor related to vapor mode label May 6, 2026
@edison1105 edison1105 merged commit 7167cf9 into vuejs:minor May 6, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: vapor related to vapor mode

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants