diff --git a/packages/reactivity/__tests__/effect.spec.ts b/packages/reactivity/__tests__/effect.spec.ts index a322c7209f4..c8182dbee36 100644 --- a/packages/reactivity/__tests__/effect.spec.ts +++ b/packages/reactivity/__tests__/effect.spec.ts @@ -900,6 +900,40 @@ describe('reactivity/effect', () => { expect(record).toBeUndefined() }) + it('should track hasOwnProperty when obj call it itself', () => { + const obj: any = reactive({}) + const has = ref(false) + const fnSpy = jest.fn() + + effect(() => { + fnSpy() + has.value = obj.hasOwnProperty('foo') + }) + expect(fnSpy).toHaveBeenCalledTimes(1) + expect(has.value).toBe(false) + + obj.foo = 1 + expect(fnSpy).toHaveBeenCalledTimes(2) + expect(has.value).toBe(true) + }) + + it('should not track hasOwnProperty when Object.prototype.hasOwnProperty.call', () => { + const obj: any = reactive({}) + const has = ref(false) + const fnSpy = jest.fn() + + effect(() => { + fnSpy() + has.value = Object.prototype.hasOwnProperty.call(obj, 'foo') + }) + expect(fnSpy).toHaveBeenCalledTimes(1) + expect(has.value).toBe(false) + + obj.foo = 1 + expect(fnSpy).toHaveBeenCalledTimes(1) + expect(has.value).toBe(false) + }) + it('should not be triggered when set with the same proxy', () => { const obj = reactive({ foo: 1 }) const observed: any = reactive({ obj }) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index dfff56f7fc5..9bddedbdf5f 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -121,7 +121,12 @@ function createGetter(isReadonly = false, shallow = false) { } if (!isReadonly) { - track(target, TrackOpTypes.GET, key) + track( + target, + TrackOpTypes.GET, + // #2619 + key === 'hasOwnProperty' ? ITERATE_KEY : key + ) } if (shallow) {