mirror of https://github.com/vuejs/core.git
test: add transform test
This commit is contained in:
parent
e3b21b25b1
commit
5f769745fa
|
@ -1,6 +1,6 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`v-bind > .camel modifier 1`] = `
|
||||
exports[`compiler: codegen 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,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`v-bind > dynamic arg 1`] = `
|
||||
exports[`compiler: codegen 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 +28,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`v-bind > no expression (shorthand) 1`] = `
|
||||
exports[`compiler: codegen 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 +42,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`v-bind > no expression 1`] = `
|
||||
exports[`compiler: codegen 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 +56,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`v-bind > should error if no expression 1`] = `
|
||||
exports[`compiler: codegen v-bind > should error if no expression 1`] = `
|
||||
"import { template as _template } from 'vue/vapor';
|
||||
|
||||
export function render(_ctx) {
|
||||
|
@ -66,7 +66,7 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`v-bind > simple expression 1`] = `
|
||||
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) {
|
||||
|
|
|
@ -1,5 +1,34 @@
|
|||
import { type RootNode, BindingTypes, ErrorCodes } from '@vue/compiler-dom'
|
||||
import { type CompilerOptions, compile as _compile } from '../../src'
|
||||
import {
|
||||
type RootNode,
|
||||
ErrorCodes,
|
||||
NodeTypes,
|
||||
BindingTypes,
|
||||
} from '@vue/compiler-dom'
|
||||
import {
|
||||
type RootIRNode,
|
||||
type CompilerOptions,
|
||||
parse,
|
||||
transform,
|
||||
transformVBind,
|
||||
transformElement,
|
||||
IRNodeTypes,
|
||||
compile as _compile,
|
||||
} from '../../src'
|
||||
|
||||
function parseWithVBind(
|
||||
template: string,
|
||||
options: CompilerOptions = {},
|
||||
): RootIRNode {
|
||||
const ast = parse(template)
|
||||
const ir = transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
bind: transformVBind,
|
||||
},
|
||||
...options,
|
||||
})
|
||||
return ir
|
||||
}
|
||||
|
||||
function compile(template: string | RootNode, options: CompilerOptions = {}) {
|
||||
let { code } = _compile(template, {
|
||||
|
@ -10,7 +39,189 @@ function compile(template: string | RootNode, options: CompilerOptions = {}) {
|
|||
return code
|
||||
}
|
||||
|
||||
describe('v-bind', () => {
|
||||
describe('compiler: transform v-bind', () => {
|
||||
test('basic', () => {
|
||||
const node = parseWithVBind(`<div v-bind:id="id"/>`)
|
||||
|
||||
expect(node.dynamic.children[0]).toMatchObject({
|
||||
id: 1,
|
||||
referenced: true,
|
||||
})
|
||||
expect(node.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({
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'id',
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
operations: [
|
||||
{
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
element: 1,
|
||||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'id',
|
||||
isStatic: true,
|
||||
loc: {
|
||||
start: { line: 1, column: 13, offset: 12 },
|
||||
end: { line: 1, column: 15, offset: 14 },
|
||||
source: 'id',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'id',
|
||||
isStatic: false,
|
||||
loc: {
|
||||
source: 'id',
|
||||
start: { line: 1, column: 17, offset: 16 },
|
||||
end: { line: 1, column: 19, offset: 18 },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('no expression', () => {
|
||||
const node = parseWithVBind(`<div v-bind:id />`)
|
||||
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
key: {
|
||||
content: `id`,
|
||||
isStatic: true,
|
||||
loc: {
|
||||
start: { line: 1, column: 13, offset: 12 },
|
||||
end: { line: 1, column: 15, offset: 14 },
|
||||
},
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false,
|
||||
loc: {
|
||||
start: { line: 1, column: 13, offset: 12 },
|
||||
end: { line: 1, column: 15, offset: 14 },
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('no expression (shorthand)', () => {
|
||||
const node = parseWithVBind(`<div :id />`)
|
||||
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
key: {
|
||||
content: `id`,
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('dynamic arg', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[id]="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
element: 1,
|
||||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'id',
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'id',
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('should error if empty expression', () => {
|
||||
const onError = vi.fn()
|
||||
const node = parseWithVBind(`<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(node.template[0]).toMatchObject({
|
||||
type: IRNodeTypes.TEMPLATE_FACTORY,
|
||||
template: '<div arg=""></div>',
|
||||
})
|
||||
})
|
||||
|
||||
test.fails('.camel modifier', () => {
|
||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test.fails('.camel modifier w/ no expression', () => {
|
||||
const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `fooBar`,
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test.fails('.camel modifier w/ dynamic arg', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
|
||||
expect(node.effect[0].operations[0]).toMatchObject({
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: false,
|
||||
somethingShouldBeTrue: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test.todo('.camel modifier w/ dynamic arg + prefixIdentifiers')
|
||||
|
||||
test.todo('.prop modifier')
|
||||
test.todo('.prop modifier w/ no expression')
|
||||
test.todo('.prop modifier w/ dynamic arg')
|
||||
test.todo('.prop modifier w/ dynamic arg + prefixIdentifiers')
|
||||
test.todo('.prop modifier (shorthand)')
|
||||
test.todo('.prop modifier (shortband) w/ no expression')
|
||||
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: {
|
||||
|
|
|
@ -372,7 +372,7 @@ function genOperation(oper: OperationNode, context: CodegenContext) {
|
|||
function genSetProp(oper: SetPropIRNode, context: CodegenContext) {
|
||||
const { push, pushWithNewline, vaporHelper } = context
|
||||
pushWithNewline(`${vaporHelper('setAttr')}(n${oper.element}, `)
|
||||
genExpression(oper.name, context)
|
||||
genExpression(oper.key, context)
|
||||
push(`, undefined, `)
|
||||
genExpression(oper.value, context)
|
||||
push(')')
|
||||
|
@ -437,7 +437,7 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
|
|||
|
||||
pushWithNewline(`${vaporHelper('on')}(n${oper.element}, `)
|
||||
// second arg: event name
|
||||
genExpression(oper.name, context)
|
||||
genExpression(oper.key, context)
|
||||
push(', ')
|
||||
|
||||
const { keys, nonKeys, options } = oper.modifiers
|
||||
|
|
|
@ -4,3 +4,11 @@ export { generate } from './generate'
|
|||
export { compile, type CompilerOptions } from './compile'
|
||||
export * from './ir'
|
||||
export * from './errors'
|
||||
export { transformElement } from './transforms/transformElement'
|
||||
export { transformInterpolation } from './transforms/transformInterpolation'
|
||||
export { transformVBind } from './transforms/vBind'
|
||||
export { transformVHtml } from './transforms/vHtml'
|
||||
export { transformVOn } from './transforms/vOn'
|
||||
export { transformOnce } from './transforms/vOnce'
|
||||
export { transformVShow } from './transforms/vShow'
|
||||
export { transformVText } from './transforms/vText'
|
||||
|
|
|
@ -58,7 +58,7 @@ export interface FragmentFactoryIRNode extends BaseIRNode {
|
|||
export interface SetPropIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.SET_PROP
|
||||
element: number
|
||||
name: IRExpression
|
||||
key: IRExpression
|
||||
value: IRExpression
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ export interface SetTextIRNode extends BaseIRNode {
|
|||
export interface SetEventIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.SET_EVENT
|
||||
element: number
|
||||
name: IRExpression
|
||||
key: IRExpression
|
||||
value: IRExpression
|
||||
modifiers: {
|
||||
// modifiers for addEventListener() options, e.g. .passive & .capture
|
||||
|
|
|
@ -36,7 +36,7 @@ export const transformVBind: DirectiveTransform = (dir, node, context) => {
|
|||
type: IRNodeTypes.SET_PROP,
|
||||
loc: dir.loc,
|
||||
element: context.reference(),
|
||||
name: arg,
|
||||
key: arg,
|
||||
value: exp,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -45,7 +45,7 @@ export const transformVOn: DirectiveTransform = (dir, node, context) => {
|
|||
type: IRNodeTypes.SET_EVENT,
|
||||
loc,
|
||||
element: context.reference(),
|
||||
name: createSimpleExpression(name, true, arg.loc),
|
||||
key: createSimpleExpression(name, true, arg.loc),
|
||||
value: exp,
|
||||
modifiers: {
|
||||
keys: keyModifiers,
|
||||
|
|
Loading…
Reference in New Issue