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('

Comp2
')

`

``

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

`+

Comp2

`

``

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: `

``