})
})
+ test('no expression', () => {
+ const node = parseWithVBind(`<div v-bind:id />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `id`,
+ isStatic: true,
+ loc: {
+ start: {
+ line: 1,
+ column: 13,
+ offset: 12
+ },
+ end: {
+ line: 1,
+ column: 15,
+ offset: 14
+ }
+ }
+ },
+ value: {
+ content: `id`,
+ isStatic: false,
+ loc: {
+ start: {
+ line: 1,
+ column: 1,
+ offset: 0
+ },
+ end: {
+ line: 1,
+ column: 1,
+ offset: 0
+ }
+ }
+ }
+ })
+ })
+
+ test('no expression (shorthand)', () => {
+ const node = parseWithVBind(`<div :id />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `id`,
+ isStatic: true
+ },
+ value: {
+ content: `id`,
+ isStatic: false
+ }
+ })
+ })
+
test('dynamic arg', () => {
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
const props = (node.codegenNode as VNodeCall).props as CallExpression
})
})
- test('should error if no expression', () => {
+ test('should error if empty expression', () => {
const onError = vi.fn()
- const node = parseWithVBind(`<div v-bind:arg />`, { onError })
+ const node = parseWithVBind(`<div v-bind:arg="" />`, { onError })
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
expect(onError.mock.calls[0][0]).toMatchObject({
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
},
end: {
line: 1,
- column: 16
+ column: 19
}
}
})
})
})
+ test('.camel modifier w/ no expression', () => {
+ const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `fooBar`,
+ isStatic: true
+ },
+ value: {
+ content: `fooBar`,
+ isStatic: false
+ }
+ })
+ })
+
test('.camel modifier w/ dynamic arg', () => {
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
const props = (node.codegenNode as VNodeCall).props as CallExpression
})
})
+ test('.prop modifier w/ no expression', () => {
+ const node = parseWithVBind(`<div v-bind:fooBar.prop />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `.fooBar`,
+ isStatic: true
+ },
+ value: {
+ content: `fooBar`,
+ isStatic: false
+ }
+ })
+ })
+
test('.prop modifier w/ dynamic arg', () => {
const node = parseWithVBind(`<div v-bind:[fooBar].prop="id"/>`)
const props = (node.codegenNode as VNodeCall).props as CallExpression
})
})
+ test('.prop modifier (shortband) w/ no expression', () => {
+ const node = parseWithVBind(`<div .fooBar />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `.fooBar`,
+ isStatic: true
+ },
+ value: {
+ content: `fooBar`,
+ isStatic: false
+ }
+ })
+ })
+
test('.attr modifier', () => {
const node = parseWithVBind(`<div v-bind:foo-bar.attr="id"/>`)
const props = (node.codegenNode as VNodeCall).props as ObjectExpression
}
})
})
+
+ test('.attr modifier w/ no expression', () => {
+ const node = parseWithVBind(`<div v-bind:foo-bar.attr />`)
+ const props = (node.codegenNode as VNodeCall).props as ObjectExpression
+ expect(props.properties[0]).toMatchObject({
+ key: {
+ content: `^foo-bar`,
+ isStatic: true
+ },
+ value: {
+ content: `fooBar`,
+ isStatic: false
+ }
+ })
+ })
})
createObjectProperty,
createSimpleExpression,
ExpressionNode,
+ locStub,
NodeTypes
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
import { camelize } from '@vue/shared'
import { CAMELIZE } from '../runtimeHelpers'
+import { processExpression } from './transformExpression'
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting
// codegen for the entire props object. This transform here is only for v-bind
// *with* args.
export const transformBind: DirectiveTransform = (dir, _node, context) => {
- const { exp, modifiers, loc } = dir
+ const { modifiers, loc } = dir
const arg = dir.arg!
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) {
}
}
+ // :arg is replaced by :arg="arg"
+ let { exp } = dir
+ if (!exp && arg.type === NodeTypes.SIMPLE_EXPRESSION) {
+ const propName = camelize(arg.loc.source)
+ const simpleExpression = createSimpleExpression(propName, false, {
+ ...locStub,
+ source: propName
+ })
+
+ exp = dir.exp = processExpression(simpleExpression, context)
+ }
+
if (
!exp ||
(exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())