diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
similarity index 50%
rename from packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap
rename to packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
index 5e3b020fa..02c09554e 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
@@ -100,86 +100,6 @@ export function render(_ctx) {
}"
`;
-exports[`compile > directives > 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) {
- const t0 = _template("
")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setAttr(n1, "foo-bar", undefined, _ctx.id)
- })
- return n0
-}"
-`;
-
-exports[`compile > directives > 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("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setAttr(n1, _ctx.id, undefined, _ctx.id)
- })
- return n0
-}"
-`;
-
-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("")
- 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("")
- 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`] = `
-"import { template as _template } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- return n0
-}"
-`;
-
-exports[`compile > directives > 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("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setAttr(n1, "id", undefined, _ctx.id)
- })
- return n0
-}"
-`;
-
exports[`compile > directives > v-cloak > basic 1`] = `
"import { template as _template } from 'vue/vapor';
@@ -190,118 +110,6 @@ export function render(_ctx) {
}"
`;
-exports[`compile > directives > v-html > should raise error and ignore children when v-html is present 1`] = `
-"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setHtml(n1, undefined, _ctx.test)
- })
- return n0
-}"
-`;
-
-exports[`compile > directives > v-html > should raise error if has no expression 1`] = `
-"import { template as _template, children as _children, setHtml as _setHtml } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _setHtml(n1, undefined, "")
- return n0
-}"
-`;
-
-exports[`compile > directives > v-html > simple expression 1`] = `
-"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setHtml(n1, undefined, _ctx.code)
- })
- return n0
-}"
-`;
-
-exports[`compile > directives > v-on > event modifier 1`] = `
-"import { template as _template, children as _children, on as _on, withModifiers as _withModifiers, withKeys as _withKeys } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1], 1: [n2], 2: [n3], 3: [n4], 4: [n5], 5: [n6], 6: [n7], 7: [n8], 8: [n9], 9: [n10], 10: [n11], 11: [n12], 12: [n13], 13: [n14], 14: [n15], 15: [n16], 16: [n17], 17: [n18], 18: [n19], 19: [n20], 20: [n21], 21: [n22],} = _children(n0)
- _on(n1, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop"]))
- _on(n2, "submit", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["prevent"]))
- _on(n3, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop", "prevent"]))
- _on(n4, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"]))
- _on(n5, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { capture: true })
- _on(n6, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { once: true })
- _on(n7, "scroll", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { passive: true })
- _on(n8, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"]))
- _on(n9, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"]))
- _on(n10, "mouseup", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["middle"]))
- _on(n11, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"]))
- _on(n12, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["enter"]))
- _on(n13, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["tab"]))
- _on(n14, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["delete"]))
- _on(n15, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["esc"]))
- _on(n16, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["space"]))
- _on(n17, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["up"]))
- _on(n18, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["down"]))
- _on(n19, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"]))
- _on(n20, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle"]))
- _on(n21, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle", "self"]))
- _on(n22, "keyup", _withKeys(_withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"]), ["enter"]))
- return n0
-}"
-`;
-
-exports[`compile > directives > v-on > simple expression 1`] = `
-"import { template as _template, children as _children, on as _on } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _on(n1, "click", (...args) => (_ctx.handleClick && _ctx.handleClick(...args)))
- return n0
-}"
-`;
-
-exports[`compile > directives > v-once > as root node 1`] = `
-"import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _setAttr(n1, "id", undefined, _ctx.foo)
- return n0
-}"
-`;
-
-exports[`compile > directives > v-once > basic 1`] = `
-"import { template as _template, children as _children, createTextNode as _createTextNode, setText as _setText, setAttr as _setAttr, prepend as _prepend } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("
")
- const n0 = t0()
- const { 0: [n3, { 1: [n2],}],} = _children(n0)
- const n1 = _createTextNode(_ctx.msg)
- _setText(n1, undefined, _ctx.msg)
- _setAttr(n2, "class", undefined, _ctx.clz)
- _prepend(n3, n1)
- return n0
-}"
-`;
-
exports[`compile > directives > v-pre > basic 1`] = `
"import { template as _template } from 'vue/vapor';
@@ -350,32 +158,6 @@ export function render(_ctx) {
}"
`;
-exports[`compile > directives > v-text > no expression 1`] = `
-"import { template as _template, children as _children, setText as _setText } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _setText(n1, undefined, "")
- return n0
-}"
-`;
-
-exports[`compile > directives > v-text > simple expression 1`] = `
-"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
-
-export function render(_ctx) {
- const t0 = _template("")
- const n0 = t0()
- const { 0: [n1],} = _children(n0)
- _effect(() => {
- _setText(n1, undefined, _ctx.str)
- })
- return n0
-}"
-`;
-
exports[`compile > dynamic root 1`] = `
"import { fragment as _fragment, createTextNode as _createTextNode, append as _append, effect as _effect, setText as _setText } from 'vue/vapor';
diff --git a/packages/compiler-vapor/__tests__/compile.spec.ts b/packages/compiler-vapor/__tests__/compile.spec.ts
new file mode 100644
index 000000000..3c7cf9562
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/compile.spec.ts
@@ -0,0 +1,210 @@
+import { type RootNode, BindingTypes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('compile', () => {
+ test('static template', () => {
+ const code = compile(
+ ``,
+ )
+ expect(code).matchSnapshot()
+ })
+
+ test('dynamic root', () => {
+ const code = compile(`{{ 1 }}{{ 2 }}`)
+ expect(code).matchSnapshot()
+ })
+
+ test('dynamic root nodes and interpolation', () => {
+ const code = compile(
+ ``,
+ )
+ expect(code).matchSnapshot()
+ })
+
+ test('static + dynamic root', () => {
+ const code = compile(
+ `{{ 1 }}{{ 2 }}3{{ 4 }}{{ 5 }}6{{ 7 }}{{ 8 }}9{{ 'A' }}{{ 'B' }}`,
+ )
+ expect(code).matchSnapshot()
+ })
+
+ test('fragment', () => {
+ const code = compile(``)
+ expect(code).matchSnapshot()
+ })
+
+ test('bindings', () => {
+ const code = compile(`count is {{ count }}.
`, {
+ bindingMetadata: {
+ count: BindingTypes.SETUP_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ describe('directives', () => {
+ describe('v-pre', () => {
+ test('basic', () => {
+ const code = compile(`{{ bar }}
\n`, {
+ bindingMetadata: {
+ foo: BindingTypes.SETUP_REF,
+ bar: BindingTypes.SETUP_REF,
+ },
+ })
+
+ expect(code).toMatchSnapshot()
+ expect(code).contains(
+ JSON.stringify('{{ bar }}
'),
+ )
+ expect(code).not.contains('effect')
+ })
+
+ // TODO: support multiple root nodes and components
+ test('should not affect siblings after it', () => {
+ const code = compile(
+ `{{ bar }}
\n` +
+ `{{ bar }}
`,
+ {
+ bindingMetadata: {
+ foo: BindingTypes.SETUP_REF,
+ bar: BindingTypes.SETUP_REF,
+ },
+ },
+ )
+
+ expect(code).toMatchSnapshot()
+ // Waiting for TODO, There should be more here.
+ })
+
+ // TODO: support multiple root nodes and components
+ test('self-closing v-pre', () => {
+ const code = compile(
+ `\n{{ bar }}
`,
+ )
+
+ expect(code).toMatchSnapshot()
+ expect(code).contains('
')
+ // Waiting for TODO, There should be more here.
+ })
+ })
+
+ describe('v-cloak', () => {
+ test('basic', () => {
+ const code = compile(`test
`)
+ expect(code).toMatchSnapshot()
+ expect(code).not.contains('v-cloak')
+ })
+ })
+
+ describe('custom directive', () => {
+ test('basic', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('binding value', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ msg: BindingTypes.SETUP_REF,
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('static parameters', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ msg: BindingTypes.SETUP_REF,
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('modifiers', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ msg: BindingTypes.SETUP_REF,
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('modifiers w/o binding', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('static parameters and modifiers', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ msg: BindingTypes.SETUP_REF,
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('dynamic parameters', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ foo: BindingTypes.SETUP_REF,
+ vExample: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+ })
+ })
+
+ describe('expression parsing', () => {
+ test('interpolation', () => {
+ const code = compile(`{{ a + b }}`, {
+ inline: true,
+ bindingMetadata: {
+ b: BindingTypes.SETUP_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ expect(code).contains('a + b.value')
+ })
+
+ test('v-bind', () => {
+ const code = compile(``, {
+ inline: true,
+ bindingMetadata: {
+ key: BindingTypes.SETUP_REF,
+ foo: BindingTypes.SETUP_MAYBE_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ expect(code).contains('key.value+1')
+ expect(code).contains('_unref(foo)[key.value+1]()')
+ })
+
+ // TODO: add more test for expression parsing (v-on, v-slot, v-for)
+ })
+})
diff --git a/packages/compiler-vapor/__tests__/compile.test.ts b/packages/compiler-vapor/__tests__/compile.test.ts
deleted file mode 100644
index 95f74715e..000000000
--- a/packages/compiler-vapor/__tests__/compile.test.ts
+++ /dev/null
@@ -1,434 +0,0 @@
-import {
- type RootNode,
- BindingTypes,
- ErrorCodes,
- DOMErrorCodes,
-} from '@vue/compiler-dom'
-import { type CompilerOptions, compile as _compile } from '../src'
-
-function compile(template: string | RootNode, options: CompilerOptions = {}) {
- let { code } = _compile(template, {
- ...options,
- mode: 'module',
- prefixIdentifiers: true,
- })
- return code
-}
-
-describe('compile', () => {
- test('static template', async () => {
- const code = await compile(
- ``,
- )
- expect(code).matchSnapshot()
- })
-
- test('dynamic root', async () => {
- const code = await compile(`{{ 1 }}{{ 2 }}`)
- expect(code).matchSnapshot()
- })
-
- test('dynamic root nodes and interpolation', async () => {
- const code = await compile(
- ``,
- )
- expect(code).matchSnapshot()
- })
-
- test('static + dynamic root', async () => {
- const code = await compile(
- `{{ 1 }}{{ 2 }}3{{ 4 }}{{ 5 }}6{{ 7 }}{{ 8 }}9{{ 'A' }}{{ 'B' }}`,
- )
- expect(code).matchSnapshot()
- })
-
- test('fragment', async () => {
- const code = await compile(``)
- expect(code).matchSnapshot()
- })
-
- test('bindings', async () => {
- const code = await compile(`count is {{ count }}.
`, {
- bindingMetadata: {
- count: BindingTypes.SETUP_REF,
- },
- })
- expect(code).matchSnapshot()
- })
-
- describe('directives', () => {
- describe('v-bind', () => {
- test('simple expression', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- id: BindingTypes.SETUP_REF,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('should error if no expression', async () => {
- const onError = vi.fn()
- const code = await compile(``, { 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(''))
- })
-
- test('no expression', async () => {
- const code = await compile('', {
- bindingMetadata: {
- id: BindingTypes.SETUP_REF,
- },
- })
-
- expect(code).matchSnapshot()
- expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
- })
-
- test('no expression (shorthand)', async () => {
- const code = await compile('', {
- bindingMetadata: {
- camelCase: BindingTypes.SETUP_REF,
- },
- })
-
- expect(code).matchSnapshot()
- expect(code).contains(
- '_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
- )
- })
-
- test('dynamic arg', async () => {
- const code = await compile('', {
- bindingMetadata: {
- id: BindingTypes.SETUP_REF,
- },
- })
-
- expect(code).matchSnapshot()
- expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
- })
-
- // TODO: camel modifier for v-bind
- test.fails('.camel modifier', async () => {
- const code = await compile(``)
-
- expect(code).matchSnapshot()
- expect(code).contains('fooBar')
- })
- })
-
- describe('v-on', () => {
- test('simple expression', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- handleClick: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('should error if no expression AND no modifier', async () => {
- const onError = vi.fn()
- await compile(``, { onError })
- expect(onError.mock.calls[0][0]).toMatchObject({
- code: ErrorCodes.X_V_ON_NO_EXPRESSION,
- loc: {
- start: {
- line: 1,
- column: 6,
- },
- end: {
- line: 1,
- column: 16,
- },
- },
- })
- })
-
- test('event modifier', async () => {
- const code = await compile(
- `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `,
- {
- bindingMetadata: {
- handleEvent: BindingTypes.SETUP_CONST,
- },
- },
- )
- expect(code).matchSnapshot()
- })
- })
-
- describe('v-html', () => {
- test('simple expression', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- code: BindingTypes.SETUP_REF,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('should raise error and ignore children when v-html is present', async () => {
- const onError = vi.fn()
- const code = await compile(`hello
`, {
- onError,
- })
- expect(code).matchSnapshot()
- expect(onError.mock.calls).toMatchObject([
- [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],
- ])
- })
-
- test('should raise error if has no expression', async () => {
- const onError = vi.fn()
- const code = await compile(``, {
- onError,
- })
- expect(code).matchSnapshot()
- expect(onError.mock.calls).toMatchObject([
- [{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],
- ])
- })
- })
-
- describe('v-text', () => {
- test('simple expression', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- str: BindingTypes.SETUP_REF,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('no expression', async () => {
- const onError = vi.fn()
- const code = await compile(``, { onError })
- expect(code).matchSnapshot()
- expect(onError.mock.calls).toMatchObject([
- [{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],
- ])
- })
- })
-
- describe('v-once', () => {
- test('basic', async () => {
- const code = await compile(
- `
- {{ msg }}
-
-
`,
- {
- bindingMetadata: {
- msg: BindingTypes.SETUP_REF,
- clz: BindingTypes.SETUP_REF,
- },
- },
- )
- expect(code).matchSnapshot()
- })
-
- test('as root node', async () => {
- const code = await compile(``)
- expect(code).toMatchSnapshot()
- expect(code).not.contains('effect')
- })
- })
-
- describe('v-pre', () => {
- test('basic', async () => {
- const code = await compile(
- `{{ bar }}
\n`,
- {
- bindingMetadata: {
- foo: BindingTypes.SETUP_REF,
- bar: BindingTypes.SETUP_REF,
- },
- },
- )
-
- expect(code).toMatchSnapshot()
- expect(code).contains(
- JSON.stringify('{{ bar }}
'),
- )
- expect(code).not.contains('effect')
- })
-
- // TODO: support multiple root nodes and components
- test('should not affect siblings after it', async () => {
- const code = await compile(
- `{{ bar }}
\n` +
- `{{ bar }}
`,
- {
- bindingMetadata: {
- foo: BindingTypes.SETUP_REF,
- bar: BindingTypes.SETUP_REF,
- },
- },
- )
-
- expect(code).toMatchSnapshot()
- // Waiting for TODO, There should be more here.
- })
-
- // TODO: support multiple root nodes and components
- test('self-closing v-pre', async () => {
- const code = await compile(
- `\n{{ bar }}
`,
- )
-
- expect(code).toMatchSnapshot()
- expect(code).contains('
')
- // Waiting for TODO, There should be more here.
- })
- })
-
- describe('v-cloak', () => {
- test('basic', async () => {
- const code = await compile(`test
`)
- expect(code).toMatchSnapshot()
- expect(code).not.contains('v-cloak')
- })
- })
-
- describe('custom directive', () => {
- test('basic', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('binding value', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- msg: BindingTypes.SETUP_REF,
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('static parameters', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- msg: BindingTypes.SETUP_REF,
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('modifiers', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- msg: BindingTypes.SETUP_REF,
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('modifiers w/o binding', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('static parameters and modifiers', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- msg: BindingTypes.SETUP_REF,
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
-
- test('dynamic parameters', async () => {
- const code = await compile(``, {
- bindingMetadata: {
- foo: BindingTypes.SETUP_REF,
- vExample: BindingTypes.SETUP_CONST,
- },
- })
- expect(code).matchSnapshot()
- })
- })
- })
-
- describe('expression parsing', () => {
- test('interpolation', async () => {
- const code = await compile(`{{ a + b }}`, {
- inline: true,
- bindingMetadata: {
- b: BindingTypes.SETUP_REF,
- },
- })
- expect(code).matchSnapshot()
- expect(code).contains('a + b.value')
- })
-
- test('v-bind', async () => {
- const code = compile(``, {
- inline: true,
- bindingMetadata: {
- key: BindingTypes.SETUP_REF,
- foo: BindingTypes.SETUP_MAYBE_REF,
- },
- })
- expect(code).matchSnapshot()
- expect(code).contains('key.value+1')
- expect(code).contains('_unref(foo)[key.value+1]()')
- })
-
- // TODO: add more test for expression parsing (v-on, v-slot, v-for)
- })
-})
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
new file mode 100644
index 000000000..379d8c21d
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap
@@ -0,0 +1,81 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`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) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, "foo-bar", undefined, _ctx.id)
+ })
+ return n0
+}"
+`;
+
+exports[`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("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, _ctx.id, undefined, _ctx.id)
+ })
+ return n0
+}"
+`;
+
+exports[`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("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, "camel-case", undefined, _ctx.camelCase)
+ })
+ return n0
+}"
+`;
+
+exports[`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("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, "id", undefined, _ctx.id)
+ })
+ return n0
+}"
+`;
+
+exports[`v-bind > should error if no expression 1`] = `
+"import { template as _template } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ return n0
+}"
+`;
+
+exports[`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("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setAttr(n1, "id", undefined, _ctx.id)
+ })
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap
new file mode 100644
index 000000000..459741e9a
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap
@@ -0,0 +1,41 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v-html > should raise error and ignore children when v-html is present 1`] = `
+"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setHtml(n1, undefined, _ctx.test)
+ })
+ return n0
+}"
+`;
+
+exports[`v-html > should raise error if has no expression 1`] = `
+"import { template as _template, children as _children, setHtml as _setHtml } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _setHtml(n1, undefined, "")
+ return n0
+}"
+`;
+
+exports[`v-html > simple expression 1`] = `
+"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setHtml(n1, undefined, _ctx.code)
+ })
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
new file mode 100644
index 000000000..df47f1598
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
@@ -0,0 +1,46 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v-on > event modifier 1`] = `
+"import { template as _template, children as _children, on as _on, withModifiers as _withModifiers, withKeys as _withKeys } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1], 1: [n2], 2: [n3], 3: [n4], 4: [n5], 5: [n6], 6: [n7], 7: [n8], 8: [n9], 9: [n10], 10: [n11], 11: [n12], 12: [n13], 13: [n14], 14: [n15], 15: [n16], 16: [n17], 17: [n18], 18: [n19], 19: [n20], 20: [n21], 21: [n22],} = _children(n0)
+ _on(n1, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop"]))
+ _on(n2, "submit", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["prevent"]))
+ _on(n3, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop", "prevent"]))
+ _on(n4, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"]))
+ _on(n5, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { capture: true })
+ _on(n6, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { once: true })
+ _on(n7, "scroll", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { passive: true })
+ _on(n8, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"]))
+ _on(n9, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"]))
+ _on(n10, "mouseup", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["middle"]))
+ _on(n11, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"]))
+ _on(n12, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["enter"]))
+ _on(n13, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["tab"]))
+ _on(n14, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["delete"]))
+ _on(n15, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["esc"]))
+ _on(n16, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["space"]))
+ _on(n17, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["up"]))
+ _on(n18, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["down"]))
+ _on(n19, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"]))
+ _on(n20, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle"]))
+ _on(n21, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle", "self"]))
+ _on(n22, "keyup", _withKeys(_withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"]), ["enter"]))
+ return n0
+}"
+`;
+
+exports[`v-on > simple expression 1`] = `
+"import { template as _template, children as _children, on as _on } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _on(n1, "click", (...args) => (_ctx.handleClick && _ctx.handleClick(...args)))
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
new file mode 100644
index 000000000..b255f5d0b
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
@@ -0,0 +1,28 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v-once > as root node 1`] = `
+"import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _setAttr(n1, "id", undefined, _ctx.foo)
+ return n0
+}"
+`;
+
+exports[`v-once > basic 1`] = `
+"import { template as _template, children as _children, createTextNode as _createTextNode, setText as _setText, setAttr as _setAttr, prepend as _prepend } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("
")
+ const n0 = t0()
+ const { 0: [n3, { 1: [n2],}],} = _children(n0)
+ const n1 = _createTextNode(_ctx.msg)
+ _setText(n1, undefined, _ctx.msg)
+ _setAttr(n2, "class", undefined, _ctx.clz)
+ _prepend(n3, n1)
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap
new file mode 100644
index 000000000..f2b62b2ee
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap
@@ -0,0 +1,27 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v-text > no expression 1`] = `
+"import { template as _template, children as _children, setText as _setText } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _setText(n1, undefined, "")
+ return n0
+}"
+`;
+
+exports[`v-text > simple expression 1`] = `
+"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
+
+export function render(_ctx) {
+ const t0 = _template("")
+ const n0 = t0()
+ const { 0: [n1],} = _children(n0)
+ _effect(() => {
+ _setText(n1, undefined, _ctx.str)
+ })
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts
new file mode 100644
index 000000000..42c304f46
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts
@@ -0,0 +1,2 @@
+// TODO: add tests for this transform
+test('baisc', () => {})
diff --git a/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts
new file mode 100644
index 000000000..42c304f46
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts
@@ -0,0 +1,2 @@
+// TODO: add tests for this transform
+test('baisc', () => {})
diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
new file mode 100644
index 000000000..6a990c786
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts
@@ -0,0 +1,88 @@
+import { type RootNode, BindingTypes, ErrorCodes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('v-bind', () => {
+ test('simple expression', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ id: BindingTypes.SETUP_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('should error if no expression', () => {
+ const onError = vi.fn()
+ const code = compile(``, { 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(''))
+ })
+
+ test('no expression', () => {
+ const code = compile('', {
+ bindingMetadata: {
+ id: BindingTypes.SETUP_REF,
+ },
+ })
+
+ expect(code).matchSnapshot()
+ expect(code).contains('_setAttr(n1, "id", undefined, _ctx.id)')
+ })
+
+ test('no expression (shorthand)', () => {
+ const code = compile('', {
+ bindingMetadata: {
+ camelCase: BindingTypes.SETUP_REF,
+ },
+ })
+
+ expect(code).matchSnapshot()
+ expect(code).contains(
+ '_setAttr(n1, "camel-case", undefined, _ctx.camelCase)',
+ )
+ })
+
+ test('dynamic arg', () => {
+ const code = compile('', {
+ bindingMetadata: {
+ id: BindingTypes.SETUP_REF,
+ },
+ })
+
+ expect(code).matchSnapshot()
+ expect(code).contains('_setAttr(n1, _ctx.id, undefined, _ctx.id)')
+ })
+
+ // TODO: camel modifier for v-bind
+ test.fails('.camel modifier', () => {
+ const code = compile(``)
+
+ expect(code).matchSnapshot()
+ expect(code).contains('fooBar')
+ })
+})
diff --git a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts
new file mode 100644
index 000000000..6d0492fa6
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts
@@ -0,0 +1,44 @@
+import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('v-html', () => {
+ test('simple expression', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ code: BindingTypes.SETUP_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('should raise error and ignore children when v-html is present', () => {
+ const onError = vi.fn()
+ const code = compile(`hello
`, {
+ onError,
+ })
+ expect(code).matchSnapshot()
+ expect(onError.mock.calls).toMatchObject([
+ [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],
+ ])
+ })
+
+ test('should raise error if has no expression', () => {
+ const onError = vi.fn()
+ const code = compile(``, {
+ onError,
+ })
+ expect(code).matchSnapshot()
+ expect(onError.mock.calls).toMatchObject([
+ [{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],
+ ])
+ })
+})
diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
new file mode 100644
index 000000000..353396ba1
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
@@ -0,0 +1,73 @@
+import { type RootNode, BindingTypes, ErrorCodes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('v-on', () => {
+ test('simple expression', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ handleClick: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('should error if no expression AND no modifier', () => {
+ const onError = vi.fn()
+ compile(``, { onError })
+ expect(onError.mock.calls[0][0]).toMatchObject({
+ code: ErrorCodes.X_V_ON_NO_EXPRESSION,
+ loc: {
+ start: {
+ line: 1,
+ column: 6,
+ },
+ end: {
+ line: 1,
+ column: 16,
+ },
+ },
+ })
+ })
+
+ test('event modifier', () => {
+ const code = compile(
+ `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ {
+ bindingMetadata: {
+ handleEvent: BindingTypes.SETUP_CONST,
+ },
+ },
+ )
+ expect(code).matchSnapshot()
+ })
+})
diff --git a/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts
new file mode 100644
index 000000000..8c87f3b2a
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts
@@ -0,0 +1,35 @@
+import { type RootNode, BindingTypes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('v-once', () => {
+ test('basic', () => {
+ const code = compile(
+ `
+ {{ msg }}
+
+
`,
+ {
+ bindingMetadata: {
+ msg: BindingTypes.SETUP_REF,
+ clz: BindingTypes.SETUP_REF,
+ },
+ },
+ )
+ expect(code).matchSnapshot()
+ })
+
+ test('as root node', () => {
+ const code = compile(``)
+ expect(code).toMatchSnapshot()
+ expect(code).not.contains('effect')
+ })
+})
diff --git a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts
new file mode 100644
index 000000000..0989ef19f
--- /dev/null
+++ b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts
@@ -0,0 +1,31 @@
+import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom'
+import { type CompilerOptions, compile as _compile } from '../../src'
+
+function compile(template: string | RootNode, options: CompilerOptions = {}) {
+ let { code } = _compile(template, {
+ ...options,
+ mode: 'module',
+ prefixIdentifiers: true,
+ })
+ return code
+}
+
+describe('v-text', () => {
+ test('simple expression', () => {
+ const code = compile(``, {
+ bindingMetadata: {
+ str: BindingTypes.SETUP_REF,
+ },
+ })
+ expect(code).matchSnapshot()
+ })
+
+ test('no expression', () => {
+ const onError = vi.fn()
+ const code = compile(``, { onError })
+ expect(code).matchSnapshot()
+ expect(onError.mock.calls).toMatchObject([
+ [{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],
+ ])
+ })
+})