diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index 5d3f92ced18..c30840a21a6 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -1231,6 +1231,24 @@ describe('compiler: element transform', () => { }) }) + test('dynamic binding shorthand', () => { + const { node, root } = parseWithBind(``) + expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT) + expect(node).toMatchObject({ + isBlock: true, + tag: { + callee: RESOLVE_DYNAMIC_COMPONENT, + arguments: [ + { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'is', + isStatic: false, + }, + ], + }, + }) + }) + test('is casting', () => { const { node, root } = parseWithBind(`
`) expect(root.helpers).toContain(RESOLVE_COMPONENT) diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index c50f7f5e969..be90eaf65d9 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -50,6 +50,7 @@ import { UNREF, } from '../runtimeHelpers' import { + findAndProcessShorthandProp, findProp, isCoreComponent, isStaticArgOf, @@ -253,7 +254,8 @@ export function resolveComponentType( // 1. dynamic component const isExplicitDynamic = isComponentTag(tag) - const isProp = findProp(node, 'is') + const isProp = + findProp(node, 'is') || findAndProcessShorthandProp(node, 'is', context) if (isProp) { if ( isExplicitDynamic || diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index 99a2c5b61a8..bcdb1d107ae 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -23,6 +23,7 @@ import { type VNodeCall, createCallExpression, createObjectExpression, + createSimpleExpression, } from './ast' import type { TransformContext } from './transform' import { @@ -36,11 +37,12 @@ import { TO_HANDLERS, WITH_MEMO, } from './runtimeHelpers' -import { NOOP, isObject, isString } from '@vue/shared' +import { NOOP, camelize, isObject, isString } from '@vue/shared' import type { PropsExpression } from './transforms/transformElement' import { parseExpression } from '@babel/parser' import type { Expression } from '@babel/types' import { unwrapTSNode } from './babelUtils' +import { processExpression } from './transforms/transformExpression' export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode => p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic @@ -263,6 +265,30 @@ export function findProp( } } +export function findAndProcessShorthandProp( + node: ElementNode, + name: string, + context: TransformContext, +): ElementNode['props'][0] | undefined { + for (let i = 0; i < node.props.length; i++) { + const p = node.props[i] + if ( + p.type !== NodeTypes.ATTRIBUTE && + p.name === 'bind' && + p.arg && + isStaticArgOf(p.arg, name) && + p.arg.type === NodeTypes.SIMPLE_EXPRESSION + ) { + const value = camelize(p.arg.content) + p.exp = createSimpleExpression(value, false, p.arg.loc) + if (!__BROWSER__) { + p.exp = processExpression(p.exp, context) + } + return p + } + } +} + export function isStaticArgOf( arg: DirectiveNode['arg'], name: string,