diff --git a/packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts b/packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts
index 958c12748..1d8bb8420 100644
--- a/packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts
+++ b/packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts
@@ -861,6 +861,114 @@ describe('renderer: optimized mode', () => {
expect(inner(root)).toBe('
')
})
+ // #13305
+ test('patch Suspense nested in list nodes in optimized mode', async () => {
+ const deps: Promise[] = []
+
+ const Item = {
+ props: {
+ someId: { type: Number, required: true },
+ },
+ async setup(props: any) {
+ const p = new Promise(resolve => setTimeout(resolve, 1))
+ deps.push(p)
+
+ await p
+ return () => (
+ openBlock(),
+ createElementBlock('li', null, [
+ createElementVNode(
+ 'p',
+ null,
+ String(props.someId),
+ PatchFlags.TEXT,
+ ),
+ ])
+ )
+ },
+ }
+
+ const list = ref([1, 2, 3])
+ const App = {
+ setup() {
+ return () => (
+ openBlock(),
+ createElementBlock(
+ Fragment,
+ null,
+ [
+ createElementVNode(
+ 'p',
+ null,
+ JSON.stringify(list.value),
+ PatchFlags.TEXT,
+ ),
+ createElementVNode('ol', null, [
+ (openBlock(),
+ createBlock(SuspenseImpl, null, {
+ fallback: withCtx(() => [
+ createElementVNode('li', null, 'Loading…'),
+ ]),
+ default: withCtx(() => [
+ (openBlock(true),
+ createElementBlock(
+ Fragment,
+ null,
+ renderList(list.value, id => {
+ return (
+ openBlock(),
+ createBlock(
+ Item,
+ {
+ key: id,
+ 'some-id': id,
+ },
+ null,
+ PatchFlags.PROPS,
+ ['some-id'],
+ )
+ )
+ }),
+ PatchFlags.KEYED_FRAGMENT,
+ )),
+ ]),
+ _: 1 /* STABLE */,
+ })),
+ ]),
+ ],
+ PatchFlags.STABLE_FRAGMENT,
+ )
+ )
+ },
+ }
+
+ const app = createApp(App)
+ app.mount(root)
+ expect(inner(root)).toBe(`[1,2,3]
` + `- Loading…
`)
+
+ await Promise.all(deps)
+ await nextTick()
+ expect(inner(root)).toBe(
+ `[1,2,3]
` +
+ `` +
+ `1
` +
+ `2
` +
+ `3
` +
+ `
`,
+ )
+
+ list.value = [3, 1, 2]
+ await nextTick()
+ expect(inner(root)).toBe(
+ `[3,1,2]
` +
+ `` +
+ `3
` +
+ `1
` +
+ `2
` +
+ `
`,
+ )
+ })
+
// #4183
test('should not take unmount children fast path /w Suspense', async () => {
const show = ref(true)
diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts
index 334858b7b..7b39aa917 100644
--- a/packages/runtime-core/src/renderer.ts
+++ b/packages/runtime-core/src/renderer.ts
@@ -961,7 +961,8 @@ function baseCreateRenderer(
// which also requires the correct parent container
!isSameVNodeType(oldVNode, newVNode) ||
// - In the case of a component, it could contain anything.
- oldVNode.shapeFlag & (ShapeFlags.COMPONENT | ShapeFlags.TELEPORT))
+ oldVNode.shapeFlag &
+ (ShapeFlags.COMPONENT | ShapeFlags.TELEPORT | ShapeFlags.SUSPENSE))
? hostParentNode(oldVNode.el)!
: // In other cases, the parent container is not actually used so we
// just pass the block element here to avoid a DOM parentNode call.