Vapor: a declared style prop on a component receives an unmerged array, same bug as #15227 but for style
scope: vapor
#15230 fixed #15227 ("Vapor: class on a component is not normalized, so a declared `class: String` prop receives an Array") by adding a `normalizeRawProp` guard in `packages/runtime-vapor/src/componentProps.ts`:
```ts
const normalizeRawProp = (key: string, value: unknown) =>
key === 'class' && value && !isString(value) ? normalizeClass(value) : value
```
I checked the compiler side (`packages/compiler-vapor/src/transforms/transformElement.ts`, `dedupeProperties`/`mergePropValues`) and it treats `class` and `style` completely symmetrically: when a component receives both a static and a dynamic binding for either (`<Child style="color:red" :style="dynamicObj" />`), both get merged into a raw array (`["color:red", dynamicObj]`). The runtime side mirrors this symmetry too — `getAttrFromRawProps` in the same `componentProps.ts` file explicitly special-cases `key === 'class' || key === 'style'` together for the fallthrough-attrs merge path (with the comment "need special merging behavior for class & style").
But `normalizeRawProp`, used when a component explicitly *declares* the prop (e.g. `defineProps({ style: Object })`), only unwraps `class` — there's no `key === 'style'` branch, and `normalizeStyle` isn't imported into this resolution path at all. So a declared `style` prop receives the raw unmerged array instead of the merged object/string VDOM would produce via `normalizeStyle` (`packages/runtime-core/src/vnode.ts`, `props.style = normalizeStyle(style)`).
### Reproduction
```vue
<!-- Child.vue -->
<script setup vapor>
defineProps<{ style?: any }>()
</script>
<template>
<pre>{{ JSON.stringify(style) }}</pre>
</template>
<!-- Parent.vue -->
<script setup vapor>
import Child from './Child.vue'
const dynamicStyle = { color: 'red' }
</script>
<template>
<Child style="font-weight:bold" :style="dynamicStyle" />
</template>
```
Expected (matches VDOM): `style` resolves to a merged object/string. Actual in Vapor: `style` is the raw array `["font-weight:bold", { color: "red" }]`.
关闭于 9 天前 2 条评论