refactor(compiler-vapor): generate fragment for only one element

closes #133
This commit is contained in:
三咲智子 Kevin Deng 2024-02-23 00:38:51 +08:00
parent 004edd3bac
commit d7bd6c99da
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
39 changed files with 670 additions and 710 deletions

View File

@ -1,110 +1,101 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compile > bindings 1`] = `
"import { children as _children, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setText(n1, "count is ", _ctx.count, "."))
return n0
return n1
}"
`;
exports[`compile > custom directive > basic 1`] = `
"import { children as _children, resolveDirective as _resolveDirective, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { resolveDirective as _resolveDirective, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_resolveDirective("vTest")], [_resolveDirective("vHello"), void 0, void 0, { world: true }]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > basic 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > binding value 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, () => _ctx.msg]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > dynamic parameters 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, () => _ctx.msg, _ctx.foo]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > modifiers 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, () => _ctx.msg, void 0, { bar: true }]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > modifiers w/o binding 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, void 0, void 0, { "foo-bar": true }]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > static parameters 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, () => _ctx.msg, "foo"]])
return n0
return n1
}"
`;
exports[`compile > directives > custom directive > static parameters and modifiers 1`] = `
"import { children as _children, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_ctx.vExample, () => _ctx.msg, "foo", { bar: true }]])
return n0
return n1
}"
`;
@ -113,8 +104,8 @@ exports[`compile > directives > v-cloak > basic 1`] = `
const t0 = _template("<div>test</div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
return n1
}"
`;
@ -123,38 +114,24 @@ exports[`compile > directives > v-pre > basic 1`] = `
const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
export function render(_ctx) {
const n0 = t0()
return n0
}"
`;
exports[`compile > directives > v-pre > self-closing v-pre 1`] = `
"import { children as _children, createTextNode as _createTextNode, append as _append, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div><div><Comp></Comp></div>")
export function render(_ctx) {
const n0 = t0()
const n2 = _children(n0, 1)
const n1 = _createTextNode()
_append(n2, n1)
_renderEffect(() => _setText(n1, _ctx.bar))
_renderEffect(() => _setDynamicProp(n2, "id", _ctx.foo))
return n0
const n1 = t0()
return n1
}"
`;
exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
"import { children as _children, createTextNode as _createTextNode, append as _append, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div><div><Comp></Comp></div>")
"import { createTextNode as _createTextNode, append as _append, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
const t1 = _template("<div><Comp></Comp></div>")
export function render(_ctx) {
const n0 = t0()
const n2 = _children(n0, 1)
const n1 = _createTextNode()
_append(n2, n1)
_renderEffect(() => _setText(n1, _ctx.bar))
_renderEffect(() => _setDynamicProp(n2, "id", _ctx.foo))
return n0
const n1 = t0()
const n3 = t1()
const n2 = _createTextNode()
_append(n3, n2)
_renderEffect(() => _setText(n2, _ctx.bar))
_renderEffect(() => _setDynamicProp(n3, "id", _ctx.foo))
return [n1, n3]
}"
`;
@ -169,16 +146,15 @@ export function render(_ctx) {
`;
exports[`compile > dynamic root nodes and interpolation 1`] = `
"import { children as _children, on as _on, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<button></button>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.handleClick)
_renderEffect(() => _setText(n1, _ctx.count, "foo", _ctx.count, "foo", _ctx.count))
_renderEffect(() => _setDynamicProp(n1, "id", _ctx.count))
return n0
return n1
}"
`;
@ -192,20 +168,23 @@ exports[`compile > expression parsing > interpolation 1`] = `
exports[`compile > expression parsing > v-bind 1`] = `
"(() => {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { [key.value+1]: _unref(foo)[key.value+1]() }))
return n0
return n1
})()"
`;
exports[`compile > fragment 1`] = `
"import { template as _template } from 'vue/vapor';
const t0 = _template("<p></p><span></span><div></div>")
const t0 = _template("<p></p>")
const t1 = _template("<span></span>")
const t2 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
const n2 = t1()
const n3 = t2()
return [n1, n2, n3]
}"
`;
@ -224,7 +203,7 @@ exports[`compile > static template 1`] = `
const t0 = _template("<div><p>hello</p><input><span></span></div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
return n1
}"
`;

View File

@ -88,17 +88,6 @@ describe('compile', () => {
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(
`<div v-pre/>\n<div :id="foo"><Comp/>{{ bar }}</div>`,
)
expect(code).toMatchSnapshot()
expect(code).contains('<div></div><div><Comp></Comp></div>')
// Waiting for TODO, There should be more here.
})
})
describe('v-cloak', () => {

View File

@ -1,26 +1,24 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: element transform > props merging: class 1`] = `
"import { children as _children, renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setClass(n1, ["foo", { bar: _ctx.isBar }]))
return n0
return n1
}"
`;
exports[`compiler: element transform > props merging: style 1`] = `
"import { children as _children, renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setStyle(n1, ["color: green", { color: 'red' }]))
return n0
return n1
}"
`;
@ -29,55 +27,51 @@ exports[`compiler: element transform > static props 1`] = `
const t0 = _template("<div id=\\"foo\\" class=\\"bar\\"></div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
return n1
}"
`;
exports[`compiler: element transform > v-bind="obj" 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, _ctx.obj))
return n0
return n1
}"
`;
exports[`compiler: element transform > v-bind="obj" after static prop 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { id: "foo" }, _ctx.obj))
return n0
return n1
}"
`;
exports[`compiler: element transform > v-bind="obj" before static prop 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, _ctx.obj, { id: "foo" }))
return n0
return n1
}"
`;
exports[`compiler: element transform > v-bind="obj" between static props 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { id: "foo" }, _ctx.obj, { class: "bar" }))
return n0
return n1
}"
`;

View File

@ -1,183 +1,168 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler v-bind > .attr modifier 1`] = `
"import { children as _children, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setAttr(n1, "foo-bar", _ctx.id))
return n0
return n1
}"
`;
exports[`compiler v-bind > .attr modifier w/ no expression 1`] = `
"import { children as _children, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setAttr(n1, "foo-bar", _ctx.fooBar))
return n0
return n1
}"
`;
exports[`compiler v-bind > .camel modifier 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProp(n1, "fooBar", _ctx.id))
return n0
return n1
}"
`;
exports[`compiler v-bind > .camel modifier w/ dynamic arg 1`] = `
"import { camelize as _camelize } from 'vue';
import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { [_camelize(_ctx.foo)]: _ctx.id }))
return n0
return n1
}"
`;
exports[`compiler v-bind > .camel modifier w/ no expression 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProp(n1, "fooBar", _ctx.fooBar))
return n0
return n1
}"
`;
exports[`compiler v-bind > .prop modifier (shortband) w/ no expression 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDOMProp(n1, "fooBar", _ctx.fooBar))
return n0
return n1
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDOMProp(n1, "fooBar", _ctx.id))
return n0
return n1
}"
`;
exports[`compiler v-bind > .prop modifier 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDOMProp(n1, "fooBar", _ctx.id))
return n0
return n1
}"
`;
exports[`compiler v-bind > .prop modifier w/ dynamic arg 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { ["." + _ctx.fooBar]: _ctx.id }))
return n0
return n1
}"
`;
exports[`compiler v-bind > .prop modifier w/ no expression 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDOMProp(n1, "fooBar", _ctx.fooBar))
return n0
return n1
}"
`;
exports[`compiler v-bind > basic 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProp(n1, "id", _ctx.id))
return n0
return n1
}"
`;
exports[`compiler v-bind > dynamic arg 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }))
return n0
return n1
}"
`;
exports[`compiler v-bind > dynamic arg w/ static attribute 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProps(n1, { [_ctx.id]: _ctx.id, foo: "bar", checked: "" }))
return n0
return n1
}"
`;
exports[`compiler v-bind > no expression (shorthand) 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProp(n1, "camel-case", _ctx.camelCase))
return n0
return n1
}"
`;
exports[`compiler v-bind > no expression 1`] = `
"import { children as _children, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setDynamicProp(n1, "id", _ctx.id))
return n0
return n1
}"
`;
@ -186,7 +171,7 @@ exports[`compiler v-bind > should error if empty expression 1`] = `
const t0 = _template("<div arg></div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
return n1
}"
`;

View File

@ -1,40 +1,38 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-for > basic v-for 1`] = `
"import { children as _children, on as _on, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue/vapor';
"import { on as _on, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n1 = _createFor(() => (_ctx.items), (_block) => {
const n2 = t0()
const n3 = _children(n2, 0)
const n3 = t0()
_on(n3, "click", () => $event => (_ctx.remove(_block.s[0])))
const _updateEffect = () => {
const [item] = _block.s
_setText(n3, item)
}
_renderEffect(_updateEffect)
return [n2, _updateEffect]
return [n3, _updateEffect]
}, (item) => (item.id))
return n1
}"
`;
exports[`compiler: v-for > multi effect 1`] = `
"import { children as _children, setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n1 = _createFor(() => (_ctx.items), (_block) => {
const n2 = t0()
const n3 = _children(n2, 0)
const n3 = t0()
const _updateEffect = () => {
const [item, index] = _block.s
_setDynamicProp(n3, "item", item)
_setDynamicProp(n3, "index", index)
}
_renderEffect(_updateEffect)
return [n2, _updateEffect]
return [n3, _updateEffect]
})
return n1
}"
@ -46,8 +44,8 @@ const t0 = _template("<div>item</div>")
export function render(_ctx) {
const n1 = _createFor(() => (_ctx.items), (_block) => {
const n2 = t0()
return [n2, () => {}]
const n3 = t0()
return [n3, () => {}]
})
return n1
}"

View File

@ -1,37 +1,34 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-html > should convert v-html to innerHTML 1`] = `
"import { children as _children, renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setHtml(n1, _ctx.code))
return n0
return n1
}"
`;
exports[`v-html > should raise error and ignore children when v-html is present 1`] = `
"import { children as _children, renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setHtml(n1, _ctx.test))
return n0
return n1
}"
`;
exports[`v-html > should raise error if has no expression 1`] = `
"import { children as _children, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setHtml as _setHtml, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_setHtml(n1, "")
return n0
return n1
}"
`;

View File

@ -1,43 +1,44 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-if > basic v-if 1`] = `
"import { children as _children, renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
const n3 = _children(n2, 0)
const n3 = t0()
_renderEffect(() => _setText(n3, _ctx.msg))
return n2
return n3
})
return n1
}"
`;
exports[`compiler: v-if > comment between branches 1`] = `
"import { children as _children, createIf as _createIf, prepend as _prepend, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { createIf as _createIf, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("<!--foo--><p></p>")
const t2 = _template("<!--bar-->fine")
const t3 = _template("<input>")
const t1 = _template("<!--foo-->")
const t2 = _template("<p></p>")
const t3 = _template("<!--bar-->")
const t4 = _template("fine")
const t5 = _template("<input>")
export function render(_ctx) {
const n0 = t3()
const n5 = _children(n0, 0)
const n14 = t5()
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
return n2
}, () => _createIf(() => (_ctx.orNot), () => {
const n3 = t1()
const n3 = t0()
return n3
}, () => _createIf(() => (_ctx.orNot), () => {
const n6 = t1()
const n7 = t2()
return [n6, n7]
}, () => {
const n4 = t2()
return n4
const n11 = t3()
const n12 = t4()
return [n11, n12]
}))
_prepend(n0, n1)
_renderEffect(() => _setText(n5, _ctx.text))
return n0
_renderEffect(() => _setText(n14, _ctx.text))
return [n1, n14]
}"
`;
@ -47,27 +48,30 @@ const t0 = _template("<div>hello</div>")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
return n2
const n3 = t0()
return n3
})
const n3 = _createIf(() => (_ctx.ok), () => {
const n4 = t0()
return n4
const n4 = _createIf(() => (_ctx.ok), () => {
const n6 = t0()
return n6
})
return [n1, n3]
return [n1, n4]
}"
`;
exports[`compiler: v-if > template v-if 1`] = `
"import { children as _children, renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>hello<p></p>")
"import { renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("hello")
const t2 = _template("<p></p>")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
const n3 = _children(n2, 2)
_renderEffect(() => _setText(n3, _ctx.msg))
return n2
const n3 = t0()
const n4 = t1()
const n5 = t2()
_renderEffect(() => _setText(n5, _ctx.msg))
return [n3, n4, n5]
})
return n1
}"
@ -80,11 +84,11 @@ const t1 = _template("<p></p>")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
return n2
}, () => {
const n3 = t1()
const n3 = t0()
return n3
}, () => {
const n5 = t1()
return n5
})
return n1
}"
@ -98,14 +102,14 @@ const t2 = _template("fine")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
return n2
}, () => _createIf(() => (_ctx.orNot), () => {
const n3 = t1()
const n3 = t0()
return n3
}, () => _createIf(() => (_ctx.orNot), () => {
const n5 = t1()
return n5
}, () => {
const n4 = t2()
return n4
const n8 = t2()
return n8
}))
return n1
}"
@ -118,11 +122,11 @@ const t1 = _template("<p></p>")
export function render(_ctx) {
const n1 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
return n2
}, () => _createIf(() => (_ctx.orNot), () => {
const n3 = t1()
const n3 = t0()
return n3
}, () => _createIf(() => (_ctx.orNot), () => {
const n5 = t1()
return n5
}))
return n1
}"

View File

@ -1,158 +1,146 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: vModel transform > modifiers > .lazy 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { lazy: true }]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > modifiers > .number 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { number: true }]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > modifiers > .trim 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model, void 0, { trim: true }]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support input (checkbox) 1`] = `
"import { children as _children, vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input type=\\"checkbox\\">")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelCheckbox, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support input (dynamic type) 1`] = `
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support input (radio) 1`] = `
"import { children as _children, vModelRadio as _vModelRadio, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelRadio as _vModelRadio, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input type=\\"radio\\">")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelRadio, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support input (text) 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input type=\\"text\\">")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support select 1`] = `
"import { children as _children, vModelSelect as _vModelSelect, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelSelect as _vModelSelect, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<select></select>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelSelect, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support simple expression 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support textarea 1`] = `
"import { children as _children, vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelText as _vModelText, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<textarea></textarea>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support w/ dynamic v-bind 1`] = `
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
_renderEffect(() => _setDynamicProps(n1, _ctx.obj))
return n0
return n1
}"
`;
exports[`compiler: vModel transform > should support w/ dynamic v-bind 2`] = `
"import { children as _children, vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
"import { vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vModelDynamic, () => _ctx.model]])
_on(n1, "update:modelValue", $event => (_ctx.model = $event))
return n0
return n1
}"
`;

View File

@ -1,81 +1,79 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-on > complex member expression w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.a['b' + _ctx.c])
return n0
return n1
}"
`;
exports[`v-on > dynamic arg 1`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _on(n1, _ctx.event, () => _ctx.handler))
return n0
return n1
}"
`;
exports[`v-on > dynamic arg with complex exp prefixing 1`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _on(n1, _ctx.event(_ctx.foo), () => _ctx.handler))
return n0
return n1
}"
`;
exports[`v-on > dynamic arg with prefixing 1`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _on(n1, _ctx.event, () => _ctx.handler))
return n0
return n1
}"
`;
exports[`v-on > event modifier 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<a></a><form></form><a></a><div></div><div></div><a></a><div></div><input><input><input><input><input><input><input><input><input><input><input><input><input><input><input>")
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<a></a>")
const t1 = _template("<form></form>")
const t2 = _template("<div></div>")
const t3 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n2 = _children(n0, 1)
const n3 = _children(n0, 2)
const n4 = _children(n0, 3)
const n5 = _children(n0, 4)
const n6 = _children(n0, 5)
const n7 = _children(n0, 6)
const n8 = _children(n0, 7)
const n9 = _children(n0, 8)
const n10 = _children(n0, 9)
const n11 = _children(n0, 10)
const n12 = _children(n0, 11)
const n13 = _children(n0, 12)
const n14 = _children(n0, 13)
const n15 = _children(n0, 14)
const n16 = _children(n0, 15)
const n17 = _children(n0, 16)
const n18 = _children(n0, 17)
const n19 = _children(n0, 18)
const n20 = _children(n0, 19)
const n21 = _children(n0, 20)
const n22 = _children(n0, 21)
const n1 = t0()
const n2 = t1()
const n3 = t0()
const n4 = t2()
const n5 = t2()
const n6 = t0()
const n7 = t2()
const n8 = t3()
const n9 = t3()
const n10 = t3()
const n11 = t3()
const n12 = t3()
const n13 = t3()
const n14 = t3()
const n15 = t3()
const n16 = t3()
const n17 = t3()
const n18 = t3()
const n19 = t3()
const n20 = t3()
const n21 = t3()
const n22 = t3()
_on(n1, "click", () => _ctx.handleEvent, undefined, {
modifiers: ["stop"]
})
@ -137,334 +135,310 @@ export function render(_ctx) {
modifiers: ["self"],
keys: ["enter"]
})
return n0
return [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21, n22]
}"
`;
exports[`v-on > function expression w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => e => _ctx.foo(e))
return n0
return n1
}"
`;
exports[`v-on > inline statement w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => (_ctx.foo($event)))
return n0
return n1
}"
`;
exports[`v-on > multiple inline statements w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => {_ctx.foo($event);_ctx.bar()})
return n0
return n1
}"
`;
exports[`v-on > should NOT add a prefix to $event if the expression is a function expression 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => {_ctx.i++;_ctx.foo($event)})
return n0
return n1
}"
`;
exports[`v-on > should NOT wrap as function if expression is already function expression (with Typescript) 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => (e: any): any => _ctx.foo(e))
return n0
return n1
}"
`;
exports[`v-on > should NOT wrap as function if expression is already function expression (with newlines) 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () =>
$event => {
_ctx.foo($event)
}
)
return n0
return n1
}"
`;
exports[`v-on > should NOT wrap as function if expression is already function expression 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => _ctx.foo($event))
return n0
return n1
}"
`;
exports[`v-on > should NOT wrap as function if expression is complex member expression 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.a['b' + _ctx.c])
return n0
return n1
}"
`;
exports[`v-on > should handle multi-line statement 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => {
_ctx.foo();
_ctx.bar()
})
return n0
return n1
}"
`;
exports[`v-on > should handle multiple inline statement 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => {_ctx.foo();_ctx.bar()})
return n0
return n1
}"
`;
exports[`v-on > should not prefix member expression 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.foo.bar)
return n0
return n1
}"
`;
exports[`v-on > should not wrap keys guard if no key modifier is present 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "keyup", () => _ctx.test, undefined, {
modifiers: ["exact"]
})
return n0
return n1
}"
`;
exports[`v-on > should support multiple events and modifiers options w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.test, undefined, {
modifiers: ["stop"]
})
_on(n1, "keyup", () => _ctx.test, undefined, {
keys: ["enter"]
})
return n0
return n1
}"
`;
exports[`v-on > should support multiple modifiers and event options w/ prefixIdentifiers: true 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.test, { capture: true, once: true }, {
modifiers: ["stop", "prevent"]
})
return n0
return n1
}"
`;
exports[`v-on > should transform click.middle 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "mouseup", () => _ctx.test, undefined, {
modifiers: ["middle"]
})
return n0
return n1
}"
`;
exports[`v-on > should transform click.middle 2`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => {
_on(n1, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, undefined, {
modifiers: ["middle"]
})
})
return n0
return n1
}"
`;
exports[`v-on > should transform click.right 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "contextmenu", () => _ctx.test, undefined, {
modifiers: ["right"]
})
return n0
return n1
}"
`;
exports[`v-on > should transform click.right 2`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => {
_on(n1, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, undefined, {
modifiers: ["right"],
keys: ["right"]
})
})
return n0
return n1
}"
`;
exports[`v-on > should wrap as function if expression is inline statement 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => $event => (_ctx.i++))
return n0
return n1
}"
`;
exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = `
"import { children as _children, renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => {
_on(n1, _ctx.e, () => _ctx.test, undefined, {
modifiers: ["left"],
keys: ["left"]
})
})
return n0
return n1
}"
`;
exports[`v-on > should wrap in unref if identifier is setup-maybe-ref w/ inline: true 1`] = `
"(() => {
const n0 = t0()
const n1 = _children(n0, 0)
const n2 = _children(n0, 1)
const n3 = _children(n0, 2)
const n1 = t0()
const n2 = t0()
const n3 = t0()
_on(n1, "click", () => $event => (x.value=_unref(y)))
_on(n2, "click", () => $event => (x.value++))
_on(n3, "click", () => $event => ({ x: x.value } = _unref(y)))
return n0
return [n1, n2, n3]
})()"
`;
exports[`v-on > should wrap keys guard for keyboard events or dynamic events 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "keydown", () => _ctx.test, { capture: true }, {
modifiers: ["stop", "ctrl"],
keys: ["a"]
})
return n0
return n1
}"
`;
exports[`v-on > should wrap keys guard for static key event w/ left/right modifiers 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "keyup", () => _ctx.test, undefined, {
keys: ["left"]
})
return n0
return n1
}"
`;
exports[`v-on > simple expression 1`] = `
"import { children as _children, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_on(n1, "click", () => _ctx.handleClick)
return n0
return n1
}"
`;

View File

@ -1,14 +1,13 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-once > as root node 1`] = `
"import { children as _children, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_setDynamicProp(n1, "id", _ctx.foo)
return n0
return n1
}"
`;
@ -17,14 +16,13 @@ exports[`compiler: v-once > basic 1`] = `
const t0 = _template("<div><span></span></div>")
export function render(_ctx) {
const n0 = t0()
const n3 = _children(n0, 0)
const n3 = t0()
const n2 = _children(n3, 0)
const n1 = _createTextNode()
_setText(n1, _ctx.msg, " ")
_setClass(n2, _ctx.clz)
_prepend(n3, n1)
return n0
return n3
}"
`;
@ -33,8 +31,8 @@ exports[`compiler: v-once > inside v-once 1`] = `
const t0 = _template("<div><div></div></div>")
export function render(_ctx) {
const n0 = t0()
return n0
const n1 = t0()
return n1
}"
`;
@ -43,9 +41,9 @@ exports[`compiler: v-once > on nested plain element 1`] = `
const t0 = _template("<div><div></div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0, 0)
const n2 = t0()
const n1 = _children(n2, 0)
_setDynamicProp(n1, "id", _ctx.foo)
return n0
return n2
}"
`;

View File

@ -1,13 +1,12 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-show transform > simple expression 1`] = `
"import { children as _children, vShow as _vShow, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
"import { vShow as _vShow, withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_withDirectives(n1, [[_vShow, () => _ctx.foo]])
return n0
return n1
}"
`;

View File

@ -1,37 +1,34 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-text > should convert v-text to textContent 1`] = `
"import { children as _children, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setText(n1, _ctx.str))
return n0
return n1
}"
`;
exports[`v-text > should raise error and ignore children when v-text is present 1`] = `
"import { children as _children, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_renderEffect(() => _setText(n1, _ctx.test))
return n0
return n1
}"
`;
exports[`v-text > should raise error if has no expression 1`] = `
"import { children as _children, setText as _setText, template as _template } from 'vue/vapor';
"import { setText as _setText, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
const n1 = _children(n0, 0)
const n1 = t0()
_setText(n1, "")
return n0
return n1
}"
`;

View File

@ -0,0 +1,3 @@
describe('compiler: children transform', () => {
test.todo('basic')
})

View File

@ -1,6 +1,7 @@
import { makeCompile } from './_utils'
import {
IRNodeTypes,
transformChildren,
transformElement,
transformVBind,
transformVOn,
@ -8,7 +9,7 @@ import {
import { NodeTypes } from '@vue/compiler-core'
const compileWithElementTransform = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
bind: transformVBind,
on: transformVOn,
@ -16,7 +17,7 @@ const compileWithElementTransform = makeCompile({
})
describe('compiler: element transform', () => {
test.todo('baisc')
test.todo('basic')
test('static props', () => {
const { code, ir } = compileWithElementTransform(

View File

@ -2,13 +2,14 @@ import { ErrorCodes, NodeTypes } from '@vue/compiler-dom'
import {
DynamicFlag,
IRNodeTypes,
transformChildren,
transformElement,
transformVBind,
} from '../../src'
import { makeCompile } from './_utils'
const compileWithVBind = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
bind: transformVBind,
},

View File

@ -2,6 +2,7 @@ import { makeCompile } from './_utils'
import {
type ForIRNode,
IRNodeTypes,
transformChildren,
transformElement,
transformText,
transformVBind,
@ -11,7 +12,12 @@ import {
import { NodeTypes } from '@vue/compiler-dom'
const compileWithVFor = makeCompile({
nodeTransforms: [transformVFor, transformText, transformElement],
nodeTransforms: [
transformVFor,
transformText,
transformElement,
transformChildren,
],
directiveTransforms: {
bind: transformVBind,
on: transformVOn,
@ -45,7 +51,7 @@ describe('compiler: v-for', () => {
render: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 0,
children: [{ template: 0 }],
},
},
keyProperty: {

View File

@ -1,9 +1,14 @@
import { BindingTypes, DOMErrorCodes, NodeTypes } from '@vue/compiler-dom'
import { IRNodeTypes, transformElement, transformVHtml } from '../../src'
import {
IRNodeTypes,
transformChildren,
transformElement,
transformVHtml,
} from '../../src'
import { makeCompile } from './_utils'
const compileWithVHtml = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
html: transformVHtml,
},

View File

@ -2,6 +2,8 @@ import { makeCompile } from './_utils'
import {
IRNodeTypes,
type IfIRNode,
transformChildren,
transformComment,
transformElement,
transformOnce,
transformText,
@ -16,6 +18,8 @@ const compileWithVIf = makeCompile({
transformVIf,
transformText,
transformElement,
transformComment,
transformChildren,
],
directiveTransforms: {
text: transformVText,
@ -44,8 +48,12 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
children: [
{
template: 0,
},
],
},
},
},
])
@ -68,15 +76,14 @@ describe('compiler: v-if', () => {
)
expect(code).matchSnapshot()
expect(ir.template).toEqual(['<div></div>hello<p></p>'])
expect(ir.template).toEqual(['<div></div>', 'hello', '<p></p>'])
expect(ir.block.effect).toEqual([])
expect((ir.block.operation[0] as IfIRNode).positive.effect).toMatchObject([
{
operations: [
{
type: IRNodeTypes.SET_TEXT,
element: 3,
element: 5,
values: [
{
content: 'msg',
@ -90,7 +97,11 @@ describe('compiler: v-if', () => {
])
expect((ir.block.operation[0] as IfIRNode).positive.dynamic).toMatchObject({
id: 2,
children: { 2: { id: 3 } },
children: {
2: {
id: 5,
},
},
})
})
@ -100,7 +111,7 @@ describe('compiler: v-if', () => {
)
expect(code).matchSnapshot()
expect(ir.template).toEqual(['<div>hello</div>'])
expect(ir.block.returns).toEqual([1, 3])
expect(ir.block.returns).toEqual([1, 4])
})
test.todo('v-if with v-once')
@ -128,13 +139,13 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 0,
children: [{ template: 0 }],
},
},
negative: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 1,
children: [{ template: 1 }],
},
},
},
@ -161,7 +172,7 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 0,
children: [{ template: 0 }],
},
},
negative: {
@ -174,7 +185,7 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 1,
children: [{ template: 1 }],
},
},
},
@ -198,7 +209,7 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 0,
children: [{ template: 0 }],
},
},
negative: {
@ -206,13 +217,13 @@ describe('compiler: v-if', () => {
positive: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 1,
children: [{ template: 1 }],
},
},
negative: {
type: IRNodeTypes.BLOCK,
dynamic: {
template: 2,
children: [{ template: 2 }],
},
},
},
@ -232,8 +243,10 @@ describe('compiler: v-if', () => {
expect(code).matchSnapshot()
expect(ir.template).toEqual([
'<div></div>',
'<!--foo--><p></p>',
'<!--bar-->fine',
'<!--foo-->',
'<p></p>',
'<!--bar-->',
'fine',
'<input>',
])

View File

@ -1,9 +1,9 @@
import { makeCompile } from './_utils'
import { transformElement, transformVModel } from '../../src'
import { transformChildren, transformElement, transformVModel } from '../../src'
import { DOMErrorCodes } from '@vue/compiler-dom'
const compileWithVModel = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
model: transformVModel,
},

View File

@ -1,9 +1,14 @@
import { BindingTypes, ErrorCodes, NodeTypes } from '@vue/compiler-dom'
import { IRNodeTypes, transformElement, transformVOn } from '../../src'
import {
IRNodeTypes,
transformChildren,
transformElement,
transformVOn,
} from '../../src'
import { makeCompile } from './_utils'
const compileWithVOn = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
on: transformVOn,
},

View File

@ -1,9 +1,9 @@
import { makeCompile } from './_utils'
import { transformElement, transformVShow } from '../../src'
import { transformChildren, transformElement, transformVShow } from '../../src'
import { DOMErrorCodes } from '@vue/compiler-dom'
const compileWithVShow = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
show: transformVShow,
},

View File

@ -1,9 +1,14 @@
import { BindingTypes, DOMErrorCodes, NodeTypes } from '@vue/compiler-dom'
import { IRNodeTypes, transformElement, transformVText } from '../../src'
import {
IRNodeTypes,
transformChildren,
transformElement,
transformVText,
} from '../../src'
import { makeCompile } from './_utils'
const compileWithVText = makeCompile({
nodeTransforms: [transformElement],
nodeTransforms: [transformElement, transformChildren],
directiveTransforms: {
text: transformVText,
},

View File

@ -13,6 +13,7 @@ import {
transform,
} from './transform'
import { type VaporCodegenResult, generate } from './generate'
import { transformChildren } from './transforms/transformChildren'
import { transformOnce } from './transforms/vOnce'
import { transformElement } from './transforms/transformElement'
import { transformVHtml } from './transforms/vHtml'
@ -26,6 +27,7 @@ import type { HackOptions } from './ir'
import { transformVModel } from './transforms/vModel'
import { transformVIf } from './transforms/vIf'
import { transformVFor } from './transforms/vFor'
import { transformComment } from './transforms/transformComment'
export { wrapTemplate } from './transforms/utils'
@ -105,6 +107,8 @@ export function getBaseTransformPreset(
transformVFor,
transformText,
transformElement,
transformComment,
transformChildren,
],
{
bind: transformVBind,

View File

@ -5,7 +5,7 @@ import type {
import type { IREffect, RootIRNode, VaporHelper } from './ir'
import { SourceMapGenerator } from 'source-map-js'
import { extend, remove } from '@vue/shared'
import { genBlockFunctionContent } from './generators/block'
import { genBlockContent } from './generators/block'
import { genTemplates } from './generators/template'
import {
type CodeFragment,
@ -118,7 +118,7 @@ export function generate(
}
push(INDENT_START)
push(...genBlockFunctionContent(ir.block, context))
push(...genBlockContent(ir.block, context))
push(INDENT_END, NEWLINE)
if (isSetupInlined) {

View File

@ -12,7 +12,7 @@ import { genEffects, genOperations } from './operation'
import { genChildren } from './template'
import { genMulti } from './utils'
export function genBlockFunction(
export function genBlock(
oper: BlockIRNode,
context: CodegenContext,
args: CodeFragment[] = [],
@ -23,21 +23,23 @@ export function genBlockFunction(
...args,
') => {',
INDENT_START,
...genBlockFunctionContent(oper, context, customReturns),
...genBlockContent(oper, context, customReturns),
INDENT_END,
NEWLINE,
'}',
]
}
export function genBlockFunctionContent(
export function genBlockContent(
{ dynamic, effect, operation, returns }: BlockIRNode,
context: CodegenContext,
customReturns?: (returns: CodeFragment[]) => CodeFragment[],
): CodeFragment[] {
const [frag, push] = buildCodeFragment()
push(...genChildren(dynamic, context, dynamic.id!))
for (const child of dynamic.children) {
push(...genChildren(child, context, child.id!))
}
const directiveOps = operation.filter(
(oper): oper is WithDirectiveIRNode =>

View File

@ -1,5 +1,5 @@
import { NewlineType } from '@vue/compiler-dom'
import { genBlockFunction } from './block'
import { genBlock } from './block'
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import type { ForIRNode, IREffect } from '../ir'
@ -38,7 +38,7 @@ export function genFor(
]
const blockFn = context.withId(
() => genBlockFunction(render, context, ['_block'], blockReturns),
() => genBlock(render, context, ['_block'], blockReturns),
idMap,
)

View File

@ -1,6 +1,6 @@
import type { CodegenContext } from '../generate'
import { IRNodeTypes, type IfIRNode } from '../ir'
import { genBlockFunction } from './block'
import { genBlock } from './block'
import { genExpression } from './expression'
import { type CodeFragment, NEWLINE, buildCodeFragment, genCall } from './utils'
@ -19,12 +19,12 @@ export function genIf(
')',
]
let positiveArg = genBlockFunction(positive, context)
let positiveArg = genBlock(positive, context)
let negativeArg: false | CodeFragment[] = false
if (negative) {
if (negative.type === IRNodeTypes.BLOCK) {
negativeArg = genBlockFunction(negative, context)
negativeArg = genBlock(negative, context)
} else {
negativeArg = ['() => ', ...genIf(negative!, context, true)]
}

View File

@ -34,7 +34,6 @@ export function genChildren(
offset--
}
const elementIndex = Number(index) + offset
const id =
child.flags & DynamicFlag.REFERENCED
? child.flags & DynamicFlag.INSERT
@ -42,6 +41,7 @@ export function genChildren(
: child.id
: undefined
const elementIndex = Number(index) + offset
const newPaths = [...paths, elementIndex]
if (id !== undefined) {

View File

@ -10,6 +10,7 @@ export {
export * from './ir'
export * from './errors'
export { transformElement } from './transforms/transformElement'
export { transformChildren } from './transforms/transformChildren'
export { transformText } from './transforms/transformText'
export { transformVBind } from './transforms/vBind'
export { transformVHtml } from './transforms/vHtml'
@ -20,3 +21,4 @@ export { transformVText } from './transforms/vText'
export { transformVIf } from './transforms/vIf'
export { transformVFor } from './transforms/vFor'
export { transformVModel } from './transforms/vModel'
export { transformComment } from './transforms/transformComment'

View File

@ -1,6 +1,7 @@
import {
type AllNode,
type TransformOptions as BaseTransformOptions,
type CommentNode,
type CompilerCompatOptions,
type ElementNode,
ElementTypes,
@ -68,6 +69,8 @@ export interface TransformContext<T extends AllNode = AllNode> {
childrenTemplate: (string | null)[]
dynamic: IRDynamicInfo
comment: CommentNode[]
inVOnce: boolean
enterBlock(ir: TransformContext['block']): () => void
@ -136,6 +139,7 @@ function createRootContext(
options: extend({}, defaultOptions, options),
dynamic: root.block.dynamic,
inVOnce: false,
comment: [],
increaseId: () => globalId++,
reference() {
@ -172,7 +176,6 @@ function createRootContext(
template: '',
childrenTemplate: [],
registerTemplate() {
this.template += this.childrenTemplate.filter(Boolean).join('')
if (!this.template) {
return -1
}
@ -196,22 +199,6 @@ function createRootContext(
return context
}
function createContext<T extends TemplateChildNode>(
node: T,
parent: TransformContext<RootNode | ElementNode>,
index: number,
): TransformContext<T> {
return extend({}, parent, {
node,
parent,
index,
template: '',
childrenTemplate: [],
dynamic: genDefaultDynamic(),
} satisfies Partial<TransformContext<T>>) satisfies TransformContext<T>
}
// AST -> IR
export function transform(
root: RootNode,
@ -241,7 +228,7 @@ export function transform(
return ir
}
function transformNode(
export function transformNode(
context: TransformContext<RootNode | TemplateChildNode>,
) {
let { node } = context
@ -267,18 +254,6 @@ function transformNode(
}
}
switch (node.type) {
case NodeTypes.ROOT:
case NodeTypes.ELEMENT: {
transformChildren(context as TransformContext<RootNode | ElementNode>)
break
}
case NodeTypes.COMMENT: {
context.template += `<!--${node.content}-->`
break
}
}
// exit transforms
context.node = node
let i = exitFns.length
@ -291,88 +266,6 @@ function transformNode(
}
}
function transformChildren(context: TransformContext<RootNode | ElementNode>) {
const { children } = context.node
let referencedCount = 0
for (const [i, child] of children.entries()) {
const childContext = createContext(child, context, i)
transformNode(childContext)
context.childrenTemplate.push(childContext.template)
context.dynamic.children[i] = childContext.dynamic
if (childContext.dynamic.flags & DynamicFlag.REFERENCED) {
referencedCount++
}
}
if (referencedCount > 1) {
context.reference()
}
processDynamicChildren(context)
}
function processDynamicChildren(
context: TransformContext<RootNode | ElementNode>,
) {
let prevDynamics: IRDynamicInfo[] = []
let hasStaticTemplate = false
const children = context.dynamic.children
const isFragment = context.block.node === context.node
const allNonTemplate = children.every(
child => child.flags & DynamicFlag.NON_TEMPLATE,
)
// all non-template: don't gen fragment but return array directly
if (isFragment && allNonTemplate) {
context.block.returns = children
.filter(child => child.flags & DynamicFlag.INSERT)
.map(child => child.id!)
return
}
// mixed: insert with anchor
context.block.returns = [context.dynamic.id!]
for (const [index, child] of children.entries()) {
if (child.flags & DynamicFlag.INSERT) {
prevDynamics.push(child)
}
if (!(child.flags & DynamicFlag.NON_TEMPLATE)) {
if (prevDynamics.length) {
if (hasStaticTemplate) {
context.childrenTemplate[index - prevDynamics.length] = `<!>`
prevDynamics[0].flags -= DynamicFlag.NON_TEMPLATE
const anchor = (prevDynamics[0].anchor = context.increaseId())
context.registerOperation({
type: IRNodeTypes.INSERT_NODE,
element: prevDynamics.map(child => child.id!),
parent: context.reference(),
anchor,
})
} else {
context.registerOperation({
type: IRNodeTypes.PREPEND_NODE,
elements: prevDynamics.map(child => child.id!),
parent: context.reference(),
})
}
prevDynamics = []
}
hasStaticTemplate = true
}
}
if (prevDynamics.length) {
context.registerOperation({
type: IRNodeTypes.APPEND_NODE,
elements: prevDynamics.map(child => child.id!),
parent: context.reference(),
})
}
}
export function createStructuralDirectiveTransform(
name: string | string[],
fn: StructuralDirectiveTransform,

View File

@ -0,0 +1,121 @@
import {
type ElementNode,
ElementTypes,
NodeTypes,
type RootNode,
type TemplateChildNode,
} from '@vue/compiler-dom'
import {
type NodeTransform,
type TransformContext,
transformNode,
} from '../transform'
import { DynamicFlag, type IRDynamicInfo, IRNodeTypes } from '../ir'
import { extend } from '@vue/shared'
import { genDefaultDynamic } from './utils'
export const transformChildren: NodeTransform = (node, context) => {
const isFragment =
node.type === NodeTypes.ROOT ||
(node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE)
if (!isFragment && node.type !== NodeTypes.ELEMENT) return
let referencedCount = 0
for (const [i, child] of node.children.entries()) {
const childContext = createContext(
child,
context as TransformContext<RootNode | ElementNode>,
i,
)
transformNode(childContext)
if (isFragment) {
childContext.reference()
childContext.registerTemplate()
if (
!(childContext.dynamic.flags & DynamicFlag.NON_TEMPLATE) ||
childContext.dynamic.flags & DynamicFlag.INSERT
) {
context.block.returns.push(childContext.dynamic.id!)
}
} else {
context.childrenTemplate.push(childContext.template)
if (childContext.dynamic.flags & DynamicFlag.REFERENCED) {
referencedCount++
}
}
context.dynamic.children[i] = childContext.dynamic
}
if (!isFragment) {
if (referencedCount > 1) {
context.reference()
}
processDynamicChildren(context as TransformContext<ElementNode>)
}
}
function processDynamicChildren(context: TransformContext<ElementNode>) {
let prevDynamics: IRDynamicInfo[] = []
let hasStaticTemplate = false
const children = context.dynamic.children
for (const [index, child] of children.entries()) {
if (child.flags & DynamicFlag.INSERT) {
prevDynamics.push(child)
}
if (!(child.flags & DynamicFlag.NON_TEMPLATE)) {
if (prevDynamics.length) {
if (hasStaticTemplate) {
context.childrenTemplate[index - prevDynamics.length] = `<!>`
prevDynamics[0].flags -= DynamicFlag.NON_TEMPLATE
const anchor = (prevDynamics[0].anchor = context.increaseId())
context.registerOperation({
type: IRNodeTypes.INSERT_NODE,
element: prevDynamics.map(child => child.id!),
parent: context.reference(),
anchor,
})
} else {
context.registerOperation({
type: IRNodeTypes.PREPEND_NODE,
elements: prevDynamics.map(child => child.id!),
parent: context.reference(),
})
}
prevDynamics = []
}
hasStaticTemplate = true
}
}
if (prevDynamics.length) {
context.registerOperation({
type: IRNodeTypes.APPEND_NODE,
elements: prevDynamics.map(child => child.id!),
parent: context.reference(),
})
}
}
function createContext<T extends TemplateChildNode>(
node: T,
parent: TransformContext<RootNode | ElementNode>,
index: number,
): TransformContext<T> {
return extend({}, parent, {
node,
parent,
index,
template: '',
childrenTemplate: [],
dynamic: genDefaultDynamic(),
} satisfies Partial<TransformContext<T>>) satisfies TransformContext<T>
}

View File

@ -0,0 +1,55 @@
import {
type CommentNode,
NodeTypes,
type TemplateChildNode,
} from '@vue/compiler-dom'
import type { NodeTransform, TransformContext } from '../transform'
import { DynamicFlag } from '../ir'
export const transformComment: NodeTransform = (node, context) => {
if (node.type !== NodeTypes.COMMENT) return
if (getSiblingIf(context as TransformContext<CommentNode>)) {
context.comment.push(node)
context.dynamic.flags |= DynamicFlag.NON_TEMPLATE
} else {
context.template += `<!--${node.content}-->`
}
}
export function getSiblingIf(
context: TransformContext<TemplateChildNode>,
reverse?: boolean,
) {
const parent = context.parent
if (!parent) return
const siblings = parent.node.children
let sibling: TemplateChildNode | undefined
let i = siblings.indexOf(context.node)
while (reverse ? --i >= 0 : ++i < siblings.length) {
sibling = siblings[i]
if (!isCommentLike(sibling)) {
break
}
}
if (
sibling &&
sibling.type === NodeTypes.ELEMENT &&
sibling.props.some(
({ type, name }) =>
type === NodeTypes.DIRECTIVE &&
['else-if', reverse ? 'if' : 'else'].includes(name),
)
) {
return sibling
}
}
function isCommentLike(node: TemplateChildNode) {
return (
node.type === NodeTypes.COMMENT ||
(node.type === NodeTypes.TEXT && !node.content.trim().length)
)
}

View File

@ -1,8 +1,6 @@
import {
type ElementNode,
ErrorCodes,
NodeTypes,
type TemplateChildNode,
createCompilerError,
createSimpleExpression,
} from '@vue/compiler-dom'
@ -15,11 +13,11 @@ import {
DynamicFlag,
type IRDynamicInfo,
IRNodeTypes,
type OperationNode,
type VaporDirectiveNode,
} from '../ir'
import { extend } from '@vue/shared'
import { genDefaultDynamic, wrapTemplate } from './utils'
import { getSiblingIf } from './transformComment'
export const transformVIf = createStructuralDirectiveTransform(
['if', 'else', 'else-if'],
@ -56,43 +54,16 @@ export function processIf(
}
} else {
// check the adjacent v-if
const parent = context.parent!
const siblings = parent.node.children
const templates = parent.childrenTemplate
const siblingsDynamic = parent.dynamic.children
const comments = []
let sibling: TemplateChildNode | undefined
let i = siblings.indexOf(node)
while (i-- >= -1) {
sibling = siblings[i]
if (
sibling &&
(sibling.type === NodeTypes.COMMENT ||
(sibling.type === NodeTypes.TEXT && !sibling.content.trim().length))
) {
if (__DEV__ && sibling.type === NodeTypes.COMMENT)
comments.unshift(sibling)
siblingsDynamic[i].flags |= DynamicFlag.NON_TEMPLATE
templates[i] = null
} else {
break
}
}
const siblingIf = getSiblingIf(context, true)
const { operation } = context.block
let lastIfNode: OperationNode
let lastIfNode = operation[operation.length - 1]
if (
// check if v-if is the sibling node
!sibling ||
sibling.type !== NodeTypes.ELEMENT ||
!sibling.props.some(
({ type, name }) =>
type === NodeTypes.DIRECTIVE && ['if', 'else-if'].includes(name),
) ||
// check if IFNode is the last operation and get the root IFNode
!(lastIfNode = operation[operation.length - 1]) ||
!siblingIf ||
// check if IfNode is the last operation and get the root IfNode
!lastIfNode ||
lastIfNode.type !== IRNodeTypes.IF
) {
context.options.onError(
@ -113,12 +84,13 @@ export function processIf(
}
// TODO ignore comments if the v-if is direct child of <transition> (PR #3622)
if (__DEV__ && comments.length) {
if (__DEV__ && context.root.comment.length) {
node = wrapTemplate(node, ['else-if', 'else'])
context.node = node = extend({}, node, {
children: [...comments, ...node.children],
children: [...context.comment, ...node.children],
})
}
context.root.comment = []
const [branch, onExit] = createIfBranch(node, context)

View File

@ -1,11 +1,4 @@
import {
children,
ref,
setText,
template,
unmountComponent,
watchEffect,
} from '../src'
import { ref, setText, template, unmountComponent, watchEffect } from '../src'
import { describe, expect } from 'vitest'
import { makeRender } from './_utils'
@ -17,9 +10,8 @@ describe('component', () => {
const count = ref(0)
const t0 = template('<div></div>')
const n0 = t0()
const n1 = children(n0, 0)
watchEffect(() => {
setText(n1, count.value)
setText(n0, count.value)
})
return n0
}).render()

View File

@ -6,7 +6,6 @@
import { setCurrentInstance } from '../src/component'
import {
children,
defineComponent,
getCurrentInstance,
nextTick,
@ -290,11 +289,10 @@ describe('component props (vapor)', () => {
props: ['foo'],
render() {
const instance = getCurrentInstance()!
const t0 = template('<div><!></div>')
const t0 = template('<div></div>')
const n0 = t0()
const n1 = children(n0, 0)
watchEffect(() => {
setText(n1, instance.props.foo)
setText(n0, instance.props.foo)
})
return n0
},
@ -307,7 +305,7 @@ describe('component props (vapor)', () => {
return { foo, id }
},
render(_ctx: Record<string, any>) {
const t0 = template('')
const t0 = template('<div>')
const n0 = t0()
renderChild(
{
@ -318,19 +316,19 @@ describe('component props (vapor)', () => {
return _ctx.id
},
},
n0 as any, // TODO: type
n0 as HTMLDivElement,
)
return n0
},
}).render()
const reset = setCurrentInstance(instance)
// expect(host.innerHTML).toBe('<div id="a">1</div>') // TODO: Fallthrough Attributes
expect(host.innerHTML).toBe('<div>1</div>')
expect(host.innerHTML).toBe('<div><div>1</div></div>')
foo.value++
await nextTick()
// expect(host.innerHTML).toBe('<div id="a">2</div>') // TODO: Fallthrough Attributes
expect(host.innerHTML).toBe('<div>2</div>')
expect(host.innerHTML).toBe('<div><div>2</div></div>')
// id.value = 'b'
// await nextTick()
@ -468,9 +466,8 @@ describe('component props (vapor)', () => {
const instance = getCurrentInstance()!
const t0 = template('<div></div>')
const n0 = t0()
const n1 = children(n0, 0)
watchEffect(() => {
setText(n1, instance.props.foo)
setText(n0, instance.props.foo)
})
return n0
},
@ -540,10 +537,9 @@ describe('component props (vapor)', () => {
const instance = getCurrentInstance()!
const t0 = template('<div></div>')
const n0 = t0()
const n1 = children(n0, 0)
watchEffect(() => {
setText(
n1,
n0,
JSON.stringify(instance.attrs) + Object.keys(instance.attrs),
)
})

View File

@ -1,6 +1,4 @@
import {
append,
children,
createIf,
insert,
nextTick,
@ -33,7 +31,6 @@ describe('createIf', () => {
const { host } = define(() => {
const n0 = t0()
const n1 = children(n0, 0)
insert(
createIf(
@ -41,10 +38,8 @@ describe('createIf', () => {
// v-if
(spyIfFn ||= vi.fn(() => {
const n2 = t1()
const n3 = children(n2, 0)
renderEffect(() => {
setText(n3, count.value)
setText(n2, count.value)
})
return n2
})),
@ -54,7 +49,7 @@ describe('createIf', () => {
return n4
})),
),
n1 as any as ParentNode,
n0 as any as ParentNode,
)
return n0
}).render()
@ -105,11 +100,10 @@ describe('createIf', () => {
return n4
},
)
append(n2, n3)
return n2
return [n2, n3]
},
)
return [n1]
return n1
}).render()
expect(host.innerHTML).toBe('Hello Vapor<!--if--><!--if-->')

View File

@ -4,11 +4,10 @@ describe('api: template', () => {
test('create element', () => {
const t = template('<div>')
const root = t()
expect(root).toBeInstanceOf(Array)
expect(root[0]).toBeInstanceOf(HTMLDivElement)
expect(root).toBeInstanceOf(HTMLDivElement)
const root2 = t()
expect(root2).toBeInstanceOf(Array)
expect(root2).toBeInstanceOf(HTMLDivElement)
expect(root2).not.toBe(root)
})
})

View File

@ -11,7 +11,9 @@ const createDemo = (defaultValue: boolean) =>
function handleClick() {
visible.value = !visible.value
}
const t0 = template('<button>toggle</button><h1>hello world</h1>')
const t0 = template(
'<div><button>toggle</button><h1>hello world</h1></div>',
)
const n0 = t0()
const n1 = children(n0, 0)
const n2 = children(n0, 1)
@ -23,11 +25,13 @@ describe('directive: v-show', () => {
test('basic', async () => {
const { host } = createDemo(true).render()
const btn = host.querySelector('button')
expect(host.innerHTML).toBe('<button>toggle</button><h1>hello world</h1>')
expect(host.innerHTML).toBe(
'<div><button>toggle</button><h1>hello world</h1></div>',
)
btn?.click()
await nextTick()
expect(host.innerHTML).toBe(
'<button>toggle</button><h1 style="display: none;">hello world</h1>',
'<div><button>toggle</button><h1 style="display: none;">hello world</h1></div>',
)
})
test('should hide content when default value is false', async () => {

View File

@ -1,30 +1,15 @@
import { isArray } from '@vue/shared'
/*! #__NO_SIDE_EFFECTS__ */
export function template(str: string): () => ChildNode[] {
let cached = false
let node: DocumentFragment
return () => {
if (!cached) {
cached = true
export function template(html: string) {
let node: ChildNode
const create = () => {
// eslint-disable-next-line no-restricted-globals
const t = document.createElement('template')
t.innerHTML = str
// first render: insert the node directly.
// this removes it from the template fragment to avoid keeping two copies
// of the inserted tree in memory, even if the template is used only once.
return fragmentToNodes((node = t.content))
} else {
// repeated renders: clone from cache. This is more performant and
// efficient when dealing with big lists where the template is repeated
// many times.
return fragmentToNodes(node)
t.innerHTML = html
return t.content.firstChild!
}
}
}
function fragmentToNodes(node: DocumentFragment): ChildNode[] {
return Array.from((node.cloneNode(true) as DocumentFragment).childNodes)
return () => (node || (node = create())).cloneNode(true)
}
/*! #__NO_SIDE_EFFECTS__ */