diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index bc827dd73..09e8c4cca 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap @@ -186,7 +186,7 @@ export function render(_ctx) { _delegate(n0, "click", () => _ctx.handleClick) _setInheritAttrs(["id"]) _renderEffect(() => _setText(n0, _ctx.count, "foo", _ctx.count, "foo", _ctx.count)) - _renderEffect(() => _setDOMProp(n0, "id", _ctx.count, true)) + _renderEffect(() => _setDOMProp(n0, "id", _ctx.count)) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap index 822a6af66..4630eadfb 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap @@ -7,7 +7,19 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["foo-bar"]) - _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.id, true)) + _renderEffect(() => _setAttr(n0, "foo-bar", _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["innerHTML"]) + _renderEffect(() => _setAttr(n0, "innerHTML", _ctx.foo)) return n0 }" `; @@ -19,7 +31,43 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["foo-bar"]) - _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.fooBar, true)) + _renderEffect(() => _setAttr(n0, "foo-bar", _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'; +const t0 = _template("") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setAttr(n0, "value", _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["textContent"]) + _renderEffect(() => _setAttr(n0, "textContent", _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setAttr(n0, "value", _ctx.foo)) return n0 }" `; @@ -31,7 +79,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.id, true)) + _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.id)) return n0 }" `; @@ -56,31 +104,79 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.fooBar, true)) + _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.fooBar)) return n0 }" `; -exports[`compiler v-bind > .prop modifier (shortband) w/ no expression 1`] = ` +exports[`compiler v-bind > .prop modifier (shorthand) 1`] = ` "import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar, true)) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id)) return n0 }" `; -exports[`compiler v-bind > .prop modifier (shorthand) 1`] = ` +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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["innerHTML"]) + _renderEffect(() => _setHtml(n0, _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'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id, true)) + _renderEffect(() => _setDOMProp(n0, "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'; +const t0 = _template("") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setDOMProp(n0, "value", _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["textContent"]) + _renderEffect(() => _setText(n0, _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setValue(n0, _ctx.foo)) return n0 }" `; @@ -92,7 +188,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id, true)) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id)) return n0 }" `; @@ -109,6 +205,18 @@ export function render(_ctx) { }" `; +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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["innerHTML"]) + _renderEffect(() => _setHtml(n0, _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'; const t0 = _template("
") @@ -116,7 +224,91 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["fooBar"]) - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar, true)) + _renderEffect(() => _setDOMProp(n0, "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'; +const t0 = _template("") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setDOMProp(n0, "value", _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["textContent"]) + _renderEffect(() => _setText(n0, _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setValue(n0, _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["innerHTML"]) + _renderEffect(() => _setHtml(n0, _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'; +const t0 = _template("
") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["textContent"]) + _renderEffect(() => _setText(n0, _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'; +const t0 = _template("") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setValue(n0, _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'; +const t0 = _template("") + +export function render(_ctx) { + const n0 = t0() + _setInheritAttrs(["value"]) + _renderEffect(() => _setDynamicProp(n0, "value", _ctx.foo)) return n0 }" `; @@ -128,11 +320,11 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["id", "title", "lang", "dir", "tabindex"]) - _renderEffect(() => _setDOMProp(n0, "id", _ctx.id, true)) - _renderEffect(() => _setDOMProp(n0, "title", _ctx.title, true)) - _renderEffect(() => _setDOMProp(n0, "lang", _ctx.lang, true)) - _renderEffect(() => _setDOMProp(n0, "dir", _ctx.dir, true)) - _renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex, true)) + _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)) return n0 }" `; @@ -144,11 +336,11 @@ const t0 = _template("") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["autofucus", "dir", "displaystyle", "mathcolor", "tabindex"]) - _renderEffect(() => _setDOMProp(n0, "autofucus", _ctx.autofucus, true)) - _renderEffect(() => _setDOMProp(n0, "dir", _ctx.dir, true)) - _renderEffect(() => _setDOMProp(n0, "displaystyle", _ctx.displaystyle, true)) - _renderEffect(() => _setDOMProp(n0, "mathcolor", _ctx.mathcolor, true)) - _renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex, true)) + _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)) return n0 }" `; @@ -160,9 +352,9 @@ const t0 = _template("") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["id", "lang", "tabindex"]) - _renderEffect(() => _setDOMProp(n0, "id", _ctx.id, true)) - _renderEffect(() => _setDOMProp(n0, "lang", _ctx.lang, true)) - _renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex, true)) + _renderEffect(() => _setDOMProp(n0, "id", _ctx.id)) + _renderEffect(() => _setDOMProp(n0, "lang", _ctx.lang)) + _renderEffect(() => _setDOMProp(n0, "tabindex", _ctx.tabindex)) return n0 }" `; @@ -214,7 +406,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["id"]) - _renderEffect(() => _setDOMProp(n0, "id", _ctx.id, true)) + _renderEffect(() => _setDOMProp(n0, "id", _ctx.id)) return n0 }" `; @@ -250,7 +442,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["camel-case"]) - _renderEffect(() => _setDynamicProp(n0, "camel-case", _ctx.camelCase, true)) + _renderEffect(() => _setDynamicProp(n0, "camel-case", _ctx.camelCase)) return n0 }" `; @@ -262,7 +454,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() _setInheritAttrs(["id"]) - _renderEffect(() => _setDOMProp(n0, "id", _ctx.id, true)) + _renderEffect(() => _setDOMProp(n0, "id", _ctx.id)) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index 344f7ac5a..a82221728 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -52,8 +52,8 @@ export function render(_ctx) { const n0 = _createFor(() => (_ctx.items), (_ctx0) => { const n2 = t0() _setInheritAttrs(["item", "index"]) - _renderEffect(() => _setDynamicProp(n2, "item", _ctx0[0].value, true)) - _renderEffect(() => _setDynamicProp(n2, "index", _ctx0[1].value, true)) + _renderEffect(() => _setDynamicProp(n2, "item", _ctx0[0].value)) + _renderEffect(() => _setDynamicProp(n2, "index", _ctx0[1].value)) return n2 }) return n0 diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap index 2665b6157..eacf622a7 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap @@ -6,7 +6,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _setDOMProp(n0, "id", _ctx.foo, true) + _setDOMProp(n0, "id", _ctx.foo) _setInheritAttrs(["id"]) return n0 }" diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts index 7f14bb25d..efaa9257c 100644 --- a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts @@ -74,7 +74,7 @@ describe('compiler v-bind', () => { }) expect(code).matchSnapshot() - expect(code).contains('_setDOMProp(n0, "id", _ctx.id, true)') + expect(code).contains('_setDOMProp(n0, "id", _ctx.id)') }) test('no expression', () => { @@ -104,7 +104,7 @@ describe('compiler v-bind', () => { ], }, }) - expect(code).contains('_setDOMProp(n0, "id", _ctx.id, true)') + expect(code).contains('_setDOMProp(n0, "id", _ctx.id)') }) test('no expression (shorthand)', () => { @@ -126,9 +126,7 @@ describe('compiler v-bind', () => { ], }, }) - expect(code).contains( - '_setDynamicProp(n0, "camel-case", _ctx.camelCase, true)', - ) + expect(code).contains('_setDynamicProp(n0, "camel-case", _ctx.camelCase)') }) test('dynamic arg', () => { @@ -288,7 +286,7 @@ describe('compiler v-bind', () => { }) expect(code).matchSnapshot() - expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.id, true)') + expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.id)') }) test('.camel modifier w/ no expression', () => { @@ -312,7 +310,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.fooBar, true)') + expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.fooBar)') }) test('.camel modifier w/ dynamic arg', () => { @@ -370,7 +368,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id, true)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)') }) test('.prop modifier w/ no expression', () => { @@ -394,7 +392,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar, true)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)') }) test('.prop modifier w/ dynamic arg', () => { @@ -451,10 +449,10 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id, true)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)') }) - test('.prop modifier (shortband) w/ no expression', () => { + test('.prop modifier (shorthand) w/ no expression', () => { const { ir, code } = compileWithVBind(`
`) expect(code).matchSnapshot() @@ -475,7 +473,55 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar, true)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)') + }) + + test('.prop modifier w/ innerHTML', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setHtml(n0, _ctx.foo)') + }) + + test('.prop modifier (shorthand) w/ innerHTML', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setHtml(n0, _ctx.foo)') + }) + + test('.prop modifier w/ textContent', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setText(n0, _ctx.foo)') + }) + + test('.prop modifier (shorthand) w/ textContent', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setText(n0, _ctx.foo)') + }) + + test('.prop modifier w/ value', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setValue(n0, _ctx.foo)') + }) + + test('.prop modifier (shorthand) w/ value', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setValue(n0, _ctx.foo)') + }) + + test('.prop modifier w/ progress value', () => { + const { code } = compileWithVBind(``) + expect(code).matchSnapshot() + expect(code).contains('_setDOMProp(n0, "value", _ctx.foo)') + }) + + test('.prop modifier (shorthand) w/ progress value', () => { + const { code } = compileWithVBind(``) + expect(code).matchSnapshot() + expect(code).contains('_setDOMProp(n0, "value", _ctx.foo)') }) test('.attr modifier', () => { @@ -499,7 +545,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setAttr(n0, "foo-bar", _ctx.id, true)') + expect(code).contains('_setAttr(n0, "foo-bar", _ctx.id)') }) test('.attr modifier w/ no expression', () => { @@ -524,7 +570,31 @@ describe('compiler v-bind', () => { }) expect(code).contains('renderEffect') - expect(code).contains('_setAttr(n0, "foo-bar", _ctx.fooBar, true)') + expect(code).contains('_setAttr(n0, "foo-bar", _ctx.fooBar)') + }) + + test('.attr modifier w/ innerHTML', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setAttr(n0, "innerHTML", _ctx.foo)') + }) + + test('.attr modifier w/ textContent', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setAttr(n0, "textContent", _ctx.foo)') + }) + + test('.attr modifier w/ value', () => { + const { code } = compileWithVBind(`
`) + expect(code).matchSnapshot() + expect(code).contains('_setAttr(n0, "value", _ctx.foo)') + }) + + test('.attr modifier w/ progress value', () => { + const { code } = compileWithVBind(``) + expect(code).matchSnapshot() + expect(code).contains('_setAttr(n0, "value", _ctx.foo)') }) test('attributes must be set as attribute', () => { @@ -561,11 +631,11 @@ describe('compiler v-bind', () => { `) expect(code).matchSnapshot() - expect(code).contains('_setDOMProp(n0, "id", _ctx.id, true)') - expect(code).contains('_setDOMProp(n0, "title", _ctx.title, true)') - expect(code).contains('_setDOMProp(n0, "lang", _ctx.lang, true)') - expect(code).contains('_setDOMProp(n0, "dir", _ctx.dir, true)') - expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex, true)') + 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)') }) test('SVG global attributes should set as dom prop', () => { @@ -574,9 +644,9 @@ describe('compiler v-bind', () => { `) expect(code).matchSnapshot() - expect(code).contains('_setDOMProp(n0, "id", _ctx.id, true)') - expect(code).contains('_setDOMProp(n0, "lang", _ctx.lang, true)') - expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex, true)') + expect(code).contains('_setDOMProp(n0, "id", _ctx.id)') + expect(code).contains('_setDOMProp(n0, "lang", _ctx.lang)') + expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex)') }) test('MathML global attributes should set as dom prop', () => { @@ -585,13 +655,43 @@ describe('compiler v-bind', () => { `) expect(code).matchSnapshot() - expect(code).contains('_setDOMProp(n0, "autofucus", _ctx.autofucus, true)') - expect(code).contains('_setDOMProp(n0, "dir", _ctx.dir, true)') - expect(code).contains( - '_setDOMProp(n0, "displaystyle", _ctx.displaystyle, true)', - ) - expect(code).contains('_setDOMProp(n0, "mathcolor", _ctx.mathcolor, true)') - expect(code).contains('_setDOMProp(n0, "tabindex", _ctx.tabindex, true)') + 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)') + }) + + test(':innerHTML', () => { + const { code } = compileWithVBind(` +
+ `) + expect(code).matchSnapshot() + expect(code).contains('_setHtml(n0, _ctx.foo)') + }) + + test(':textContext', () => { + const { code } = compileWithVBind(` +
+ `) + expect(code).matchSnapshot() + expect(code).contains('_setText(n0, _ctx.foo)') + }) + + test(':value', () => { + const { code } = compileWithVBind(` + + `) + expect(code).matchSnapshot() + expect(code).contains('_setValue(n0, _ctx.foo)') + }) + + test(':value w/ progress', () => { + const { code } = compileWithVBind(` + + `) + expect(code).matchSnapshot() + expect(code).contains('_setDynamicProp(n0, "value", _ctx.foo)') }) test('number value', () => { diff --git a/packages/compiler-vapor/src/generators/prop.ts b/packages/compiler-vapor/src/generators/prop.ts index 295b177d6..e30d4c7ed 100644 --- a/packages/compiler-vapor/src/generators/prop.ts +++ b/packages/compiler-vapor/src/generators/prop.ts @@ -23,6 +23,7 @@ import { } from './utils' import { attributeCache, + canSetValueDirectly, isHTMLGlobalAttr, isHTMLTag, isMathMLGlobalAttr, @@ -44,39 +45,7 @@ export function genSetProp( tag, } = oper - const keyName = key.content - const tagName = tag.toUpperCase() - const attrCacheKey = `${tagName}_${keyName}` - - let helperName: VaporHelper - let omitKey = false - if (keyName === 'class') { - helperName = 'setClass' - omitKey = true - } else if (keyName === 'style') { - helperName = 'setStyle' - omitKey = true - } else if (modifier) { - helperName = modifier === '.' ? 'setDOMProp' : 'setAttr' - } else if ( - attributeCache[attrCacheKey] === undefined - ? (attributeCache[attrCacheKey] = shouldSetAsAttr( - tag.toUpperCase(), - keyName, - )) - : attributeCache[attrCacheKey] - ) { - helperName = 'setAttr' - } else if ( - (isHTMLTag(tag) && isHTMLGlobalAttr(keyName)) || - (isSVGTag(tag) && isSvgGlobalAttr(keyName)) || - (isMathMLTag(tag) && isMathMLGlobalAttr(keyName)) - ) { - helperName = 'setDOMProp' - } else { - helperName = 'setDynamicProp' - } - + const { helperName, omitKey } = getRuntimeHelper(tag, key.content, modifier) return [ NEWLINE, ...genCall( @@ -84,7 +53,10 @@ export function genSetProp( `n${oper.element}`, omitKey ? false : genExpression(key, context), genPropValue(values, context), - oper.root && 'true', + // only `setClass` and `setStyle` need merge inherit attr + oper.root && (helperName === 'setClass' || helperName === 'setStyle') + ? 'true' + : undefined, ), ] } @@ -196,3 +168,70 @@ export function genSetInheritAttrs( if (value == null) return [] return [NEWLINE, ...genCall(vaporHelper('setInheritAttrs'), value)] } + +function getRuntimeHelper( + tag: string, + keyName: string, + modifier: '.' | '^' | undefined, +) { + const tagName = tag.toUpperCase() + let helperName: VaporHelper + let omitKey = false + + if (modifier) { + if (modifier === '.') { + const helper = getSpecialHelper(keyName, tagName) + if (helper) { + helperName = helper.name + omitKey = helper.omitKey + } else { + helperName = 'setDOMProp' + omitKey = false + } + } else { + helperName = 'setAttr' + } + } else { + const attrCacheKey = `${tagName}_${keyName}` + const helper = getSpecialHelper(keyName, tagName) + if (helper) { + helperName = helper.name + omitKey = helper.omitKey + } else if ( + attributeCache[attrCacheKey] === undefined + ? (attributeCache[attrCacheKey] = shouldSetAsAttr(tagName, keyName)) + : attributeCache[attrCacheKey] + ) { + helperName = 'setAttr' + } else if ( + (isHTMLTag(tag) && isHTMLGlobalAttr(keyName)) || + (isSVGTag(tag) && isSvgGlobalAttr(keyName)) || + (isMathMLTag(tag) && isMathMLGlobalAttr(keyName)) + ) { + helperName = 'setDOMProp' + } else { + helperName = 'setDynamicProp' + } + } + return { helperName, omitKey } +} + +const specialHelpers: Record = + { + class: { name: 'setClass', omitKey: true }, + style: { name: 'setStyle', omitKey: true }, + innerHTML: { name: 'setHtml', omitKey: true }, + textContent: { name: 'setText', omitKey: true }, + } + +const getSpecialHelper = ( + keyName: string, + tagName: string, +): { name: VaporHelper; omitKey: boolean } | null => { + // special case for 'value' property + if (keyName === 'value' && canSetValueDirectly(tagName)) { + return { name: 'setValue', omitKey: true } + } + + return specialHelpers[keyName] || null +} diff --git a/packages/runtime-vapor/__tests__/dom/prop.spec.ts b/packages/runtime-vapor/__tests__/dom/prop.spec.ts index 7ccb1f51e..c5e526b35 100644 --- a/packages/runtime-vapor/__tests__/dom/prop.spec.ts +++ b/packages/runtime-vapor/__tests__/dom/prop.spec.ts @@ -7,6 +7,7 @@ import { setDynamicProps, setHtml, setText, + setValue, } from '../../src/dom/prop' import { setStyle } from '../../src/dom/style' import { @@ -239,43 +240,32 @@ describe('patchProp', () => { }) }) - describe('setDOMProp', () => { - test('should set DOM property', () => { - const el = document.createElement('div') - setDOMProp(el, 'textContent', null) - expect(el.textContent).toBe('') - setDOMProp(el, 'textContent', 'foo') - expect(el.textContent).toBe('foo') - - setDOMProp(el, 'innerHTML', null) - expect(el.innerHTML).toBe('') - setDOMProp(el, 'innerHTML', '

bar

') - expect(el.innerHTML).toBe('

bar

') - }) - + describe('setValue', () => { test('should set value prop', () => { const el = document.createElement('input') - setDOMProp(el, 'value', 'foo') + setValue(el, 'foo') expect(el.value).toBe('foo') - setDOMProp(el, 'value', null) + setValue(el, null) expect(el.value).toBe('') expect(el.getAttribute('value')).toBe(null) const obj = {} - setDOMProp(el, 'value', obj) + setValue(el, obj) expect(el.value).toBe(obj.toString()) expect((el as any)._value).toBe(obj) const option = document.createElement('option') - setDOMProp(option, 'textContent', 'foo') + setText(option, 'foo') expect(option.value).toBe('foo') expect(option.getAttribute('value')).toBe(null) - setDOMProp(option, 'value', 'bar') + setValue(option, 'bar') expect(option.textContent).toBe('foo') expect(option.value).toBe('bar') expect(option.getAttribute('value')).toBe('bar') }) + }) + describe('setDOMProp', () => { test('should be boolean prop', () => { const el = document.createElement('select') setDOMProp(el, 'multiple', '') @@ -455,6 +445,8 @@ describe('patchProp', () => { describe('setText', () => { test('should set textContent', () => { const el = document.createElement('div') + setText(el, null) + expect(el.textContent).toBe('') setText(el, 'foo') expect(el.textContent).toBe('foo') setText(el, 'bar') @@ -465,6 +457,8 @@ describe('patchProp', () => { describe('setHtml', () => { test('should set innerHTML', () => { const el = document.createElement('div') + setHtml(el, null) + expect(el.innerHTML).toBe('') setHtml(el, '

foo

') expect(el.innerHTML).toBe('

foo

') setHtml(el, '

bar

') diff --git a/packages/runtime-vapor/src/dom/prop.ts b/packages/runtime-vapor/src/dom/prop.ts index 8dfe24875..bd6ce1f12 100644 --- a/packages/runtime-vapor/src/dom/prop.ts +++ b/packages/runtime-vapor/src/dom/prop.ts @@ -1,5 +1,6 @@ import { attributeCache, + canSetValueDirectly, includeBooleanAttr, isArray, isFunction, @@ -50,42 +51,28 @@ export function setAttr(el: Element, key: string, value: any): void { } } -export function setDOMProp(el: any, key: string, value: any): void { - const oldVal = recordPropMetadata(el, key, value) +export function setValue(el: any, value: any): void { + const oldVal = recordPropMetadata(el, 'value', value) if (value === oldVal) return - if (key === 'innerHTML' || key === 'textContent') { - // TODO special checks - // if (prevChildren) { - // unmountChildren(prevChildren, parentComponent, parentSuspense) - // } - el[key] = value == null ? '' : value - return + // store value as _value as well since + // non-string values will be stringified. + el._value = value + // #4956: