mirror of https://github.com/vuejs/core.git
fix(compiler-vapor): handle same-name shorthand edge case for in-DOM templates
fix https://github.com/vuejs/core/issues/10280
This commit is contained in:
parent
5e52ac9ab4
commit
3957dabb8c
|
@ -183,7 +183,7 @@ export function render(_ctx) {
|
||||||
|
|
||||||
exports[`compiler v-bind > should error if empty expression 1`] = `
|
exports[`compiler v-bind > should error if empty expression 1`] = `
|
||||||
"import { template as _template } from 'vue/vapor';
|
"import { template as _template } from 'vue/vapor';
|
||||||
const t0 = _template("<div arg=\\"\\"></div>")
|
const t0 = _template("<div arg></div>")
|
||||||
|
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
|
|
|
@ -245,11 +245,29 @@ describe('compiler v-bind', () => {
|
||||||
})
|
})
|
||||||
expect(ir.template[0]).toMatchObject({
|
expect(ir.template[0]).toMatchObject({
|
||||||
type: IRNodeTypes.TEMPLATE_FACTORY,
|
type: IRNodeTypes.TEMPLATE_FACTORY,
|
||||||
template: '<div arg=""></div>',
|
template: '<div arg></div>',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).matchSnapshot()
|
expect(code).matchSnapshot()
|
||||||
expect(code).contains(JSON.stringify('<div arg=""></div>'))
|
expect(code).contains(JSON.stringify('<div arg></div>'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('error on invalid argument for same-name shorthand', () => {
|
||||||
|
const onError = vi.fn()
|
||||||
|
compileWithVBind(`<div v-bind:[arg] />`, { onError })
|
||||||
|
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||||
|
code: ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
|
||||||
|
loc: {
|
||||||
|
start: {
|
||||||
|
line: 1,
|
||||||
|
column: 13,
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
line: 1,
|
||||||
|
column: 18,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.camel modifier', () => {
|
test('.camel modifier', () => {
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const transformRef: NodeTransform = (node, context) => {
|
||||||
if (dir.type === NodeTypes.DIRECTIVE) {
|
if (dir.type === NodeTypes.DIRECTIVE) {
|
||||||
value =
|
value =
|
||||||
(dir.exp as SimpleExpressionNode | undefined) ||
|
(dir.exp as SimpleExpressionNode | undefined) ||
|
||||||
normalizeBindShorthand(dir.arg as SimpleExpressionNode)
|
normalizeBindShorthand(dir.arg as SimpleExpressionNode, context)
|
||||||
} else {
|
} else {
|
||||||
value = dir.value ? JSON.stringify(dir.value.content) : '""'
|
value = dir.value ? JSON.stringify(dir.value.content) : '""'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,29 @@
|
||||||
import {
|
import {
|
||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
|
NodeTypes,
|
||||||
type SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
createCompilerError,
|
createCompilerError,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import { camelize, isReservedProp } from '@vue/shared'
|
import { camelize, isReservedProp } from '@vue/shared'
|
||||||
import type { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform, TransformContext } from '../transform'
|
||||||
|
|
||||||
|
// same-name shorthand - :arg is expanded to :arg="arg"
|
||||||
export function normalizeBindShorthand(
|
export function normalizeBindShorthand(
|
||||||
arg: SimpleExpressionNode,
|
arg: SimpleExpressionNode,
|
||||||
|
context: TransformContext,
|
||||||
): SimpleExpressionNode {
|
): SimpleExpressionNode {
|
||||||
// shorthand syntax https://github.com/vuejs/core/pull/9451
|
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {
|
||||||
|
// only simple expression is allowed for same-name shorthand
|
||||||
|
context.options.onError(
|
||||||
|
createCompilerError(
|
||||||
|
ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,
|
||||||
|
arg.loc,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return createSimpleExpression('', true, arg.loc)
|
||||||
|
}
|
||||||
|
|
||||||
const propName = camelize(arg.content)
|
const propName = camelize(arg.content)
|
||||||
const exp = createSimpleExpression(propName, false, arg.loc)
|
const exp = createSimpleExpression(propName, false, arg.loc)
|
||||||
exp.ast = null
|
exp.ast = null
|
||||||
|
@ -18,12 +31,13 @@ export function normalizeBindShorthand(
|
||||||
}
|
}
|
||||||
|
|
||||||
export const transformVBind: DirectiveTransform = (dir, node, context) => {
|
export const transformVBind: DirectiveTransform = (dir, node, context) => {
|
||||||
let { exp, loc, modifiers } = dir
|
const { loc, modifiers } = dir
|
||||||
|
let { exp } = dir
|
||||||
const arg = dir.arg!
|
const arg = dir.arg!
|
||||||
|
|
||||||
if (arg.isStatic && isReservedProp(arg.content)) return
|
if (arg.isStatic && isReservedProp(arg.content)) return
|
||||||
|
|
||||||
if (!exp) exp = normalizeBindShorthand(arg)
|
if (!exp) exp = normalizeBindShorthand(arg, context)
|
||||||
|
|
||||||
let camel = false
|
let camel = false
|
||||||
if (modifiers.includes('camel')) {
|
if (modifiers.includes('camel')) {
|
||||||
|
@ -35,11 +49,15 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exp.content.trim()) {
|
if (!exp.content.trim()) {
|
||||||
context.options.onError(
|
if (!__BROWSER__) {
|
||||||
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
|
// #10280 only error against empty expression in non-browser build
|
||||||
)
|
// because :foo in in-DOM templates will be parsed into :foo="" by the
|
||||||
context.template += ` ${arg.content}=""`
|
// browser
|
||||||
return
|
context.options.onError(
|
||||||
|
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
exp = createSimpleExpression('', true, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in New Issue