From c51115df48ab146d7238817bee6fea7fd1998796 Mon Sep 17 00:00:00 2001 From: unadlib Date: Fri, 19 Apr 2024 16:16:00 +0800 Subject: [PATCH] fix(finalization): fix proxy revoked error in finalization with marking --- src/utils/finalize.ts | 16 +++++++++++---- test/index.test.ts | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/utils/finalize.ts b/src/utils/finalize.ts index 1e512654..f545c62d 100644 --- a/src/utils/finalize.ts +++ b/src/utils/finalize.ts @@ -12,10 +12,14 @@ import { } from './draft'; import { forEach } from './forEach'; -export function handleValue(target: any, handledSet: WeakSet) { +export function handleValue( + target: any, + handledSet: WeakSet, + options?: ProxyDraft['options'] +) { if ( isDraft(target) || - !isDraftable(target) || + !isDraftable(target, options) || handledSet.has(target) || Object.isFrozen(target) ) @@ -35,7 +39,7 @@ export function handleValue(target: any, handledSet: WeakSet) { // final update value set(isSet ? setMap! : target, key, updatedValue); } else { - handleValue(value, handledSet); + handleValue(value, handledSet, options); } }); if (setMap) { @@ -57,7 +61,11 @@ export function finalizeAssigned(proxyDraft: ProxyDraft, key: PropertyKey) { proxyDraft.assignedMap!.get(key) && copy ) { - handleValue(get(copy, key), proxyDraft.finalities.handledSet); + handleValue( + get(copy, key), + proxyDraft.finalities.handledSet, + proxyDraft.options + ); } } diff --git a/test/index.test.ts b/test/index.test.ts index 9e789dc4..f90c4124 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -13,6 +13,7 @@ import { Draft, markSimpleObject, rawReturn, + makeCreator, } from '../src'; import { PROXY_DRAFT } from '../src/constant'; @@ -3881,3 +3882,49 @@ test('object with non-enumerable Symbol key at root - 1', () => { foobar: 'str', }); }); + +test('#37 - Proxy revoked error with `mark` option when performing chai deep equality', () => { + class Entity { + constructor(public readonly name: string) {} + } + + class Group { + constructor( + public readonly id: string, + public readonly children: Entity[] + ) {} + + public clone() { + return new Group(this.id, this.children); + } + } + + class Data { + constructor(public readonly groupData: Record) {} + } + + const create = makeCreator({ + mark: () => 'immutable', + }); + + const entity1 = new Entity('entity1'); + const entity2 = new Entity('entity2'); + + const data = new Data({ + id1: new Group('id1', []), + id2: new Group('id2', [entity1]), + id3: new Group('id3', [entity2]), + }); + + expect( + create(data, (draft) => { + draft.groupData.id1 = draft.groupData.id1.clone(); + }) + ).toEqual( + new Data({ + id1: new Group('id1', []), + id2: new Group('id2', [entity1]), + id3: new Group('id3', [entity2]), + }) + ); +});