From: edison Date: Wed, 24 Sep 2025 09:08:25 +0000 (+0800) Subject: fix(custom-element): use PatchFlags.BAIL for slot when props are present (#13907) X-Git-Tag: v3.5.22~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5358bca4a80cf52d19ed91967eeaa025a786083d;p=thirdparty%2Fvuejs%2Fcore.git fix(custom-element): use PatchFlags.BAIL for slot when props are present (#13907) close #13904 --- diff --git a/packages/runtime-core/src/helpers/renderSlot.ts b/packages/runtime-core/src/helpers/renderSlot.ts index 92f7dab36..2f1296bb1 100644 --- a/packages/runtime-core/src/helpers/renderSlot.ts +++ b/packages/runtime-core/src/helpers/renderSlot.ts @@ -37,6 +37,7 @@ export function renderSlot( isAsyncWrapper(currentRenderingInstance!.parent) && currentRenderingInstance!.parent.ce) ) { + const hasProps = Object.keys(props).length > 0 // in custom element mode, render as actual slot outlets // wrap it with a fragment because in shadowRoot: false mode the slot // element gets replaced by injected content @@ -47,7 +48,7 @@ export function renderSlot( Fragment, null, [createVNode('slot', props, fallback && fallback())], - PatchFlags.STABLE_FRAGMENT, + hasProps ? PatchFlags.BAIL : PatchFlags.STABLE_FRAGMENT, ) ) } diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index cb09cf4d9..52350dfd2 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -638,6 +638,33 @@ describe('defineCustomElement', () => { `
fallback
`, ) }) + + test('render slot props', async () => { + const foo = ref('foo') + const E = defineCustomElement({ + render() { + return [ + h( + 'div', + null, + renderSlot(this.$slots, 'default', { class: foo.value }), + ), + ] + }, + }) + customElements.define('my-el-slot-props', E) + container.innerHTML = `hi` + const e = container.childNodes[0] as VueElement + expect(e.shadowRoot!.innerHTML).toBe( + `
`, + ) + + foo.value = 'bar' + await nextTick() + expect(e.shadowRoot!.innerHTML).toBe( + `
`, + ) + }) }) describe('provide/inject', () => {