refactor: drop recordPropMetadata + merge renderEffect (#301)

This commit is contained in:
edison 2024-12-11 14:02:34 +08:00 committed by GitHub
parent a3edc274e4
commit 1bb9a0f8c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 772 additions and 394 deletions

View File

@ -1,12 +1,13 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compile > bindings 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
_renderEffect(() => _setText(n0, "count is ", _ctx.count, "."))
let _count
_renderEffect(() => _count !== _ctx.count && _setText(n0, "count is ", (_count = _ctx.count), "."))
return n0
}"
`;
@ -151,7 +152,7 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
`;
exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, createTextNode as _createTextNode, insert as _insert, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, createTextNode as _createTextNode, insert as _insert, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
const t1 = _template("<div></div>")
@ -162,7 +163,8 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
const n1 = _createComponent(_component_Comp)
const n2 = _createTextNode(() => [_ctx.bar])
_insert([n1, n2], n3)
_renderEffect(() => _setDOMProp(n3, "id", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setDOMProp(n3, "id", (_foo = _ctx.foo)))
return [n0, n3]
}"
`;
@ -177,7 +179,7 @@ export function render(_ctx) {
`;
exports[`compile > dynamic root nodes and interpolation 1`] = `
"import { delegate as _delegate, setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setText as _setText, setDOMProp as _setDOMProp, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
"import { delegate as _delegate, setInheritAttrs as _setInheritAttrs, setText as _setText, setDOMProp as _setDOMProp, renderEffect as _renderEffect, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
const t0 = _template("<button></button>")
_delegateEvents("click")
@ -185,8 +187,14 @@ export function render(_ctx) {
const n0 = t0()
_delegate(n0, "click", () => _ctx.handleClick)
_setInheritAttrs(["id"])
_renderEffect(() => _setText(n0, _ctx.count, "foo", _ctx.count, "foo", _ctx.count))
_renderEffect(() => _setDOMProp(n0, "id", _ctx.count))
let _count
_renderEffect(() => {
if(_count !== _ctx.count) {
_setText(n0, _ctx.count, "foo", _ctx.count, "foo", _ctx.count)
_setDOMProp(n0, "id", _ctx.count)
_count = _ctx.count
}
})
return n0
}"
`;
@ -202,7 +210,8 @@ exports[`compile > expression parsing > v-bind 1`] = `
"((_ctx) => {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ [key.value+1]: _unref(foo)[key.value+1]() }], true))
let _key_value, _foo, _key_value_foo
_renderEffect(() => (_key_value !== key.value || _foo !== _unref(foo)) && (_key_value_foo = _setDynamicProps(n0, _key_value_foo, [{ [key.value+1]: _unref(foo)[key.value+1]() }], true)))
return n0
})()"
`;

View File

@ -194,7 +194,9 @@ describe('compile', () => {
})
expect(code).matchSnapshot()
expect(code).contains('key.value+1')
expect(code).contains('_unref(foo)[key.value+1]()')
expect(code).contains(
'(_key_value !== key.value || _foo !== _unref(foo)) && (_key_value_foo = _setDynamicProps(n0, _key_value_foo, [{ [key.value+1]: _unref(foo)[key.value+1]() }], true))',
)
})
// TODO: add more test for expression parsing (v-on, v-slot, v-for)

View File

@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: children transform > children & sibling references 1`] = `
"import { next as _next, createTextNode as _createTextNode, insert as _insert, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { next as _next, createTextNode as _createTextNode, insert as _insert, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div><p></p> <!><p></p></div>")
export function render(_ctx) {
@ -11,8 +11,11 @@ export function render(_ctx) {
const n2 = n3.nextSibling
const n1 = _createTextNode(() => [_ctx.second, " ", _ctx.third, " "])
_insert(n1, n4, n3)
_renderEffect(() => _setText(n0, _ctx.first))
_renderEffect(() => _setText(n2, _ctx.forth))
let _first, _forth
_renderEffect(() => {
_first !== _ctx.first && _setText(n0, (_first = _ctx.first))
_forth !== _ctx.forth && _setText(n2, (_forth = _ctx.forth))
})
return n4
}"
`;

View File

@ -297,13 +297,14 @@ export function render(_ctx) {
`;
exports[`compiler: element transform > props merging: class 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setClass as _setClass, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["class"])
_renderEffect(() => _setClass(n0, ["foo", { bar: _ctx.isBar }], true))
let _isBar
_renderEffect(() => _isBar !== _ctx.isBar && _setClass(n0, ["foo", { bar: (_isBar = _ctx.isBar) }], true))
return n0
}"
`;
@ -326,7 +327,7 @@ export function render(_ctx) {
`;
exports[`compiler: element transform > props merging: style 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
@ -349,55 +350,59 @@ export function render(_ctx) {
`;
exports[`compiler: element transform > v-bind="obj" 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj], true))
let _obj
_renderEffect(() => _obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [_ctx.obj], true)))
return n0
}"
`;
exports[`compiler: element transform > v-bind="obj" after static prop 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj], true))
let _obj
_renderEffect(() => _obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [{ id: "foo" }, _ctx.obj], true)))
return n0
}"
`;
exports[`compiler: element transform > v-bind="obj" before static prop 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj, { id: "foo" }], true))
let _obj
_renderEffect(() => _obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [_ctx.obj, { id: "foo" }], true)))
return n0
}"
`;
exports[`compiler: element transform > v-bind="obj" between static props 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true))
let _obj
_renderEffect(() => _obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true)))
return n0
}"
`;
exports[`compiler: element transform > v-on="obj" 1`] = `
"import { renderEffect as _renderEffect, setDynamicEvents as _setDynamicEvents, template as _template } from 'vue/vapor';
"import { setDynamicEvents as _setDynamicEvents, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {

View File

@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: template ref transform > dynamic ref 1`] = `
"import { renderEffect as _renderEffect, setRef as _setRef, template as _template } from 'vue/vapor';
"import { setRef as _setRef, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {

View File

@ -1,366 +1,401 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler v-bind > .attr modifier 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["foo-bar"])
_renderEffect(() => _setAttr(n0, "foo-bar", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && _setAttr(n0, "foo-bar", (_id = _ctx.id)))
return n0
}"
`;
exports[`compiler v-bind > .attr modifier w/ innerHTML 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["innerHTML"])
_renderEffect(() => _setAttr(n0, "innerHTML", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setAttr(n0, "innerHTML", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .attr modifier w/ no expression 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["foo-bar"])
_renderEffect(() => _setAttr(n0, "foo-bar", _ctx.fooBar))
let _fooBar
_renderEffect(() => _fooBar !== _ctx.fooBar && _setAttr(n0, "foo-bar", (_fooBar = _ctx.fooBar)))
return n0
}"
`;
exports[`compiler v-bind > .attr modifier w/ progress value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<progress></progress>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setAttr(n0, "value", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setAttr(n0, "value", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .attr modifier w/ textContent 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["textContent"])
_renderEffect(() => _setAttr(n0, "textContent", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setAttr(n0, "textContent", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .attr modifier w/ value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setAttr(n0, "value", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setAttr(n0, "value", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .camel modifier 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && (_id = _setDynamicProp(n0, "fooBar", _id, _ctx.id)))
return n0
}"
`;
exports[`compiler v-bind > .camel modifier w/ dynamic arg 1`] = `
"import { camelize as _camelize } from 'vue';
import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }], true))
let _foo, _id, _foo_id
_renderEffect(() => (_foo !== _ctx.foo || _id !== _ctx.id) && (_foo_id = _setDynamicProps(n0, _foo_id, [{ [_camelize(_ctx.foo)]: _ctx.id }], true)))
return n0
}"
`;
exports[`compiler v-bind > .camel modifier w/ no expression 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.fooBar))
let _fooBar
_renderEffect(() => _fooBar !== _ctx.fooBar && (_fooBar = _setDynamicProp(n0, "fooBar", _fooBar, _ctx.fooBar)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && _setDOMProp(n0, "fooBar", (_id = _ctx.id)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) w/ innerHTML 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setHtml as _setHtml, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["innerHTML"])
_renderEffect(() => _setHtml(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) w/ no expression 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar))
let _fooBar
_renderEffect(() => _fooBar !== _ctx.fooBar && _setDOMProp(n0, "fooBar", (_fooBar = _ctx.fooBar)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) w/ progress value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<progress></progress>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setDOMProp(n0, "value", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setDOMProp(n0, "value", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) w/ textContent 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["textContent"])
_renderEffect(() => _setText(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier (shorthand) w/ value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setValue as _setValue, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setValue as _setValue, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setValue(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && _setDOMProp(n0, "fooBar", (_id = _ctx.id)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ dynamic arg 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }], true))
let _fooBar, _id, _fooBar_id
_renderEffect(() => (_fooBar !== _ctx.fooBar || _id !== _ctx.id) && (_fooBar_id = _setDynamicProps(n0, _fooBar_id, [{ ["." + _ctx.fooBar]: _ctx.id }], true)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ innerHTML 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setHtml as _setHtml, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["innerHTML"])
_renderEffect(() => _setHtml(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ no expression 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["fooBar"])
_renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar))
let _fooBar
_renderEffect(() => _fooBar !== _ctx.fooBar && _setDOMProp(n0, "fooBar", (_fooBar = _ctx.fooBar)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ progress value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<progress></progress>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setDOMProp(n0, "value", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setDOMProp(n0, "value", (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ textContent 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["textContent"])
_renderEffect(() => _setText(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > .prop modifier w/ value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setValue as _setValue, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setValue as _setValue, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setValue(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > :innerHTML 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setHtml as _setHtml, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["innerHTML"])
_renderEffect(() => _setHtml(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > :textContext 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["textContent"])
_renderEffect(() => _setText(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > :value 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setValue as _setValue, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setValue as _setValue, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setValue(n0, _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > :value w/ progress 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<progress></progress>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["value"])
_renderEffect(() => _setDynamicProp(n0, "value", _ctx.foo))
let _foo
_renderEffect(() => _foo !== _ctx.foo && (_foo = _setDynamicProp(n0, "value", _foo, _ctx.foo)))
return n0
}"
`;
exports[`compiler v-bind > HTML global attributes should set as dom prop 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["id", "title", "lang", "dir", "tabindex"])
_renderEffect(() => _setDOMProp(n0, "id", _ctx.id))
_renderEffect(() => _setDOMProp(n0, "title", _ctx.title))
_renderEffect(() => _setDOMProp(n0, "lang", _ctx.lang))
_renderEffect(() => _setDOMProp(n0, "dir", _ctx.dir))
_renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex))
let _id, _title, _lang, _dir, _tabindex
_renderEffect(() => {
_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))
_title !== _ctx.title && _setDOMProp(n0, "title", (_title = _ctx.title))
_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))
_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))
_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))
})
return n0
}"
`;
exports[`compiler v-bind > MathML global attributes should set as dom prop 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<math></math>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["autofucus", "dir", "displaystyle", "mathcolor", "tabindex"])
_renderEffect(() => _setDOMProp(n0, "autofucus", _ctx.autofucus))
_renderEffect(() => _setDOMProp(n0, "dir", _ctx.dir))
_renderEffect(() => _setDOMProp(n0, "displaystyle", _ctx.displaystyle))
_renderEffect(() => _setDOMProp(n0, "mathcolor", _ctx.mathcolor))
_renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex))
let _autofucus, _dir, _displaystyle, _mathcolor, _tabindex
_renderEffect(() => {
_autofucus !== _ctx.autofucus && _setDOMProp(n0, "autofucus", (_autofucus = _ctx.autofucus))
_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))
_displaystyle !== _ctx.displaystyle && _setDOMProp(n0, "displaystyle", (_displaystyle = _ctx.displaystyle))
_mathcolor !== _ctx.mathcolor && _setDOMProp(n0, "mathcolor", (_mathcolor = _ctx.mathcolor))
_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))
})
return n0
}"
`;
exports[`compiler v-bind > SVG global attributes should set as dom prop 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<svg></svg>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["id", "lang", "tabindex"])
_renderEffect(() => _setDOMProp(n0, "id", _ctx.id))
_renderEffect(() => _setDOMProp(n0, "lang", _ctx.lang))
_renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex))
let _id, _lang, _tabindex
_renderEffect(() => {
_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))
_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))
_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))
})
return n0
}"
`;
exports[`compiler v-bind > attributes must be set as attribute 1`] = `
"import { renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor';
"import { setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("<input>")
const t2 = _template("<textarea></textarea>")
@ -377,84 +412,106 @@ export function render(_ctx) {
const n4 = t4()
const n5 = t5()
const n6 = t6()
_renderEffect(() => _setAttr(n0, "spellcheck", _ctx.spellcheck))
_renderEffect(() => _setAttr(n0, "draggable", _ctx.draggable))
_renderEffect(() => _setAttr(n0, "translate", _ctx.translate))
_renderEffect(() => _setAttr(n0, "form", _ctx.form))
_renderEffect(() => _setAttr(n1, "list", _ctx.list))
_renderEffect(() => _setAttr(n2, "type", _ctx.type))
let _spellcheck, _draggable, _translate, _form, _list, _type, _width, _height
_renderEffect(() => {
_spellcheck !== _ctx.spellcheck && _setAttr(n0, "spellcheck", (_spellcheck = _ctx.spellcheck))
_draggable !== _ctx.draggable && _setAttr(n0, "draggable", (_draggable = _ctx.draggable))
_translate !== _ctx.translate && _setAttr(n0, "translate", (_translate = _ctx.translate))
_form !== _ctx.form && _setAttr(n0, "form", (_form = _ctx.form))
_list !== _ctx.list && _setAttr(n1, "list", (_list = _ctx.list))
_type !== _ctx.type && _setAttr(n2, "type", (_type = _ctx.type))
if(_width !== _ctx.width) {
_setAttr(n3, "width", _ctx.width)
_setAttr(n4, "width", _ctx.width)
_setAttr(n5, "width", _ctx.width)
_setAttr(n6, "width", _ctx.width)
})
_renderEffect(() => {
_width = _ctx.width
}
if(_height !== _ctx.height) {
_setAttr(n3, "height", _ctx.height)
_setAttr(n4, "height", _ctx.height)
_setAttr(n5, "height", _ctx.height)
_setAttr(n6, "height", _ctx.height)
_height = _ctx.height
}
})
return [n0, n1, n2, n3, n4, n5, n6]
}"
`;
exports[`compiler v-bind > basic 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["id"])
_renderEffect(() => _setDOMProp(n0, "id", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id)))
return n0
}"
`;
exports[`compiler v-bind > bind member expression 1`] = `
"import { setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
let _obj
_renderEffect(() => _obj !== _ctx.obj.count.bar && _setDOMProp(n0, "id", (_obj = _ctx.obj.count.bar)))
return [n0, n1]
}"
`;
exports[`compiler v-bind > dynamic arg 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true))
let _id, _title, _id_title
_renderEffect(() => (_id !== _ctx.id || _title !== _ctx.title) && (_id_title = _setDynamicProps(n0, _id_title, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true)))
return n0
}"
`;
exports[`compiler v-bind > dynamic arg w/ static attribute 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true))
let _id
_renderEffect(() => _id !== _ctx.id && (_id = _setDynamicProps(n0, _id, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true)))
return n0
}"
`;
exports[`compiler v-bind > no expression (shorthand) 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDynamicProp as _setDynamicProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["camel-case"])
_renderEffect(() => _setDynamicProp(n0, "camel-case", _ctx.camelCase))
let _camelCase
_renderEffect(() => _camelCase !== _ctx.camelCase && (_camelCase = _setDynamicProp(n0, "camel-case", _camelCase, _ctx.camelCase)))
return n0
}"
`;
exports[`compiler v-bind > no expression 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_setInheritAttrs(["id"])
_renderEffect(() => _setDOMProp(n0, "id", _ctx.id))
let _id
_renderEffect(() => _id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id)))
return n0
}"
`;

View File

@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-for > array de-structured value 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
@ -15,7 +15,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > basic v-for 1`] = `
"import { delegate as _delegate, renderEffect as _renderEffect, setText as _setText, createFor as _createFor, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
"import { delegate as _delegate, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
_delegateEvents("click")
@ -31,7 +31,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > function params w/ prefixIdentifiers: false 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
@ -45,15 +45,17 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > multi effect 1`] = `
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setInheritAttrs as _setInheritAttrs, 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 n0 = _createFor(() => (_ctx.items), (_ctx0) => {
const n2 = t0()
_setInheritAttrs(["item", "index"])
_renderEffect(() => _setDynamicProp(n2, "item", _ctx0[0].value))
_renderEffect(() => _setDynamicProp(n2, "index", _ctx0[1].value))
_renderEffect(() => {
_setDynamicProp(n2, "item", _ctx0[0].value)
_setDynamicProp(n2, "index", _ctx0[1].value)
})
return n2
})
return n0
@ -61,7 +63,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > nested v-for 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, insert as _insert, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, createFor as _createFor, insert as _insert, template as _template } from 'vue/vapor';
const t0 = _template("<span></span>")
const t1 = _template("<div></div>")
@ -81,7 +83,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > object de-structured value 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
@ -95,7 +97,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-for > v-for aliases w/ complex expressions 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {

View File

@ -1,23 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-html > should convert v-html to innerHTML 1`] = `
"import { renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setHtml as _setHtml, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
_renderEffect(() => _setHtml(n0, _ctx.code))
let _code
_renderEffect(() => _code !== _ctx.code && _setHtml(n0, (_code = _ctx.code)))
return n0
}"
`;
exports[`v-html > should raise error and ignore children when v-html is present 1`] = `
"import { renderEffect as _renderEffect, setHtml as _setHtml, template as _template } from 'vue/vapor';
"import { setHtml as _setHtml, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setHtml(n0, _ctx.test))
let _test
_renderEffect(() => _test !== _ctx.test && _setHtml(n0, (_test = _ctx.test)))
return n0
}"
`;

View File

@ -1,13 +1,14 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compiler: v-if > basic v-if 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = _createIf(() => (_ctx.ok), () => {
const n2 = t0()
_renderEffect(() => _setText(n2, _ctx.msg))
let _msg
_renderEffect(() => _msg !== _ctx.msg && _setText(n2, (_msg = _ctx.msg)))
return n2
})
return n0
@ -15,7 +16,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-if > comment between branches 1`] = `
"import { createIf as _createIf, renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { createIf as _createIf, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("<!--foo-->")
const t2 = _template("<p></p>")
@ -37,7 +38,8 @@ export function render(_ctx) {
const n11 = t4()
return [n10, n11]
}))
_renderEffect(() => _setText(n13, _ctx.text))
let _text
_renderEffect(() => _text !== _ctx.text && _setText(n13, (_text = _ctx.text)))
return [n0, n13]
}"
`;
@ -60,7 +62,7 @@ export function render(_ctx) {
`;
exports[`compiler: v-if > template v-if 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, createIf as _createIf, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
const t1 = _template("hello")
const t2 = _template("<p></p>")
@ -70,7 +72,8 @@ export function render(_ctx) {
const n2 = t0()
const n3 = t1()
const n4 = t2()
_renderEffect(() => _setText(n4, _ctx.msg))
let _msg
_renderEffect(() => _msg !== _ctx.msg && _setText(n4, (_msg = _ctx.msg)))
return [n2, n3, n4]
})
return n0

View File

@ -246,7 +246,7 @@ export function render(_ctx) {
`;
exports[`compiler: vModel transform > should support w/ dynamic v-bind 1`] = `
"import { vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, delegate as _delegate, setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor';
"import { vModelDynamic as _vModelDynamic, withDirectives as _withDirectives, delegate as _delegate, setInheritAttrs as _setInheritAttrs, setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<input>")
export function render(_ctx) {
@ -254,7 +254,8 @@ export function render(_ctx) {
_withDirectives(n0, [[_vModelDynamic, () => _ctx.model]])
_delegate(n0, "update:modelValue", () => $event => (_ctx.model = $event))
_setInheritAttrs(true)
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj], true))
let _obj
_renderEffect(() => _obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [_ctx.obj], true)))
return n0
}"
`;

View File

@ -13,12 +13,13 @@ export function render(_ctx) {
`;
exports[`v-on > dynamic arg 1`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, _ctx.event, () => _ctx.handler, {
effect: true
})
@ -28,12 +29,13 @@ export function render(_ctx) {
`;
exports[`v-on > dynamic arg with complex exp prefixing 1`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, _ctx.event(_ctx.foo), () => _ctx.handler, {
effect: true
})
@ -43,12 +45,13 @@ export function render(_ctx) {
`;
exports[`v-on > dynamic arg with prefixing 1`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, _ctx.event, () => _ctx.handler, {
effect: true
})
@ -372,12 +375,13 @@ export function render(_ctx) {
`;
exports[`v-on > should transform click.middle 2`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, {
modifiers: ["middle"],
effect: true
@ -402,12 +406,13 @@ export function render(_ctx) {
`;
exports[`v-on > should transform click.right 2`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, {
modifiers: ["right"],
keys: ["right"],
@ -431,12 +436,13 @@ export function render(_ctx) {
`;
exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = `
"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor';
"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
_on(n0, _ctx.e, () => _ctx.test, {
modifiers: ["left"],
keys: ["left"],

View File

@ -1,23 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-text > should convert v-text to textContent 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx, $props, $emit, $attrs, $slots) {
const n0 = t0()
_renderEffect(() => _setText(n0, _ctx.str))
let _str
_renderEffect(() => _str !== _ctx.str && _setText(n0, (_str = _ctx.str)))
return n0
}"
`;
exports[`v-text > should raise error and ignore children when v-text is present 1`] = `
"import { renderEffect as _renderEffect, setText as _setText, template as _template } from 'vue/vapor';
"import { setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue/vapor';
const t0 = _template("<div></div>")
export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setText(n0, _ctx.test))
let _test
_renderEffect(() => _test !== _ctx.test && _setText(n0, (_test = _ctx.test)))
return n0
}"
`;

View File

@ -588,7 +588,9 @@ describe('compiler: element transform', () => {
],
},
])
expect(code).contains('_setDynamicProps(n0, [_ctx.obj], true)')
expect(code).contains(
'_obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [_ctx.obj], true))',
)
})
test('v-bind="obj" after static prop', () => {
@ -625,7 +627,7 @@ describe('compiler: element transform', () => {
},
])
expect(code).contains(
'_setDynamicProps(n0, [{ id: "foo" }, _ctx.obj], true)',
'_obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [{ id: "foo" }, _ctx.obj], true))',
)
})
@ -653,7 +655,7 @@ describe('compiler: element transform', () => {
},
])
expect(code).contains(
'_setDynamicProps(n0, [_ctx.obj, { id: "foo" }], true)',
'_obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [_ctx.obj, { id: "foo" }], true))',
)
})
@ -682,7 +684,7 @@ describe('compiler: element transform', () => {
},
])
expect(code).contains(
'_setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true)',
'_obj !== _ctx.obj && (_obj = _setDynamicProps(n0, _obj, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true))',
)
})

View File

@ -74,7 +74,9 @@ describe('compiler v-bind', () => {
})
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "id", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
)
})
test('no expression', () => {
@ -104,7 +106,9 @@ describe('compiler v-bind', () => {
],
},
})
expect(code).contains('_setDOMProp(n0, "id", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
)
})
test('no expression (shorthand)', () => {
@ -126,7 +130,9 @@ describe('compiler v-bind', () => {
],
},
})
expect(code).contains('_setDynamicProp(n0, "camel-case", _ctx.camelCase)')
expect(code).contains(
'_camelCase !== _ctx.camelCase && (_camelCase = _setDynamicProp(n0, "camel-case", _camelCase, _ctx.camelCase))',
)
})
test('dynamic arg', () => {
@ -171,7 +177,7 @@ describe('compiler v-bind', () => {
],
})
expect(code).contains(
'_setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true)',
'(_id !== _ctx.id || _title !== _ctx.title) && (_id_title = _setDynamicProps(n0, _id_title, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true))',
)
})
@ -224,7 +230,7 @@ describe('compiler v-bind', () => {
],
})
expect(code).contains(
'_setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true)',
'_id !== _ctx.id && (_id = _setDynamicProps(n0, _id, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true))',
)
})
@ -286,7 +292,9 @@ describe('compiler v-bind', () => {
})
expect(code).matchSnapshot()
expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && (_id = _setDynamicProp(n0, "fooBar", _id, _ctx.id))',
)
})
test('.camel modifier w/ no expression', () => {
@ -310,7 +318,9 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.fooBar)')
expect(code).contains(
'_fooBar !== _ctx.fooBar && (_fooBar = _setDynamicProp(n0, "fooBar", _fooBar, _ctx.fooBar))',
)
})
test('.camel modifier w/ dynamic arg', () => {
@ -341,7 +351,7 @@ describe('compiler v-bind', () => {
expect(code).matchSnapshot()
expect(code).contains('renderEffect')
expect(code).contains(
`_setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }], true)`,
`(_foo !== _ctx.foo || _id !== _ctx.id) && (_foo_id = _setDynamicProps(n0, _foo_id, [{ [_camelize(_ctx.foo)]: _ctx.id }], true))`,
)
})
@ -368,7 +378,9 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "fooBar", (_id = _ctx.id))',
)
})
test('.prop modifier w/ no expression', () => {
@ -392,7 +404,9 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)')
expect(code).contains(
'_fooBar !== _ctx.fooBar && _setDOMProp(n0, "fooBar", (_fooBar = _ctx.fooBar))',
)
})
test('.prop modifier w/ dynamic arg', () => {
@ -422,7 +436,7 @@ describe('compiler v-bind', () => {
})
expect(code).contains('renderEffect')
expect(code).contains(
`_setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }], true)`,
`(_fooBar !== _ctx.fooBar || _id !== _ctx.id) && (_fooBar_id = _setDynamicProps(n0, _fooBar_id, [{ ["." + _ctx.fooBar]: _ctx.id }], true))`,
)
})
@ -449,7 +463,9 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "fooBar", (_id = _ctx.id))',
)
})
test('.prop modifier (shorthand) w/ no expression', () => {
@ -473,55 +489,73 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)')
expect(code).contains(
'_fooBar !== _ctx.fooBar && _setDOMProp(n0, "fooBar", (_fooBar = _ctx.fooBar))',
)
})
test('.prop modifier w/ innerHTML', () => {
const { code } = compileWithVBind(`<div :innerHTML.prop="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setHtml(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier (shorthand) w/ innerHTML', () => {
const { code } = compileWithVBind(`<div .innerHTML="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setHtml(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier w/ textContent', () => {
const { code } = compileWithVBind(`<div :textContent.prop="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setText(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier (shorthand) w/ textContent', () => {
const { code } = compileWithVBind(`<div .textContent="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setText(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier w/ value', () => {
const { code } = compileWithVBind(`<div :value.prop="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setValue(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier (shorthand) w/ value', () => {
const { code } = compileWithVBind(`<div .value="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setValue(n0, _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo))',
)
})
test('.prop modifier w/ progress value', () => {
const { code } = compileWithVBind(`<progress :value.prop="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "value", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setDOMProp(n0, "value", (_foo = _ctx.foo))',
)
})
test('.prop modifier (shorthand) w/ progress value', () => {
const { code } = compileWithVBind(`<progress .value="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "value", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setDOMProp(n0, "value", (_foo = _ctx.foo))',
)
})
test('.attr modifier', () => {
@ -545,7 +579,9 @@ describe('compiler v-bind', () => {
},
})
expect(code).contains('renderEffect')
expect(code).contains('_setAttr(n0, "foo-bar", _ctx.id)')
expect(code).contains(
'_id !== _ctx.id && _setAttr(n0, "foo-bar", (_id = _ctx.id))',
)
})
test('.attr modifier w/ no expression', () => {
@ -570,31 +606,41 @@ describe('compiler v-bind', () => {
})
expect(code).contains('renderEffect')
expect(code).contains('_setAttr(n0, "foo-bar", _ctx.fooBar)')
expect(code).contains(
'_fooBar !== _ctx.fooBar && _setAttr(n0, "foo-bar", (_fooBar = _ctx.fooBar))',
)
})
test('.attr modifier w/ innerHTML', () => {
const { code } = compileWithVBind(`<div :innerHTML.attr="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setAttr(n0, "innerHTML", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setAttr(n0, "innerHTML", (_foo = _ctx.foo))',
)
})
test('.attr modifier w/ textContent', () => {
const { code } = compileWithVBind(`<div :textContent.attr="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setAttr(n0, "textContent", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setAttr(n0, "textContent", (_foo = _ctx.foo))',
)
})
test('.attr modifier w/ value', () => {
const { code } = compileWithVBind(`<div :value.attr="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setAttr(n0, "value", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setAttr(n0, "value", (_foo = _ctx.foo))',
)
})
test('.attr modifier w/ progress value', () => {
const { code } = compileWithVBind(`<progress :value.attr="foo" />`)
expect(code).matchSnapshot()
expect(code).contains('_setAttr(n0, "value", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && _setAttr(n0, "value", (_foo = _ctx.foo))',
)
})
test('attributes must be set as attribute', () => {
@ -609,20 +655,35 @@ describe('compiler v-bind', () => {
`)
expect(code).matchSnapshot()
expect(code).contains('_setAttr(n0, "spellcheck", _ctx.spellcheck)')
expect(code).contains('_setAttr(n0, "draggable", _ctx.draggable)')
expect(code).contains('_setAttr(n0, "translate", _ctx.translate)')
expect(code).contains('_setAttr(n0, "form", _ctx.form)')
expect(code).contains('_setAttr(n1, "list", _ctx.list)')
expect(code).contains('_setAttr(n2, "type", _ctx.type)')
expect(code).contains(
'_spellcheck !== _ctx.spellcheck && _setAttr(n0, "spellcheck", (_spellcheck = _ctx.spellcheck))',
)
expect(code).contains(
'_draggable !== _ctx.draggable && _setAttr(n0, "draggable", (_draggable = _ctx.draggable))',
)
expect(code).contains(
'_translate !== _ctx.translate && _setAttr(n0, "translate", (_translate = _ctx.translate))',
)
expect(code).contains(
'_form !== _ctx.form && _setAttr(n0, "form", (_form = _ctx.form))',
)
expect(code).contains(
'_list !== _ctx.list && _setAttr(n1, "list", (_list = _ctx.list))',
)
expect(code).contains(
'_type !== _ctx.type && _setAttr(n2, "type", (_type = _ctx.type))',
)
expect(code).contains('if(_width !== _ctx.width) {')
expect(code).contains('if(_height !== _ctx.height) {')
expect(code).contains('_height = _ctx.height')
expect(code).contains('_height = _ctx.height')
expect(code).contains('_setAttr(n3, "width", _ctx.width)')
expect(code).contains('_setAttr(n3, "height", _ctx.height)')
expect(code).contains('_setAttr(n4, "width", _ctx.width)')
expect(code).contains('_setAttr(n4, "height", _ctx.height)')
expect(code).contains('_setAttr(n5, "width", _ctx.width)')
expect(code).contains('_setAttr(n5, "height", _ctx.height)')
expect(code).contains('_setAttr(n6, "width", _ctx.width)')
expect(code).contains('_setAttr(n6, "height", _ctx.height)')
expect(code).contains(' _setAttr(n6, "width", _ctx.width)')
})
test('HTML global attributes should set as dom prop', () => {
@ -631,11 +692,21 @@ describe('compiler v-bind', () => {
`)
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "id", _ctx.id)')
expect(code).contains('_setDOMProp(n0, "title", _ctx.title)')
expect(code).contains('_setDOMProp(n0, "lang", _ctx.lang)')
expect(code).contains('_setDOMProp(n0, "dir", _ctx.dir)')
expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
)
expect(code).contains(
'_title !== _ctx.title && _setDOMProp(n0, "title", (_title = _ctx.title))',
)
expect(code).contains(
'_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))',
)
expect(code).contains(
'_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))',
)
expect(code).contains(
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
)
})
test('SVG global attributes should set as dom prop', () => {
@ -644,9 +715,15 @@ describe('compiler v-bind', () => {
`)
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "id", _ctx.id)')
expect(code).contains('_setDOMProp(n0, "lang", _ctx.lang)')
expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex)')
expect(code).contains(
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
)
expect(code).contains(
'_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))',
)
expect(code).contains(
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
)
})
test('MathML global attributes should set as dom prop', () => {
@ -655,11 +732,21 @@ describe('compiler v-bind', () => {
`)
expect(code).matchSnapshot()
expect(code).contains('_setDOMProp(n0, "autofucus", _ctx.autofucus)')
expect(code).contains('_setDOMProp(n0, "dir", _ctx.dir)')
expect(code).contains('_setDOMProp(n0, "displaystyle", _ctx.displaystyle)')
expect(code).contains('_setDOMProp(n0, "mathcolor", _ctx.mathcolor)')
expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex)')
expect(code).contains(
'_autofucus !== _ctx.autofucus && _setDOMProp(n0, "autofucus", (_autofucus = _ctx.autofucus))',
)
expect(code).contains(
'_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))',
)
expect(code).contains(
'_displaystyle !== _ctx.displaystyle && _setDOMProp(n0, "displaystyle", (_displaystyle = _ctx.displaystyle))',
)
expect(code).contains(
'_mathcolor !== _ctx.mathcolor && _setDOMProp(n0, "mathcolor", (_mathcolor = _ctx.mathcolor))',
)
expect(code).contains(
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
)
})
test(':innerHTML', () => {
@ -667,7 +754,10 @@ describe('compiler v-bind', () => {
<div :innerHTML="foo"/>
`)
expect(code).matchSnapshot()
expect(code).contains('_setHtml(n0, _ctx.foo)')
expect(code).contains('let _foo')
expect(code).contains(
'_foo !== _ctx.foo && _setHtml(n0, (_foo = _ctx.foo))',
)
})
test(':textContext', () => {
@ -675,7 +765,10 @@ describe('compiler v-bind', () => {
<div :textContent="foo"/>
`)
expect(code).matchSnapshot()
expect(code).contains('_setText(n0, _ctx.foo)')
expect(code).contains('let _foo')
expect(code).contains(
'_foo !== _ctx.foo && _setText(n0, (_foo = _ctx.foo))',
)
})
test(':value', () => {
@ -683,7 +776,10 @@ describe('compiler v-bind', () => {
<input :value="foo"/>
`)
expect(code).matchSnapshot()
expect(code).contains('_setValue(n0, _ctx.foo)')
expect(code).contains('let _foo')
expect(code).contains(
'_foo !== _ctx.foo && _setValue(n0, (_foo = _ctx.foo))',
)
})
test(':value w/ progress', () => {
@ -691,7 +787,19 @@ describe('compiler v-bind', () => {
<progress :value="foo"/>
`)
expect(code).matchSnapshot()
expect(code).contains('_setDynamicProp(n0, "value", _ctx.foo)')
expect(code).contains(
'_foo !== _ctx.foo && (_foo = _setDynamicProp(n0, "value", _foo, _ctx.foo))',
)
})
test('bind member expression', () => {
const { code } = compileWithVBind(`
<div :id="obj.count.bar"></div>/>
`)
expect(code).matchSnapshot()
expect(code).contains(
'_obj !== _ctx.obj.count.bar && _setDOMProp(n0, "id", (_obj = _ctx.obj.count.bar))',
)
})
test('number value', () => {

View File

@ -2,7 +2,7 @@ import type {
CodegenOptions as BaseCodegenOptions,
BaseCodegenResult,
} from '@vue/compiler-dom'
import type { BlockIRNode, RootIRNode, VaporHelper } from './ir'
import type { BlockIRNode, IREffect, RootIRNode, VaporHelper } from './ir'
import { extend, remove } from '@vue/shared'
import { genBlockContent } from './generators/block'
import { genTemplates } from './generators/template'
@ -35,6 +35,15 @@ export class CodegenContext {
delegates: Set<string> = new Set<string>()
processingRenderEffect: IREffect | undefined = undefined
allRenderEffectSeenNames: Record<string, number> = Object.create(null)
shouldCacheRenderEffectDeps = (): boolean => {
// only need to generate effect deps when it's not nested in v-for
return !!(
this.processingRenderEffect && !this.processingRenderEffect.inVFor
)
}
identifiers: Record<string, string[]> = Object.create(null)
block: BlockIRNode

View File

@ -1,4 +1,4 @@
import { isGloballyAllowed } from '@vue/shared'
import { isArray, isGloballyAllowed } from '@vue/shared'
import {
BindingTypes,
NewlineType,
@ -95,7 +95,14 @@ export function genExpression(
)
if (i === ids.length - 1 && end < content.length) {
push([content.slice(end), NewlineType.Unknown])
const rest = content.slice(end)
const last = frag[frag.length - 1]
if (hasMemberExpression && isArray(last)) {
// merge rest content into the last identifier's generated name
last[0] += rest
} else {
push([rest, NewlineType.Unknown])
}
}
})

View File

@ -2,18 +2,17 @@ import type { CodegenContext } from '../generate'
import type { SetHtmlIRNode } from '../ir'
import { genExpression } from './expression'
import { type CodeFragment, NEWLINE, genCall } from './utils'
import { processValues } from './prop'
export function genSetHtml(
oper: SetHtmlIRNode,
context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
return [
NEWLINE,
...genCall(
vaporHelper('setHtml'),
`n${oper.element}`,
genExpression(oper.value, context),
),
]
const { vaporHelper, shouldCacheRenderEffectDeps } = context
const { value, element } = oper
let html = genExpression(value, context)
if (shouldCacheRenderEffectDeps()) {
processValues(context, [html])
}
return [NEWLINE, ...genCall(vaporHelper('setHtml'), `n${element}`, html)]
}

View File

@ -78,9 +78,33 @@ export function genEffects(
effects: IREffect[],
context: CodegenContext,
): CodeFragment[] {
const [frag, push] = buildCodeFragment()
for (const effect of effects) {
push(...genEffect(effect, context))
const { vaporHelper } = context
const [frag, push, unshift] = buildCodeFragment()
const declareNames = new Set<string>()
let operationsCount = 0
for (let i = 0; i < effects.length; i++) {
const effect = (context.processingRenderEffect = effects[i])
operationsCount += effect.operations.length
const frags = genEffect(effect, context, declareNames)
const needSemi = frag[frag.length - 1] === ')' && frags[0] === '('
i > 0 && push(NEWLINE)
push(needSemi ? ';' : undefined, ...frags)
}
const newLineCount = frag.filter(frag => frag === NEWLINE).length
if (newLineCount > 1 || operationsCount > 1) {
unshift(`{`, INDENT_START, NEWLINE)
push(INDENT_END, NEWLINE, '}')
}
if (effects.length) {
unshift(NEWLINE, `${vaporHelper('renderEffect')}(() => `)
push(`)`)
}
// declare variables: let _foo, _bar
if (declareNames.size) {
frag.splice(1, 0, `let ${[...declareNames].join(', ')}`, NEWLINE)
}
return frag
}
@ -88,21 +112,50 @@ export function genEffects(
export function genEffect(
{ operations }: IREffect,
context: CodegenContext,
allDeclareNames: Set<string>,
): CodeFragment[] {
const { vaporHelper } = context
const [frag, push] = buildCodeFragment(
NEWLINE,
`${vaporHelper('renderEffect')}(() => `,
)
const { processingRenderEffect } = context
const [frag, push] = buildCodeFragment()
const { declareNames, earlyCheckExps } = processingRenderEffect!
const operationsExps = genOperations(operations, context)
const [operationsExps, pushOps] = buildCodeFragment()
operations.forEach(op => pushOps(...genOperation(op, context)))
if (declareNames.size) {
allDeclareNames.add([...declareNames].join(', '))
}
const newlineCount = operationsExps.filter(frag => frag === NEWLINE).length
if (newlineCount > 1) {
push('{', INDENT_START, ...operationsExps, INDENT_END, NEWLINE, '})')
// multiline check expression: if (_foo !== _ctx.foo || _bar !== _ctx.bar) {
const checkExpsStart: CodeFragment[] =
earlyCheckExps.length > 0
? [`if(`, ...earlyCheckExps.join(' || '), `) {`, INDENT_START]
: []
const checkExpsEnd: CodeFragment[] =
earlyCheckExps.length > 0 ? [INDENT_END, NEWLINE, '}'] : []
// assignment: _foo = _ctx.foo; _bar = _ctx.bar
const assignmentExps: CodeFragment[] =
earlyCheckExps.length > 0
? [NEWLINE, ...earlyCheckExps.map(c => c.replace('!==', '=')).join(';')]
: []
push(
...checkExpsStart,
...operationsExps,
...assignmentExps,
...checkExpsEnd,
)
} else {
push(...operationsExps.filter(frag => frag !== NEWLINE), ')')
// single line check expression: (_foo !== _ctx.foo || _bar !== _ctx.bar) &&
const multiple = earlyCheckExps.length > 1
const checkExps: CodeFragment[] =
earlyCheckExps.length > 0
? [
multiple ? `(` : undefined,
...earlyCheckExps.join(' || '),
multiple ? `)` : undefined,
' && ',
]
: []
push(...checkExps, ...operationsExps.filter(frag => frag !== NEWLINE))
}
return frag

View File

@ -24,6 +24,7 @@ import {
import {
attributeCache,
canSetValueDirectly,
isArray,
isHTMLGlobalAttr,
isHTMLTag,
isMathMLGlobalAttr,
@ -44,20 +45,30 @@ export function genSetProp(
prop: { key, values, modifier },
tag,
} = oper
const { helperName, omitKey } = getRuntimeHelper(tag, key.content, modifier)
const propValue = genPropValue(values, context)
const { prevValueName, shouldWrapInParentheses } = processPropValues(
context,
helperName,
[propValue],
)
return [
NEWLINE,
...(prevValueName
? [shouldWrapInParentheses ? `(` : undefined, `${prevValueName} = `]
: []),
...genCall(
[vaporHelper(helperName), null],
`n${oper.element}`,
omitKey ? false : genExpression(key, context),
genPropValue(values, context),
...(prevValueName ? [`${prevValueName}`] : []),
propValue,
// only `setClass` and `setStyle` need merge inherit attr
oper.root && (helperName === 'setClass' || helperName === 'setStyle')
? 'true'
: undefined,
),
...(prevValueName && shouldWrapInParentheses ? [`)`] : []),
]
}
@ -67,24 +78,31 @@ export function genDynamicProps(
context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
return [
NEWLINE,
...genCall(
vaporHelper('setDynamicProps'),
`n${oper.element}`,
genMulti(
DELIMITERS_ARRAY,
...oper.props.map(
props =>
const values = oper.props.map(props =>
Array.isArray(props)
? genLiteralObjectProps(props, context) // static and dynamic arg props
: props.kind === IRDynamicPropsKind.ATTRIBUTE
? genLiteralObjectProps([props], context) // dynamic arg props
: genExpression(props.value, context), // v-bind=""
),
),
: genExpression(props.value, context),
) // v-bind=""
const { prevValueName, shouldWrapInParentheses } = processPropValues(
context,
'setDynamicProps',
values,
)
return [
NEWLINE,
...(prevValueName
? [shouldWrapInParentheses ? `(` : undefined, `${prevValueName} = `]
: []),
...genCall(
vaporHelper('setDynamicProps'),
`n${oper.element}`,
...(prevValueName ? [`${prevValueName}`] : []),
genMulti(DELIMITERS_ARRAY, ...values),
oper.root && 'true',
),
...(prevValueName && shouldWrapInParentheses ? [`)`] : []),
]
}
@ -235,3 +253,95 @@ const getSpecialHelper = (
return specialHelpers[keyName] || null
}
// those runtime helpers will return the prevValue
const helpersNeedCachedReturnValue = [
'setStyle',
'setDynamicProp',
'setDynamicProps',
]
function processPropValues(
context: CodegenContext,
helperName: string,
values: CodeFragment[][],
): { prevValueName: string | undefined; shouldWrapInParentheses: boolean } {
const { shouldCacheRenderEffectDeps, processingRenderEffect } = context
// single-line render effect and the operation needs cache return a value,
// the expression needs to be wrapped in parentheses.
// e.g. _foo === _ctx.foo && (_foo = _setStyle(...))
let shouldWrapInParentheses: boolean = false
let prevValueName
if (shouldCacheRenderEffectDeps()) {
const needReturnValue = helpersNeedCachedReturnValue.includes(helperName)
processValues(context, values, !needReturnValue)
const { declareNames } = processingRenderEffect!
// if the operation needs to cache the return value and has multiple declareNames,
// combine them into a single name as the return value name.
if (declareNames.size > 0 && needReturnValue) {
prevValueName = [...declareNames].join('')
declareNames.add(prevValueName)
}
shouldWrapInParentheses = processingRenderEffect!.operations.length === 1
}
return { prevValueName, shouldWrapInParentheses }
}
export function processValues(
context: CodegenContext,
values: CodeFragment[][],
needRewrite: boolean = true,
): string[] {
const allCheckExps: string[] = []
values.forEach(value => {
const checkExps = processValue(context, value, needRewrite)
if (checkExps) allCheckExps.push(...checkExps, ' && ')
})
return allCheckExps.length > 0
? (context.processingRenderEffect!.earlyCheckExps = [
...new Set(allCheckExps),
])
: []
}
function processValue(
context: CodegenContext,
values: CodeFragment[],
needRewrite: boolean = true,
): string[] | undefined {
const { processingRenderEffect, allRenderEffectSeenNames } = context
const { declareNames, rewrittenNames, earlyCheckExps, operations } =
processingRenderEffect!
const isSingleLine = operations.length === 1
for (const frag of values) {
if (!isArray(frag)) continue
// [code, newlineIndex, loc, name] -> [(_name = code), newlineIndex, loc, name]
const [newName, , , rawName] = frag
if (rawName) {
let name = rawName.replace(/[^\w]/g, '_')
if (rewrittenNames.has(name)) continue
rewrittenNames.add(name)
name = `_${name}`
if (declareNames.has(name)) continue
if (allRenderEffectSeenNames[name] === undefined)
allRenderEffectSeenNames[name] = 0
else name += ++allRenderEffectSeenNames[name]
declareNames.add(name)
earlyCheckExps.push(`${name} !== ${newName}`)
if (needRewrite && isSingleLine) {
// replace the original code fragment with the assignment expression
frag[0] = `(${name} = ${newName})`
}
}
}
if (earlyCheckExps.length > 0) {
return [[...new Set(earlyCheckExps)].join(' && ')]
}
}

View File

@ -8,21 +8,19 @@ import {
genCall,
genMulti,
} from './utils'
import { processValues } from './prop'
export function genSetText(
oper: SetTextIRNode,
context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
const { vaporHelper, shouldCacheRenderEffectDeps } = context
const { element, values } = oper
return [
NEWLINE,
...genCall(
vaporHelper('setText'),
`n${element}`,
...values.map(value => genExpression(value, context)),
),
]
const texts = values.map(value => genExpression(value, context))
if (shouldCacheRenderEffectDeps()) {
processValues(context, texts)
}
return [NEWLINE, ...genCall(vaporHelper('setText'), `n${element}`, ...texts)]
}
export function genCreateTextNode(

View File

@ -29,9 +29,14 @@ export type CodeFragments = Exclude<CodeFragment, any[]> | CodeFragment[]
export function buildCodeFragment(
...frag: CodeFragment[]
): [CodeFragment[], (...items: CodeFragment[]) => number] {
): [
CodeFragment[],
(...items: CodeFragment[]) => number,
(...items: CodeFragment[]) => number,
] {
const push = frag.push.bind(frag)
return [frag, push]
const unshift = frag.unshift.bind(frag)
return [frag, push, unshift]
}
export type CodeFragmentDelimiters = [

View File

@ -266,7 +266,12 @@ export interface IRDynamicInfo {
export interface IREffect {
expressions: SimpleExpressionNode[]
identifiers: string[]
operations: OperationNode[]
declareNames: Set<string>
rewrittenNames: Set<string>
earlyCheckExps: string[]
inVFor: boolean
}
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> &

View File

@ -5,6 +5,7 @@ import {
type CompilerCompatOptions,
type ElementNode,
ElementTypes,
type ExpressionNode,
NodeTypes,
type RootNode,
type SimpleExpressionNode,
@ -12,8 +13,16 @@ import {
defaultOnError,
defaultOnWarn,
isVSlot,
walkIdentifiers,
} from '@vue/compiler-dom'
import { EMPTY_OBJ, NOOP, extend, isArray, isString } from '@vue/shared'
import {
EMPTY_OBJ,
NOOP,
extend,
isArray,
isString,
looseEqual,
} from '@vue/shared'
import {
type BlockIRNode,
DynamicFlag,
@ -142,8 +151,10 @@ export class TransformContext<T extends AllNode = AllNode> {
if (this.inVOnce || expressions.length === 0) {
return this.registerOperation(...operations)
}
const ids = new Set<string>()
expressions.forEach(exp => extractIdentifiers(ids, exp))
const existing = this.block.effect.find(e =>
isSameExpression(e.expressions, expressions),
looseEqual(e.identifiers, Array.from(ids)),
)
if (existing) {
existing.operations.push(...operations)
@ -151,16 +162,13 @@ export class TransformContext<T extends AllNode = AllNode> {
this.block.effect.push({
expressions,
operations,
earlyCheckExps: [],
declareNames: new Set<string>(),
rewrittenNames: new Set<string>(),
inVFor: this.inVFor > 0,
identifiers: Array.from(ids),
})
}
function isSameExpression(
a: SimpleExpressionNode[],
b: SimpleExpressionNode[],
) {
if (a.length !== b.length) return false
return a.every((exp, i) => exp.content === b[i].content)
}
}
registerOperation(...node: OperationNode[]): void {
this.block.operation.push(...node)
@ -296,3 +304,11 @@ export function createStructuralDirectiveTransform(
}
}
}
function extractIdentifiers(ids: Set<string>, node: ExpressionNode) {
if (node.ast) {
walkIdentifiers(node.ast, n => ids.add(n.name), true)
} else if (node.ast === null) {
ids.add((node as SimpleExpressionNode).content)
}
}

View File

@ -78,7 +78,8 @@ describe('api: setup context', () => {
inheritAttrs: false,
setup(props, { attrs }) {
const el = document.createElement('div')
renderEffect(() => setDynamicProps(el, [attrs]))
let prev: any
renderEffect(() => (prev = setDynamicProps(el, prev, [attrs])))
return el
},
})
@ -115,7 +116,10 @@ describe('api: setup context', () => {
const n0 = createComponent(Wrapper, null, {
default: () => {
const n0 = template('<div>')() as HTMLDivElement
renderEffect(() => setDynamicProps(n0, [attrs], true))
let prev: any
renderEffect(
() => (prev = setDynamicProps(n0, prev, [attrs], true)),
)
return n0
},
})

View File

@ -14,7 +14,6 @@ import {
ComponentInternalInstance,
setCurrentInstance,
} from '../../src/component'
import { getMetadata, recordPropMetadata } from '../../src/componentMetadata'
import { getCurrentScope } from '@vue/reactivity'
let removeComponentInstance = NOOP
@ -35,34 +34,6 @@ afterEach(() => {
})
describe('patchProp', () => {
describe('recordPropMetadata', () => {
test('should record prop metadata', () => {
const node = {} as Node // the node is just a key
let prev = recordPropMetadata(node, 'class', 'foo')
expect(prev).toBeUndefined()
prev = recordPropMetadata(node, 'class', 'bar')
expect(prev).toBe('foo')
prev = recordPropMetadata(node, 'style', 'color: red')
expect(prev).toBeUndefined()
prev = recordPropMetadata(node, 'style', 'color: blue')
expect(prev).toBe('color: red')
expect(getMetadata(node)).toEqual([
{ class: 'bar', style: 'color: blue' },
{},
])
})
test('should have different metadata for different nodes', () => {
const node1 = {} as Node
const node2 = {} as Node
recordPropMetadata(node1, 'class', 'foo')
recordPropMetadata(node2, 'class', 'bar')
expect(getMetadata(node1)).toEqual([{ class: 'foo' }, {}])
expect(getMetadata(node2)).toEqual([{ class: 'bar' }, {}])
})
})
describe('setClass', () => {
test('should set class', () => {
const el = document.createElement('div')
@ -78,83 +49,87 @@ describe('patchProp', () => {
describe('setStyle', () => {
test('should set style', () => {
const el = document.createElement('div')
setStyle(el, 'color: red')
setStyle(el, '', 'color: red')
expect(el.style.cssText).toBe('color: red;')
})
test('should work with camelCase', () => {
const el = document.createElement('div')
setStyle(el, { fontSize: '12px' })
setStyle(el, null, { fontSize: '12px' })
expect(el.style.cssText).toBe('font-size: 12px;')
})
test('shoud set style with object and array property', () => {
const el = document.createElement('div')
setStyle(el, { color: 'red' })
let prev: any
prev = setStyle(el, prev, { color: 'red' })
expect(el.style.cssText).toBe('color: red;')
setStyle(el, [{ color: 'blue' }, { fontSize: '12px' }])
setStyle(el, prev, [{ color: 'blue' }, { fontSize: '12px' }])
expect(el.style.cssText).toBe('color: blue; font-size: 12px;')
})
test('should remove if falsy value', () => {
const el = document.createElement('div')
setStyle(el, { color: undefined, borderRadius: null })
let prev
prev = setStyle(el, prev, { color: undefined, borderRadius: null })
expect(el.style.cssText).toBe('')
setStyle(el, { color: 'red' })
prev = setStyle(el, prev, { color: 'red' })
expect(el.style.cssText).toBe('color: red;')
setStyle(el, { color: undefined, borderRadius: null })
setStyle(el, prev, { color: undefined, borderRadius: null })
expect(el.style.cssText).toBe('')
})
test('should work with !important', () => {
const el = document.createElement('div')
setStyle(el, { color: 'red !important' })
setStyle(el, null, { color: 'red !important' })
expect(el.style.cssText).toBe('color: red !important;')
})
test('should work with camelCase and !important', () => {
const el = document.createElement('div')
setStyle(el, { fontSize: '12px !important' })
setStyle(el, null, { fontSize: '12px !important' })
expect(el.style.cssText).toBe('font-size: 12px !important;')
})
test('should work with multiple entries', () => {
const el = document.createElement('div')
setStyle(el, { color: 'red', marginRight: '10px' })
setStyle(el, null, { color: 'red', marginRight: '10px' })
expect(el.style.getPropertyValue('color')).toBe('red')
expect(el.style.getPropertyValue('margin-right')).toBe('10px')
})
test('should patch with falsy style value', () => {
const el = document.createElement('div')
setStyle(el, { width: '100px' })
let prev: any
prev = setStyle(el, prev, { width: '100px' })
expect(el.style.cssText).toBe('width: 100px;')
setStyle(el, { width: 0 })
prev = setStyle(el, prev, { width: 0 })
expect(el.style.cssText).toBe('width: 0px;')
})
test('should remove style attribute on falsy value', () => {
const el = document.createElement('div')
setStyle(el, { width: '100px' })
let prev: any
prev = setStyle(el, prev, { width: '100px' })
expect(el.style.cssText).toBe('width: 100px;')
setStyle(el, { width: undefined })
prev = setStyle(el, prev, { width: undefined })
expect(el.style.cssText).toBe('')
setStyle(el, { width: '100px' })
prev = setStyle(el, prev, { width: '100px' })
expect(el.style.cssText).toBe('width: 100px;')
setStyle(el, null)
setStyle(el, prev, null)
expect(el.hasAttribute('style')).toBe(false)
expect(el.style.cssText).toBe('')
})
test('should warn for trailing semicolons', () => {
const el = document.createElement('div')
setStyle(el, { color: 'red;' })
setStyle(el, null, { color: 'red;' })
expect(
`Unexpected semicolon at the end of 'color' style value: 'red;'`,
).toHaveBeenWarned()
setStyle(el, { '--custom': '100; ' })
setStyle(el, null, { '--custom': '100; ' })
expect(
`Unexpected semicolon at the end of '--custom' style value: '100; '`,
).toHaveBeenWarned()
@ -162,13 +137,16 @@ describe('patchProp', () => {
test('should not warn for trailing semicolons', () => {
const el = document.createElement('div')
setStyle(el, { '--custom': '100\\;' })
setStyle(el, null, { '--custom': '100\\;' })
expect(el.style.getPropertyValue('--custom')).toBe('100\\;')
})
test('should work with shorthand properties', () => {
const el = document.createElement('div')
setStyle(el, { borderBottom: '1px solid red', border: '1px solid green' })
setStyle(el, null, {
borderBottom: '1px solid red',
border: '1px solid green',
})
expect(el.style.border).toBe('1px solid green')
expect(el.style.borderBottom).toBe('1px solid green')
})
@ -193,19 +171,21 @@ describe('patchProp', () => {
test('should work with css custom properties', () => {
const el = mockElementWithStyle()
setStyle(el as any, { '--theme': 'red' })
setStyle(el as any, null, { '--theme': 'red' })
expect(el.style.getPropertyValue('--theme')).toBe('red')
})
test('should auto vendor prefixing', () => {
const el = mockElementWithStyle()
setStyle(el as any, { transition: 'all 1s' })
setStyle(el as any, null, { transition: 'all 1s' })
expect(el.style.WebkitTransition).toBe('all 1s')
})
test('should work with multiple values', () => {
const el = mockElementWithStyle()
setStyle(el as any, { display: ['-webkit-box', '-ms-flexbox', 'flex'] })
setStyle(el as any, null, {
display: ['-webkit-box', '-ms-flexbox', 'flex'],
})
expect(el.style.display).toBe('flex')
})
})
@ -335,12 +315,13 @@ describe('patchProp', () => {
describe('setDynamicProp', () => {
const element = document.createElement('div')
let prev: any
function setDynamicProp(
key: string,
value: any,
el = element.cloneNode(true) as HTMLElement,
) {
_setDynamicProp(el, key, value)
prev = _setDynamicProp(el, key, prev, value)
return el
}
@ -397,25 +378,25 @@ describe('patchProp', () => {
describe('setDynamicProps', () => {
test('basic set dynamic props', () => {
const el = document.createElement('div')
setDynamicProps(el, [{ foo: 'val' }, { bar: 'val' }])
setDynamicProps(el, null, [{ foo: 'val' }, { bar: 'val' }])
expect(el.getAttribute('foo')).toBe('val')
expect(el.getAttribute('bar')).toBe('val')
})
test('should merge props', () => {
const el = document.createElement('div')
setDynamicProps(el, [{ foo: 'val' }, { foo: 'newVal' }])
setDynamicProps(el, null, [{ foo: 'val' }, { foo: 'newVal' }])
expect(el.getAttribute('foo')).toBe('newVal')
})
test('should reset old props', () => {
const el = document.createElement('div')
setDynamicProps(el, [{ foo: 'val' }])
let prev: any
prev = setDynamicProps(el, prev, [{ foo: 'val' }])
expect(el.attributes.length).toBe(1)
expect(el.getAttribute('foo')).toBe('val')
setDynamicProps(el, [{ bar: 'val' }])
prev = setDynamicProps(el, prev, [{ bar: 'val' }])
expect(el.attributes.length).toBe(1)
expect(el.getAttribute('bar')).toBe('val')
expect(el.getAttribute('foo')).toBeNull()
@ -424,18 +405,19 @@ describe('patchProp', () => {
test('should reset old modifier props', () => {
const el = document.createElement('div')
setDynamicProps(el, [{ ['.foo']: 'val' }])
let prev: any
prev = setDynamicProps(el, prev, [{ ['.foo']: 'val' }])
expect((el as any).foo).toBe('val')
setDynamicProps(el, [{ ['.bar']: 'val' }])
prev = setDynamicProps(el, prev, [{ ['.bar']: 'val' }])
expect((el as any).bar).toBe('val')
expect((el as any).foo).toBe('')
setDynamicProps(el, [{ ['^foo']: 'val' }])
prev = setDynamicProps(el, prev, [{ ['^foo']: 'val' }])
expect(el.attributes.length).toBe(1)
expect(el.getAttribute('foo')).toBe('val')
setDynamicProps(el, [{ ['^bar']: 'val' }])
prev = setDynamicProps(el, prev, [{ ['^bar']: 'val' }])
expect(el.attributes.length).toBe(1)
expect(el.getAttribute('bar')).toBe('val')
expect(el.getAttribute('foo')).toBeNull()

View File

@ -119,6 +119,7 @@ export function fallThroughAttrs(
}
}
let prevAttrs = instance.attrs
renderEffect(() => {
for (const key in instance.attrs) {
if (dynamicAttrs && dynamicAttrs.includes(key)) continue
@ -130,7 +131,7 @@ export function fallThroughAttrs(
value = instance.attrs[key]
}
setDynamicProp(element, key, value)
setDynamicProp(element, key, prevAttrs[key], value)
}
})
}

View File

@ -24,6 +24,7 @@ export function fallbackComponent(
if (rawProps || Object.keys(instance.attrs).length) {
rawProps = [() => instance.attrs, ...normalizeRawProps(rawProps)]
let prevValue: any, prevStyle: any
renderEffect(() => {
let classes: unknown[] | undefined
let styles: unknown[] | undefined
@ -34,12 +35,16 @@ export function fallbackComponent(
const value = getter ? valueOrGetter() : valueOrGetter
if (key === 'class') (classes ||= []).push(value)
else if (key === 'style') (styles ||= []).push(value)
else setDynamicProp(el, key, value)
else {
prevValue = setDynamicProp(el, key, prevValue, value)
}
},
)
if (classes) setClass(el, classes)
if (styles) setStyle(el, styles)
if (styles) {
prevStyle = setStyle(el, prevStyle, styles)
}
})
}

View File

@ -18,13 +18,6 @@ export function getMetadata(
return el.$$metadata || (el.$$metadata = [{}, {}])
}
export function recordPropMetadata(el: Node, key: string, value: any): any {
const metadata = getMetadata(el)[MetadataKind.prop]
const prev = metadata[key]
if (prev !== value) metadata[key] = value
return prev
}
export function recordEventMetadata(el: Node, key: string, value: any) {
const metadata = getMetadata(el)[MetadataKind.event]
const handlers = (metadata[key] ||= [])

View File

@ -14,11 +14,6 @@ import {
} from '@vue/shared'
import { warn } from '../warning'
import { setStyle } from './style'
import {
MetadataKind,
getMetadata,
recordPropMetadata,
} from '../componentMetadata'
import { on } from './event'
import type { Data } from '@vue/runtime-shared'
import { currentInstance } from '../component'
@ -29,32 +24,18 @@ export function mergeInheritAttr(key: string, value: any): unknown {
}
export function setClass(el: Element, value: any, root?: boolean): void {
const prev = recordPropMetadata(
el,
'class',
(value = normalizeClass(root ? mergeInheritAttr('class', value) : value)),
)
if (value !== prev && (value || prev)) {
el.className = value
}
el.className = normalizeClass(root ? mergeInheritAttr('class', value) : value)
}
export function setAttr(el: Element, key: string, value: any): void {
const oldVal = recordPropMetadata(el, key, value)
if (value !== oldVal) {
if (value != null) {
el.setAttribute(key, value)
} else {
el.removeAttribute(key)
}
}
}
export function setValue(el: any, value: any): void {
const oldVal = recordPropMetadata(el, 'value', value)
if (value === oldVal) return
// store value as _value as well since
// non-string values will be stringified.
el._value = value
@ -71,9 +52,6 @@ export function setValue(el: any, value: any): void {
}
export function setDOMProp(el: any, key: string, value: any): void {
const oldVal = recordPropMetadata(el, key, value)
if (value === oldVal) return
let needRemove = false
if (value === '' || value == null) {
const type = typeof el[key]
@ -109,13 +87,18 @@ export function setDOMProp(el: any, key: string, value: any): void {
needRemove && el.removeAttribute(key)
}
export function setDynamicProp(el: Element, key: string, value: any): void {
export function setDynamicProp(
el: Element,
key: string,
prev: any,
value: any,
): any {
// TODO
const isSVG = false
if (key === 'class') {
setClass(el, value)
} else if (key === 'style') {
setStyle(el as HTMLElement, value)
return setStyle(el as HTMLElement, prev, value)
} else if (isOn(key)) {
on(el, key[2].toLowerCase() + key.slice(3), () => value, { effect: true })
} else if (
@ -150,30 +133,42 @@ export function setDynamicProp(el: Element, key: string, value: any): void {
export function setDynamicProps(
el: Element,
oldProps: any,
args: any[],
root?: boolean,
): void {
const oldProps = getMetadata(el)[MetadataKind.prop]
// const oldProps = getMetadata(el)[MetadataKind.prop]
if (root) {
args.unshift(currentInstance!.attrs)
}
const props = args.length > 1 ? mergeProps(...args) : args[0]
if (oldProps) {
for (const key in oldProps) {
// TODO should these keys be allowed as dynamic keys? The current logic of the runtime-core will throw an error
if (key === 'textContent' || key === 'innerHTML') {
continue
}
const oldValue = oldProps[key]
const hasNewValue = props[key] || props['.' + key] || props['^' + key]
if (oldProps[key] && !hasNewValue) {
setDynamicProp(el, key, null)
if (oldValue && !hasNewValue) {
setDynamicProp(el, key, oldValue, null)
}
}
}
const prev = Object.create(null)
for (const key in props) {
setDynamicProp(el, key, props[key])
setDynamicProp(
el,
key,
oldProps ? oldProps[key] : undefined,
(prev[key] = props[key]),
)
}
return prev
}
export function mergeProp(
@ -213,18 +208,11 @@ export function mergeProps(...args: Data[]): Data {
}
export function setText(el: Node, ...values: any[]): void {
const text = values.map(v => toDisplayString(v)).join('')
const oldVal = recordPropMetadata(el, 'textContent', text)
if (text !== oldVal) {
el.textContent = text
}
el.textContent = values.map(v => toDisplayString(v)).join('')
}
export function setHtml(el: Element, value: any): void {
const oldVal = recordPropMetadata(el, 'innerHTML', value)
if (value !== oldVal) {
el.innerHTML = value == null ? '' : value
}
}
// TODO copied from runtime-dom

View File

@ -7,16 +7,17 @@ import {
normalizeStyle,
} from '@vue/shared'
import { warn } from '../warning'
import { recordPropMetadata } from '../componentMetadata'
import { mergeInheritAttr } from './prop'
export function setStyle(el: HTMLElement, value: any, root?: boolean): void {
const prev = recordPropMetadata(
el,
'style',
(value = normalizeStyle(root ? mergeInheritAttr('style', value) : value)),
)
export function setStyle(
el: HTMLElement,
prev: any,
value: any,
root?: boolean,
): any {
value = normalizeStyle(root ? mergeInheritAttr('style', value) : value)
patchStyle(el, prev, value)
return value
}
// TODO copied from packages/runtime-dom/src/modules/style.ts