From: daiwei Date: Wed, 16 Apr 2025 13:28:36 +0000 (+0800) Subject: test: add tests X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a5ea558a5b25ef0218c5e6b3ba352eb8bd12508;p=thirdparty%2Fvuejs%2Fcore.git test: add tests --- diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index df438d47ee..fa14f6d48f 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -5,6 +5,10 @@ import { Teleport, type VueElement, createApp, + createBlock, + createCommentVNode, + createElementBlock, + createElementVNode, defineAsyncComponent, defineComponent, defineCustomElement, @@ -12,12 +16,14 @@ import { inject, nextTick, onMounted, + openBlock, provide, ref, render, renderSlot, useHost, useShadowRoot, + withCtx, } from '../src' declare var __VUE_HMR_RUNTIME__: HMRRuntime @@ -1131,6 +1137,92 @@ describe('defineCustomElement', () => { expect(target.innerHTML).toBe(`default`) app.unmount() }) + + //#13206 + test('should update slotted children correctly w/ shadowRoot false', async () => { + const E = defineCustomElement( + defineComponent({ + props: { + isShown: { type: Boolean, required: true }, + }, + render() { + return this.isShown + ? h('div', { key: 0 }, [renderSlot(this.$slots, 'default')]) + : null + }, + }), + { shadowRoot: false }, + ) + customElements.define('ce-shadow-root-false', E) + + const Comp = defineComponent({ + props: { + isShown: { type: Boolean, required: true }, + }, + render() { + return h('ce-shadow-root-false', { 'is-shown': this.isShown }, [ + renderSlot(this.$slots, 'default'), + ]) + }, + }) + + const isShown = ref(false) + const count = ref(0) + + function click() { + isShown.value = !isShown.value + count.value++ + } + + const App = { + render() { + return ( + openBlock(), + createBlock( + Comp, + { isShown: isShown.value }, + { + default: withCtx(() => [ + createElementVNode('div', null, isShown.value, 1 /* TEXT */), + count.value > 1 + ? (openBlock(), createElementBlock('div', { key: 0 }, 'hi')) + : createCommentVNode('v-if', true), + ]), + _: 1 /* STABLE */, + }, + 8 /* PROPS */, + ['isShown'], + ) + ) + }, + } + const container = document.createElement('div') + document.body.appendChild(container) + + const app = createApp(App) + app.mount(container) + expect(container.innerHTML).toBe( + ``, + ) + + click() + await nextTick() + expect(container.innerHTML).toBe( + `
true
`, + ) + + click() + await nextTick() + expect(container.innerHTML).toBe( + ``, + ) + + click() + await nextTick() + expect(container.innerHTML).toBe( + `
true
hi
`, + ) + }) }) describe('helpers', () => { diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 5cab16ad67..ebd75b252a 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -665,9 +665,8 @@ export class VueElement */ _updateSlots(children: VNode[]): void { children.forEach(child => { - this._slots![child.slotName!] = collectElements( - child.children as VNodeArrayChildren, - ) + // slot children are always Fragments + this._slots![child.slotName!] = collectFragmentElements(child) }) } @@ -725,16 +724,24 @@ export function useShadowRoot(): ShadowRoot | null { return el && el.shadowRoot } +function collectFragmentElements(child: VNode): Node[] { + return [ + child.el as Node, + ...collectElements(child.children as VNodeArrayChildren), + child.anchor as Node, + ] +} + function collectElements(children: VNodeArrayChildren): Node[] { const nodes: Node[] = [] - for (const vnode of children) { - if (isArray(vnode)) { - nodes.push(...collectElements(vnode)) - } else if (isVNode(vnode)) { - if (vnode.type === Fragment) { - nodes.push(...collectElements(vnode.children as VNodeArrayChildren)) - } else if (vnode.el) { - nodes.push(vnode.el as Node) + for (const child of children) { + if (isArray(child)) { + nodes.push(...collectElements(child)) + } else if (isVNode(child)) { + if (child.type === Fragment) { + nodes.push(...collectFragmentElements(child)) + } else if (child.el) { + nodes.push(child.el as Node) } } }