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,