Skip to content

Commit 50ba141

Browse files
committed
fix(runtime-core): use separate emits caches for components and mixins
1 parent 44973bb commit 50ba141

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

packages/runtime-core/__tests__/componentEmits.spec.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import {
55
type ComponentPublicInstance,
6+
createApp,
67
defineComponent,
78
h,
89
nextTick,
@@ -599,3 +600,78 @@ describe('component: emit', () => {
599600
expect(renderFn).toHaveBeenCalledTimes(1)
600601
})
601602
})
603+
604+
test('merging emits for a component that is also used as a mixin', () => {
605+
const render = () => h('div')
606+
const CompA = {
607+
render,
608+
}
609+
610+
const mixin = {
611+
emits: {
612+
one: (arg: number) => arg === 1,
613+
},
614+
}
615+
616+
const CompB = {
617+
mixins: [mixin, CompA],
618+
created(this: ComponentPublicInstance) {
619+
this.$emit('one', 1)
620+
},
621+
render,
622+
}
623+
624+
const app = createApp({
625+
render() {
626+
return [h(CompA), ', ', h(CompB)]
627+
},
628+
})
629+
630+
app.mixin({
631+
emits: {
632+
one: (arg: number) => arg === 0,
633+
two: null,
634+
},
635+
})
636+
637+
const root = nodeOps.createElement('div')
638+
app.mount(root)
639+
expect(`event validation failed for event "one"`).not.toHaveBeenWarned()
640+
})
641+
642+
test('merging props from global mixins and extends', () => {
643+
let renderProxy: any
644+
let extendedRenderProxy: any
645+
const render = () => h('div')
646+
const Comp = {
647+
mounted(this: ComponentPublicInstance) {
648+
renderProxy = this
649+
},
650+
render,
651+
}
652+
653+
const ExtendedComp = {
654+
extends: Comp,
655+
mounted(this: ComponentPublicInstance) {
656+
extendedRenderProxy = this
657+
},
658+
render,
659+
}
660+
661+
const app = createApp({
662+
render: () => [h(ExtendedComp), h(Comp)],
663+
})
664+
665+
const emits = {
666+
one: (arg: number) => arg === 0,
667+
two: (arg: number) => arg === 0,
668+
}
669+
app.mixin({ emits })
670+
671+
const root = nodeOps.createElement('div')
672+
app.mount(root)
673+
expect(renderProxy._.emitsOptions).toMatchObject(emits)
674+
expect(extendedRenderProxy._.emitsOptions).toMatchObject(emits)
675+
// expect(`event validation failed for event "comp"`).toHaveBeenWarned();
676+
// expect(`event validation failed for event "extended-comp"`).toHaveBeenWarned();
677+
})

packages/runtime-core/src/componentEmits.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,14 @@ export function emit(
219219
}
220220
}
221221

222+
const mixinEmitsCache = new WeakMap<ConcreteComponent, ObjectEmitsOptions>()
222223
export function normalizeEmitsOptions(
223224
comp: ConcreteComponent,
224225
appContext: AppContext,
225226
asMixin = false,
226227
): ObjectEmitsOptions | null {
227-
const cache = appContext.emitsCache
228+
const cache =
229+
__FEATURE_OPTIONS_API__ && asMixin ? mixinEmitsCache : appContext.emitsCache
228230
const cached = cache.get(comp)
229231
if (cached !== undefined) {
230232
return cached

0 commit comments

Comments
 (0)