]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): use separate emits caches for components and mixins (#11661)
authorRed Huang <gcaaa31928@gmail.com>
Tue, 2 Sep 2025 09:15:46 +0000 (17:15 +0800)
committerGitHub <noreply@github.com>
Tue, 2 Sep 2025 09:15:46 +0000 (17:15 +0800)
packages/runtime-core/__tests__/componentEmits.spec.ts
packages/runtime-core/src/componentEmits.ts

index dc82c04919fdf4b09a69ad22f6a6de539936dcd4..1b8bcf9a4a0c549b4df8279ebfb0f7c2827c7926 100644 (file)
@@ -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()
+  })
 })
index c03bead3a9280cf1e7bbf4a286123b877e09011b..abbfe28888b56f7cbde0d449645df5c0d77f3732 100644 (file)
@@ -232,12 +232,14 @@ export function emit(
   }
 }
 
+const mixinEmitsCache = new WeakMap<ConcreteComponent, ObjectEmitsOptions>()
 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