mirror of https://github.com/vuejs/core.git
test: combine with transform and codegen tests for `v-bind` (#45)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
12250a85b9
commit
b421aa91a2
|
@ -1,6 +1,6 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`compiler: codegen v-bind > .camel modifier 1`] = `
|
||||
exports[`compiler v-bind > .camel modifier 1`] = `
|
||||
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||
|
||||
export function render(_ctx) {
|
||||
|
@ -14,7 +14,49 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen v-bind > dynamic arg 1`] = `
|
||||
exports[`compiler v-bind > .camel modifier w/ dynamic arg 1`] = `
|
||||
"import { camelize as _camelize } from 'vue';
|
||||
|
||||
export function render(_ctx) {
|
||||
const t0 = _template("<div></div>")
|
||||
const n0 = t0()
|
||||
const { 0: [n1],} = _children(n0)
|
||||
_effect(() => {
|
||||
_setAttr(n1, _camelize(_ctx.foo), undefined, _ctx.id)
|
||||
})
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler v-bind > .camel modifier w/ 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, "fooBar", undefined, _ctx.fooBar)
|
||||
})
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler v-bind > basic 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[`compiler v-bind > dynamic arg 1`] = `
|
||||
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||
|
||||
export function render(_ctx) {
|
||||
|
@ -28,7 +70,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen v-bind > no expression (shorthand) 1`] = `
|
||||
exports[`compiler 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) {
|
||||
|
@ -42,7 +84,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen v-bind > no expression 1`] = `
|
||||
exports[`compiler 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) {
|
||||
|
@ -56,7 +98,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen v-bind > should error if no expression 1`] = `
|
||||
exports[`compiler v-bind > should error if empty expression 1`] = `
|
||||
"import { template as _template } from 'vue/vapor';
|
||||
|
||||
export function render(_ctx) {
|
||||
|
@ -65,17 +107,3 @@ export function render(_ctx) {
|
|||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen v-bind > simple 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
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
import {
|
||||
type RootNode,
|
||||
ErrorCodes,
|
||||
NodeTypes,
|
||||
BindingTypes,
|
||||
} from '@vue/compiler-dom'
|
||||
import { ErrorCodes, NodeTypes } from '@vue/compiler-dom'
|
||||
import {
|
||||
type RootIRNode,
|
||||
type CompilerOptions,
|
||||
|
@ -13,48 +8,45 @@ import {
|
|||
transformElement,
|
||||
IRNodeTypes,
|
||||
compile as _compile,
|
||||
generate,
|
||||
} from '../../src'
|
||||
|
||||
function parseWithVBind(
|
||||
function compileWithVBind(
|
||||
template: string,
|
||||
options: CompilerOptions = {},
|
||||
): RootIRNode {
|
||||
const ast = parse(template)
|
||||
): {
|
||||
ir: RootIRNode
|
||||
code: string
|
||||
} {
|
||||
const ast = parse(template, { prefixIdentifiers: true, ...options })
|
||||
const ir = transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
bind: transformVBind,
|
||||
},
|
||||
...options,
|
||||
})
|
||||
return ir
|
||||
}
|
||||
|
||||
function compile(template: string | RootNode, options: CompilerOptions = {}) {
|
||||
let { code } = _compile(template, {
|
||||
...options,
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true,
|
||||
...options,
|
||||
})
|
||||
return code
|
||||
const { code } = generate(ir, { prefixIdentifiers: true, ...options })
|
||||
return { ir, code }
|
||||
}
|
||||
|
||||
describe('compiler: transform v-bind', () => {
|
||||
describe('compiler v-bind', () => {
|
||||
test('basic', () => {
|
||||
const node = parseWithVBind(`<div v-bind:id="id"/>`)
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:id="id"/>`)
|
||||
|
||||
expect(node.dynamic.children[0]).toMatchObject({
|
||||
expect(ir.dynamic.children[0]).toMatchObject({
|
||||
id: 1,
|
||||
referenced: true,
|
||||
})
|
||||
expect(node.template[0]).toMatchObject({
|
||||
expect(ir.template[0]).toMatchObject({
|
||||
type: IRNodeTypes.TEMPLATE_FACTORY,
|
||||
template: '<div></div>',
|
||||
})
|
||||
expect(node.effect).lengthOf(1)
|
||||
expect(node.effect[0].expressions).lengthOf(1)
|
||||
expect(node.effect[0].operations).lengthOf(1)
|
||||
expect(node.effect[0]).toMatchObject({
|
||||
expect(ir.effect).lengthOf(1)
|
||||
expect(ir.effect[0].expressions).lengthOf(1)
|
||||
expect(ir.effect[0].operations).lengthOf(1)
|
||||
expect(ir.effect[0]).toMatchObject({
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
|
@ -89,12 +81,15 @@ describe('compiler: transform v-bind', () => {
|
|||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('no expression', () => {
|
||||
const node = parseWithVBind(`<div v-bind:id />`)
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:id />`)
|
||||
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
key: {
|
||||
content: `id`,
|
||||
|
@ -113,27 +108,35 @@ describe('compiler: transform v-bind', () => {
|
|||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('no expression (shorthand)', () => {
|
||||
const node = parseWithVBind(`<div :id />`)
|
||||
const { ir, code } = compileWithVBind(`<div :camel-case />`)
|
||||
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
key: {
|
||||
content: `id`,
|
||||
content: `camel-case`,
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
content: `camelCase`,
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains(
|
||||
'_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
|
||||
)
|
||||
})
|
||||
|
||||
test('dynamic arg', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:[id]="id"/>`)
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
element: 1,
|
||||
key: {
|
||||
|
@ -147,11 +150,17 @@ describe('compiler: transform v-bind', () => {
|
|||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('should error if empty expression', () => {
|
||||
const onError = vi.fn()
|
||||
const node = parseWithVBind(`<div v-bind:arg="" />`, { onError })
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:arg="" />`, {
|
||||
onError,
|
||||
})
|
||||
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
|
||||
loc: {
|
||||
|
@ -159,15 +168,19 @@ describe('compiler: transform v-bind', () => {
|
|||
end: { line: 1, column: 19 },
|
||||
},
|
||||
})
|
||||
expect(node.template[0]).toMatchObject({
|
||||
expect(ir.template[0]).toMatchObject({
|
||||
type: IRNodeTypes.TEMPLATE_FACTORY,
|
||||
template: '<div arg=""></div>',
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains(JSON.stringify('<div arg=""></div>'))
|
||||
})
|
||||
|
||||
test('.camel modifier', () => {
|
||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
|
||||
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true,
|
||||
|
@ -177,11 +190,15 @@ describe('compiler: transform v-bind', () => {
|
|||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, "fooBar", undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('.camel modifier w/ no expression', () => {
|
||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:foo-bar.camel />`)
|
||||
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true,
|
||||
|
@ -191,11 +208,16 @@ describe('compiler: transform v-bind', () => {
|
|||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('effect')
|
||||
expect(code).contains('_setAttr(n1, "fooBar", undefined, _ctx.fooBar)')
|
||||
})
|
||||
|
||||
test('.camel modifier w/ dynamic arg', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
const { ir, code } = compileWithVBind(`<div v-bind:[foo].camel="id"/>`)
|
||||
|
||||
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||
runtimeCamelize: true,
|
||||
key: {
|
||||
content: `foo`,
|
||||
|
@ -206,6 +228,12 @@ describe('compiler: transform v-bind', () => {
|
|||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('effect')
|
||||
expect(code).contains(
|
||||
`_setAttr(n1, _camelize(_ctx.foo), undefined, _ctx.id)`,
|
||||
)
|
||||
})
|
||||
|
||||
test.todo('.camel modifier w/ dynamic arg + prefixIdentifiers')
|
||||
|
@ -219,80 +247,3 @@ describe('compiler: transform v-bind', () => {
|
|||
test.todo('.attr modifier')
|
||||
test.todo('.attr modifier w/ no expression')
|
||||
})
|
||||
|
||||
// TODO: combine with above
|
||||
describe('compiler: codegen v-bind', () => {
|
||||
test('simple expression', () => {
|
||||
const code = compile(`<div :id="id"></div>`, {
|
||||
bindingMetadata: {
|
||||
id: BindingTypes.SETUP_REF,
|
||||
},
|
||||
})
|
||||
expect(code).matchSnapshot()
|
||||
})
|
||||
|
||||
test('should error if no expression', () => {
|
||||
const onError = vi.fn()
|
||||
const code = compile(`<div v-bind:arg="" />`, { onError })
|
||||
|
||||
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 6,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 19,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
// the arg is static
|
||||
expect(code).contains(JSON.stringify('<div arg=""></div>'))
|
||||
})
|
||||
|
||||
test('no expression', () => {
|
||||
const code = compile('<div v-bind:id />', {
|
||||
bindingMetadata: {
|
||||
id: BindingTypes.SETUP_REF,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('no expression (shorthand)', () => {
|
||||
const code = compile('<div :camel-case />', {
|
||||
bindingMetadata: {
|
||||
camelCase: BindingTypes.SETUP_REF,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains(
|
||||
'_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
|
||||
)
|
||||
})
|
||||
|
||||
test('dynamic arg', () => {
|
||||
const code = compile('<div v-bind:[id]="id"/>', {
|
||||
bindingMetadata: {
|
||||
id: BindingTypes.SETUP_REF,
|
||||
},
|
||||
})
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
|
||||
})
|
||||
|
||||
test('.camel modifier', () => {
|
||||
const code = compile(`<div v-bind:foo-bar.camel="id"/>`)
|
||||
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('fooBar')
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue