fix(watch): support traversing symbol properties in deep watcher (#10969)

close #402
This commit is contained in:
skirtle 2024-05-30 04:03:44 +01:00 committed by GitHub
parent 6f9587f63b
commit a3e8aafbcc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 0 deletions

View File

@ -932,6 +932,52 @@ describe('api: watch', () => {
expect(dummy).toEqual([1, 2])
})
it('deep with symbols', async () => {
const symbol1 = Symbol()
const symbol2 = Symbol()
const symbol3 = Symbol()
const symbol4 = Symbol()
const raw: any = {
[symbol1]: {
[symbol2]: 1,
},
}
Object.defineProperty(raw, symbol3, {
writable: true,
enumerable: false,
value: 1,
})
const state = reactive(raw)
const spy = vi.fn()
watch(() => state, spy, { deep: true })
await nextTick()
expect(spy).toHaveBeenCalledTimes(0)
state[symbol1][symbol2] = 2
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
// Non-enumerable properties don't trigger deep watchers
state[symbol3] = 3
await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
// Adding a new symbol property
state[symbol4] = 1
await nextTick()
expect(spy).toHaveBeenCalledTimes(2)
// Removing a symbol property
delete state[symbol4]
await nextTick()
expect(spy).toHaveBeenCalledTimes(3)
})
it('immediate', async () => {
const count = ref(0)
const cb = vi.fn()

View File

@ -493,6 +493,11 @@ export function traverse(
for (const key in value) {
traverse(value[key], depth, seen)
}
for (const key of Object.getOwnPropertySymbols(value)) {
if (Object.prototype.propertyIsEnumerable.call(value, key)) {
traverse(value[key as any], depth, seen)
}
}
}
return value
}