From 1c02e5a9c2dbabf741e7381e9ead84b97a345510 Mon Sep 17 00:00:00 2001 From: Thorsten Luenborg Date: Sat, 17 Sep 2022 11:51:35 +0200 Subject: [PATCH] fix(runtime-core): ensure tracking is paused when emit() calls handler so it can safely be called in effects fix: #6669 --- .../__tests__/componentEmits.spec.ts | 36 ++++++++++++++++++- packages/runtime-core/src/componentEmits.ts | 3 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/componentEmits.spec.ts b/packages/runtime-core/__tests__/componentEmits.spec.ts index f22be2de0c..11a5339d8a 100644 --- a/packages/runtime-core/__tests__/componentEmits.spec.ts +++ b/packages/runtime-core/__tests__/componentEmits.spec.ts @@ -7,7 +7,9 @@ import { h, nodeOps, toHandlers, - nextTick + nextTick, + ref, + watchEffect } from '@vue/runtime-test' import { isEmitListener } from '../src/componentEmits' @@ -431,4 +433,36 @@ describe('component: emit', () => { await nextTick() expect(fn).not.toHaveBeenCalled() }) + + test('should not track during listener execution', async () => { + const counter = ref(0) + const Comp = defineComponent({ + emits: ['interaction'], + setup(props, { emit }) { + const doEmit = ref(true) + watchEffect(() => { + if (doEmit.value) emit('interaction') + }) + return () => h('div') + } + }) + const el = nodeOps.createElement('div') + render( + h(Comp, { + onInteraction: async () => { + if (counter.value < 5) { + await nextTick() + counter.value++ + } + } + }), + el + ) + + await nextTick() + await nextTick() + await nextTick() + + expect(counter.value).toBe(1) + }) }) diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index b113eaa535..03500368b5 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -27,6 +27,7 @@ import { compatModelEventPrefix, compatModelEmit } from './compat/componentVModel' +import { pauseTracking, resetTracking } from '@vue/reactivity' export type ObjectEmitsOptions = Record< string, @@ -161,12 +162,14 @@ export function emit( } if (handler) { + pauseTracking() callWithAsyncErrorHandling( handler, instance, ErrorCodes.COMPONENT_EVENT_HANDLER, args ) + resetTracking() } const onceHandler = props[handlerName + `Once`] -- 2.47.2