diff --git a/packages/runtime-core/__tests__/componentEmits.spec.ts b/packages/runtime-core/__tests__/componentEmits.spec.ts index dc82c0491..1b8bcf9a4 100644 --- a/packages/runtime-core/__tests__/componentEmits.spec.ts +++ b/packages/runtime-core/__tests__/componentEmits.spec.ts @@ -3,6 +3,7 @@ import { type ComponentPublicInstance, + createApp, defineComponent, h, nextTick, @@ -598,4 +599,45 @@ describe('component: emit', () => { render(h(ComponentC), el) expect(renderFn).toHaveBeenCalledTimes(1) }) + + test('merging emits for a component that is also used as a mixin', () => { + const render = () => h('div') + const CompA = { + render, + } + const validateByMixin = vi.fn(() => true) + const validateByGlobalMixin = vi.fn(() => true) + + const mixin = { + emits: { + one: validateByMixin, + }, + } + + const CompB = defineComponent({ + mixins: [mixin, CompA], + created(this) { + this.$emit('one', 1) + }, + render, + }) + + const app = createApp({ + render() { + return [h(CompA), h(CompB)] + }, + }) + + app.mixin({ + emits: { + one: validateByGlobalMixin, + two: null, + }, + }) + + const root = nodeOps.createElement('div') + app.mount(root) + expect(validateByMixin).toHaveBeenCalledTimes(1) + expect(validateByGlobalMixin).not.toHaveBeenCalled() + }) }) diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index db52bc88c..0b35a93ba 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -228,12 +228,14 @@ export function emit( } } +const mixinEmitsCache = new WeakMap() export function normalizeEmitsOptions( comp: ConcreteComponent, appContext: AppContext, asMixin = false, ): ObjectEmitsOptions | null { - const cache = appContext.emitsCache + const cache = + __FEATURE_OPTIONS_API__ && asMixin ? mixinEmitsCache : appContext.emitsCache const cached = cache.get(comp) if (cached !== undefined) { return cached