diff --git a/packages/runtime-core/src/helpers/renderSlot.ts b/packages/runtime-core/src/helpers/renderSlot.ts index 152c5a4b81c..d5feae617a6 100644 --- a/packages/runtime-core/src/helpers/renderSlot.ts +++ b/packages/runtime-core/src/helpers/renderSlot.ts @@ -35,7 +35,7 @@ export function renderSlot( let slot = slots[name] // vapor slots rendered in vdom - if (slot && slots._vapor) { + if (slot && (slot as any).__vapor) { const ret = (openBlock(), createBlock(VaporSlot, props)) ret.vs = { slot, fallback } return ret diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index 08326d4d5d9..a4b62c04d91 100644 --- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts +++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts @@ -1,4 +1,4 @@ -import { defineComponent, h } from '@vue/runtime-dom' +import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom' import { makeInteropRender } from './_utils' import { createComponent, defineVaporComponent } from '../src' @@ -9,7 +9,66 @@ describe('vdomInterop', () => { describe.todo('emit', () => {}) - describe.todo('slots', () => {}) + describe('slots', () => { + test('basic', () => { + const VDomChild = defineComponent({ + setup(_, { slots }) { + return () => renderSlot(slots, 'default') + }, + }) + + const VaporChild = defineVaporComponent({ + setup() { + return createComponent( + VDomChild as any, + null, + { + default: () => document.createTextNode('default slot'), + }, + true, + ) + }, + }) + + const { html } = define({ + setup() { + return () => h(VaporChild as any) + }, + }).render() + + expect(html()).toBe('default slot') + }) + + test('functional slot', () => { + const VDomChild = defineComponent({ + setup(_, { slots }) { + console.log(slots.default) + return () => createVNode(slots.default!) + }, + }) + + const VaporChild = defineVaporComponent({ + setup() { + return createComponent( + VDomChild as any, + null, + { + default: () => document.createTextNode('default slot'), + }, + true, + ) + }, + }) + + const { html } = define({ + setup() { + return () => h(VaporChild as any) + }, + }).render() + + expect(html()).toBe('default slot') + }) + }) describe.todo('provide', () => {}) diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 9cf65c57143..b43801272e2 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -186,7 +186,7 @@ export function getAttrFromRawProps(rawProps: RawProps, key: string): unknown { source = dynamicSources[i] isDynamic = isFunction(source) source = isDynamic ? (source as Function)() : source - if (hasOwn(source, key)) { + if (source && hasOwn(source, key)) { const value = isDynamic ? source[key] : source[key]() if (merged) { merged.push(value) diff --git a/packages/runtime-vapor/src/vdomInterop.ts b/packages/runtime-vapor/src/vdomInterop.ts index e277024d73b..a085d310060 100644 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@ -134,11 +134,17 @@ const vaporSlotPropsProxyHandler: ProxyHandler< const vaporSlotsProxyHandler: ProxyHandler = { get(target, key) { - if (key === '_vapor') { - return target - } else { - return target[key] - } + const fn = target[key] + return isFunction(fn) + ? new Proxy(fn, { + get(fnTarget, fnKey) { + if (fnKey === '__vapor') { + return true + } + return fnTarget[fnKey] + }, + }) + : fn }, }