mirror of https://github.com/vuejs/core.git
fix(watch): use maximum depth for duplicates (#13434)
This commit is contained in:
parent
99d54b28b4
commit
f2699a5cb3
|
@ -331,17 +331,17 @@ export function watch(
|
||||||
export function traverse(
|
export function traverse(
|
||||||
value: unknown,
|
value: unknown,
|
||||||
depth: number = Infinity,
|
depth: number = Infinity,
|
||||||
seen?: Set<unknown>,
|
seen?: Map<unknown, number>,
|
||||||
): unknown {
|
): unknown {
|
||||||
if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
|
if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
seen = seen || new Set()
|
seen = seen || new Map()
|
||||||
if (seen.has(value)) {
|
if ((seen.get(value) || 0) >= depth) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
seen.add(value)
|
seen.set(value, depth)
|
||||||
depth--
|
depth--
|
||||||
if (isRef(value)) {
|
if (isRef(value)) {
|
||||||
traverse(value.value, depth, seen)
|
traverse(value.value, depth, seen)
|
||||||
|
|
|
@ -1689,6 +1689,57 @@ describe('api: watch', () => {
|
||||||
expect(cb).toHaveBeenCalledTimes(4)
|
expect(cb).toHaveBeenCalledTimes(4)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('watching the same object at different depths', async () => {
|
||||||
|
const arr1: any[] = reactive([[[{ foo: {} }]]])
|
||||||
|
const arr2 = arr1[0]
|
||||||
|
const arr3 = arr2[0]
|
||||||
|
const obj = arr3[0]
|
||||||
|
arr1.push(arr3)
|
||||||
|
|
||||||
|
const cb1 = vi.fn()
|
||||||
|
const cb2 = vi.fn()
|
||||||
|
const cb3 = vi.fn()
|
||||||
|
const cb4 = vi.fn()
|
||||||
|
watch(arr1, cb1, { deep: 1 })
|
||||||
|
watch(arr1, cb2, { deep: 2 })
|
||||||
|
watch(arr1, cb3, { deep: 3 })
|
||||||
|
watch(arr1, cb4, { deep: 4 })
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
expect(cb1).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb2).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb3).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb4).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
|
obj.foo = {}
|
||||||
|
await nextTick()
|
||||||
|
expect(cb1).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb2).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb3).toHaveBeenCalledTimes(1)
|
||||||
|
expect(cb4).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
obj.foo.bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(cb1).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb2).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb3).toHaveBeenCalledTimes(1)
|
||||||
|
expect(cb4).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
arr3.push(obj.foo)
|
||||||
|
await nextTick()
|
||||||
|
expect(cb1).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb2).toHaveBeenCalledTimes(1)
|
||||||
|
expect(cb3).toHaveBeenCalledTimes(2)
|
||||||
|
expect(cb4).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
obj.foo.bar = 2
|
||||||
|
await nextTick()
|
||||||
|
expect(cb1).toHaveBeenCalledTimes(0)
|
||||||
|
expect(cb2).toHaveBeenCalledTimes(1)
|
||||||
|
expect(cb3).toHaveBeenCalledTimes(3)
|
||||||
|
expect(cb4).toHaveBeenCalledTimes(4)
|
||||||
|
})
|
||||||
|
|
||||||
test('pause / resume', async () => {
|
test('pause / resume', async () => {
|
||||||
const count = ref(0)
|
const count = ref(0)
|
||||||
const cb = vi.fn()
|
const cb = vi.fn()
|
||||||
|
|
Loading…
Reference in New Issue