-import { type Ref, nextTick, ref } from '@vue/runtime-dom'
+import {
+ type Ref,
+ createApp,
+ defineComponent,
+ h,
+ nextTick,
+ ref,
+} from '@vue/runtime-dom'
import {
createComponent,
defineVaporComponent,
setProp,
setStyle,
template,
+ vaporInteropPlugin,
} from '../src'
import { makeRender } from './_utils'
import { stringifyStyle } from '@vue/shared'
const el = host.children[0]
expect(el.classList.length).toBe(0)
})
+
+ it('should not fallthrough emit handlers to vdom child', () => {
+ const VDomChild = defineComponent({
+ emits: ['click'],
+ setup(_, { emit }) {
+ return () => h('button', { onClick: () => emit('click') }, 'click me')
+ },
+ })
+
+ const fn = vi.fn()
+ const VaporChild = defineVaporComponent({
+ emits: ['click'],
+ setup() {
+ return createComponent(
+ VDomChild as any,
+ { onClick: () => fn },
+ null,
+ true,
+ )
+ },
+ })
+
+ const App = {
+ setup() {
+ return () => h(VaporChild as any)
+ },
+ }
+
+ const root = document.createElement('div')
+ createApp(App).use(vaporInteropPlugin).mount(root)
+
+ expect(root.innerHTML).toBe('<button>click me</button>')
+ const button = root.querySelector('button')!
+ button.dispatchEvent(new Event('click'))
+
+ // fn should be called once
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
type Slots,
type VNode,
type VaporInteropInterface,
+ createInternalObject,
createVNode,
currentInstance,
ensureRenderer,
+ isEmitListener,
onScopeDispose,
renderSlot,
shallowRef,
// overwrite how the vdom instance handles props
vnode.vi = (instance: ComponentInternalInstance) => {
instance.props = wrapper.props
- instance.attrs = wrapper.attrs
+
+ const attrs = (instance.attrs = createInternalObject())
+ for (const key in wrapper.attrs) {
+ if (!isEmitListener(instance.emitsOptions, key)) {
+ attrs[key] = wrapper.attrs[key]
+ }
+ }
+
instance.slots =
wrapper.slots === EMPTY_OBJ
? EMPTY_OBJ