dai-shi / dai-shi/proxy-compare

Error when call `createProxy` twice with the same but frozen object using `targetCache`

Open
#70 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
311
Forks
19
PR merge metrics
No merged PRs in 30d

Description

Hi! I caught an error when trying to pass `targetCache`.

Problem appears if call `createProxy` with a regular object, then with the same (by link) but frozen object.

```typescript
const targetCache = new WeakMap();

const original = { list: [{ i: 10 }, { i: 20 }] };
const proxy1 = createProxy(original, new WeakMap(), undefined, targetCache);

Object.freeze(original);

const proxy2 = createProxy(original, new WeakMap(), undefined, targetCache);
console.log(proxy2.list);
```
Error:
```
'get' on proxy: property 'list' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '[object Array]' but got '[object Array]')
```
https://codesandbox.io/p/sandbox/proxy-compare-test-forked-ksskgg

First time we call `createProxy`, it stores target without a copy. And then if call `createProxy` with frozen object, it hits in to `targetCache` and receives that target without copy.
https://github.com/dai-shi/proxy-compare/blob/1c0f138cbaa5bb0dd736f305d43e74bb1ecf0c74/src/index.ts#L209C1-L219C1

In my case I can fix it if I guarantee that an object is frozen when call `createProxy` first time.
But you can fix it if check `needsToCopyTargetObject` before get from the targetCache.

Example of solution:
```typescript
const target = getOriginalObject(obj);
let copied;

if (needsToCopyTargetObject(target)) {
[, copied] = targetCache && (targetCache as TargetCache).get(obj);

if (!copied) {
copied = copyTargetObject(target);
}

targetCache?.set(obj, [target, copied]);
}
```

Do you think is there a reason to fix that case at your library? I can open a PR if you are.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/index.ts at the targetCache handling around lines 209-219, then reproduce the provided createProxy example with the object frozen between calls. Check how needsToCopyTargetObject and cached targets interact; done means the second proxy can read the frozen object's list without a Proxy invariant error.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.