fix(runtime-core): ensure tracking is paused when emit() calls handler so it can safely be called in effects

fix: #6669
This commit is contained in:
Thorsten Luenborg 2022-09-17 11:51:35 +02:00
parent 8772a01a92
commit 1c02e5a9c2
2 changed files with 38 additions and 1 deletions

View 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)
})
})

View 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`]