// 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) {
}"
`;
-exports[`compiler: codegen v-bind > dynamic arg 1`] = `
-"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
+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, _ctx.id, undefined, _ctx.id)
+ _setAttr(n1, _camelize(_ctx.foo), undefined, _ctx.id)
})
return n0
}"
`;
-exports[`compiler: codegen v-bind > no expression (shorthand) 1`] = `
+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 n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
- _setAttr(n1, "camel-case", undefined, _ctx.camelCase)
+ _setAttr(n1, "fooBar", undefined, _ctx.fooBar)
})
return n0
}"
`;
-exports[`compiler: codegen v-bind > no expression 1`] = `
+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) {
}"
`;
-exports[`compiler: codegen v-bind > should error if no expression 1`] = `
-"import { template as _template } from 'vue/vapor';
+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) {
- const t0 = _template("<div arg=\\"\\"></div>")
+ const t0 = _template("<div></div>")
const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, _ctx.id, undefined, _ctx.id)
+ })
return n0
}"
`;
-exports[`compiler: codegen v-bind > simple expression 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) {
+ const t0 = _template("<div></div>")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, "camel-case", undefined, _ctx.camelCase)
+ })
+ return n0
+}"
+`;
+
+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) {
return n0
}"
`;
+
+exports[`compiler v-bind > should error if empty expression 1`] = `
+"import { template as _template } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("<div arg=\\"\\"></div>")
+ const n0 = t0()
+ return n0
+}"
+`;
-import {
- type RootNode,
- ErrorCodes,
- NodeTypes,
- BindingTypes,
-} from '@vue/compiler-dom'
+import { ErrorCodes, NodeTypes } from '@vue/compiler-dom'
import {
type RootIRNode,
type CompilerOptions,
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,
},
],
})
+
+ 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`,
},
},
})
+
+ 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: {
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: {
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,
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,
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`,
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('.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')
- })
-})