Skip to content

Commit

Permalink
fix(watch): new property addition should trigger deep watcher with ge…
Browse files Browse the repository at this point in the history
…tter

close vuejs#12967
close vuejs#12972
  • Loading branch information
yyx990803 committed Dec 6, 2023
1 parent a174c29 commit 6d857f5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/v3/apiWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,11 @@ function doWatch(
}

const instance = currentInstance
const call = (fn: Function, type: string, args: any[] | null = null) =>
invokeWithErrorHandling(fn, null, args, instance, type)
const call = (fn: Function, type: string, args: any[] | null = null) => {
const res = invokeWithErrorHandling(fn, null, args, instance, type)
if (deep && res && res.__ob__) res.__ob__.dep.depend()
return res
}

let getter: () => any
let forceTrigger = false
Expand All @@ -209,6 +212,7 @@ function doWatch(
if (isRef(s)) {
return s.value
} else if (isReactive(s)) {
s.__ob__.dep.depend()
return traverse(s)
} else if (isFunction(s)) {
return call(s, WATCHER_GETTER)
Expand Down
31 changes: 31 additions & 0 deletions test/unit/features/v3/apiWatch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1200,4 +1200,35 @@ describe('api: watch', () => {
expect(parentSpy).toHaveBeenCalledTimes(1)
expect(childSpy).toHaveBeenCalledTimes(1)
})

// #12967
test('trigger when adding new property with Vue.set (getter)', async () => {
const spy = vi.fn()
const r = reactive({ exist: 5 })
watch(() => r, spy, { deep: true })
set(r, 'add', 1)

await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
})

test('trigger when adding new property with Vue.set (getter in array source)', async () => {
const spy = vi.fn()
const r = reactive({ exist: 5 })
watch([() => r], spy, { deep: true })
set(r, 'add', 1)

await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
})

test('trigger when adding new property with Vue.set (reactive in array source)', async () => {
const spy = vi.fn()
const r = reactive({ exist: 5 })
watch([r], spy, { deep: true })
set(r, 'add', 1)

await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
})
})

0 comments on commit 6d857f5

Please sign in to comment.