fix(teleport/ssr): fix Teleport hydration regression due to targetSta… · vuejs/core@7b18cdb (original) (raw)
`@@ -265,7 +265,7 @@ describe('SSR hydration', () => {
`
265
265
`const fn = vi.fn()
`
266
266
`const teleportContainer = document.createElement('div')
`
267
267
`teleportContainer.id = 'teleport'
`
268
``
`` -
teleportContainer.innerHTML = <span>foo</span><span class="foo"></span><!--teleport anchor-->
``
``
268
`` +
teleportContainer.innerHTML = <!--teleport start anchor--><span>foo</span><span class="foo"></span><!--teleport anchor-->
``
269
269
`document.body.appendChild(teleportContainer)
`
270
270
``
271
271
`const { vnode, container } = mountWithHydration(
`
`@@ -281,13 +281,14 @@ describe('SSR hydration', () => {
`
281
281
`expect(vnode.anchor).toBe(container.lastChild)
`
282
282
``
283
283
`expect(vnode.target).toBe(teleportContainer)
`
``
284
`+
expect(vnode.targetStart).toBe(teleportContainer.childNodes[0])
`
284
285
`expect((vnode.children as VNode[])[0].el).toBe(
`
285
``
`-
teleportContainer.childNodes[0],
`
``
286
`+
teleportContainer.childNodes[1],
`
286
287
`)
`
287
288
`expect((vnode.children as VNode[])[1].el).toBe(
`
288
``
`-
teleportContainer.childNodes[1],
`
``
289
`+
teleportContainer.childNodes[2],
`
289
290
`)
`
290
``
`-
expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[2])
`
``
291
`+
expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[3])
`
291
292
``
292
293
`// event handler
`
293
294
`triggerEvent('click', teleportContainer.querySelector('.foo')!)
`
`@@ -296,7 +297,7 @@ describe('SSR hydration', () => {
`
296
297
`msg.value = 'bar'
`
297
298
`await nextTick()
`
298
299
`expect(teleportContainer.innerHTML).toBe(
`
299
``
`` -
<span>bar</span><span class="bar"></span><!--teleport anchor-->,
``
``
300
`` +
<!--teleport start anchor--><span>bar</span><span class="bar"></span><!--teleport anchor-->,
``
300
301
`)
`
301
302
`})
`
302
303
``
`@@ -326,7 +327,7 @@ describe('SSR hydration', () => {
`
326
327
``
327
328
`const teleportHtml = ctx.teleports!['#teleport2']
`
328
329
`expect(teleportHtml).toMatchInlineSnapshot(
`
329
``
`` -
"<span>foo</span><span class="foo"></span><!--teleport anchor--><span>foo2</span><span class="foo2"></span><!--teleport anchor-->",
``
``
330
`` +
"<!--teleport start anchor--><span>foo</span><span class="foo"></span><!--teleport anchor--><!--teleport start anchor--><span>foo2</span><span class="foo2"></span><!--teleport anchor-->",
``
330
331
`)
`
331
332
``
332
333
`teleportContainer.innerHTML = teleportHtml
`
`@@ -342,16 +343,18 @@ describe('SSR hydration', () => {
`
342
343
`expect(teleportVnode2.anchor).toBe(container.childNodes[4])
`
343
344
``
344
345
`expect(teleportVnode1.target).toBe(teleportContainer)
`
``
346
`+
expect(teleportVnode1.targetStart).toBe(teleportContainer.childNodes[0])
`
345
347
`expect((teleportVnode1 as any).children[0].el).toBe(
`
346
``
`-
teleportContainer.childNodes[0],
`
``
348
`+
teleportContainer.childNodes[1],
`
347
349
`)
`
348
``
`-
expect(teleportVnode1.targetAnchor).toBe(teleportContainer.childNodes[2])
`
``
350
`+
expect(teleportVnode1.targetAnchor).toBe(teleportContainer.childNodes[3])
`
349
351
``
350
352
`expect(teleportVnode2.target).toBe(teleportContainer)
`
``
353
`+
expect(teleportVnode2.targetStart).toBe(teleportContainer.childNodes[4])
`
351
354
`expect((teleportVnode2 as any).children[0].el).toBe(
`
352
``
`-
teleportContainer.childNodes[3],
`
``
355
`+
teleportContainer.childNodes[5],
`
353
356
`)
`
354
``
`-
expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[5])
`
``
357
`+
expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[7])
`
355
358
``
356
359
`// // event handler
`
357
360
`triggerEvent('click', teleportContainer.querySelector('.foo')!)
`
`@@ -363,7 +366,7 @@ describe('SSR hydration', () => {
`
363
366
`msg.value = 'bar'
`
364
367
`await nextTick()
`
365
368
`expect(teleportContainer.innerHTML).toMatchInlineSnapshot(
`
366
``
`` -
"<span>bar</span><span class="bar"></span><!--teleport anchor--><span>bar2</span><span class="bar2"></span><!--teleport anchor-->",
``
``
369
`` +
"<!--teleport start anchor--><span>bar</span><span class="bar"></span><!--teleport anchor--><!--teleport start anchor--><span>bar2</span><span class="bar2"></span><!--teleport anchor-->",
``
367
370
`)
`
368
371
`})
`
369
372
``
`@@ -390,7 +393,9 @@ describe('SSR hydration', () => {
`
390
393
`)
`
391
394
``
392
395
`const teleportHtml = ctx.teleports!['#teleport3']
`
393
``
`` -
expect(teleportHtml).toMatchInlineSnapshot("<!--teleport anchor-->")
``
``
396
`+
expect(teleportHtml).toMatchInlineSnapshot(
`
``
397
`` +
"<!--teleport start anchor--><!--teleport anchor-->",
``
``
398
`+
)
`
394
399
``
395
400
`teleportContainer.innerHTML = teleportHtml
`
396
401
`document.body.appendChild(teleportContainer)
`
`@@ -413,7 +418,8 @@ describe('SSR hydration', () => {
`
413
418
`expect(children[2].el).toBe(container.childNodes[6])
`
414
419
``
415
420
`expect(teleportVnode.target).toBe(teleportContainer)
`
416
``
`-
expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[0])
`
``
421
`+
expect(teleportVnode.targetStart).toBe(teleportContainer.childNodes[0])
`
``
422
`+
expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[1])
`
417
423
``
418
424
`// // event handler
`
419
425
`triggerEvent('click', container.querySelector('.foo')!)
`
`@@ -454,7 +460,7 @@ describe('SSR hydration', () => {
`
454
460
`test('Teleport (as component root)', () => {
`
455
461
`const teleportContainer = document.createElement('div')
`
456
462
`teleportContainer.id = 'teleport4'
`
457
``
`` -
teleportContainer.innerHTML = hello<!--teleport anchor-->
``
``
463
`` +
teleportContainer.innerHTML = <!--teleport start anchor-->hello<!--teleport anchor-->
``
458
464
`document.body.appendChild(teleportContainer)
`
459
465
``
460
466
`const wrapper = {
`
`@@ -483,7 +489,7 @@ describe('SSR hydration', () => {
`
483
489
`test('Teleport (nested)', () => {
`
484
490
`const teleportContainer = document.createElement('div')
`
485
491
`teleportContainer.id = 'teleport5'
`
486
``
`` -
teleportContainer.innerHTML = <div><!--teleport start--><!--teleport end--></div><!--teleport anchor--><div>child</div><!--teleport anchor-->
``
``
492
`` +
teleportContainer.innerHTML = <!--teleport start anchor--><div><!--teleport start--><!--teleport end--></div><!--teleport anchor--><!--teleport start anchor--><div>child</div><!--teleport anchor-->
``
487
493
`document.body.appendChild(teleportContainer)
`
488
494
``
489
495
`const { vnode, container } = mountWithHydration(
`
`@@ -498,7 +504,7 @@ describe('SSR hydration', () => {
`
498
504
`expect(vnode.anchor).toBe(container.lastChild)
`
499
505
``
500
506
`const childDivVNode = (vnode as any).children[0]
`
501
``
`-
const div = teleportContainer.firstChild
`
``
507
`+
const div = teleportContainer.childNodes[1]
`
502
508
`expect(childDivVNode.el).toBe(div)
`
503
509
`expect(vnode.targetAnchor).toBe(div?.nextSibling)
`
504
510
``
`@@ -548,6 +554,66 @@ describe('SSR hydration', () => {
`
548
554
`teleportContainer.id = 'target'
`
549
555
`document.body.appendChild(teleportContainer)
`
550
556
``
``
557
`+
// server render
`
``
558
`+
const ctx: SSRContext = {}
`
``
559
`+
container.innerHTML = await renderToString(h(App), ctx)
`
``
560
`+
expect(container.innerHTML).toBe(
`
``
561
`+
'
',`
``
562
`+
)
`
``
563
`+
teleportContainer.innerHTML = ctx.teleports!['#target']
`
``
564
+
``
565
`+
// hydrate
`
``
566
`+
createSSRApp(App).mount(container)
`
``
567
`+
expect(container.innerHTML).toBe(
`
``
568
`+
'
',`
``
569
`+
)
`
``
570
`+
expect(teleportContainer.innerHTML).toBe(
`
``
571
`+
'Teleported Comp1',
`
``
572
`+
)
`
``
573
`` +
expect(Hydration children mismatch).not.toHaveBeenWarned()
``
``
574
+
``
575
`+
toggle.value = false
`
``
576
`+
await nextTick()
`
``
577
`+
expect(container.innerHTML).toBe('
`
``
578
`+
expect(teleportContainer.innerHTML).toBe('')
`
``
579
`+
})
`
``
580
+
``
581
`+
test('Teleport unmount (mismatch + full integration)', async () => {
`
``
582
`+
const Comp1 = {
`
``
583
`` +
template: `
``
``
584
`+
`
``
585
`+
Teleported Comp1
`
``
586
`+
`
``
587
`` +
`,
``
``
588
`+
}
`
``
589
`+
const Comp2 = {
`
``
590
`` +
template: `
``
``
591
`+
`
``
592
`` +
`,
``
``
593
`+
}
`
``
594
+
``
595
`+
const toggle = ref(true)
`
``
596
`+
const App = {
`
``
597
`` +
template: `
``
``
598
`+
`
``
599
`+
`
``
600
`+
`
``
601
`+
`
``
602
`` +
`,
``
``
603
`+
components: {
`
``
604
`+
Comp1,
`
``
605
`+
Comp2,
`
``
606
`+
},
`
``
607
`+
setup() {
`
``
608
`+
return { toggle }
`
``
609
`+
},
`
``
610
`+
}
`
``
611
+
``
612
`+
const container = document.createElement('div')
`
``
613
`+
const teleportContainer = document.createElement('div')
`
``
614
`+
teleportContainer.id = 'target'
`
``
615
`+
document.body.appendChild(teleportContainer)
`
``
616
+
551
617
`// server render
`
552
618
`container.innerHTML = await renderToString(h(App))
`
553
619
`expect(container.innerHTML).toBe(
`
`@@ -569,7 +635,7 @@ describe('SSR hydration', () => {
`
569
635
`expect(teleportContainer.innerHTML).toBe('')
`
570
636
`})
`
571
637
``
572
``
`-
test('Teleport target change (full integration)', async () => {
`
``
638
`+
test('Teleport target change (mismatch + full integration)', async () => {
`
573
639
`const target = ref('#target1')
`
574
640
`const Comp = {
`
575
641
`` template: `
``