From 11ddbfb7cf7b498d4f05fda3bc1bcde4867b83ff Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Fri, 1 Dec 2023 18:09:23 +0000 Subject: [PATCH] fix: guard against undefined nested parent (#41) --- __tests__/07_nested_map_spec.ts | 63 +++++++++++++++++++++++++++++++++ src/index.ts | 4 +++ 2 files changed, 67 insertions(+) diff --git a/__tests__/07_nested_map_spec.ts b/__tests__/07_nested_map_spec.ts index df7bb92..1242b8c 100644 --- a/__tests__/07_nested_map_spec.ts +++ b/__tests__/07_nested_map_spec.ts @@ -147,4 +147,67 @@ describe('issue #14', () => { expect(listener1).toBeCalledTimes(2); expect(listener2).toBeCalledTimes(2); }); + + it('nested map delete', async () => { + type State = Record<'items', { + [key: string]: { + color: string; + } + }>; + const doc = new Y.Doc(); + const p = proxy({ items: { item1: { color: 'blue' }, item2: { color: 'red' } } }); + const m = doc.getMap('map') as any; + + bind(p, m); + + delete p.items.item1; + await Promise.resolve(); + + expect(m.get('items').get('item1')).toBeUndefined() + expect(m.get('items').get('item2')).toBeDefined() + }); + + + it('nested map delete child and parent', async () => { + type State = Record<'parents', { + [key: string]: Record<'children', { + [key: string]: { + color: string; + } + }> + }>; + const doc = new Y.Doc(); + const p = proxy({ + parents: { + parent1: { + children: { + child1: { color: 'blue' } + } + }, + parent2: { + children: { + child2: { color: 'red' } + } + } + } + }); + const m = doc.getMap('map') as any; + + bind(p, m); + + delete p.parents.parent1.children.child1; + delete p.parents.parent1; + await Promise.resolve(); + + expect(m.toJSON()).toStrictEqual({ + parents: { + parent2: { + children: { + child2: { color: 'red' } + } + } + } + }) + }); + }); diff --git a/src/index.ts b/src/index.ts index 4d2f46d..9fa0201 100644 --- a/src/index.ts +++ b/src/index.ts @@ -73,9 +73,13 @@ const getNestedValues = ( for (let i = 0; i < path.length; i += 1) { const k = path[i]; if (yv instanceof Y.Map) { + // parent may already be deleted + if (!pv) break pv = pv[k]; yv = yv.get(k as string); } else if (yv instanceof Y.Array) { + // parent may already be deleted + if (!pv) break const index = Number(k); pv = pv[k]; yv = yv.get(index);