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
|
// 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';
|
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||||
|
|
||||||
export function render(_ctx) {
|
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';
|
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||||
|
|
||||||
export function render(_ctx) {
|
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';
|
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||||
|
|
||||||
export function render(_ctx) {
|
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';
|
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
|
||||||
|
|
||||||
export function render(_ctx) {
|
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';
|
"import { template as _template } from 'vue/vapor';
|
||||||
|
|
||||||
export function render(_ctx) {
|
export function render(_ctx) {
|
||||||
|
@ -65,17 +107,3 @@ export function render(_ctx) {
|
||||||
return n0
|
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 {
|
import { ErrorCodes, NodeTypes } from '@vue/compiler-dom'
|
||||||
type RootNode,
|
|
||||||
ErrorCodes,
|
|
||||||
NodeTypes,
|
|
||||||
BindingTypes,
|
|
||||||
} from '@vue/compiler-dom'
|
|
||||||
import {
|
import {
|
||||||
type RootIRNode,
|
type RootIRNode,
|
||||||
type CompilerOptions,
|
type CompilerOptions,
|
||||||
|
@ -13,48 +8,45 @@ import {
|
||||||
transformElement,
|
transformElement,
|
||||||
IRNodeTypes,
|
IRNodeTypes,
|
||||||
compile as _compile,
|
compile as _compile,
|
||||||
|
generate,
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
|
|
||||||
function parseWithVBind(
|
function compileWithVBind(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {},
|
options: CompilerOptions = {},
|
||||||
): RootIRNode {
|
): {
|
||||||
const ast = parse(template)
|
ir: RootIRNode
|
||||||
|
code: string
|
||||||
|
} {
|
||||||
|
const ast = parse(template, { prefixIdentifiers: true, ...options })
|
||||||
const ir = transform(ast, {
|
const ir = transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformVBind,
|
bind: transformVBind,
|
||||||
},
|
},
|
||||||
...options,
|
|
||||||
})
|
|
||||||
return ir
|
|
||||||
}
|
|
||||||
|
|
||||||
function compile(template: string | RootNode, options: CompilerOptions = {}) {
|
|
||||||
let { code } = _compile(template, {
|
|
||||||
...options,
|
|
||||||
mode: 'module',
|
|
||||||
prefixIdentifiers: true,
|
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', () => {
|
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,
|
id: 1,
|
||||||
referenced: true,
|
referenced: true,
|
||||||
})
|
})
|
||||||
expect(node.template[0]).toMatchObject({
|
expect(ir.template[0]).toMatchObject({
|
||||||
type: IRNodeTypes.TEMPLATE_FACTORY,
|
type: IRNodeTypes.TEMPLATE_FACTORY,
|
||||||
template: '<div></div>',
|
template: '<div></div>',
|
||||||
})
|
})
|
||||||
expect(node.effect).lengthOf(1)
|
expect(ir.effect).lengthOf(1)
|
||||||
expect(node.effect[0].expressions).lengthOf(1)
|
expect(ir.effect[0].expressions).lengthOf(1)
|
||||||
expect(node.effect[0].operations).lengthOf(1)
|
expect(ir.effect[0].operations).lengthOf(1)
|
||||||
expect(node.effect[0]).toMatchObject({
|
expect(ir.effect[0]).toMatchObject({
|
||||||
expressions: [
|
expressions: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
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', () => {
|
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,
|
type: IRNodeTypes.SET_PROP,
|
||||||
key: {
|
key: {
|
||||||
content: `id`,
|
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)', () => {
|
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,
|
type: IRNodeTypes.SET_PROP,
|
||||||
key: {
|
key: {
|
||||||
content: `id`,
|
content: `camel-case`,
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `camelCase`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
expect(code).matchSnapshot()
|
||||||
|
expect(code).contains(
|
||||||
|
'_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('dynamic arg', () => {
|
test('dynamic arg', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
|
const { ir, code } = compileWithVBind(`<div v-bind:[id]="id"/>`)
|
||||||
expect(node.effect[0].operations[0]).toMatchObject({
|
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||||
type: IRNodeTypes.SET_PROP,
|
type: IRNodeTypes.SET_PROP,
|
||||||
element: 1,
|
element: 1,
|
||||||
key: {
|
key: {
|
||||||
|
@ -147,11 +150,17 @@ describe('compiler: transform v-bind', () => {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
expect(code).matchSnapshot()
|
||||||
|
expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should error if empty expression', () => {
|
test('should error if empty expression', () => {
|
||||||
const onError = vi.fn()
|
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({
|
expect(onError.mock.calls[0][0]).toMatchObject({
|
||||||
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
|
code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
|
||||||
loc: {
|
loc: {
|
||||||
|
@ -159,15 +168,19 @@ describe('compiler: transform v-bind', () => {
|
||||||
end: { line: 1, column: 19 },
|
end: { line: 1, column: 19 },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(node.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).contains(JSON.stringify('<div arg=""></div>'))
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.camel modifier', () => {
|
test('.camel modifier', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
|
const { ir, code } = compileWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
|
||||||
expect(node.effect[0].operations[0]).toMatchObject({
|
|
||||||
|
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
|
@ -177,11 +190,15 @@ describe('compiler: transform v-bind', () => {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
expect(code).matchSnapshot()
|
||||||
|
expect(code).contains('_setAttr(n1, "fooBar", undefined, _ctx.id)')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.camel modifier w/ no expression', () => {
|
test('.camel modifier w/ no expression', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
|
const { ir, code } = compileWithVBind(`<div v-bind:foo-bar.camel />`)
|
||||||
expect(node.effect[0].operations[0]).toMatchObject({
|
|
||||||
|
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
|
@ -191,11 +208,16 @@ describe('compiler: transform v-bind', () => {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
expect(code).matchSnapshot()
|
||||||
|
expect(code).contains('effect')
|
||||||
|
expect(code).contains('_setAttr(n1, "fooBar", undefined, _ctx.fooBar)')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.camel modifier w/ dynamic arg', () => {
|
test('.camel modifier w/ dynamic arg', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
|
const { ir, code } = compileWithVBind(`<div v-bind:[foo].camel="id"/>`)
|
||||||
expect(node.effect[0].operations[0]).toMatchObject({
|
|
||||||
|
expect(ir.effect[0].operations[0]).toMatchObject({
|
||||||
runtimeCamelize: true,
|
runtimeCamelize: true,
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
|
@ -206,6 +228,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
isStatic: false,
|
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')
|
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')
|
||||||
test.todo('.attr modifier w/ no expression')
|
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