CREATE_VNODE,
MERGE_PROPS,
RESOLVE_DIRECTIVE,
- APPLY_DIRECTIVES
+ APPLY_DIRECTIVES,
+ TO_HANDLERS
} from '../../src/runtimeConstants'
import {
CallExpression,
})
})
+ test('v-on="obj"', () => {
+ const { root, node } = parseWithElementTransform(
+ `<div id="foo" v-on="obj" class="bar" />`
+ )
+ expect(root.imports).toContain(MERGE_PROPS)
+ expect(node.callee).toBe(CREATE_VNODE)
+ expect(node.arguments[1]).toMatchObject({
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: MERGE_PROPS,
+ arguments: [
+ createStaticObjectMatcher({
+ id: 'foo'
+ }),
+ {
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: TO_HANDLERS,
+ arguments: [
+ {
+ type: NodeTypes.EXPRESSION,
+ content: `obj`
+ }
+ ]
+ },
+ createStaticObjectMatcher({
+ class: 'bar'
+ })
+ ]
+ })
+ })
+
+ test('v-on="obj" + v-bind="obj"', () => {
+ const { root, node } = parseWithElementTransform(
+ `<div id="foo" v-on="handlers" v-bind="obj" />`
+ )
+ expect(root.imports).toContain(MERGE_PROPS)
+ expect(node.callee).toBe(CREATE_VNODE)
+ expect(node.arguments[1]).toMatchObject({
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: MERGE_PROPS,
+ arguments: [
+ createStaticObjectMatcher({
+ id: 'foo'
+ }),
+ {
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: TO_HANDLERS,
+ arguments: [
+ {
+ type: NodeTypes.EXPRESSION,
+ content: `handlers`
+ }
+ ]
+ },
+ {
+ type: NodeTypes.EXPRESSION,
+ content: `obj`
+ }
+ ]
+ })
+ })
+
test('error on v-bind with no argument', () => {
const onError = jest.fn()
parseWithElementTransform(`<div v-bind/>`, { onError })
APPLY_DIRECTIVES,
RESOLVE_DIRECTIVE,
RESOLVE_COMPONENT,
- MERGE_PROPS
+ MERGE_PROPS,
+ TO_HANDLERS
} from '../runtimeConstants'
const toValidId = (str: string): string => str.replace(/[^\w]/g, '')
}
}
+type PropsExpression = ObjectExpression | CallExpression | ExpressionNode
+
function buildProps(
- { loc, props }: ElementNode,
+ { loc: elementLoc, props }: ElementNode,
context: TransformContext
): {
- props: ObjectExpression | CallExpression | ExpressionNode
+ props: PropsExpression
directives: DirectiveNode[]
} {
let properties: ObjectExpression['properties'] = []
- const mergeArgs: Array<ObjectExpression | ExpressionNode> = []
+ const mergeArgs: PropsExpression[] = []
const runtimeDirectives: DirectiveNode[] = []
for (let i = 0; i < props.length; i++) {
)
} else {
// directives
- // special case for v-bind with no argument
- if (prop.name === 'bind' && !prop.arg) {
- if (prop.exp) {
+ const { name, arg, exp, loc } = prop
+ // special case for v-bind and v-on with no argument
+ const isBind = name === 'bind'
+ if (!arg && (isBind || name === 'on')) {
+ if (exp) {
if (properties.length) {
- mergeArgs.push(createObjectExpression(properties, loc))
+ mergeArgs.push(createObjectExpression(properties, elementLoc))
properties = []
}
- mergeArgs.push(prop.exp)
+ if (isBind) {
+ mergeArgs.push(exp)
+ } else {
+ // v-on="obj" -> toHandlers(obj)
+ context.imports.add(TO_HANDLERS)
+ mergeArgs.push({
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ loc,
+ callee: TO_HANDLERS,
+ arguments: [exp]
+ })
+ }
} else {
context.onError(
- createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, prop.loc)
+ createCompilerError(
+ isBind
+ ? ErrorCodes.X_V_BIND_NO_EXPRESSION
+ : ErrorCodes.X_V_ON_NO_EXPRESSION,
+ loc
+ )
)
}
continue
}
- const directiveTransform = context.directiveTransforms[prop.name]
+ const directiveTransform = context.directiveTransforms[name]
if (directiveTransform) {
+ // has built-in directive transform.
const { props, needRuntime } = directiveTransform(prop, context)
if (isArray(props)) {
properties.push(...props)
}
}
- let ret: ObjectExpression | CallExpression | ExpressionNode
+ let propsExpression: PropsExpression
- // has v-bind="object", wrap with mergeProps
+ // has v-bind="object" or v-on="object", wrap with mergeProps
if (mergeArgs.length) {
if (properties.length) {
- mergeArgs.push(createObjectExpression(properties, loc))
+ mergeArgs.push(createObjectExpression(properties, elementLoc))
}
if (mergeArgs.length > 1) {
context.imports.add(MERGE_PROPS)
- ret = createCallExpression(MERGE_PROPS, mergeArgs, loc)
+ propsExpression = createCallExpression(MERGE_PROPS, mergeArgs, elementLoc)
} else {
// single v-bind with nothing else - no need for a mergeProps call
- ret = mergeArgs[0]
+ propsExpression = mergeArgs[0]
}
} else {
- ret = createObjectExpression(properties, loc)
+ propsExpression = createObjectExpression(properties, elementLoc)
}
return {
- props: ret,
+ props: propsExpression,
directives: runtimeDirectives
}
}