[Vapor] compiler: custom directive with an inline object-literal value generates an arrow function with a bare `{ ... }` body
### Vue version
3.6.0-rc.2
### Link to minimal reproduction
https://play.vuejs.org/#eNqVkU9rwzAMxb+K8GUJpM7+wA4hzRjbaYftMNgpMEKstgbXNrLiNpR+92mUwHbYYSchoaffe+ikHmPUeULVqDaNZCNDQp4i5CEG6no/Bp8Y8jPuA6yhQFfBFvljcBOWsO7g1HsAdJrxyE/BM3qWvZf3t1edmKzf2s1cLIoHXZRl78/LWYMXpg1eRFc7dC5c9b6tL2PBS8O4j25g7L5JbeyCR4gUIhLPUCTrBOlmOFDw2wqMJRzZZgSpKDXB5A1urEdTNm0dL2eMzZBXRlKte3WStOKu+eXn3KtOuCPugjNIbS2SxQIfwmLBCqBIs+fhCEgU6D+QCgLvkBq4+QvX1j/iq0p9ZqQkSvnXnb7X1ysa9a06fwFMxJ8l
### Steps to reproduce
A vapor SFC with a custom directive that receives an inline object literal, the way object options are typically passed to directives (e.g. PrimeVue's `v-tooltip="{ value: ..., pt: ... }"`):
```vue
<script setup vapor>
const vDemo = (el, getValue) => {
el.textContent = JSON.stringify(getValue?.())
}
const description = 'hello'
</script>
<template>
<div v-demo="{ value: description }">placeholder</div>
<div v-demo="{ value: description, other: 1 }">placeholder</div>
</template>
```
Canonical repro of the codegen itself (node, `vue@3.6.0-rc.2`):
```js
import { compileTemplate } from 'vue/compiler-sfc'
const out = compileTemplate({
id: 'x',
filename: 'App.vue',
source: `<div v-demo="{ value: description }">placeholder</div>
<div v-demo="{ value: description, other: 1 }">p2</div>`,
vapor: true,
compilerOptions: { bindingMetadata: { vDemo: 'setup-const', description: 'setup-const' } },
})
console.log(out.code)
```
emits:
```js
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
_withVaporDirectives(n0, [[_ctx.vDemo, () => { value: _ctx.description }]])
const n1 = t1()
_withVaporDirectives(n1, [[_ctx.vDemo, () => { value: _ctx.description, other: 1 }]])
return [n0, n1]
}
```
The directive value expression is wrapped in an arrow function without parenthesizing the object literal.
### What is expected?
The getter should return the object:
```js
_withVaporDirectives(n0, [[_ctx.vDemo, () => ({ value: _ctx.description })]])
```
VDOM mode handles the same template correctly.
### What is actually happening?
1. **Single property, non-inline mode — silently wrong.** `() => { value: _ctx.description }` parses as an arrow with a *block body* containing a labeled statement, so the getter returns `undefined`. No compile error, no runtime error — the directive just receives `undefined` instead of the object.
2. **Two or more properties — SyntaxError.** `() => { value: _ctx.description, other: 1 }` is not valid JavaScript. In a Vite build this fails the build with `Expected a semicolon or an implicit semicolon after a statement, but found none` pointing into the generated SFC code.
3. **Inline mode (playground) — directive receives the raw object instead of a getter.** In the playground repro above, the directive's second argument is the object itself rather than a function, so `getValue?.()` throws `getValue is not a function`.
### System Info
```shell
System: macOS 26.6 (arm64)
Binaries: node v26.7.0, pnpm 11.18.0
npmPackages: vue 3.6.0-rc.2, @vitejs/plugin-vue 6.0.8, vite 8.2.1
```
### Any additional comments?
_No response_
关闭于 11 天前 1 条评论