Skip to content

Commit

Permalink
fix(compiler-vapor): handle same-name shorthand edge case for in-DOM …
Browse files Browse the repository at this point in the history
…templates

fix vuejs/core#10280
  • Loading branch information
sxzz committed Feb 7, 2024
1 parent 5e52ac9 commit b37912e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export function render(_ctx) {
exports[`compiler v-bind > should error if empty expression 1`] = `
"import { template as _template } from 'vue/vapor';
const t0 = _template("<div arg=\\"\\"></div>")
const t0 = _template("<div arg></div>")
export function render(_ctx) {
const n0 = t0()
Expand Down
22 changes: 20 additions & 2 deletions packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,29 @@ describe('compiler v-bind', () => {
})
expect(ir.template[0]).toMatchObject({
type: IRNodeTypes.TEMPLATE_FACTORY,
template: '<div arg=""></div>',
template: '<div arg></div>',
})

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', () => {
Expand Down
36 changes: 27 additions & 9 deletions packages/compiler-vapor/src/transforms/vBind.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
import {
ErrorCodes,
NodeTypes,
type SimpleExpressionNode,
createCompilerError,
createSimpleExpression,
} from '@vue/compiler-dom'
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(
arg: SimpleExpressionNode,
context: TransformContext,
): 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 exp = createSimpleExpression(propName, false, arg.loc)
exp.ast = null
return exp
}

export const transformVBind: DirectiveTransform = (dir, node, context) => {
let { exp, loc, modifiers } = dir
const { loc, modifiers } = dir
let { exp } = dir
const arg = dir.arg!

if (arg.isStatic && isReservedProp(arg.content)) return

if (!exp) exp = normalizeBindShorthand(arg)
if (!exp) exp = normalizeBindShorthand(arg, context)

let camel = false
if (modifiers.includes('camel')) {
Expand All @@ -35,11 +49,15 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
}

if (!exp.content.trim()) {
context.options.onError(
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
)
context.template += ` ${arg.content}=""`
return
if (!__BROWSER__) {
// #10280 only error against empty expression in non-browser build
// because :foo in in-DOM templates will be parsed into :foo="" by the
// browser
context.options.onError(
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
)
}
exp = createSimpleExpression('', true, loc)
}

return {
Expand Down

0 comments on commit b37912e

Please sign in to comment.