Преглед изворни кода

chore: Merge branch 'main' into minor

Evan You пре 2 година
родитељ
комит
9f64d2b681

+ 13 - 0
CHANGELOG.md

@@ -1,3 +1,16 @@
+## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16)
+
+### Bug Fixes
+
+* **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)
+* **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)
+* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))
+* **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)
+* **types:** fix `shallowRef` type error ([#9839](https://github.com/vuejs/core/issues/9839)) ([9a57158](https://github.com/vuejs/core/commit/9a571582b53220270e498d8712ea59312c0bef3a))
+* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))
+
+
+
 # [3.4.0-beta.2](https://github.com/vuejs/core/compare/v3.4.0-beta.1...v3.4.0-beta.2) (2023-12-14)
 
 

+ 31 - 3
packages/dts-test/ref.test-d.ts

@@ -163,6 +163,17 @@ const state = reactive({
 
 expectType<string>(state.foo.label)
 
+describe('ref with generic', <T extends { name: string }>() => {
+  const r = {} as T
+  const s = ref(r)
+  expectType<string>(s.value.name)
+
+  const rr = {} as MaybeRef<T>
+  // should at least allow casting
+  const ss = ref(rr) as Ref<T>
+  expectType<string>(ss.value.name)
+})
+
 // shallowRef
 type Status = 'initial' | 'ready' | 'invalidating'
 const shallowStatus = shallowRef<Status>('initial')
@@ -201,11 +212,28 @@ if (refStatus.value === 'initial') {
   expectType<IsAny<typeof a>>(false)
 }
 
-describe('shallowRef with generic', <T>() => {
-  const r = ref({}) as MaybeRef<T>
-  expectType<ShallowRef<T> | Ref<T>>(shallowRef(r))
+describe('shallowRef with generic', <T extends { name: string }>() => {
+  const r = {} as T
+  const s = shallowRef(r)
+  expectType<string>(s.value.name)
+  expectType<ShallowRef<T>>(shallowRef(r))
+
+  const rr = {} as MaybeRef<T>
+  // should at least allow casting
+  const ss = shallowRef(rr) as Ref<T> | ShallowRef<T>
+  expectType<string>(ss.value.name)
 })
 
+{
+  // should return ShallowRef<T> | Ref<T>, not ShallowRef<T | Ref<T>>
+  expectType<ShallowRef<{ name: string }> | Ref<{ name: string }>>(
+    shallowRef({} as MaybeRef<{ name: string }>)
+  )
+  expectType<ShallowRef<number> | Ref<string[]> | ShallowRef<string>>(
+    shallowRef('' as Ref<string[]> | string | number)
+  )
+}
+
 // proxyRefs: should return `reactive` directly
 const r1 = reactive({
   k: 'v'

+ 7 - 3
packages/reactivity/src/ref.ts

@@ -127,9 +127,13 @@ export type ShallowRef<T = any> = Ref<T> & { [ShallowRefMarker]?: true }
  * @param value - The "inner value" for the shallow ref.
  * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowref}
  */
-export function shallowRef<T>(value: MaybeRef<T>): Ref<T> | ShallowRef<T>
-export function shallowRef<T extends Ref>(value: T): T
-export function shallowRef<T>(value: T): ShallowRef<T>
+export function shallowRef<T>(
+  value: T
+): Ref extends T
+  ? T extends Ref
+    ? IfAny<T, ShallowRef<T>, T>
+    : ShallowRef<T>
+  : ShallowRef<T>
 export function shallowRef<T = any>(): ShallowRef<T | undefined>
 export function shallowRef(value?: unknown) {
   return createRef(value, true)

+ 35 - 0
packages/runtime-core/__tests__/hydration.spec.ts

@@ -1255,6 +1255,41 @@ describe('SSR hydration', () => {
     expect(`mismatch`).not.toHaveBeenWarned()
   })
 
+  test('transition appear w/ event listener', async () => {
+    const container = document.createElement('div')
+    container.innerHTML = `<template><button>0</button></template>`
+    createSSRApp({
+      data() {
+        return {
+          count: 0
+        }
+      },
+      template: `
+        <Transition appear>
+          <button @click="count++">{{count}}</button>
+        </Transition>
+      `
+    }).mount(container)
+
+    expect(container.firstChild).toMatchInlineSnapshot(`
+      <button
+        class="v-enter-from v-enter-active"
+      >
+        0
+      </button>
+    `)
+
+    triggerEvent('click', container.querySelector('button')!)
+    await nextTick()
+    expect(container.firstChild).toMatchInlineSnapshot(`
+      <button
+        class="v-enter-from v-enter-active"
+      >
+        1
+      </button>
+    `)
+  })
+
   describe('mismatch handling', () => {
     test('text node', () => {
       const { container } = mountWithHydration(`foo`, () => 'bar')

+ 31 - 0
packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts

@@ -293,4 +293,35 @@ describe('useCssVars', () => {
     await nextTick()
     expect(target.children.length).toBe(0)
   })
+
+  test('with string style', async () => {
+    document.body.innerHTML = ''
+    const state = reactive({ color: 'red' })
+    const root = document.createElement('div')
+    const disabled = ref(false)
+
+    const App = {
+      setup() {
+        useCssVars(() => state)
+        return () => [
+          h(
+            'div',
+            { style: disabled.value ? 'pointer-events: none' : undefined },
+            'foo'
+          )
+        ]
+      }
+    }
+    render(h(App), root)
+    await nextTick()
+    for (const c of [].slice.call(root.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
+    }
+    disabled.value = true
+    await nextTick()
+
+    for (const c of [].slice.call(root.children as any)) {
+      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
+    }
+  })
 })

+ 4 - 0
packages/runtime-dom/src/helpers/useCssVars.ts

@@ -10,6 +10,7 @@ import {
 } from '@vue/runtime-core'
 import { ShapeFlags } from '@vue/shared'
 
+export const CSS_VAR_TEXT = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '')
 /**
  * Runtime helper for SFC's CSS variable injection feature.
  * @private
@@ -79,8 +80,11 @@ function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
 function setVarsOnNode(el: Node, vars: Record<string, string>) {
   if (el.nodeType === 1) {
     const style = (el as HTMLElement).style
+    let cssText = ''
     for (const key in vars) {
       style.setProperty(`--${key}`, vars[key])
+      cssText += `--${key}: ${vars[key]};`
     }
+    ;(style as any)[CSS_VAR_TEXT] = cssText
   }
 }

+ 6 - 0
packages/runtime-dom/src/modules/style.ts

@@ -1,6 +1,7 @@
 import { isString, hyphenate, capitalize, isArray } from '@vue/shared'
 import { camelize, warn } from '@vue/runtime-core'
 import { vShowOldKey } from '../directives/vShow'
+import { CSS_VAR_TEXT } from '../helpers/useCssVars'
 
 type Style = string | Record<string, string | string[]> | null
 
@@ -22,6 +23,11 @@ export function patchStyle(el: Element, prev: Style, next: Style) {
     const currentDisplay = style.display
     if (isCssString) {
       if (prev !== next) {
+        // #9821
+        const cssVarText = (style as any)[CSS_VAR_TEXT]
+        if (cssVarText) {
+          ;(next as string) += ';' + cssVarText
+        }
         style.cssText = next as string
       }
     } else if (prev) {

+ 25 - 0
pnpm-lock.yaml

@@ -296,6 +296,31 @@ importers:
         specifier: workspace:*
         version: link:../shared
 
+  packages/reactivity-transform:
+    dependencies:
+      '@babel/parser':
+        specifier: ^7.23.5
+        version: 7.23.5
+      '@vue/compiler-core':
+        specifier: workspace:*
+        version: link:../compiler-core
+      '@vue/shared':
+        specifier: workspace:*
+        version: link:../shared
+      estree-walker:
+        specifier: ^2.0.2
+        version: 2.0.2
+      magic-string:
+        specifier: ^0.30.5
+        version: 0.30.5
+    devDependencies:
+      '@babel/core':
+        specifier: ^7.23.5
+        version: 7.23.5
+      '@babel/types':
+        specifier: ^7.23.5
+        version: 7.23.5
+
   packages/runtime-core:
     dependencies:
       '@vue/reactivity':