]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): ensure tracking is paused when emit() calls handler so it can... linusborg/pause-tracking-in-emit-6669 6688/head
authorThorsten Luenborg <t.luenborg@googlemail.com>
Sat, 17 Sep 2022 09:51:35 +0000 (11:51 +0200)
committerThorsten Luenborg <t.luenborg@googlemail.com>
Sat, 17 Sep 2022 10:00:03 +0000 (12:00 +0200)
fix: #6669

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

index f22be2de0c1239b819c542c22fbdebcead2a2f94..11a5339d8a524087432bf01823120b9833d41528 100644 (file)
@@ -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)
+  })
 })
index b113eaa53573489ea75873d0d7d0d16b2d896ca5..03500368b58b05b4e84cbefff7e4ff09b2fc1928 100644 (file)
@@ -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`]