dai-shi / dai-shi/proxy-compare
Error when call `createProxy` twice with the same but frozen object using `targetCache`
- 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