Skip to content

Commit 0227b4a

Browse files
committed
fix(suspense): fix suspense nested child updates in template mode
fix #2214
1 parent 128ec46 commit 0227b4a

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

packages/runtime-core/__tests__/components/Suspense.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
onErrorCaptured,
1515
shallowRef
1616
} from '@vue/runtime-test'
17+
import { createApp } from 'vue'
1718

1819
describe('Suspense', () => {
1920
const deps: Promise<any>[] = []
@@ -1068,4 +1069,28 @@ describe('Suspense', () => {
10681069
expect(serializeInner(root)).toBe(`<div>two</div>`)
10691070
expect(calls).toEqual([`one mounted`, `one unmounted`, `two mounted`])
10701071
})
1072+
1073+
// #2214
1074+
// Since suspense renders its own root like a component, it should not patch
1075+
// its content in optimized mode.
1076+
test('should not miss nested element updates when used in templates', async () => {
1077+
const n = ref(1)
1078+
const Comp = {
1079+
setup() {
1080+
return { n }
1081+
},
1082+
template: `
1083+
<Suspense>
1084+
<div><span>{{ n }}</span></div>
1085+
</Suspense>
1086+
`
1087+
}
1088+
const root = document.createElement('div')
1089+
createApp(Comp).mount(root)
1090+
expect(root.innerHTML).toBe(`<div><span>1</span></div>`)
1091+
1092+
n.value++
1093+
await nextTick()
1094+
expect(root.innerHTML).toBe(`<div><span>2</span></div>`)
1095+
})
10711096
})

packages/runtime-core/src/components/Suspense.ts

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ export const SuspenseImpl = {
6969
anchor,
7070
parentComponent,
7171
isSVG,
72-
optimized,
7372
rendererInternals
7473
)
7574
}
@@ -121,8 +120,7 @@ function mountSuspense(
121120
null,
122121
parentComponent,
123122
suspense,
124-
isSVG,
125-
optimized
123+
isSVG
126124
)
127125
// now check if we have encountered any async deps
128126
if (suspense.deps > 0) {
@@ -135,8 +133,7 @@ function mountSuspense(
135133
anchor,
136134
parentComponent,
137135
null, // fallback tree will not have suspense context
138-
isSVG,
139-
optimized
136+
isSVG
140137
)
141138
setActiveBranch(suspense, vnode.ssFallback!)
142139
} else {
@@ -152,7 +149,6 @@ function patchSuspense(
152149
anchor: RendererNode | null,
153150
parentComponent: ComponentInternalInstance | null,
154151
isSVG: boolean,
155-
optimized: boolean,
156152
{ p: patch, um: unmount, o: { createElement } }: RendererInternals
157153
) {
158154
const suspense = (n2.suspense = n1.suspense)!
@@ -173,8 +169,7 @@ function patchSuspense(
173169
null,
174170
parentComponent,
175171
suspense,
176-
isSVG,
177-
optimized
172+
isSVG
178173
)
179174
if (suspense.deps <= 0) {
180175
suspense.resolve()
@@ -186,8 +181,7 @@ function patchSuspense(
186181
anchor,
187182
parentComponent,
188183
null, // fallback tree will not have suspense context
189-
isSVG,
190-
optimized
184+
isSVG
191185
)
192186
setActiveBranch(suspense, newFallback)
193187
}
@@ -220,8 +214,7 @@ function patchSuspense(
220214
null,
221215
parentComponent,
222216
suspense,
223-
isSVG,
224-
optimized
217+
isSVG
225218
)
226219
if (suspense.deps <= 0) {
227220
suspense.resolve()
@@ -233,8 +226,7 @@ function patchSuspense(
233226
anchor,
234227
parentComponent,
235228
null, // fallback tree will not have suspense context
236-
isSVG,
237-
optimized
229+
isSVG
238230
)
239231
setActiveBranch(suspense, newFallback)
240232
}
@@ -247,8 +239,7 @@ function patchSuspense(
247239
anchor,
248240
parentComponent,
249241
suspense,
250-
isSVG,
251-
optimized
242+
isSVG
252243
)
253244
// force resolve
254245
suspense.resolve(true)
@@ -261,8 +252,7 @@ function patchSuspense(
261252
null,
262253
parentComponent,
263254
suspense,
264-
isSVG,
265-
optimized
255+
isSVG
266256
)
267257
if (suspense.deps <= 0) {
268258
suspense.resolve()
@@ -279,8 +269,7 @@ function patchSuspense(
279269
anchor,
280270
parentComponent,
281271
suspense,
282-
isSVG,
283-
optimized
272+
isSVG
284273
)
285274
setActiveBranch(suspense, newBranch)
286275
} else {
@@ -300,8 +289,7 @@ function patchSuspense(
300289
null,
301290
parentComponent,
302291
suspense,
303-
isSVG,
304-
optimized
292+
isSVG
305293
)
306294
if (suspense.deps <= 0) {
307295
// incoming branch has no async deps, resolve now.
@@ -327,7 +315,6 @@ export interface SuspenseBoundary {
327315
parent: SuspenseBoundary | null
328316
parentComponent: ComponentInternalInstance | null
329317
isSVG: boolean
330-
optimized: boolean
331318
container: RendererElement
332319
hiddenContainer: RendererElement
333320
anchor: RendererNode | null
@@ -392,7 +379,6 @@ function createSuspenseBoundary(
392379
parent,
393380
parentComponent,
394381
isSVG,
395-
optimized,
396382
container,
397383
hiddenContainer,
398384
anchor,
@@ -499,8 +485,7 @@ function createSuspenseBoundary(
499485
activeBranch,
500486
parentComponent,
501487
container,
502-
isSVG,
503-
optimized
488+
isSVG
504489
} = suspense
505490

506491
// invoke @fallback event
@@ -522,8 +507,7 @@ function createSuspenseBoundary(
522507
anchor,
523508
parentComponent,
524509
null, // fallback tree will not have suspense context
525-
isSVG,
526-
optimized
510+
isSVG
527511
)
528512
setActiveBranch(suspense, fallbackVNode)
529513
}

0 commit comments

Comments
 (0)