feat(compiler-vapor): shorthand & no expression

This commit is contained in:
三咲智子 Kevin Deng 2023-12-07 00:36:42 +08:00
parent 8482bad7af
commit 3d9f0ac614
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
3 changed files with 54 additions and 23 deletions

View File

@ -44,11 +44,39 @@ export function render(_ctx) {
}" }"
`; `;
exports[`compile > directives > v-bind > no expression (shorthand) 1`] = `
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
_setAttr(n1, "camel-case", undefined, _ctx.camelCase)
})
return n0
}"
`;
exports[`compile > directives > v-bind > no expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
_setAttr(n1, "id", undefined, _ctx.id)
})
return n0
}"
`;
exports[`compile > directives > v-bind > should error if no expression 1`] = ` exports[`compile > directives > v-bind > should error if no expression 1`] = `
"import { template as _template } from 'vue/vapor'; "import { template as _template } from 'vue/vapor';
export function render(_ctx) { export function render(_ctx) {
const t0 = _template("<div></div>") const t0 = _template("<div arg=\\"\\"></div>")
const n0 = t0() const n0 = t0()
return n0 return n0
}" }"

View File

@ -71,8 +71,7 @@ describe('compile', () => {
expect(code).matchSnapshot() expect(code).matchSnapshot()
}) })
// TODO: fix this test test('should error if no expression', async () => {
test.fails('should error if no expression', async () => {
const onError = vi.fn() const onError = vi.fn()
const code = await compile(`<div v-bind:arg="" />`, { onError }) const code = await compile(`<div v-bind:arg="" />`, { onError })
@ -92,11 +91,10 @@ describe('compile', () => {
expect(code).matchSnapshot() expect(code).matchSnapshot()
// the arg is static // the arg is static
expect(code).contains(JSON.stringify('<div arg="" ></div>')) expect(code).contains(JSON.stringify('<div arg=""></div>'))
}) })
// TODO: support shorthand syntax for v-bind #9451 test('no expression', async () => {
test.fails('no expression', async () => {
const code = await compile('<div v-bind:id />', { const code = await compile('<div v-bind:id />', {
bindingMetadata: { bindingMetadata: {
id: BindingTypes.SETUP_REF, id: BindingTypes.SETUP_REF,
@ -107,16 +105,17 @@ describe('compile', () => {
expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)') expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
}) })
// TODO: support shorthand syntax for v-bind #9451 test('no expression (shorthand)', async () => {
test.fails('no expression (shorthand)', async () => { const code = await compile('<div :camel-case />', {
const code = await compile('<div :id />', {
bindingMetadata: { bindingMetadata: {
id: BindingTypes.SETUP_REF, camelCase: BindingTypes.SETUP_REF,
}, },
}) })
expect(code).matchSnapshot() expect(code).matchSnapshot()
expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)') expect(code).contains(
'_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
)
}) })
test('dynamic arg', async () => { test('dynamic arg', async () => {

View File

@ -5,8 +5,9 @@ import {
ErrorCodes, ErrorCodes,
createCompilerError, createCompilerError,
ElementTypes, ElementTypes,
createSimpleExpression,
} from '@vue/compiler-dom' } from '@vue/compiler-dom'
import { isBuiltInDirective, isVoidTag } from '@vue/shared' import { camelize, isBuiltInDirective, isVoidTag } from '@vue/shared'
import { NodeTransform, TransformContext } from '../transform' import { NodeTransform, TransformContext } from '../transform'
import { VaporDirectiveNode, IRNodeTypes } from '../ir' import { VaporDirectiveNode, IRNodeTypes } from '../ir'
@ -68,7 +69,7 @@ function transformProp(
return return
} }
const { arg, exp, loc } = prop let { arg, exp, loc } = prop
const directiveTransform = context.options.directiveTransforms[name] const directiveTransform = context.options.directiveTransforms[name]
if (directiveTransform) { if (directiveTransform) {
directiveTransform(prop, node, context) directiveTransform(prop, node, context)
@ -84,19 +85,22 @@ function transformProp(
switch (name) { switch (name) {
case 'bind': { case 'bind': {
if (!exp || !exp.content.trim()) { if (!arg) {
// TODO support v-bind="{}"
return
}
if (!exp) {
// shorthand syntax https://github.com/vuejs/core/pull/9451
const propName = camelize(arg.content)
exp = createSimpleExpression(propName, false, arg.loc)
exp.ast = null
}
if (!exp.content.trim()) {
context.options.onError( context.options.onError(
createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc), createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),
) )
return context.template += ` ${arg.content}=""`
}
if (exp === null) {
// TODO: Vue 3.4 supported shorthand syntax
// https://github.com/vuejs/core/pull/9451
return
} else if (!arg) {
// TODO support v-bind="{}"
return return
} }