Skip to content

Commit

Permalink
fix(useReactive): cannot set a object with read-only and non-configur…
Browse files Browse the repository at this point in the history
…able property (alibaba#2247)

* fix: throw error when set a read-only and non-configurable data property

* style: update
  • Loading branch information
liuyib committed Jul 13, 2023
1 parent 33caa72 commit c14a27f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
30 changes: 30 additions & 0 deletions packages/hooks/src/useReactive/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,36 @@ describe('test useReactive feature', () => {
expect(() => result.current.v.Module).not.toThrowError();
});

it('test JSX element', () => {
const hook = renderHook(() => useReactive({ html: <div role="id">foo</div> }));
const proxy = hook.result.current;
const wrap = render(proxy.html);
const html = wrap.getByRole('id');

expect(html.textContent).toBe('foo');
act(() => {
proxy.html = <div role="id">bar</div>;
wrap.rerender(proxy.html);
});
expect(html.textContent).toBe('bar');
hook.unmount();
});

it('test read-only and non-configurable data property', () => {
const obj = {} as { user: { name: string } };
Reflect.defineProperty(obj, 'user', {
value: { name: 'foo' },
writable: false,
configurable: false,
});

const hook = renderHook(() => useReactive(obj));
const proxy = hook.result.current;

expect(() => proxy.user.name).not.toThrowError();
hook.unmount();
});

it('test input1', () => {
const wrap = render(<Demo />);

Expand Down
6 changes: 6 additions & 0 deletions packages/hooks/src/useReactive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ function observer<T extends Record<string, any>>(initialVal: T, cb: () => void):
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);

// https://github.com/alibaba/hooks/issues/1317
const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
if (!descriptor?.configurable && !descriptor?.writable) {
return res;
}

// Only proxy plain object or array,
// otherwise it will cause: https://github.com/alibaba/hooks/issues/2080
return isPlainObject(res) || Array.isArray(res) ? observer(res, cb) : res;
Expand Down

0 comments on commit c14a27f

Please sign in to comment.