Merge tag 'v3.4.5'

This commit is contained in:
三咲智子 Kevin Deng 2024-01-04 17:43:25 +08:00
commit c9fe3f12e7
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
15 changed files with 156 additions and 73 deletions

View File

@ -1,3 +1,15 @@
## [3.4.5](https://github.com/vuejs/core/compare/v3.4.4...v3.4.5) (2024-01-04)
### Bug Fixes
* **compiler-sfc:** fix co-usage of defineModel transform options and props destructure ([b20350d](https://github.com/vuejs/core/commit/b20350ded562d27e5901f308d0bc13344f840c4a)), closes [#9972](https://github.com/vuejs/core/issues/9972)
* **compiler-sfc:** fix sfc template unref rewrite for class instantiation ([ae60a91](https://github.com/vuejs/core/commit/ae60a91cc23424493071ad9088782763eb1e8ff7)), closes [#6483](https://github.com/vuejs/core/issues/6483) [#6491](https://github.com/vuejs/core/issues/6491)
* **compiler-ssr:** fix node clone edge case caused by AST reuse ([#9983](https://github.com/vuejs/core/issues/9983)) ([7dbdb3e](https://github.com/vuejs/core/commit/7dbdb3edf0ab648965331ca42f069387c97a1c8a)), closes [#9981](https://github.com/vuejs/core/issues/9981)
* **watch:** cleanup watcher effect from scope when manually stopped ([#9978](https://github.com/vuejs/core/issues/9978)) ([d2d8955](https://github.com/vuejs/core/commit/d2d89551bb06dc05cb7ae0496b8f345ae0de78ed))
## [3.4.4](https://github.com/vuejs/core/compare/v3.4.3...v3.4.4) (2024-01-03)

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",

View File

@ -17,8 +17,8 @@ export default {
__expose();
const modelValue = _useModel(__props, "modelValue")
const c = _useModel(__props, "count")
const toString = _useModel(__props, "toString")
const c = _useModel(__props, 'count')
const toString = _useModel(__props, 'toString')
return { modelValue, c, toString }
}
@ -40,7 +40,10 @@ export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
const modelValue = _useModel(__props, "modelValue", { get(v) { return v - 1 }, set: (v) => { return v + 1 }, })
const modelValue = _useModel(__props, "modelValue", {
get(v) { return v - 1 },
set: (v) => { return v + 1 },
})
return { modelValue }
}
@ -63,7 +66,36 @@ export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
const modelValue = _useModel(__props, "modelValue", { get(v) { return v - 1 }, set: (v) => { return v + 1 }, })
const modelValue = _useModel(__props, "modelValue", {
get(v) { return v - 1 },
set: (v) => { return v + 1 },
})
return { modelValue }
}
})"
`;
exports[`defineModel() > usage w/ props destructure 1`] = `
"import { useModel as _useModel, mergeModels as _mergeModels, defineComponent as _defineComponent } from 'vue'
export default /*#__PURE__*/_defineComponent({
props: /*#__PURE__*/_mergeModels({
x: { type: Number, required: true }
}, {
"modelValue": {
},
"modelModifiers": {},
}),
emits: ["update:modelValue"],
setup(__props: any, { expose: __expose }) {
__expose();
const modelValue = _useModel(__props, "modelValue", {
set: (v) => { return v + __props.x }
})
return { modelValue }
}
@ -84,7 +116,7 @@ export default {
__expose();
const count = _useModel(__props, "count")
const count = _useModel(__props, 'count')
return { count }
}
@ -132,10 +164,10 @@ export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
const modelValue = _useModel(__props, "modelValue")
const count = _useModel(__props, "count")
const disabled = _useModel(__props, "disabled")
const any = _useModel(__props, "any")
const modelValue = _useModel<boolean | string>(__props, "modelValue")
const count = _useModel<number>(__props, 'count')
const disabled = _useModel<number>(__props, 'disabled')
const any = _useModel<any | boolean>(__props, 'any')
return { modelValue, count, disabled, any }
}
@ -163,11 +195,11 @@ export default /*#__PURE__*/_defineComponent({
setup(__props, { expose: __expose }) {
__expose();
const modelValue = _useModel(__props, "modelValue")
const fn = _useModel(__props, "fn")
const fnWithDefault = _useModel(__props, "fnWithDefault")
const str = _useModel(__props, "str")
const optional = _useModel(__props, "optional")
const modelValue = _useModel<boolean>(__props, "modelValue")
const fn = _useModel<() => void>(__props, 'fn')
const fnWithDefault = _useModel<() => void>(__props, 'fnWithDefault')
const str = _useModel<string>(__props, 'str')
const optional = _useModel<string>(__props, 'optional')
return { modelValue, fn, fnWithDefault, str, optional }
}

View File

@ -23,7 +23,8 @@ describe('defineModel()', () => {
expect(content).toMatch(
`const modelValue = _useModel(__props, "modelValue")`,
)
expect(content).toMatch(`const c = _useModel(__props, "count")`)
expect(content).toMatch(`const c = _useModel(__props, 'count')`)
expect(content).toMatch(`const toString = _useModel(__props, 'toString')`)
expect(content).toMatch(`return { modelValue, c, toString }`)
expect(content).not.toMatch('defineModel')
@ -71,7 +72,7 @@ describe('defineModel()', () => {
"count": {},
"countModifiers": {},
})`)
expect(content).toMatch(`const count = _useModel(__props, "count")`)
expect(content).toMatch(`const count = _useModel(__props, 'count')`)
expect(content).not.toMatch('defineModel')
expect(bindings).toStrictEqual({
foo: BindingTypes.PROPS,
@ -104,11 +105,15 @@ describe('defineModel()', () => {
)
expect(content).toMatch(
`const modelValue = _useModel(__props, "modelValue")`,
`const modelValue = _useModel<boolean | string>(__props, "modelValue")`,
)
expect(content).toMatch(`const count = _useModel<number>(__props, 'count')`)
expect(content).toMatch(
`const disabled = _useModel<number>(__props, 'disabled')`,
)
expect(content).toMatch(
`const any = _useModel<any | boolean>(__props, 'any')`,
)
expect(content).toMatch(`const count = _useModel(__props, "count")`)
expect(content).toMatch(`const disabled = _useModel(__props, "disabled")`)
expect(content).toMatch(`const any = _useModel(__props, "any")`)
expect(bindings).toStrictEqual({
modelValue: BindingTypes.SETUP_REF,
@ -143,10 +148,10 @@ describe('defineModel()', () => {
'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]',
)
expect(content).toMatch(
`const modelValue = _useModel(__props, "modelValue")`,
`const modelValue = _useModel<boolean>(__props, "modelValue")`,
)
expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
expect(content).toMatch(`const str = _useModel(__props, "str")`)
expect(content).toMatch(`const fn = _useModel<() => void>(__props, 'fn')`)
expect(content).toMatch(`const str = _useModel<string>(__props, 'str')`)
expect(bindings).toStrictEqual({
modelValue: BindingTypes.SETUP_REF,
fn: BindingTypes.SETUP_REF,
@ -171,7 +176,10 @@ describe('defineModel()', () => {
assertCode(content)
expect(content).toMatch(/"modelValue": {\s+required: true,?\s+}/m)
expect(content).toMatch(
`_useModel(__props, "modelValue", { get(v) { return v - 1 }, set: (v) => { return v + 1 }, })`,
`_useModel(__props, "modelValue", {
get(v) { return v - 1 },
set: (v) => { return v + 1 },
})`,
)
const { content: content2 } = compile(
@ -191,7 +199,26 @@ describe('defineModel()', () => {
/"modelValue": {\s+default: 0,\s+required: true,?\s+}/m,
)
expect(content2).toMatch(
`_useModel(__props, "modelValue", { get(v) { return v - 1 }, set: (v) => { return v + 1 }, })`,
`_useModel(__props, "modelValue", {
get(v) { return v - 1 },
set: (v) => { return v + 1 },
})`,
)
})
test('usage w/ props destructure', () => {
const { content } = compile(
`
<script setup lang="ts">
const { x } = defineProps<{ x: number }>()
const modelValue = defineModel({
set: (v) => { return v + x }
})
</script>
`,
{ propsDestructure: true },
)
assertCode(content)
expect(content).toMatch(`set: (v) => { return v + __props.x }`)
})
})

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",

View File

@ -33,7 +33,8 @@ export function processDefineModel(
let modelName: string
let options: Node | undefined
const arg0 = node.arguments[0] && unwrapTSNode(node.arguments[0])
if (arg0 && arg0.type === 'StringLiteral') {
const hasName = arg0 && arg0.type === 'StringLiteral'
if (hasName) {
modelName = arg0.value
options = node.arguments[1]
} else {
@ -46,39 +47,42 @@ export function processDefineModel(
}
let optionsString = options && ctx.getString(options)
let runtimeOptions = ''
let transformOptions = ''
let optionsRemoved = !options
if (options) {
if (options.type === 'ObjectExpression') {
for (let i = options.properties.length - 1; i >= 0; i--) {
const p = options.properties[i]
if (p.type === 'SpreadElement' || p.computed) {
runtimeOptions = optionsString!
break
}
if (
(p.type === 'ObjectProperty' || p.type === 'ObjectMethod') &&
((p.key.type === 'Identifier' &&
(p.key.name === 'get' || p.key.name === 'set')) ||
(p.key.type === 'StringLiteral' &&
(p.key.value === 'get' || p.key.value === 'set')))
) {
transformOptions = ctx.getString(p) + ', ' + transformOptions
// remove transform option from prop options to avoid duplicates
const offset = p.start! - options.start!
const next = options.properties[i + 1]
const end = (next ? next.start! : options.end! - 1) - options.start!
optionsString =
optionsString.slice(0, offset) + optionsString.slice(end)
}
if (
options &&
options.type === 'ObjectExpression' &&
!options.properties.some(p => p.type === 'SpreadElement' || p.computed)
) {
let removed = 0
for (let i = options.properties.length - 1; i >= 0; i--) {
const p = options.properties[i]
const next = options.properties[i + 1]
const start = p.start!
const end = next ? next.start! : options.end! - 1
if (
(p.type === 'ObjectProperty' || p.type === 'ObjectMethod') &&
((p.key.type === 'Identifier' &&
(p.key.name === 'get' || p.key.name === 'set')) ||
(p.key.type === 'StringLiteral' &&
(p.key.value === 'get' || p.key.value === 'set')))
) {
// remove runtime-only options from prop options to avoid duplicates
optionsString =
optionsString.slice(0, start - options.start!) +
optionsString.slice(end - options.start!)
} else {
// remove prop options from runtime options
removed++
ctx.s.remove(ctx.startOffset! + start, ctx.startOffset! + end)
}
if (!runtimeOptions && transformOptions) {
runtimeOptions = `{ ${transformOptions} }`
}
} else {
runtimeOptions = optionsString!
}
if (removed === options.properties.length) {
optionsRemoved = true
ctx.s.remove(
ctx.startOffset! + (hasName ? arg0.end! : options.start!),
ctx.startOffset! + options.end!,
)
}
}
@ -91,12 +95,20 @@ export function processDefineModel(
// register binding type
ctx.bindingMetadata[modelName] = BindingTypes.PROPS
// defineModel -> useModel
ctx.s.overwrite(
ctx.startOffset! + node.start!,
ctx.startOffset! + node.end!,
`${ctx.helper('useModel')}(__props, ${JSON.stringify(modelName)}${
runtimeOptions ? `, ${runtimeOptions}` : ``
})`,
ctx.startOffset! + node.callee.start!,
ctx.startOffset! + node.callee.end!,
ctx.helper('useModel'),
)
// inject arguments
ctx.s.appendLeft(
ctx.startOffset! +
(node.arguments.length ? node.arguments[0].start! : node.end! - 1),
`__props, ` +
(hasName
? ``
: `${JSON.stringify(modelName)}${optionsRemoved ? `` : `, `}`),
)
return true

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/runtime-core",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/runtime-core",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/runtime-dom",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/runtime-dom",
"main": "index.js",
"module": "dist/runtime-dom.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/server-renderer",
"version": "3.4.4",
"version": "3.4.5",
"description": "@vue/server-renderer",
"main": "index.js",
"module": "dist/server-renderer.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/shared",
"version": "3.4.4",
"version": "3.4.5",
"description": "internal utils shared across @vue packages",
"main": "index.js",
"module": "dist/shared.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "@vue/compat",
"version": "3.4.4",
"version": "3.4.5",
"description": "Vue 3 compatibility build for Vue 2",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",

View File

@ -1,6 +1,6 @@
{
"name": "vue",
"version": "3.4.4",
"version": "3.4.5",
"description": "The progressive JavaScript framework for building modern web UI.",
"main": "index.js",
"module": "dist/vue.runtime.esm-bundler.js",