Skip to content

Commit 3b9227b

Browse files
Merge branch 'main' into fix-vModel-checkbox
2 parents 3880db7 + 04d2c05 commit 3b9227b

File tree

23 files changed

+202
-46
lines changed

23 files changed

+202
-46
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16)
2+
3+
4+
### Bug Fixes
5+
6+
* **hydration:** handle appear transition before patch props ([#9837](https://github.com/vuejs/core/issues/9837)) ([e70f4c4](https://github.com/vuejs/core/commit/e70f4c47c553b6e16d8fad70743271ca23802fe7)), closes [#9832](https://github.com/vuejs/core/issues/9832)
7+
* **sfc/cssVars:** fix loss of CSS v-bind variables when setting inline style with string value ([#9824](https://github.com/vuejs/core/issues/9824)) ([0a387df](https://github.com/vuejs/core/commit/0a387dfb1d04afb6eae4296b6da76dfdaca77af4)), closes [#9821](https://github.com/vuejs/core/issues/9821)
8+
* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))
9+
* **types:** add `xmlns:xlink` to `SVGAttributes` ([#9300](https://github.com/vuejs/core/issues/9300)) ([0d61b42](https://github.com/vuejs/core/commit/0d61b429ecf63591d31e09702058fa4c7132e1a7)), closes [#9299](https://github.com/vuejs/core/issues/9299)
10+
* **types:** fix `shallowRef` type error ([#9839](https://github.com/vuejs/core/issues/9839)) ([9a57158](https://github.com/vuejs/core/commit/9a571582b53220270e498d8712ea59312c0bef3a))
11+
* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))
12+
13+
14+
115
## [3.3.11](https://github.com/vuejs/core/compare/v3.3.10...v3.3.11) (2023-12-08)
216

317

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"private": true,
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"packageManager": "[email protected]",
55
"type": "module",
66
"scripts": {

packages/compiler-core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-core",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/compiler-core",
55
"main": "index.js",
66
"module": "dist/compiler-core.esm-bundler.js",

packages/compiler-dom/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-dom",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/compiler-dom",
55
"main": "index.js",
66
"module": "dist/compiler-dom.esm-bundler.js",

packages/compiler-sfc/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-sfc",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/compiler-sfc",
55
"main": "dist/compiler-sfc.cjs.js",
66
"module": "dist/compiler-sfc.esm-browser.js",

packages/compiler-ssr/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/compiler-ssr",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/compiler-ssr",
55
"main": "dist/compiler-ssr.cjs.js",
66
"types": "dist/compiler-ssr.d.ts",

packages/dts-test/ref.test-d.ts

+31-3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,17 @@ const state = reactive({
163163

164164
expectType<string>(state.foo.label)
165165

166+
describe('ref with generic', <T extends { name: string }>() => {
167+
const r = {} as T
168+
const s = ref(r)
169+
expectType<string>(s.value.name)
170+
171+
const rr = {} as MaybeRef<T>
172+
// should at least allow casting
173+
const ss = ref(rr) as Ref<T>
174+
expectType<string>(ss.value.name)
175+
})
176+
166177
// shallowRef
167178
type Status = 'initial' | 'ready' | 'invalidating'
168179
const shallowStatus = shallowRef<Status>('initial')
@@ -201,11 +212,28 @@ if (refStatus.value === 'initial') {
201212
expectType<IsAny<typeof a>>(false)
202213
}
203214

204-
describe('shallowRef with generic', <T>() => {
205-
const r = ref({}) as MaybeRef<T>
206-
expectType<ShallowRef<T> | Ref<T>>(shallowRef(r))
215+
describe('shallowRef with generic', <T extends { name: string }>() => {
216+
const r = {} as T
217+
const s = shallowRef(r)
218+
expectType<string>(s.value.name)
219+
expectType<ShallowRef<T>>(shallowRef(r))
220+
221+
const rr = {} as MaybeRef<T>
222+
// should at least allow casting
223+
const ss = shallowRef(rr) as Ref<T> | ShallowRef<T>
224+
expectType<string>(ss.value.name)
207225
})
208226

227+
{
228+
// should return ShallowRef<T> | Ref<T>, not ShallowRef<T | Ref<T>>
229+
expectType<ShallowRef<{ name: string }> | Ref<{ name: string }>>(
230+
shallowRef({} as MaybeRef<{ name: string }>)
231+
)
232+
expectType<ShallowRef<number> | Ref<string[]> | ShallowRef<string>>(
233+
shallowRef('' as Ref<string[]> | string | number)
234+
)
235+
}
236+
209237
// proxyRefs: should return `reactive` directly
210238
const r1 = reactive({
211239
k: 'v'

packages/reactivity-transform/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/reactivity-transform",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/reactivity-transform",
55
"main": "dist/reactivity-transform.cjs.js",
66
"files": [

packages/reactivity/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/reactivity",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/reactivity",
55
"main": "index.js",
66
"module": "dist/reactivity.esm-bundler.js",

packages/reactivity/src/ref.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,13 @@ export type ShallowRef<T = any> = Ref<T> & { [ShallowRefMarker]?: true }
114114
* @param value - The "inner value" for the shallow ref.
115115
* @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowref}
116116
*/
117-
export function shallowRef<T>(value: MaybeRef<T>): Ref<T> | ShallowRef<T>
118-
export function shallowRef<T extends Ref>(value: T): T
119-
export function shallowRef<T>(value: T): ShallowRef<T>
117+
export function shallowRef<T>(
118+
value: T
119+
): Ref extends T
120+
? T extends Ref
121+
? IfAny<T, ShallowRef<T>, T>
122+
: ShallowRef<T>
123+
: ShallowRef<T>
120124
export function shallowRef<T = any>(): ShallowRef<T | undefined>
121125
export function shallowRef(value?: unknown) {
122126
return createRef(value, true)

packages/runtime-core/__tests__/hydration.spec.ts

+35
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,41 @@ describe('SSR hydration', () => {
11141114
expect(`mismatch`).not.toHaveBeenWarned()
11151115
})
11161116

1117+
test('transition appear w/ event listener', async () => {
1118+
const container = document.createElement('div')
1119+
container.innerHTML = `<template><button>0</button></template>`
1120+
createSSRApp({
1121+
data() {
1122+
return {
1123+
count: 0
1124+
}
1125+
},
1126+
template: `
1127+
<Transition appear>
1128+
<button @click="count++">{{count}}</button>
1129+
</Transition>
1130+
`
1131+
}).mount(container)
1132+
1133+
expect(container.firstChild).toMatchInlineSnapshot(`
1134+
<button
1135+
class="v-enter-from v-enter-active"
1136+
>
1137+
0
1138+
</button>
1139+
`)
1140+
1141+
triggerEvent('click', container.querySelector('button')!)
1142+
await nextTick()
1143+
expect(container.firstChild).toMatchInlineSnapshot(`
1144+
<button
1145+
class="v-enter-from v-enter-active"
1146+
>
1147+
1
1148+
</button>
1149+
`)
1150+
})
1151+
11171152
describe('mismatch handling', () => {
11181153
test('text node', () => {
11191154
const { container } = mountWithHydration(`foo`, () => 'bar')

packages/runtime-core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/runtime-core",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/runtime-core",
55
"main": "index.js",
66
"module": "dist/runtime-core.esm-bundler.js",

packages/runtime-core/src/hydration.ts

+22-21
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,28 @@ export function createHydrationFunctions(
344344
if (dirs) {
345345
invokeDirectiveHook(vnode, null, parentComponent, 'created')
346346
}
347+
348+
// handle appear transition
349+
let needCallTransitionHooks = false
350+
if (isTemplateNode(el)) {
351+
needCallTransitionHooks =
352+
needTransition(parentSuspense, transition) &&
353+
parentComponent &&
354+
parentComponent.vnode.props &&
355+
parentComponent.vnode.props.appear
356+
357+
const content = (el as HTMLTemplateElement).content
358+
.firstChild as Element
359+
360+
if (needCallTransitionHooks) {
361+
transition!.beforeEnter(content)
362+
}
363+
364+
// replace <template> node with inner children
365+
replaceNode(content, el, parentComponent)
366+
vnode.el = el = content
367+
}
368+
347369
// props
348370
if (props) {
349371
if (
@@ -390,27 +412,6 @@ export function createHydrationFunctions(
390412
invokeVNodeHook(vnodeHooks, parentComponent, vnode)
391413
}
392414

393-
// handle appear transition
394-
let needCallTransitionHooks = false
395-
if (isTemplateNode(el)) {
396-
needCallTransitionHooks =
397-
needTransition(parentSuspense, transition) &&
398-
parentComponent &&
399-
parentComponent.vnode.props &&
400-
parentComponent.vnode.props.appear
401-
402-
const content = (el as HTMLTemplateElement).content
403-
.firstChild as Element
404-
405-
if (needCallTransitionHooks) {
406-
transition!.beforeEnter(content)
407-
}
408-
409-
// replace <template> node with inner children
410-
replaceNode(content, el, parentComponent)
411-
vnode.el = el = content
412-
}
413-
414415
if (dirs) {
415416
invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')
416417
}

packages/runtime-dom/__tests__/directives/vOn.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,32 @@ describe('runtime-dom: v-on directive', () => {
135135
handler(event, 'value', true)
136136
expect(fn).toBeCalledWith(event, 'value', true)
137137
})
138+
139+
it('withKeys cache wrapped listener separately for different modifiers', () => {
140+
const el1 = document.createElement('button')
141+
const el2 = document.createElement('button')
142+
const fn = vi.fn()
143+
const handler1 = withKeys(fn, ['a'])
144+
const handler2 = withKeys(fn, ['b'])
145+
expect(handler1 === handler2).toBe(false)
146+
patchEvent(el1, 'onKeyup', null, handler1, null)
147+
patchEvent(el2, 'onKeyup', null, handler2, null)
148+
triggerEvent(el1, 'keyup', e => (e.key = 'a'))
149+
triggerEvent(el2, 'keyup', e => (e.key = 'b'))
150+
expect(fn).toBeCalledTimes(2)
151+
})
152+
153+
it('withModifiers cache wrapped listener separately for different modifiers', () => {
154+
const el1 = document.createElement('button')
155+
const el2 = document.createElement('button')
156+
const fn = vi.fn()
157+
const handler1 = withModifiers(fn, ['ctrl'])
158+
const handler2 = withModifiers(fn, ['shift'])
159+
expect(handler1 === handler2).toBe(false)
160+
patchEvent(el1, 'onClick', null, handler1, null)
161+
patchEvent(el2, 'onClick', null, handler2, null)
162+
triggerEvent(el1, 'click', e => (e.ctrlKey = true))
163+
triggerEvent(el2, 'click', e => (e.shiftKey = true))
164+
expect(fn).toBeCalledTimes(2)
165+
})
138166
})

packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts

+31
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,35 @@ describe('useCssVars', () => {
293293
await nextTick()
294294
expect(target.children.length).toBe(0)
295295
})
296+
297+
test('with string style', async () => {
298+
document.body.innerHTML = ''
299+
const state = reactive({ color: 'red' })
300+
const root = document.createElement('div')
301+
const disabled = ref(false)
302+
303+
const App = {
304+
setup() {
305+
useCssVars(() => state)
306+
return () => [
307+
h(
308+
'div',
309+
{ style: disabled.value ? 'pointer-events: none' : undefined },
310+
'foo'
311+
)
312+
]
313+
}
314+
}
315+
render(h(App), root)
316+
await nextTick()
317+
for (const c of [].slice.call(root.children as any)) {
318+
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
319+
}
320+
disabled.value = true
321+
await nextTick()
322+
323+
for (const c of [].slice.call(root.children as any)) {
324+
expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
325+
}
326+
})
296327
})

packages/runtime-dom/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/runtime-dom",
3-
"version": "3.3.11",
3+
"version": "3.3.12",
44
"description": "@vue/runtime-dom",
55
"main": "index.js",
66
"module": "dist/runtime-dom.esm-bundler.js",

packages/runtime-dom/src/directives/vOn.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ const modifierGuards: Record<
3535
export const withModifiers = <
3636
T extends (event: Event, ...args: unknown[]) => any
3737
>(
38-
fn: T & { _withMods?: T },
38+
fn: T & { _withMods?: { [key: string]: T } },
3939
modifiers: string[]
4040
) => {
41+
const cache = fn._withMods || (fn._withMods = {})
42+
const cacheKey = modifiers.join('.')
4143
return (
42-
fn._withMods ||
43-
(fn._withMods = ((event, ...args) => {
44+
cache[cacheKey] ||
45+
(cache[cacheKey] = ((event, ...args) => {
4446
for (let i = 0; i < modifiers.length; i++) {
4547
const guard = modifierGuards[modifiers[i]]
4648
if (guard && guard(event, modifiers)) return
@@ -66,7 +68,7 @@ const keyNames: Record<string, string | string[]> = {
6668
* @private
6769
*/
6870
export const withKeys = <T extends (event: KeyboardEvent) => any>(
69-
fn: T & { _withKeys?: T },
71+
fn: T & { _withKeys?: { [k: string]: T } },
7072
modifiers: string[]
7173
) => {
7274
let globalKeyCodes: LegacyConfig['keyCodes']
@@ -88,9 +90,12 @@ export const withKeys = <T extends (event: KeyboardEvent) => any>(
8890
}
8991
}
9092

93+
const cache: { [k: string]: T } = fn._withKeys || (fn._withKeys = {})
94+
const cacheKey = modifiers.join('.')
95+
9196
return (
92-
fn._withKeys ||
93-
(fn._withKeys = (event => {
97+
cache[cacheKey] ||
98+
(cache[cacheKey] = (event => {
9499
if (!('key' in event)) {
95100
return
96101
}

packages/runtime-dom/src/helpers/useCssVars.ts

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '@vue/runtime-core'
1111
import { ShapeFlags } from '@vue/shared'
1212

13+
export const CSS_VAR_TEXT = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '')
1314
/**
1415
* Runtime helper for SFC's CSS variable injection feature.
1516
* @private
@@ -79,8 +80,11 @@ function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
7980
function setVarsOnNode(el: Node, vars: Record<string, string>) {
8081
if (el.nodeType === 1) {
8182
const style = (el as HTMLElement).style
83+
let cssText = ''
8284
for (const key in vars) {
8385
style.setProperty(`--${key}`, vars[key])
86+
cssText += `--${key}: ${vars[key]};`
8487
}
88+
;(style as any)[CSS_VAR_TEXT] = cssText
8589
}
8690
}

0 commit comments

Comments
 (0)