]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-vapor): render slot fallback if no content is provided edison/fix/emptySlot 13561/head
authordaiwei <daiwei521@126.com>
Fri, 4 Jul 2025 01:44:04 +0000 (09:44 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 4 Jul 2025 01:44:04 +0000 (09:44 +0800)
packages/runtime-vapor/__tests__/_utils.ts
packages/runtime-vapor/__tests__/vdomInterop.spec.ts [new file with mode: 0644]
packages/runtime-vapor/src/vdomInterop.ts

index 0ed645544784c82eb4de0dda1fbc17a8ed4eb512..f794d409f23a0d213ebe215c3b9c7f442a73a242 100644 (file)
@@ -1,7 +1,8 @@
-import { createVaporApp } from '../src'
+import { createVaporApp, vaporInteropPlugin } from '../src'
 import type { App } from '@vue/runtime-dom'
 import type { VaporComponent, VaporComponentInstance } from '../src/component'
 import type { RawProps } from '../src/componentProps'
+import { type Component, createApp } from 'vue'
 
 export interface RenderContext {
   component: VaporComponent
@@ -82,3 +83,54 @@ export function makeRender<C = VaporComponent>(
 
   return define
 }
+
+export interface InteropRenderContext {
+  mount: (container?: string | ParentNode) => InteropRenderContext
+  render: (
+    props?: RawProps,
+    container?: string | ParentNode,
+  ) => InteropRenderContext
+  html: () => string
+}
+
+export function makeInteropRender(): (comp: Component) => InteropRenderContext {
+  let host: HTMLElement
+  beforeEach(() => {
+    host = document.createElement('div')
+  })
+  afterEach(() => {
+    host.remove()
+  })
+
+  function define(comp: Component) {
+    let app: App
+    function render(
+      props: RawProps | undefined = undefined,
+      container: string | ParentNode = host,
+    ) {
+      app?.unmount()
+      app = createApp(comp, props)
+      app.use(vaporInteropPlugin)
+      return mount(container)
+    }
+
+    function mount(container: string | ParentNode = host) {
+      app.mount(container)
+      return res()
+    }
+
+    function html() {
+      return host.innerHTML
+    }
+
+    const res = () => ({
+      mount,
+      render,
+      html,
+    })
+
+    return res()
+  }
+
+  return define
+}
diff --git a/packages/runtime-vapor/__tests__/vdomInterop.spec.ts b/packages/runtime-vapor/__tests__/vdomInterop.spec.ts
new file mode 100644 (file)
index 0000000..44bbf00
--- /dev/null
@@ -0,0 +1,29 @@
+import { h } from 'vue'
+import { createSlot, defineVaporComponent, template } from '../src'
+import { makeInteropRender } from './_utils'
+
+const define = makeInteropRender()
+
+describe('vdomInterop', () => {
+  describe('slots', () => {
+    test('should render slot fallback if no slot content is provided', () => {
+      const VaporChild = defineVaporComponent({
+        setup() {
+          const n0 = createSlot('default', null, () => {
+            const n2 = template('<div>hi</div>')()
+            return n2
+          })
+          return n0
+        },
+      })
+
+      const { html } = define({
+        setup() {
+          return () => h(VaporChild as any)
+        },
+      }).render()
+
+      expect(html()).toBe('<div>hi</div>')
+    })
+  })
+})
index e277024d73b6b22f169574ae2f049fa8013d42d5..bcae37b6c8ad16643f03ca5ee865f2b307b3b6a7 100644 (file)
@@ -236,24 +236,26 @@ function renderVDOMSlot(
   frag.insert = (parentNode, anchor) => {
     if (!isMounted) {
       renderEffect(() => {
-        const vnode = renderSlot(
-          slotsRef.value,
-          isFunction(name) ? name() : name,
-          props,
-        )
-        if ((vnode.children as any[]).length) {
-          if (fallbackNodes) {
-            remove(fallbackNodes, parentNode)
-            fallbackNodes = undefined
-          }
-          internals.p(
-            oldVNode,
-            vnode,
-            parentNode,
-            anchor,
-            parentComponent as any,
+        if (slotsRef.value) {
+          const vnode = renderSlot(
+            slotsRef.value,
+            isFunction(name) ? name() : name,
+            props,
           )
-          oldVNode = vnode
+          if ((vnode.children as any[]).length) {
+            if (fallbackNodes) {
+              remove(fallbackNodes, parentNode)
+              fallbackNodes = undefined
+            }
+            internals.p(
+              oldVNode,
+              vnode,
+              parentNode,
+              anchor,
+              parentComponent as any,
+            )
+            oldVNode = vnode
+          }
         } else {
           if (fallback && !fallbackNodes) {
             // mount fallback