From 6105cf9c59db14d3bfa36d4bcdad6ed9a9944103 Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 25 Nov 2025 16:20:48 +0800 Subject: [PATCH] fix(compiler-vapor): prevent `_camelize` from receiving nullish value for dynamic `v-bind` keys with `.camel` modifier. --- .../__snapshots__/vBind.spec.ts.snap | 13 +++++++- .../__tests__/transforms/vBind.spec.ts | 33 +++++++++++++++++-- .../compiler-vapor/src/generators/prop.ts | 1 + 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap index e2c94526b9b..bd02d764df2 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap @@ -361,13 +361,24 @@ export function render(_ctx) { }" `; +exports[`compiler v-bind > .camel modifier w/ dynamic arg + prefixIdentifiers 1`] = ` +"import { camelize as _camelize, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue'; +const t0 = _template("
", true) + +export function render(_ctx) { + const n0 = t0() + _renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo(_ctx.bar) || "")]: _ctx.id }])) + return n0 +}" +`; + exports[`compiler v-bind > .camel modifier w/ dynamic arg 1`] = ` "import { camelize as _camelize, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue'; const t0 = _template("
", true) export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }])) + _renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo || "")]: _ctx.id }])) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts index 230ae2c4da4..17295beeaae 100644 --- a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts @@ -341,11 +341,40 @@ describe('compiler v-bind', () => { expect(code).matchSnapshot() expect(code).contains('renderEffect') expect(code).contains( - `_setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }])`, + `_setDynamicProps(n0, [{ [_camelize(_ctx.foo || "")]: _ctx.id }])`, ) }) - test.todo('.camel modifier w/ dynamic arg + prefixIdentifiers') + test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => { + const { ir, code } = compileWithVBind( + `
`, + { + prefixIdentifiers: true, + }, + ) + expect(code).matchSnapshot() + expect(ir.block.effect[0].operations[0]).toMatchObject({ + type: IRNodeTypes.SET_DYNAMIC_PROPS, + props: [ + [ + { + key: { + content: `foo(bar)`, + isStatic: false, + }, + values: [ + { + content: `id`, + isStatic: false, + }, + ], + runtimeCamelize: true, + modifier: undefined, + }, + ], + ], + }) + }) test('.prop modifier', () => { const { ir, code } = compileWithVBind(`
`) diff --git a/packages/compiler-vapor/src/generators/prop.ts b/packages/compiler-vapor/src/generators/prop.ts index 63c6471f1f4..d6e73017fd2 100644 --- a/packages/compiler-vapor/src/generators/prop.ts +++ b/packages/compiler-vapor/src/generators/prop.ts @@ -138,6 +138,7 @@ export function genPropKey( let key = genExpression(node, context) if (runtimeCamelize) { + key.push(' || ""') key = genCall(helper('camelize'), key) } if (handler) {