From 73fd810eebdd383a2b4629f67736c4db1f428abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=B1=E6=9E=9C=E5=B1=B1=E5=A4=A7=E5=9C=A3?= <316783812@qq.com> Date: Fri, 10 Nov 2023 16:47:08 +0800 Subject: [PATCH] fix(reactivity): onCleanup also needs to be cleaned (#8655) close #5151 close #7695 --- .../runtime-core/__tests__/apiWatch.spec.ts | 35 +++++++++++++++++++ packages/runtime-core/src/apiWatch.ts | 3 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index dcb1d6a5f28..48fdd2888ec 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1205,4 +1205,39 @@ describe('api: watch', () => { expect(countWE).toBe(3) expect(countW).toBe(2) }) + + // #5151 + test('OnCleanup also needs to be cleaned,', async () => { + const spy1 = vi.fn() + const spy2 = vi.fn() + const num = ref(0) + + watch(num, (value, oldValue, onCleanup) => { + if (value > 1) { + return + } + spy1() + onCleanup(() => { + // OnCleanup also needs to be cleaned + spy2() + }) + }) + + num.value++ + await nextTick() + expect(spy1).toHaveBeenCalledTimes(1) + expect(spy2).toHaveBeenCalledTimes(0) + + num.value++ + await nextTick() + + expect(spy1).toHaveBeenCalledTimes(1) + expect(spy2).toHaveBeenCalledTimes(1) + + num.value++ + await nextTick() + // would not be calld when value>1 + expect(spy1).toHaveBeenCalledTimes(1) + expect(spy2).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 1b85ba12d19..71b15fd6e04 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -273,10 +273,11 @@ function doWatch( getter = () => traverse(baseGetter()) } - let cleanup: () => void + let cleanup: (() => void) | undefined let onCleanup: OnCleanup = (fn: () => void) => { cleanup = effect.onStop = () => { callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP) + cleanup = effect.onStop = undefined } }