From 2b0c959542417d0ccde654c29392d6540a325333 Mon Sep 17 00:00:00 2001
From: daiwei <daiwei521@126.com>
Date: Fri, 27 Sep 2024 08:54:33 +0800
Subject: [PATCH 1/3] fix(transition/ssr): make transition appear work with
 Suspense

---
 packages/runtime-core/src/hydration.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 82972e17174..52abc18bf2f 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -31,7 +31,7 @@ import {
   normalizeStyle,
   stringifyStyle,
 } from '@vue/shared'
-import { type RendererInternals, needTransition } from './renderer'
+import type { RendererInternals } from './renderer'
 import { setRef } from './rendererTemplateRef'
 import {
   type SuspenseBoundary,
@@ -385,7 +385,8 @@ export function createHydrationFunctions(
       let needCallTransitionHooks = false
       if (isTemplateNode(el)) {
         needCallTransitionHooks =
-          needTransition(parentSuspense, transition) &&
+          transition &&
+          !transition.persisted &&
           parentComponent &&
           parentComponent.vnode.props &&
           parentComponent.vnode.props.appear

From f9f2287bf6c036894a71d6f29ffd8bda166e070f Mon Sep 17 00:00:00 2001
From: daiwei <daiwei521@126.com>
Date: Fri, 27 Sep 2024 09:08:49 +0800
Subject: [PATCH 2/3] test: add test case

---
 .../runtime-core/__tests__/hydration.spec.ts  | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts
index c98f1f473bd..a1fb8cde33f 100644
--- a/packages/runtime-core/__tests__/hydration.spec.ts
+++ b/packages/runtime-core/__tests__/hydration.spec.ts
@@ -1613,6 +1613,36 @@ describe('SSR hydration', () => {
     `)
   })
 
+  test('Suspense + transition appear', async () => {
+    const { vnode, container } = mountWithHydration(
+      `<template><div>foo</div></template>`,
+      () =>
+        h(Suspense, {}, () =>
+          h(
+            Transition,
+            { appear: true },
+            {
+              default: () => h('div', 'foo'),
+            },
+          ),
+        ),
+    )
+
+    expect(vnode.el).toBe(container.firstChild)
+    // wait for hydration to finish
+    await new Promise(r => setTimeout(r))
+
+    expect(container.firstChild).toMatchInlineSnapshot(`
+      <div
+        class="v-enter-from v-enter-active"
+      >
+        foo
+      </div>
+    `)
+    await nextTick()
+    expect(vnode.el).toBe(container.firstChild)
+  })
+
   // #10607
   test('update component stable slot (prod + optimized mode)', async () => {
     __DEV__ = false

From d0e0b8810ab92c4dd4096ad69ada7f65ea37673a Mon Sep 17 00:00:00 2001
From: daiwei <daiwei521@126.com>
Date: Fri, 27 Sep 2024 15:23:00 +0800
Subject: [PATCH 3/3] chore: tweaks

---
 packages/runtime-core/src/hydration.ts | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts
index 52abc18bf2f..c49db529c38 100644
--- a/packages/runtime-core/src/hydration.ts
+++ b/packages/runtime-core/src/hydration.ts
@@ -31,7 +31,7 @@ import {
   normalizeStyle,
   stringifyStyle,
 } from '@vue/shared'
-import type { RendererInternals } from './renderer'
+import { type RendererInternals, needTransition } from './renderer'
 import { setRef } from './rendererTemplateRef'
 import {
   type SuspenseBoundary,
@@ -385,8 +385,10 @@ export function createHydrationFunctions(
       let needCallTransitionHooks = false
       if (isTemplateNode(el)) {
         needCallTransitionHooks =
-          transition &&
-          !transition.persisted &&
+          needTransition(
+            null, // no need check parentSuspense in hydration
+            transition,
+          ) &&
           parentComponent &&
           parentComponent.vnode.props &&
           parentComponent.vnode.props.appear