Skip to content

Commit

Permalink
fix(custom-elements): work with async component + slots (#4657)
Browse files Browse the repository at this point in the history
close #4639
  • Loading branch information
edison1105 committed Apr 13, 2022
1 parent 1612971 commit f4d2c9f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
11 changes: 9 additions & 2 deletions packages/runtime-core/src/helpers/renderSlot.ts
Expand Up @@ -4,8 +4,9 @@ import {
ContextualRenderFn,
currentRenderingInstance
} from '../componentRenderContext'
import { Comment, isVNode } from '../vnode'
import {
Comment,
isVNode,
VNodeArrayChildren,
openBlock,
createBlock,
Expand All @@ -15,6 +16,7 @@ import {
import { PatchFlags, SlotFlags } from '@vue/shared'
import { warn } from '../warning'
import { createVNode } from '@vue/runtime-core'
import { isAsyncWrapper } from '../apiAsyncComponent'

/**
* Compiler runtime helper for rendering `<slot/>`
Expand All @@ -29,7 +31,12 @@ export function renderSlot(
fallback?: () => VNodeArrayChildren,
noSlotted?: boolean
): VNode {
if (currentRenderingInstance!.isCE) {
if (
currentRenderingInstance!.isCE ||
(currentRenderingInstance!.parent &&
isAsyncWrapper(currentRenderingInstance!.parent) &&
currentRenderingInstance!.parent.isCE)
) {
return createVNode(
'slot',
name === 'default' ? null : { name },
Expand Down
28 changes: 28 additions & 0 deletions packages/runtime-dom/__tests__/customElement.spec.ts
Expand Up @@ -457,5 +457,33 @@ describe('defineCustomElement', () => {
const e = container.childNodes[0] as VueElement
expect(e.shadowRoot!.innerHTML).toBe(`<div>20,number</div>`)
})

test('with slots', async () => {
const E = defineCustomElement(
defineAsyncComponent(() => {
return Promise.resolve({
render(this: any) {
return [
h('div', null, [
renderSlot(this.$slots, 'default', undefined, () => [
h('div', 'fallback')
])
]),
h('div', null, renderSlot(this.$slots, 'named'))
]
}
})
})
)
customElements.define('my-el-async-slots', E)
container.innerHTML = `<my-el-async-slots><span>hi</span></my-el-async-slots>`

await new Promise(r => setTimeout(r))

const e = container.childNodes[0] as VueElement
expect(e.shadowRoot!.innerHTML).toBe(
`<div><slot><div>fallback</div></slot></div><div><slot name="named"></slot></div>`
)
})
})
})

0 comments on commit f4d2c9f

Please sign in to comment.