From a359aff61a705546a3cf3b066c5b5aca128c31b2 Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <260480378@qq.com> Date: Sat, 5 Jul 2025 12:02:34 +0800 Subject: [PATCH 1/3] feat(runtime-vapor): support functional slot in vdom component --- .../runtime-core/src/helpers/renderSlot.ts | 2 +- .../__tests__/vdomInterop.spec.ts | 33 +++++++++++++++++-- packages/runtime-vapor/src/vdomInterop.ts | 16 ++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) 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..afa090d0df0 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 { defineComponent, h, renderSlot } from '@vue/runtime-dom' import { makeInteropRender } from './_utils' import { createComponent, defineVaporComponent } from '../src' @@ -9,7 +9,36 @@ describe('vdomInterop', () => { describe.todo('emit', () => {}) - describe.todo('slots', () => {}) + describe('slots', () => { + test('functional slot', () => { + 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') + }) + }) describe.todo('provide', () => {}) 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 }, } From 4d05dfd6f8f0180c2f5d390e15d2fb102fb6cf47 Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <260480378@qq.com> Date: Sat, 5 Jul 2025 12:25:03 +0800 Subject: [PATCH 2/3] chore: update tests --- .../__tests__/vdomInterop.spec.ts | 34 +++++++++++++++++-- packages/runtime-vapor/src/componentProps.ts | 2 +- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index afa090d0df0..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, renderSlot } from '@vue/runtime-dom' +import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom' import { makeInteropRender } from './_utils' import { createComponent, defineVaporComponent } from '../src' @@ -10,7 +10,7 @@ describe('vdomInterop', () => { describe.todo('emit', () => {}) describe('slots', () => { - test('functional slot', () => { + test('basic', () => { const VDomChild = defineComponent({ setup(_, { slots }) { return () => renderSlot(slots, 'default') @@ -38,6 +38,36 @@ describe('vdomInterop', () => { 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) From 0c927dfad6baf72826567521f509355884ec8948 Mon Sep 17 00:00:00 2001 From: zhiyuanzmj <260480378@qq.com> Date: Tue, 8 Jul 2025 14:45:37 +0800 Subject: [PATCH 3/3] chore: remove console.log --- packages/runtime-vapor/__tests__/vdomInterop.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts index a4b62c04d91..582e67dd876 100644 --- a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts +++ b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts @@ -42,7 +42,6 @@ describe('vdomInterop', () => { test('functional slot', () => { const VDomChild = defineComponent({ setup(_, { slots }) { - console.log(slots.default) return () => createVNode(slots.default!) }, })