diff --git a/src/reactive-handler.ts b/src/reactive-handler.ts index a0e0160..80f7f30 100644 --- a/src/reactive-handler.ts +++ b/src/reactive-handler.ts @@ -43,7 +43,7 @@ function lockShadowTarget(membrane: ReactiveMembrane, shadowTarget: ReactiveMemb targetKeys.forEach((key: PropertyKey) => { let descriptor = getOwnPropertyDescriptor(originalTarget, key) as PropertyDescriptor; - // We do not need to wrap the descriptor if not configurable + // We do not need to wrap the descriptor if configurable // Because we can deal with wrapping it when user goes through // Get own property descriptor. There is also a chance that this descriptor // could change sometime in the future, so we can defer wrapping diff --git a/test/reactive-handler.spec.ts b/test/reactive-handler.spec.ts index 2a991b4..2a34101 100644 --- a/test/reactive-handler.spec.ts +++ b/test/reactive-handler.spec.ts @@ -593,4 +593,43 @@ describe('ReactiveHandler', () => { expect(accessSpy).toHaveBeenCalledTimes(2); expect(accessSpy).toHaveBeenLastCalledWith(obj.foo, 'bar'); }); + + describe('getOwnPropertyDescriptor', () => { + it('should return reactive proxy when property accessed via raw getter', () => { + const target = new ReactiveMembrane(); + const todos = {}; + const observable = {}; + Object.defineProperty(todos, 'foo', { + get() { + return observable; + }, + configurable: true + }); + const expected = target.getProxy(observable); + + const proxy = target.getProxy(todos); + expect(proxy.foo).toBe(expected); + + const desc = Object.getOwnPropertyDescriptor(proxy, 'foo'); + const { get } = desc; + expect(get()).toBe(expected); + }); + it('should return reactive proxy when property accessed via descriptor', () => { + const target = new ReactiveMembrane(); + const todos = {}; + const observable = {}; + Object.defineProperty(todos, 'foo', { + value : observable, + configurable: true + }); + const expected = target.getProxy(observable); + + const proxy = target.getProxy(todos); + expect(proxy.foo).toBe(expected); + + const desc = Object.getOwnPropertyDescriptor(proxy, 'foo'); + const { value } = desc; + expect(value).toBe(expected); + }); + }) }); diff --git a/test/read-only-handler.spec.ts b/test/read-only-handler.spec.ts index 8894949..09c66bf 100644 --- a/test/read-only-handler.spec.ts +++ b/test/read-only-handler.spec.ts @@ -271,4 +271,41 @@ describe('ReadOnlyHandler', () => { doNothing(readOnly.foo); }).not.toThrow(); }); + + describe('getOwnPropertyDescriptor', () => { + it('should return reactive proxy when property accessed via raw getter', () => { + const target = new ReactiveMembrane(); + const todos = {}; + Object.defineProperty(todos, 'entry', { + get() { + return { foo: 'bar' }; + }, + configurable: true + }); + + const proxy = target.getReadOnlyProxy(todos); + const desc = Object.getOwnPropertyDescriptor(proxy, 'entry'); + const { get } = desc; + expect(() => { + get().foo = ''; + }).toThrow(); + expect(todos['entry'].foo).toEqual('bar'); + }); + it('should return reactive proxy when property accessed via descriptor', () => { + const target = new ReactiveMembrane(); + const todos = {}; + Object.defineProperty(todos, 'entry', { + value : { foo: 'bar' }, + configurable: true + }); + + const proxy = target.getReadOnlyProxy(todos); + const desc = Object.getOwnPropertyDescriptor(proxy, 'entry'); + const { value } = desc; + expect( () => { + value.foo = ''; + }).toThrow(); + expect(todos['entry'].foo).toEqual('bar'); + }); + }) });