diff --git a/package.json b/package.json index b1338f986..b1ffb9401 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dev-prepare-cjs": "node scripts/prepare-cjs.js || npm run build-all-cjs", "dev-compiler": "run-p \"dev template-explorer\" serve open", "dev-sfc": "run-s dev-prepare-cjs dev-sfc-run", - "dev-sfc-serve": "vite packages-private/sfc-playground --host", + "dev-sfc-serve": "vite packages-private/sfc-playground", "dev-sfc-run": "run-p \"dev compiler-sfc -f esm-browser\" \"dev vue -if esm-bundler-runtime\" \"dev vue -ipf esm-browser-runtime\" \"dev server-renderer -if esm-bundler\" dev-sfc-serve", "dev-vapor": "pnpm -C playground run dev", "serve": "serve", diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index 7d0eca13f..067610dc7 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap @@ -140,11 +140,12 @@ export function render(_ctx) { `; exports[`compile > directives > v-pre > basic 1`] = ` -"import { template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("
{{ bar }}
") export function render(_ctx, $props) { const n0 = t0() + _setInheritAttrs(false) return n0 }" `; @@ -176,15 +177,16 @@ export function render(_ctx) { `; exports[`compile > dynamic root nodes and interpolation 1`] = ` -"import { delegate as _delegate, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { delegate as _delegate, setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setText as _setText, setDynamicProp as _setDynamicProp, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("") _delegateEvents("click") 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(() => _setDynamicProp(n0, "id", _ctx.count)) + _renderEffect(() => _setDynamicProp(n0, "id", _ctx.count, true)) return n0 }" `; @@ -199,7 +201,8 @@ exports[`compile > expression parsing > interpolation 1`] = ` exports[`compile > expression parsing > v-bind 1`] = ` "((_ctx) => { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { [key.value+1]: _unref(foo)[key.value+1]() })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ [key.value+1]: _unref(foo)[key.value+1]() }], true)) return n0 })()" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap index 8e4509e19..d06052b81 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap @@ -286,22 +286,24 @@ export function render(_ctx) { `; exports[`compiler: element transform > props + children 1`] = ` -"import { template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() + _setInheritAttrs(false) return n0 }" `; exports[`compiler: element transform > props merging: class 1`] = ` -"import { renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setClass as _setClass, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setClass(n0, ["foo", { bar: _ctx.isBar }])) + _setInheritAttrs(["class"]) + _renderEffect(() => _setClass(n0, ["foo", { bar: _ctx.isBar }], true)) return n0 }" `; @@ -324,66 +326,72 @@ export function render(_ctx) { `; exports[`compiler: element transform > props merging: style 1`] = ` -"import { renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setStyle as _setStyle, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setStyle(n0, ["color: green", { color: 'red' }])) + _setInheritAttrs(["style"]) + _renderEffect(() => _setStyle(n0, ["color: green", { color: 'red' }], true)) return n0 }" `; exports[`compiler: element transform > static props 1`] = ` -"import { template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() + _setInheritAttrs(false) return n0 }" `; exports[`compiler: element transform > v-bind="obj" 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, _ctx.obj)) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [_ctx.obj], true)) return n0 }" `; exports[`compiler: element transform > v-bind="obj" after static prop 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { id: "foo" }, _ctx.obj)) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj], true)) return n0 }" `; exports[`compiler: element transform > v-bind="obj" before static prop 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, _ctx.obj, { id: "foo" })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [_ctx.obj, { id: "foo" }], true)) return n0 }" `; exports[`compiler: element transform > v-bind="obj" between static props 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { id: "foo" }, _ctx.obj, { class: "bar" })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true)) 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 16cbc2066..5e1e43c88 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap @@ -1,177 +1,193 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`compiler v-bind > .attr modifier 1`] = ` -"import { renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.id)) + _setInheritAttrs(["foo-bar"]) + _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > .attr modifier w/ no expression 1`] = ` -"import { renderEffect as _renderEffect, setAttr as _setAttr, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.fooBar)) + _setInheritAttrs(["foo-bar"]) + _renderEffect(() => _setAttr(n0, "foo-bar", _ctx.fooBar, true)) return n0 }" `; exports[`compiler v-bind > .camel modifier 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.id)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > .camel modifier w/ dynamic arg 1`] = ` "import { camelize as _camelize } from 'vue'; -import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { [_camelize(_ctx.foo)]: _ctx.id })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }], true)) return n0 }" `; exports[`compiler v-bind > .camel modifier w/ no expression 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.fooBar)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDynamicProp(n0, "fooBar", _ctx.fooBar, true)) return n0 }" `; exports[`compiler v-bind > .prop modifier (shortband) w/ no expression 1`] = ` -"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar, true)) return n0 }" `; exports[`compiler v-bind > .prop modifier (shorthand) 1`] = ` -"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > .prop modifier 1`] = ` -"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > .prop modifier w/ dynamic arg 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { ["." + _ctx.fooBar]: _ctx.id })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }], true)) return n0 }" `; exports[`compiler v-bind > .prop modifier w/ no expression 1`] = ` -"import { renderEffect as _renderEffect, setDOMProp as _setDOMProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar)) + _setInheritAttrs(["fooBar"]) + _renderEffect(() => _setDOMProp(n0, "fooBar", _ctx.fooBar, true)) return n0 }" `; exports[`compiler v-bind > basic 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDynamicProp(n0, "id", _ctx.id)) + _setInheritAttrs(["id"]) + _renderEffect(() => _setDynamicProp(n0, "id", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > dynamic arg 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true)) return n0 }" `; exports[`compiler v-bind > dynamic arg w/ static attribute 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _renderEffect(() => _setDynamicProps(n0, { [_ctx.id]: _ctx.id, foo: "bar", checked: "" })) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true)) return n0 }" `; exports[`compiler v-bind > no expression (shorthand) 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDynamicProp(n0, "camel-case", _ctx.camelCase)) + _setInheritAttrs(["camel-case"]) + _renderEffect(() => _setDynamicProp(n0, "camel-case", _ctx.camelCase, true)) return n0 }" `; exports[`compiler v-bind > no expression 1`] = ` -"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"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() - _renderEffect(() => _setDynamicProp(n0, "id", _ctx.id)) + _setInheritAttrs(["id"]) + _renderEffect(() => _setDynamicProp(n0, "id", _ctx.id, true)) return n0 }" `; exports[`compiler v-bind > should error if empty expression 1`] = ` -"import { template as _template } from 'vue/vapor'; +"import { setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() + _setInheritAttrs(false) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap index 5aec9a164..87bc349f4 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap @@ -126,13 +126,14 @@ export function render(_ctx) { `; exports[`compiler: vModel transform > should support input (checkbox) 1`] = ` -"import { vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, delegate as _delegate, template as _template } from 'vue/vapor'; +"import { vModelCheckbox as _vModelCheckbox, withDirectives as _withDirectives, delegate as _delegate, setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("") export function render(_ctx) { const n0 = t0() _withDirectives(n0, [[_vModelCheckbox, () => _ctx.model]]) _delegate(n0, "update:modelValue", () => $event => (_ctx.model = $event)) + _setInheritAttrs(false) return n0 }" `; @@ -150,25 +151,27 @@ export function render(_ctx) { `; exports[`compiler: vModel transform > should support input (radio) 1`] = ` -"import { vModelRadio as _vModelRadio, withDirectives as _withDirectives, delegate as _delegate, template as _template } from 'vue/vapor'; +"import { vModelRadio as _vModelRadio, withDirectives as _withDirectives, delegate as _delegate, setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("") export function render(_ctx) { const n0 = t0() _withDirectives(n0, [[_vModelRadio, () => _ctx.model]]) _delegate(n0, "update:modelValue", () => $event => (_ctx.model = $event)) + _setInheritAttrs(false) return n0 }" `; exports[`compiler: vModel transform > should support input (text) 1`] = ` -"import { vModelText as _vModelText, withDirectives as _withDirectives, delegate as _delegate, template as _template } from 'vue/vapor'; +"import { vModelText as _vModelText, withDirectives as _withDirectives, delegate as _delegate, setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("") export function render(_ctx) { const n0 = t0() _withDirectives(n0, [[_vModelText, () => _ctx.model]]) _delegate(n0, "update:modelValue", () => $event => (_ctx.model = $event)) + _setInheritAttrs(false) return n0 }" `; @@ -243,14 +246,15 @@ 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, 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, renderEffect as _renderEffect, setDynamicProps as _setDynamicProps, template as _template } from 'vue/vapor'; const t0 = _template("") export function render(_ctx) { const n0 = t0() _withDirectives(n0, [[_vModelDynamic, () => _ctx.model]]) _delegate(n0, "update:modelValue", () => $event => (_ctx.model = $event)) - _renderEffect(() => _setDynamicProps(n0, _ctx.obj)) + _setInheritAttrs(true) + _renderEffect(() => _setDynamicProps(n0, [_ctx.obj], true)) 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 1c382d8be..70c9e35ab 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap @@ -1,12 +1,13 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`compiler: v-once > as root node 1`] = ` -"import { setDynamicProp as _setDynamicProp, template as _template } from 'vue/vapor'; +"import { setDynamicProp as _setDynamicProp, setInheritAttrs as _setInheritAttrs, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _setDynamicProp(n0, "id", _ctx.foo) + _setDynamicProp(n0, "id", _ctx.foo, true) + _setInheritAttrs(["id"]) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts index dacfab982..2b5f89464 100644 --- a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts @@ -588,7 +588,7 @@ describe('compiler: element transform', () => { ], }, ]) - expect(code).contains('_setDynamicProps(n0, _ctx.obj)') + expect(code).contains('_setDynamicProps(n0, [_ctx.obj], true)') }) test('v-bind="obj" after static prop', () => { @@ -624,7 +624,9 @@ describe('compiler: element transform', () => { ], }, ]) - expect(code).contains('_setDynamicProps(n0, { id: "foo" }, _ctx.obj)') + expect(code).contains( + '_setDynamicProps(n0, [{ id: "foo" }, _ctx.obj], true)', + ) }) test('v-bind="obj" before static prop', () => { @@ -650,7 +652,9 @@ describe('compiler: element transform', () => { ], }, ]) - expect(code).contains('_setDynamicProps(n0, _ctx.obj, { id: "foo" })') + expect(code).contains( + '_setDynamicProps(n0, [_ctx.obj, { id: "foo" }], true)', + ) }) test('v-bind="obj" between static props', () => { @@ -678,7 +682,7 @@ describe('compiler: element transform', () => { }, ]) expect(code).contains( - '_setDynamicProps(n0, { id: "foo" }, _ctx.obj, { class: "bar" })', + '_setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true)', ) }) @@ -723,6 +727,9 @@ describe('compiler: element transform', () => { delegate: true, effect: false, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) }) diff --git a/packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts index 22f68f953..b9adeb51e 100644 --- a/packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts @@ -30,8 +30,8 @@ describe('compiler: template ref transform', () => { flags: DynamicFlag.REFERENCED, }) expect(ir.template).toEqual(['
']) - expect(ir.block.operation).lengthOf(1) - expect(ir.block.operation[0]).toMatchObject({ + expect(ir.block.operation).lengthOf(2) + expect(ir.block.operation[1]).toMatchObject({ type: IRNodeTypes.SET_TEMPLATE_REF, element: 0, value: { @@ -56,6 +56,9 @@ describe('compiler: template ref transform', () => { }) expect(ir.template).toEqual(['
']) expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, { type: IRNodeTypes.DECLARE_OLD_REF, id: 0, diff --git a/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts b/packages/compiler-vapor/__tests__/transforms/vBind.spec.ts index 39b02a5e4..0097d0b7c 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('_setDynamicProp(n0, "id", _ctx.id)') + expect(code).contains('_setDynamicProp(n0, "id", _ctx.id, true)') }) test('no expression', () => { @@ -104,7 +104,7 @@ describe('compiler v-bind', () => { ], }, }) - expect(code).contains('_setDynamicProp(n0, "id", _ctx.id)') + expect(code).contains('_setDynamicProp(n0, "id", _ctx.id, true)') }) test('no expression (shorthand)', () => { @@ -126,7 +126,9 @@ describe('compiler v-bind', () => { ], }, }) - expect(code).contains('_setDynamicProp(n0, "camel-case", _ctx.camelCase)') + expect(code).contains( + '_setDynamicProp(n0, "camel-case", _ctx.camelCase, true)', + ) }) test('dynamic arg', () => { @@ -171,7 +173,7 @@ describe('compiler v-bind', () => { ], }) expect(code).contains( - '_setDynamicProps(n0, { [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title })', + '_setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, [_ctx.title]: _ctx.title }], true)', ) }) @@ -224,7 +226,7 @@ describe('compiler v-bind', () => { ], }) expect(code).contains( - '_setDynamicProps(n0, { [_ctx.id]: _ctx.id, foo: "bar", checked: "" })', + '_setDynamicProps(n0, [{ [_ctx.id]: _ctx.id, foo: "bar", checked: "" }], true)', ) }) @@ -286,7 +288,7 @@ describe('compiler v-bind', () => { }) expect(code).matchSnapshot() - expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.id)') + expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.id, true)') }) test('.camel modifier w/ no expression', () => { @@ -310,7 +312,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.fooBar)') + expect(code).contains('_setDynamicProp(n0, "fooBar", _ctx.fooBar, true)') }) test('.camel modifier w/ dynamic arg', () => { @@ -341,7 +343,7 @@ describe('compiler v-bind', () => { expect(code).matchSnapshot() expect(code).contains('renderEffect') expect(code).contains( - `_setDynamicProps(n0, { [_camelize(_ctx.foo)]: _ctx.id })`, + `_setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }], true)`, ) }) @@ -368,7 +370,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id, true)') }) test('.prop modifier w/ no expression', () => { @@ -392,7 +394,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar, true)') }) test('.prop modifier w/ dynamic arg', () => { @@ -422,7 +424,7 @@ describe('compiler v-bind', () => { }) expect(code).contains('renderEffect') expect(code).contains( - `_setDynamicProps(n0, { ["." + _ctx.fooBar]: _ctx.id })`, + `_setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }], true)`, ) }) @@ -449,7 +451,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.id, true)') }) test('.prop modifier (shortband) w/ no expression', () => { @@ -473,7 +475,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar)') + expect(code).contains('_setDOMProp(n0, "fooBar", _ctx.fooBar, true)') }) test('.attr modifier', () => { @@ -497,7 +499,7 @@ describe('compiler v-bind', () => { }, }) expect(code).contains('renderEffect') - expect(code).contains('_setAttr(n0, "foo-bar", _ctx.id)') + expect(code).contains('_setAttr(n0, "foo-bar", _ctx.id, true)') }) test('.attr modifier w/ no expression', () => { @@ -522,6 +524,6 @@ describe('compiler v-bind', () => { }) expect(code).contains('renderEffect') - expect(code).contains('_setAttr(n0, "foo-bar", _ctx.fooBar)') + expect(code).contains('_setAttr(n0, "foo-bar", _ctx.fooBar, true)') }) }) diff --git a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts index 612016107..d66c9df57 100644 --- a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts @@ -28,7 +28,11 @@ describe('v-html', () => { expect(vaporHelpers).contains('setHtml') expect(helpers.size).toBe(0) - expect(ir.block.operation).toEqual([]) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, + ]) expect(ir.block.effect).toMatchObject([ { expressions: [ @@ -70,7 +74,11 @@ describe('v-html', () => { // children should have been removed expect(ir.template).toEqual(['
']) - expect(ir.block.operation).toEqual([]) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, + ]) expect(ir.block.effect).toMatchObject([ { expressions: [ diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts index d8794b602..3c74c1971 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts @@ -47,6 +47,9 @@ describe('v-on', () => { keyOverride: undefined, delegate: true, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) }) @@ -91,7 +94,11 @@ describe('v-on', () => { expect(vaporHelpers).contains('on') expect(vaporHelpers).contains('renderEffect') expect(helpers.size).toBe(0) - expect(ir.block.operation).toEqual([]) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, + ]) expect(ir.block.effect[0].operations[0]).toMatchObject({ type: IRNodeTypes.SET_EVENT, @@ -130,7 +137,11 @@ describe('v-on', () => { expect(vaporHelpers).contains('on') expect(vaporHelpers).contains('renderEffect') expect(helpers.size).toBe(0) - expect(ir.block.operation).toEqual([]) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, + ]) expect(ir.block.effect[0].operations[0]).toMatchObject({ type: IRNodeTypes.SET_EVENT, @@ -169,6 +180,9 @@ describe('v-on', () => { }, delegate: true, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).contains(`_delegate(n0, "click", () => $event => (_ctx.i++))`) }) @@ -206,6 +220,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: 'foo();bar()' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) // should wrap with `{` for multiple statements // in this case the return value is discarded and the behavior is @@ -224,6 +241,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: '\nfoo();\nbar()\n' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) // should wrap with `{` for multiple statements // in this case the return value is discarded and the behavior is @@ -244,6 +264,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: 'foo($event)' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) // should NOT prefix $event expect(code).contains( @@ -262,6 +285,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: 'foo($event);bar()' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) // should NOT prefix $event expect(code).contains( @@ -278,6 +304,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: '$event => foo($event)' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).contains( `_delegate(n0, "click", () => $event => _ctx.foo($event))`, @@ -296,6 +325,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: '(e: any): any => foo(e)' }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).contains( `_delegate(n0, "click", () => (e: any): any => _ctx.foo(e))`, @@ -323,6 +355,9 @@ describe('v-on', () => { `, }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) }) @@ -349,6 +384,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: `a['b' + c]` }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -361,6 +399,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: `a['b' + c]` }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -378,6 +419,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, value: { content: `e => foo(e)` }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).contains(`_delegate(n0, "click", () => e => _ctx.foo(e))`) }) @@ -432,6 +476,9 @@ describe('v-on', () => { keyOverride: undefined, delegate: false, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).contains( `_on(n0, "click", () => _ctx.test, { @@ -487,6 +534,9 @@ describe('v-on', () => { options: [], }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -529,6 +579,9 @@ describe('v-on', () => { options: ['capture'], }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -543,6 +596,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, modifiers: { nonKeys: ['exact'] }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -562,6 +618,9 @@ describe('v-on', () => { options: [], }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -604,6 +663,9 @@ describe('v-on', () => { modifiers: { nonKeys: ['right'] }, keyOverride: undefined, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -645,6 +707,9 @@ describe('v-on', () => { modifiers: { nonKeys: ['middle'] }, keyOverride: undefined, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).matchSnapshot() @@ -694,6 +759,9 @@ describe('v-on', () => { type: IRNodeTypes.SET_EVENT, delegate: true, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) }) }) diff --git a/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts index 19c306aaa..f3f8679b4 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts @@ -68,6 +68,7 @@ describe('compiler: v-once', () => { elements: [0], parent: 2, }, + { type: IRNodeTypes.SET_INHERIT_ATTRS }, ]) }) @@ -96,6 +97,9 @@ describe('compiler: v-once', () => { ], }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) expect(code).not.contains('effect') }) @@ -128,6 +132,9 @@ describe('compiler: v-once', () => { ], }, }, + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, ]) }) @@ -147,6 +154,7 @@ describe('compiler: v-once', () => { elements: [0], parent: 1, }, + { type: IRNodeTypes.SET_INHERIT_ATTRS }, ]) }) @@ -160,7 +168,7 @@ describe('compiler: v-once', () => { expect(code).toMatchSnapshot() expect(helpers).lengthOf(0) expect(ir.block.effect).lengthOf(0) - expect(ir.block.operation).lengthOf(0) + expect(ir.block.operation).lengthOf(1) }) test.todo('with hoistStatic: true') diff --git a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts index 7bd2c0777..4542da09b 100644 --- a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts @@ -28,7 +28,11 @@ describe('v-text', () => { expect(vaporHelpers).contains('setText') expect(helpers.size).toBe(0) - expect(ir.block.operation).toEqual([]) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.SET_INHERIT_ATTRS, + }, + ]) expect(ir.block.effect).toMatchObject([ { diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts index a0df80790..d936a6340 100644 --- a/packages/compiler-vapor/src/generators/component.ts +++ b/packages/compiler-vapor/src/generators/component.ts @@ -28,7 +28,7 @@ import { genMulti, } from './utils' import { genExpression } from './expression' -import { genPropKey } from './prop' +import { genPropKey, genPropValue } from './prop' import { createSimpleExpression, toValidAssetId, @@ -121,14 +121,15 @@ function genStaticProps( } function genProp(prop: IRProp, context: CodegenContext, isStatic?: boolean) { + const values = genPropValue(prop.values, context) return [ ...genPropKey(prop, context), ': ', ...(prop.handler ? genEventHandler(context, prop.values[0]) : isStatic - ? ['() => (', ...genExpression(prop.values[0], context), ')'] - : genExpression(prop.values[0], context)), + ? ['() => (', ...values, ')'] + : values), ...(prop.model ? [...genModelEvent(prop, context), ...genModelModifiers(prop, context)] : []), diff --git a/packages/compiler-vapor/src/generators/expression.ts b/packages/compiler-vapor/src/generators/expression.ts index fee6cc18a..ad4058465 100644 --- a/packages/compiler-vapor/src/generators/expression.ts +++ b/packages/compiler-vapor/src/generators/expression.ts @@ -132,7 +132,7 @@ function genIdentifier( prefix = `${raw}: ` } - const type = bindingMetadata[raw] + const type = bindingMetadata && bindingMetadata[raw] if (inline) { switch (type) { case BindingTypes.SETUP_LET: diff --git a/packages/compiler-vapor/src/generators/operation.ts b/packages/compiler-vapor/src/generators/operation.ts index 244de2ad3..b637e797a 100644 --- a/packages/compiler-vapor/src/generators/operation.ts +++ b/packages/compiler-vapor/src/generators/operation.ts @@ -6,7 +6,7 @@ import { genFor } from './for' import { genSetHtml } from './html' import { genIf } from './if' import { genSetModelValue } from './modelValue' -import { genDynamicProps, genSetProp } from './prop' +import { genDynamicProps, genSetInheritAttrs, genSetProp } from './prop' import { genDeclareOldRef, genSetTemplateRef } from './templateRef' import { genCreateTextNode, genSetText } from './text' import { @@ -67,6 +67,8 @@ export function genOperation( return genDeclareOldRef(oper) case IRNodeTypes.SLOT_OUTLET_NODE: return genSlotOutlet(oper, context) + case IRNodeTypes.SET_INHERIT_ATTRS: + return genSetInheritAttrs(oper, context) } return [] diff --git a/packages/compiler-vapor/src/generators/prop.ts b/packages/compiler-vapor/src/generators/prop.ts index 3b6a44182..120aa3733 100644 --- a/packages/compiler-vapor/src/generators/prop.ts +++ b/packages/compiler-vapor/src/generators/prop.ts @@ -8,6 +8,7 @@ import { IRDynamicPropsKind, type IRProp, type SetDynamicPropsIRNode, + type SetInheritAttrsIRNode, type SetPropIRNode, type VaporHelper, } from '../ir' @@ -55,6 +56,7 @@ export function genSetProp( `n${oper.element}`, omitKey ? false : genExpression(key, context), genPropValue(values, context), + oper.root && 'true', ), ] } @@ -70,14 +72,18 @@ export function genDynamicProps( ...genCall( vaporHelper('setDynamicProps'), `n${oper.element}`, - ...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="" + genMulti( + DELIMITERS_ARRAY, + ...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="" + ), ), + oper.root && 'true', ), ] } @@ -125,7 +131,10 @@ export function genPropKey( return ['[', modifier && `${JSON.stringify(modifier)} + `, ...key, ']'] } -function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) { +export function genPropValue( + values: SimpleExpressionNode[], + context: CodegenContext, +): CodeFragment[] { if (values.length === 1) { return genExpression(values[0], context) } @@ -134,3 +143,28 @@ function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) { ...values.map(expr => genExpression(expr, context)), ) } + +export function genSetInheritAttrs( + { staticProps, dynamicProps }: SetInheritAttrsIRNode, + context: CodegenContext, +): CodeFragment[] { + const { vaporHelper } = context + + // - `undefined` : no props + // - `false` : all props are static + // - `string[]` : list of props are dynamic + // - `true` : all props as dynamic + const value = + dynamicProps === true + ? 'true' + : dynamicProps.length + ? genMulti( + DELIMITERS_ARRAY, + ...dynamicProps.map(p => JSON.stringify(p)), + ) + : staticProps + ? 'false' + : null + if (value == null) return [] + return [NEWLINE, ...genCall(vaporHelper('setInheritAttrs'), value)] +} diff --git a/packages/compiler-vapor/src/generators/utils.ts b/packages/compiler-vapor/src/generators/utils.ts index 9f3b8ad2e..f001d8e92 100644 --- a/packages/compiler-vapor/src/generators/utils.ts +++ b/packages/compiler-vapor/src/generators/utils.ts @@ -46,7 +46,7 @@ export function genMulti( ...frags: CodeFragments[] ): CodeFragment[] { if (placeholder) { - while (!frags[frags.length - 1]) { + while (frags.length > 0 && !frags[frags.length - 1]) { frags.pop() } frags = frags.map(frag => frag || placeholder) diff --git a/packages/compiler-vapor/src/ir/index.ts b/packages/compiler-vapor/src/ir/index.ts index 0b0b87fc4..8b887e924 100644 --- a/packages/compiler-vapor/src/ir/index.ts +++ b/packages/compiler-vapor/src/ir/index.ts @@ -24,6 +24,7 @@ export enum IRNodeTypes { SET_HTML, SET_TEMPLATE_REF, SET_MODEL_VALUE, + SET_INHERIT_ATTRS, INSERT_NODE, PREPEND_NODE, @@ -93,12 +94,14 @@ export interface SetPropIRNode extends BaseIRNode { type: IRNodeTypes.SET_PROP element: number prop: IRProp + root: boolean } export interface SetDynamicPropsIRNode extends BaseIRNode { type: IRNodeTypes.SET_DYNAMIC_PROPS element: number props: IRProps[] + root: boolean } export interface SetDynamicEventsIRNode extends BaseIRNode { @@ -156,6 +159,12 @@ export interface SetModelValueIRNode extends BaseIRNode { isComponent: boolean } +export interface SetInheritAttrsIRNode extends BaseIRNode { + type: IRNodeTypes.SET_INHERIT_ATTRS + staticProps: boolean + dynamicProps: true | string[] +} + export interface CreateTextNodeIRNode extends BaseIRNode { type: IRNodeTypes.CREATE_TEXT_NODE id: number @@ -220,6 +229,7 @@ export type OperationNode = | SetHtmlIRNode | SetTemplateRefIRNode | SetModelValueIRNode + | SetInheritAttrsIRNode | CreateTextNodeIRNode | InsertNodeIRNode | PrependNodeIRNode diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts index fd64e84a1..c894c724b 100644 --- a/packages/compiler-vapor/src/transforms/transformElement.ts +++ b/packages/compiler-vapor/src/transforms/transformElement.ts @@ -64,9 +64,15 @@ export const transformElement: NodeTransform = (node, context) => { isDynamicComponent, ) + const singleRoot = + context.root === context.parent && + context.parent.node.children.filter( + child => child.type !== NodeTypes.COMMENT, + ).length === 1 ;(isComponent ? transformComponentElement : transformNativeElement)( node as any, propsResult, + singleRoot, context as TransformContext, isDynamicComponent, ) @@ -76,6 +82,7 @@ export const transformElement: NodeTransform = (node, context) => { function transformComponentElement( node: ComponentNode, propsResult: PropsResult, + singleRoot: boolean, context: TransformContext, isDynamicComponent: boolean, ) { @@ -108,16 +115,13 @@ function transformComponentElement( } context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT - const root = - context.root === context.parent && context.parent.node.children.length === 1 - context.registerOperation({ type: IRNodeTypes.CREATE_COMPONENT_NODE, id: context.reference(), tag, props: propsResult[0] ? propsResult[1] : [propsResult[1]], asset, - root, + root: singleRoot, slots: [...context.slots], once: context.inVOnce, dynamic: dynamicComponent, @@ -162,6 +166,7 @@ function resolveSetupReference(name: string, context: TransformContext) { function transformNativeElement( node: PlainElementNode, propsResult: PropsResult, + singleRoot: boolean, context: TransformContext, ) { const { tag } = node @@ -172,29 +177,43 @@ function transformNativeElement( template += `<${tag}` if (scopeId) template += ` ${scopeId}` + let staticProps = false + const dynamicProps: string[] = [] if (propsResult[0] /* dynamic props */) { const [, dynamicArgs, expressions] = propsResult context.registerEffect(expressions, { type: IRNodeTypes.SET_DYNAMIC_PROPS, element: context.reference(), props: dynamicArgs, + root: singleRoot, }) } else { for (const prop of propsResult[1]) { const { key, values } = prop if (key.isStatic && values.length === 1 && values[0].isStatic) { + staticProps = true template += ` ${key.content}` if (values[0].content) template += `="${values[0].content}"` } else { + dynamicProps.push(key.content) context.registerEffect(values, { type: IRNodeTypes.SET_PROP, element: context.reference(), prop, + root: singleRoot, }) } } } + if (singleRoot) { + context.registerOperation({ + type: IRNodeTypes.SET_INHERIT_ATTRS, + staticProps: staticProps, + dynamicProps: propsResult[0] ? true : dynamicProps, + }) + } + template += `>` + context.childrenTemplate.join('') // TODO remove unnecessary close tag, e.g. if it's the last element of the template if (!isVoidTag(tag)) { diff --git a/packages/runtime-vapor/__tests__/apiSetupContext.spec.ts b/packages/runtime-vapor/__tests__/apiSetupContext.spec.ts index 7bee76beb..947e70421 100644 --- a/packages/runtime-vapor/__tests__/apiSetupContext.spec.ts +++ b/packages/runtime-vapor/__tests__/apiSetupContext.spec.ts @@ -11,6 +11,7 @@ import { ref, renderEffect, setDynamicProps, + setInheritAttrs, template, watchEffect, } from '../src' @@ -77,9 +78,7 @@ describe('api: setup context', () => { inheritAttrs: false, setup(props, { attrs }) { const el = document.createElement('div') - renderEffect(() => { - setDynamicProps(el, attrs) - }) + renderEffect(() => setDynamicProps(el, [attrs])) return el }, }) @@ -103,23 +102,24 @@ describe('api: setup context', () => { const toggle = ref(true) const Wrapper = defineComponent({ - setup(_, { slots }) { - return slots.default!() + setup(_) { + const n0 = createSlot('default') + setInheritAttrs(false, true) + return n0 }, }) const Child = defineComponent({ inheritAttrs: false, setup(_: any, { attrs }: any) { - return createComponent(Wrapper, null, { + const n0 = createComponent(Wrapper, null, { default: () => { const n0 = template('
')() as HTMLDivElement - renderEffect(() => { - setDynamicProps(n0, attrs) - }) + renderEffect(() => setDynamicProps(n0, [attrs], true)) return n0 }, }) + return n0 }, }) diff --git a/packages/runtime-vapor/__tests__/componentAttrs.spec.ts b/packages/runtime-vapor/__tests__/componentAttrs.spec.ts index 18effd8e0..d66474559 100644 --- a/packages/runtime-vapor/__tests__/componentAttrs.spec.ts +++ b/packages/runtime-vapor/__tests__/componentAttrs.spec.ts @@ -3,6 +3,7 @@ import { getCurrentInstance, nextTick, ref, + setInheritAttrs, setText, template, watchEffect, @@ -18,7 +19,8 @@ describe('attribute fallthrough', () => { props: ['foo'], render() { const instance = getCurrentInstance()! - const n0 = t0() + const n0 = t0() as Element + setInheritAttrs() watchEffect(() => setText(n0, instance.props.foo)) return n0 }, @@ -62,7 +64,8 @@ describe('attribute fallthrough', () => { inheritAttrs: false, render() { const instance = getCurrentInstance()! - const n0 = t0() + const n0 = t0() as Element + setInheritAttrs() watchEffect(() => setText(n0, instance.props.foo)) return n0 }, @@ -105,7 +108,8 @@ describe('attribute fallthrough', () => { props: ['custom-attr'], render() { const instance = getCurrentInstance()! - const n0 = t0() + const n0 = t0() as Element + setInheritAttrs() watchEffect(() => setText(n0, instance.attrs.foo)) return n0 }, diff --git a/packages/runtime-vapor/__tests__/dom/prop.spec.ts b/packages/runtime-vapor/__tests__/dom/prop.spec.ts index ab5a3d4e6..7ccb1f51e 100644 --- a/packages/runtime-vapor/__tests__/dom/prop.spec.ts +++ b/packages/runtime-vapor/__tests__/dom/prop.spec.ts @@ -407,25 +407,25 @@ describe('patchProp', () => { describe('setDynamicProps', () => { test('basic set dynamic props', () => { const el = document.createElement('div') - setDynamicProps(el, { foo: 'val' }, { bar: 'val' }) + setDynamicProps(el, [{ 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, [{ foo: 'val' }, { foo: 'newVal' }]) expect(el.getAttribute('foo')).toBe('newVal') }) test('should reset old props', () => { const el = document.createElement('div') - setDynamicProps(el, { foo: 'val' }) + setDynamicProps(el, [{ foo: 'val' }]) expect(el.attributes.length).toBe(1) expect(el.getAttribute('foo')).toBe('val') - setDynamicProps(el, { bar: 'val' }) + setDynamicProps(el, [{ bar: 'val' }]) expect(el.attributes.length).toBe(1) expect(el.getAttribute('bar')).toBe('val') expect(el.getAttribute('foo')).toBeNull() @@ -434,18 +434,18 @@ describe('patchProp', () => { test('should reset old modifier props', () => { const el = document.createElement('div') - setDynamicProps(el, { ['.foo']: 'val' }) + setDynamicProps(el, [{ ['.foo']: 'val' }]) expect((el as any).foo).toBe('val') - setDynamicProps(el, { ['.bar']: 'val' }) + setDynamicProps(el, [{ ['.bar']: 'val' }]) expect((el as any).bar).toBe('val') expect((el as any).foo).toBe('') - setDynamicProps(el, { ['^foo']: 'val' }) + setDynamicProps(el, [{ ['^foo']: 'val' }]) expect(el.attributes.length).toBe(1) expect(el.getAttribute('foo')).toBe('val') - setDynamicProps(el, { ['^bar']: 'val' }) + setDynamicProps(el, [{ ['^bar']: 'val' }]) expect(el.attributes.length).toBe(1) expect(el.getAttribute('bar')).toBe('val') expect(el.getAttribute('foo')).toBeNull() diff --git a/packages/runtime-vapor/src/apiCreateComponent.ts b/packages/runtime-vapor/src/apiCreateComponent.ts index 7b9198832..326a3b2f8 100644 --- a/packages/runtime-vapor/src/apiCreateComponent.ts +++ b/packages/runtime-vapor/src/apiCreateComponent.ts @@ -5,18 +5,13 @@ import { currentInstance, } from './component' import { setupComponent } from './apiRender' -import { - type NormalizedRawProps, - type RawProps, - normalizeRawProps, - walkRawProps, -} from './componentProps' +import { type RawProps, normalizeRawProps } from './componentProps' import { type RawSlots, isDynamicSlotFn } from './componentSlots' -import { withAttrs } from './componentAttrs' +import { setInheritAttrs, withAttrs } from './componentAttrs' import { isString } from '@vue/shared' import { renderEffect } from './renderEffect' import { normalizeBlock } from './dom/element' -import { setDynamicProp } from './dom/prop' +import { setDynamicProps } from './dom/prop' export function createComponent( comp: Component | string, @@ -25,11 +20,12 @@ export function createComponent( singleRoot: boolean = false, once: boolean = false, ): ComponentInternalInstance | HTMLElement { + const current = currentInstance! + if (isString(comp)) { - return fallbackComponent(comp, rawProps, slots) + return fallbackComponent(comp, rawProps, slots, current, singleRoot) } - const current = currentInstance! const instance = createComponentInstance( comp, singleRoot ? withAttrs(rawProps) : rawProps, @@ -48,17 +44,16 @@ function fallbackComponent( comp: string, rawProps: RawProps | null, slots: RawSlots | null, + instance: ComponentInternalInstance, + singleRoot: boolean = false, ): HTMLElement { // eslint-disable-next-line no-restricted-globals const el = document.createElement(comp) - if (rawProps) { - rawProps = normalizeRawProps(rawProps) - renderEffect(() => { - walkRawProps(rawProps as NormalizedRawProps, (key, value, getter) => { - setDynamicProp(el, key, getter ? value() : value) - }) - }) + if (rawProps || Object.keys(instance.attrs).length) { + renderEffect(() => + setDynamicProps(el, normalizeRawProps(rawProps), singleRoot), + ) } if (slots) { @@ -72,5 +67,9 @@ function fallbackComponent( } } + if (singleRoot) { + setInheritAttrs(true) + } + return el } diff --git a/packages/runtime-vapor/src/apiRender.ts b/packages/runtime-vapor/src/apiRender.ts index 7dd97193e..751a92c05 100644 --- a/packages/runtime-vapor/src/apiRender.ts +++ b/packages/runtime-vapor/src/apiRender.ts @@ -16,10 +16,10 @@ import { shallowReadonly, } from '@vue/reactivity' import { isArray, isFunction, isObject } from '@vue/shared' -import { fallThroughAttrs } from './componentAttrs' import { VaporErrorCodes, callWithErrorHandling } from './errorHandling' import { endMeasure, startMeasure } from './profiling' import { devtoolsComponentAdded } from './devtools' +import { fallThroughAttrs } from './componentAttrs' export const fragmentKey: unique symbol = Symbol(__DEV__ ? `fragmentKey` : ``) @@ -86,9 +86,6 @@ export function setupComponent(instance: ComponentInternalInstance): void { resetTracking() } - if (block instanceof DocumentFragment) { - block = Array.from(block.childNodes) - } if (!block) { // TODO: warn no template block = [] diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts index ca0cb7fa0..fdfcd55f0 100644 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@ -174,6 +174,13 @@ export interface ComponentInternalInstance { emit: EmitFn emitted: Record | null attrs: Data + /** + * - `undefined` : no props + * - `false` : all props are static + * - `string[]` : list of props are dynamic + * - `true` : all props as dynamic + */ + dynamicAttrs?: string[] | boolean slots: StaticSlots refs: Data // exposed properties via expose() diff --git a/packages/runtime-vapor/src/componentAttrs.ts b/packages/runtime-vapor/src/componentAttrs.ts index 53f951299..ce0ad86ca 100644 --- a/packages/runtime-vapor/src/componentAttrs.ts +++ b/packages/runtime-vapor/src/componentAttrs.ts @@ -1,11 +1,14 @@ -import { camelize, isArray } from '@vue/shared' +import { camelize, isArray, normalizeClass, normalizeStyle } from '@vue/shared' import { type ComponentInternalInstance, currentInstance } from './component' import { isEmitListener } from './componentEmits' -import { setDynamicProps } from './dom/prop' import { type RawProps, walkRawProps } from './componentProps' import { renderEffect } from './renderEffect' +import { mergeProp, setDynamicProp } from './dom/prop' -export function patchAttrs(instance: ComponentInternalInstance): void { +export function patchAttrs( + instance: ComponentInternalInstance, + hasDynamicProps?: boolean, +): void { const { attrs, rawProps, @@ -14,6 +17,8 @@ export function patchAttrs(instance: ComponentInternalInstance): void { if (!rawProps.length) return const keys = new Set() + const classes: any[] = [] + const styles: any[] = [] walkRawProps(rawProps, registerAttr) for (const key in attrs) { @@ -22,14 +27,42 @@ export function patchAttrs(instance: ComponentInternalInstance): void { } } + setClassOrStyle(classes, 'class', normalizeClass) + setClassOrStyle(styles, 'style', normalizeStyle) + + function setClassOrStyle( + values: any[], + field: 'class' | 'style', + normalize: (value: any) => any, + ) { + if (values.length) { + if (hasDynamicProps) { + Object.defineProperty(attrs, field, { + get() { + return normalize(values.map(value => value())) + }, + enumerable: true, + configurable: true, + }) + } else { + attrs[field] = normalizeClass(values) + } + } + } + function registerAttr(key: string, value: any, getter?: boolean) { if ( (!options || !(camelize(key) in options)) && !isEmitListener(instance.emitsOptions, key) && - !keys.has(key) + (key === 'class' || key === 'style' || !keys.has(key)) ) { keys.add(key) - if (getter) { + + if (key === 'class' || key === 'style') { + ;(key === 'class' ? classes : styles).push( + hasDynamicProps ? (getter ? value : () => value) : value, + ) + } else if (getter) { Object.defineProperty(attrs, key, { get: value, enumerable: true, @@ -57,16 +90,47 @@ export function fallThroughAttrs(instance: ComponentInternalInstance): void { const { block, type: { inheritAttrs }, + dynamicAttrs, } = instance - if (inheritAttrs === false) return + if ( + inheritAttrs === false || + !(block instanceof Element) || + // all props as dynamic + dynamicAttrs === true + ) + return - if (block instanceof Element) { + const hasStaticAttrs = dynamicAttrs || dynamicAttrs === false + + let initial: Record | undefined + if (hasStaticAttrs) { // attrs in static template - const initial: Record = {} + initial = {} for (let i = 0; i < block.attributes.length; i++) { const attr = block.attributes[i] + if (dynamicAttrs && dynamicAttrs.includes(attr.name)) continue initial[attr.name] = attr.value } - renderEffect(() => setDynamicProps(block, instance.attrs, initial)) } + + renderEffect(() => { + for (const key in instance.attrs) { + if (dynamicAttrs && dynamicAttrs.includes(key)) continue + + let value: unknown + if (hasStaticAttrs) { + value = mergeProp(key, instance.attrs[key], initial![key]) + } else { + value = instance.attrs[key] + } + + setDynamicProp(block, key, value) + } + }) +} + +export function setInheritAttrs(dynamicAttrs?: string[] | boolean): void { + const instance = currentInstance! + if (instance.type.inheritAttrs === false) return + instance.dynamicAttrs = dynamicAttrs } diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 6e2332881..1fb8d79f6 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -116,7 +116,7 @@ export function initProps( } if (hasDynamicProps) { - firstEffect(instance, () => patchAttrs(instance)) + firstEffect(instance, () => patchAttrs(instance, true)) } else { patchAttrs(instance) } diff --git a/packages/runtime-vapor/src/dom/prop.ts b/packages/runtime-vapor/src/dom/prop.ts index 411533722..a00caedee 100644 --- a/packages/runtime-vapor/src/dom/prop.ts +++ b/packages/runtime-vapor/src/dom/prop.ts @@ -18,9 +18,20 @@ import { } from '../componentMetadata' import { on } from './event' import type { Data } from '@vue/runtime-shared' +import { currentInstance } from '../component' + +export function mergeInheritAttr(key: string, value: any): unknown { + const instance = currentInstance! + return mergeProp(key, instance.attrs[key], value) +} + +export function setClass(el: Element, value: any, root?: boolean): void { + const prev = recordPropMetadata( + el, + 'class', + (value = normalizeClass(root ? mergeInheritAttr('class', value) : value)), + ) -export function setClass(el: Element, value: any): void { - const prev = recordPropMetadata(el, 'class', (value = normalizeClass(value))) if (value !== prev && (value || prev)) { el.className = value } @@ -109,7 +120,12 @@ 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, + value: any, + root?: boolean, +): void { // TODO const isSVG = false if (key === 'class') { @@ -132,8 +148,15 @@ export function setDynamicProp(el: Element, key: string, value: any): void { } } -export function setDynamicProps(el: Element, ...args: any): void { +export function setDynamicProps( + el: Element, + args: any[], + root?: boolean, +): void { const oldProps = getMetadata(el)[MetadataKind.prop] + if (root) { + args.unshift(currentInstance!.attrs) + } const props = args.length > 1 ? mergeProps(...args) : args[0] for (const key in oldProps) { @@ -153,32 +176,36 @@ export function setDynamicProps(el: Element, ...args: any): void { } } -// TODO copied from runtime-core +export function mergeProp( + key: string, + existing: unknown, + incoming: unknown, +): unknown { + if (key === 'class') { + if (existing !== incoming) { + return normalizeClass([existing, incoming]) + } + } else if (key === 'style') { + return normalizeStyle([existing, incoming]) + } else if (isOn(key)) { + if ( + incoming && + existing !== incoming && + !(isArray(existing) && existing.includes(incoming)) + ) { + return existing ? [].concat(existing as any, incoming as any) : incoming + } + } + return incoming +} + export function mergeProps(...args: Data[]): Data { const ret: Data = {} for (let i = 0; i < args.length; i++) { const toMerge = args[i] for (const key in toMerge) { - if (key === 'class') { - if (ret.class !== toMerge.class) { - ret.class = normalizeClass([ret.class, toMerge.class]) - } - } else if (key === 'style') { - ret.style = normalizeStyle([ret.style, toMerge.style]) - } else if (isOn(key)) { - const existing = ret[key] - const incoming = toMerge[key] - if ( - incoming && - existing !== incoming && - !(isArray(existing) && existing.includes(incoming)) - ) { - ret[key] = existing - ? [].concat(existing as any, incoming as any) - : incoming - } - } else if (key !== '') { - ret[key] = toMerge[key] + if (key !== '') { + ret[key] = mergeProp(key, ret[key], toMerge[key]) } } } diff --git a/packages/runtime-vapor/src/dom/style.ts b/packages/runtime-vapor/src/dom/style.ts index b7ecfa53c..5ee233a0c 100644 --- a/packages/runtime-vapor/src/dom/style.ts +++ b/packages/runtime-vapor/src/dom/style.ts @@ -8,9 +8,14 @@ import { } from '@vue/shared' import { warn } from '../warning' import { recordPropMetadata } from '../componentMetadata' +import { mergeInheritAttr } from './prop' -export function setStyle(el: HTMLElement, value: any): void { - const prev = recordPropMetadata(el, 'style', (value = normalizeStyle(value))) +export function setStyle(el: HTMLElement, value: any, root?: boolean): void { + const prev = recordPropMetadata( + el, + 'style', + (value = normalizeStyle(root ? mergeInheritAttr('style', value) : value)), + ) patchStyle(el, prev, value) } diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts index 0a652b208..f1d77f2ee 100644 --- a/packages/runtime-vapor/src/index.ts +++ b/packages/runtime-vapor/src/index.ts @@ -130,6 +130,7 @@ export { createIf } from './apiCreateIf' export { createFor, createForSlots } from './apiCreateFor' export { createComponent } from './apiCreateComponent' export { createSelector } from './apiCreateSelector' +export { setInheritAttrs } from './componentAttrs' export { resolveComponent, diff --git a/playground/package.json b/playground/package.json index 8c28097d5..c3e21f038 100644 --- a/playground/package.json +++ b/playground/package.json @@ -12,7 +12,7 @@ "vue": "workspace:*" }, "devDependencies": { - "@vitejs/plugin-vue": "https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5", + "@vitejs/plugin-vue": "https://pkg.pr.new/@vitejs/plugin-vue@481bcd4", "vite": "catalog:", "vite-hyper-config": "^0.4.0", "vite-plugin-inspect": "^0.8.7" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45a506eda..37f7290fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -521,8 +521,8 @@ importers: version: link:../packages/vue devDependencies: '@vitejs/plugin-vue': - specifier: https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5 - version: https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@packages+vue) + specifier: https://pkg.pr.new/@vitejs/plugin-vue@481bcd4 + version: https://pkg.pr.new/@vitejs/plugin-vue@481bcd4(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@packages+vue) vite: specifier: 'catalog:' version: 5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0) @@ -1416,6 +1416,14 @@ packages: vite: ^5.0.0 vue: ^3.2.25 + '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@481bcd4': + resolution: {tarball: https://pkg.pr.new/@vitejs/plugin-vue@481bcd4} + version: 5.1.5 + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + vue: ^3.2.25 + '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5': resolution: {tarball: https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5} version: 5.1.4 @@ -4495,15 +4503,15 @@ snapshots: vite: 5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0) vue: link:packages/vue - '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@3.5.12(typescript@5.6.2))': + '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@481bcd4(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@packages+vue)': dependencies: vite: 5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0) - vue: 3.5.12(typescript@5.6.2) + vue: link:packages/vue - '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@packages+vue)': + '@vitejs/plugin-vue@https://pkg.pr.new/@vitejs/plugin-vue@e3c5ce5(vite@5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0))(vue@3.5.12(typescript@5.6.2))': dependencies: vite: 5.4.8(@types/node@22.8.7)(sass@1.80.6)(terser@5.33.0) - vue: link:packages/vue + vue: 3.5.12(typescript@5.6.2) '@vitest/coverage-v8@2.1.1(vitest@2.1.1)': dependencies: