Skip to content

Commit cb87b62

Browse files
committedFeb 7, 2024·
fix(compiler-core): handle same-name shorthand edge case for in-DOM templates
Also add error for invalid arguments for same-name shorthand. close #10280
1 parent 0bced13 commit cb87b62

File tree

3 files changed

+59
-13
lines changed

3 files changed

+59
-13
lines changed
 

‎packages/compiler-core/__tests__/transforms/vBind.spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,22 @@ describe('compiler: transform v-bind', () => {
408408
},
409409
})
410410
})
411+
412+
test('error on invalid argument for same-name shorthand', () => {
413+
const onError = vi.fn()
414+
parseWithVBind(`<div v-bind:[arg] />`, { onError })
415+
expect(onError.mock.calls[0][0]).toMatchObject({
416+
code: ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
417+
loc: {
418+
start: {
419+
line: 1,
420+
column: 13,
421+
},
422+
end: {
423+
line: 1,
424+
column: 18,
425+
},
426+
},
427+
})
428+
})
411429
})

‎packages/compiler-core/src/errors.ts

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export enum ErrorCodes {
7878
X_V_FOR_MALFORMED_EXPRESSION,
7979
X_V_FOR_TEMPLATE_KEY_PLACEMENT,
8080
X_V_BIND_NO_EXPRESSION,
81+
X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
8182
X_V_ON_NO_EXPRESSION,
8283
X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
8384
X_V_SLOT_MIXED_SLOT_USAGE,
@@ -156,6 +157,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
156157
[ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,
157158
[ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT]: `<template v-for> key should be placed on the <template> tag.`,
158159
[ErrorCodes.X_V_BIND_NO_EXPRESSION]: `v-bind is missing expression.`,
160+
[ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT]: `v-bind with same-name shorthand only allows static argument.`,
159161
[ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression.`,
160162
[ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET]: `Unexpected custom directive on <slot> outlet.`,
161163
[ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE]:

‎packages/compiler-core/src/transforms/vBind.ts

+39-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { DirectiveTransform } from '../transform'
22
import {
33
type ExpressionNode,
44
NodeTypes,
5+
type SimpleExpressionNode,
56
createObjectProperty,
67
createSimpleExpression,
78
} from '../ast'
@@ -17,10 +18,45 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
1718
const { modifiers, loc } = dir
1819
const arg = dir.arg!
1920

20-
// :arg is replaced by :arg="arg"
2121
let { exp } = dir
22-
if (!exp && arg.type === NodeTypes.SIMPLE_EXPRESSION) {
23-
const propName = camelize(arg.content)
22+
23+
// handle empty expression
24+
if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {
25+
if (!__BROWSER__) {
26+
// #10280 only error against empty expression in non-browser build
27+
// because :foo in in-DOM templates will be parsed into :foo="" by the
28+
// browser
29+
context.onError(
30+
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
31+
)
32+
return {
33+
props: [
34+
createObjectProperty(arg, createSimpleExpression('', true, loc)),
35+
],
36+
}
37+
} else {
38+
exp = undefined
39+
}
40+
}
41+
42+
// same-name shorthand - :arg is expanded to :arg="arg"
43+
if (!exp) {
44+
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {
45+
// only simple expression is allowed for same-name shorthand
46+
context.onError(
47+
createCompilerError(
48+
ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
49+
arg.loc,
50+
),
51+
)
52+
return {
53+
props: [
54+
createObjectProperty(arg, createSimpleExpression('', true, loc)),
55+
],
56+
}
57+
}
58+
59+
const propName = camelize((arg as SimpleExpressionNode).content)
2460
exp = dir.exp = createSimpleExpression(propName, false, arg.loc)
2561
if (!__BROWSER__) {
2662
exp = dir.exp = processExpression(exp, context)
@@ -57,16 +93,6 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
5793
}
5894
}
5995

60-
if (
61-
!exp ||
62-
(exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())
63-
) {
64-
context.onError(createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc))
65-
return {
66-
props: [createObjectProperty(arg, createSimpleExpression('', true, loc))],
67-
}
68-
}
69-
7096
return {
7197
props: [createObjectProperty(arg, exp)],
7298
}

0 commit comments

Comments
 (0)
Please sign in to comment.