From c694a24ebb257701c5ca45ad6b7cf7ed4bcf8c82 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Tue, 17 Oct 2023 16:19:03 +0800 Subject: [PATCH 1/2] fix(runtime-core): incorrect callback parameters when reactive array ref passes to watch --- packages/runtime-core/__tests__/apiWatch.spec.ts | 10 ++++++++++ packages/runtime-core/src/apiWatch.ts | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index f24ce80b9df..8052fbaec84 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -94,6 +94,16 @@ describe('api: watch', () => { expect(spy).toBeCalledWith([1], expect.anything(), expect.anything()) }) + it('watching single source: reactive with array ref', async () => { + const foo = reactive([ref(0)]) + const callback = vi.fn() + watch(foo, callback) + foo[0].value++ + await nextTick() + expect(callback).toBeCalledTimes(1) + expect(callback).toBeCalledWith([1], expect.anything(), expect.anything()) + }) + it('should not fire if watched getter result did not change', async () => { const spy = vi.fn() const n = ref(0) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 1b85ba12d19..5dc1494f00b 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -202,16 +202,17 @@ function doWatch( getCurrentScope() === currentInstance?.scope ? currentInstance : null // const instance = currentInstance let getter: () => any + let sourceIsReactive = false let forceTrigger = false let isMultiSource = false - if (isRef(source)) { getter = () => source.value forceTrigger = isShallow(source) - } else if (isReactive(source)) { + } else if ((sourceIsReactive = isReactive(source)) && !isArray(source)) { getter = () => source deep = true } else if (isArray(source)) { + deep = sourceIsReactive isMultiSource = true forceTrigger = source.some(s => isReactive(s) || isShallow(s)) getter = () => @@ -222,6 +223,8 @@ function doWatch( return traverse(s) } else if (isFunction(s)) { return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER) + } else if (sourceIsReactive) { + return s } else { __DEV__ && warnInvalidSource(s) } From ebad56f73df4df98079ab2e5d7f30a804e0860f8 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Tue, 17 Oct 2023 20:00:53 +0800 Subject: [PATCH 2/2] refactor: improve --- packages/runtime-core/src/apiWatch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 5dc1494f00b..892110200e3 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -212,7 +212,6 @@ function doWatch( getter = () => source deep = true } else if (isArray(source)) { - deep = sourceIsReactive isMultiSource = true forceTrigger = source.some(s => isReactive(s) || isShallow(s)) getter = () => @@ -224,6 +223,7 @@ function doWatch( } else if (isFunction(s)) { return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER) } else if (sourceIsReactive) { + deep = true return s } else { __DEV__ && warnInvalidSource(s)