File tree Expand file tree Collapse file tree 4 files changed +39
-6
lines changed Expand file tree Collapse file tree 4 files changed +39
-6
lines changed Original file line number Diff line number Diff line change @@ -26,7 +26,27 @@ describe('vdomInterop', () => {
2626 } )
2727 } )
2828
29- describe . todo ( 'emit' , ( ) => { } )
29+ describe ( 'emit' , ( ) => {
30+ test ( 'emit from vapor child to vdom parent' , ( ) => {
31+ const VaporChild = defineVaporComponent ( {
32+ emits : [ 'click' ] ,
33+ setup ( _ , { emit } ) {
34+ emit ( 'click' )
35+ return [ ]
36+ } ,
37+ } )
38+
39+ const fn = vi . fn ( )
40+ define ( {
41+ setup ( ) {
42+ return ( ) => h ( VaporChild as any , { onClick : fn } )
43+ } ,
44+ } ) . render ( )
45+
46+ // fn should be called once
47+ expect ( fn ) . toHaveBeenCalledTimes ( 1 )
48+ } )
49+ } )
3050
3151 describe ( 'slots' , ( ) => {
3252 test ( 'basic' , ( ) => {
Original file line number Diff line number Diff line change 11import { type ObjectEmitsOptions , baseEmit } from '@vue/runtime-dom'
22import type { VaporComponent , VaporComponentInstance } from './component'
33import { EMPTY_OBJ , hasOwn , isArray } from '@vue/shared'
4- import { resolveSource } from './componentProps'
4+ import { type RawProps , resolveSource } from './componentProps'
5+ import { interopKey } from './vdomInterop'
56
67/**
78 * The logic from core isn't too reusable so it's better to duplicate here
@@ -40,13 +41,17 @@ export function emit(
4041 )
4142}
4243
43- function propGetter ( rawProps : Record < string , any > , key : string ) {
44+ function propGetter ( rawProps : RawProps , key : string ) {
4445 const dynamicSources = rawProps . $
4546 if ( dynamicSources ) {
4647 let i = dynamicSources . length
4748 while ( i -- ) {
4849 const source = resolveSource ( dynamicSources [ i ] )
49- if ( hasOwn ( source , key ) ) return resolveSource ( source [ key ] )
50+ if ( hasOwn ( source , key ) )
51+ // for props passed from VDOM component, no need to resolve
52+ return dynamicSources [ interopKey ]
53+ ? source [ key ]
54+ : resolveSource ( source [ key ] )
5055 }
5156 }
5257 return rawProps [ key ] && resolveSource ( rawProps [ key ] )
Original file line number Diff line number Diff line change @@ -23,10 +23,11 @@ import {
2323import { ReactiveFlags } from '@vue/reactivity'
2424import { normalizeEmitsOptions } from './componentEmits'
2525import { renderEffect } from './renderEffect'
26+ import type { interopKey } from './vdomInterop'
2627
2728export type RawProps = Record < string , ( ) => unknown > & {
2829 // generated by compiler for :[key]="x" or v-bind="x"
29- $ ?: DynamicPropsSource [ ]
30+ $ ?: DynamicPropsSource [ ] & { [ interopKey ] ?: boolean }
3031}
3132
3233export type DynamicPropsSource =
Original file line number Diff line number Diff line change @@ -37,6 +37,8 @@ import { renderEffect } from './renderEffect'
3737import { createTextNode } from './dom/node'
3838import { optimizePropertyLookup } from './dom/prop'
3939
40+ export const interopKey : unique symbol = Symbol ( `interop` )
41+
4042// mounting vapor components and slots in vdom
4143const vaporInteropImpl : Omit <
4244 VaporInteropInterface ,
@@ -51,11 +53,16 @@ const vaporInteropImpl: Omit<
5153 const propsRef = shallowRef ( vnode . props )
5254 const slotsRef = shallowRef ( vnode . children )
5355
56+ const dynamicPropSource : ( ( ) => any ) [ ] & { [ interopKey ] ?: boolean } = [
57+ ( ) => propsRef . value ,
58+ ]
59+ // mark as interop props
60+ dynamicPropSource [ interopKey ] = true
5461 // @ts -expect-error
5562 const instance = ( vnode . component = createComponent (
5663 vnode . type as any as VaporComponent ,
5764 {
58- $ : [ ( ) => propsRef . value ] ,
65+ $ : dynamicPropSource ,
5966 } as RawProps ,
6067 {
6168 _ : slotsRef , // pass the slots ref
You can’t perform that action at this time.
0 commit comments