]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-vapor): handle vapor attrs fallthrough to vdom component
authordaiwei <daiwei521@126.com>
Tue, 1 Jul 2025 14:38:02 +0000 (22:38 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 1 Jul 2025 14:38:02 +0000 (22:38 +0800)
packages/runtime-vapor/__tests__/componentAttrs.spec.ts
packages/runtime-vapor/__tests__/componentSlots.spec.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/componentProps.ts

index 109b1aa2fa4b96ffe959e606d78216631e535581..6fef2ba601e06fbf22128ca7c32e5cecf31400de 100644 (file)
@@ -445,4 +445,33 @@ describe('attribute fallthrough', () => {
     // fn should be called once
     expect(fn).toHaveBeenCalledTimes(1)
   })
+
+  it('should fallthrough attrs to vdom child', () => {
+    const VDomChild = defineComponent({
+      setup() {
+        return () => h('div')
+      },
+    })
+
+    const VaporChild = defineVaporComponent({
+      setup() {
+        return createComponent(
+          VDomChild as any,
+          { foo: () => 'vapor foo' },
+          null,
+          true,
+        )
+      },
+    })
+
+    const App = {
+      setup() {
+        return () => h(VaporChild as any, { foo: 'foo', bar: 'bar' })
+      },
+    }
+
+    const root = document.createElement('div')
+    createApp(App).use(vaporInteropPlugin).mount(root)
+    expect(root.innerHTML).toBe('<div foo="vapor foo" bar="bar"></div>')
+  })
 })
index 58076fff9eea213c8180d87ef5ed089951560798..d6f4c0af30f76ea7019d0613820baf7f9c2fb702 100644 (file)
@@ -241,14 +241,11 @@ describe('component: slots', () => {
         }),
       ).render()
 
-      expect(props).toEqual({ foo: 100, baz: 'qux' })
+      // foo has higher priority than bindObj.foo
+      expect(props).toEqual({ foo: 0, baz: 'qux' })
 
       foo.value = 2
       await nextTick()
-      expect(props).toEqual({ foo: 100, baz: 'qux' })
-
-      delete bindObj.value.foo
-      await nextTick()
       expect(props).toEqual({ foo: 2, baz: 'qux' })
     })
 
index af15133dbe54f7510deb7abc2bf85e88f76f6250..190dbc5fc0cdd7ad2ea307c35ea310895f436a99 100644 (file)
@@ -150,19 +150,6 @@ export function createComponent(
     resetInsertionState()
   }
 
-  // vdom interop enabled and component is not an explicit vapor component
-  if (appContext.vapor && !component.__vapor) {
-    const frag = appContext.vapor.vdomMount(
-      component as any,
-      rawProps,
-      rawSlots,
-    )
-    if (!isHydrating && _insertionParent) {
-      insert(frag, _insertionParent, _insertionAnchor)
-    }
-    return frag
-  }
-
   if (
     isSingleRoot &&
     component.inheritAttrs !== false &&
@@ -181,6 +168,19 @@ export function createComponent(
     }
   }
 
+  // vdom interop enabled and component is not an explicit vapor component
+  if (appContext.vapor && !component.__vapor) {
+    const frag = appContext.vapor.vdomMount(
+      component as any,
+      rawProps,
+      rawSlots,
+    )
+    if (!isHydrating && _insertionParent) {
+      insert(frag, _insertionParent, _insertionAnchor)
+    }
+    return frag
+  }
+
   const instance = new VaporComponentInstance(
     component,
     rawProps as RawProps,
index 9cf65c57143a4f72b3b466cd5732bde7cd5cead1..a8fbafd5f9fd243415f5cae2d7af3669b670200e 100644 (file)
@@ -178,6 +178,16 @@ export function getAttrFromRawProps(rawProps: RawProps, key: string): unknown {
   if (key === '$') return
   // need special merging behavior for class & style
   const merged = key === 'class' || key === 'style' ? ([] as any[]) : undefined
+
+  // rawProps has high priority
+  if (hasOwn(rawProps, key)) {
+    if (merged) {
+      merged.push(rawProps[key]())
+    } else {
+      return rawProps[key]()
+    }
+  }
+
   const dynamicSources = rawProps.$
   if (dynamicSources) {
     let i = dynamicSources.length
@@ -196,13 +206,7 @@ export function getAttrFromRawProps(rawProps: RawProps, key: string): unknown {
       }
     }
   }
-  if (hasOwn(rawProps, key)) {
-    if (merged) {
-      merged.push(rawProps[key]())
-    } else {
-      return rawProps[key]()
-    }
-  }
+
   if (merged && merged.length) {
     return merged
   }