From 91193ab44ffe3a4d2d2215682202bbf26cd58471 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:52:53 +0100 Subject: [PATCH] bug: unable to recover from loading a corrupted layout --- .../dockview/dockviewComponent.spec.ts | 73 +++++++++++++++++++ .../src/dockview/dockviewComponent.ts | 20 ++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts index 1c99baabc..e1cdbe3e0 100644 --- a/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts +++ b/packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts @@ -4063,4 +4063,77 @@ describe('dockviewComponent', () => { expect(tabDragEvents.length).toBe(0); expect(groupDragEvents.length).toBe(1); }); + + test('loading a corrupted layout', () => { + const container = document.createElement('div'); + + const dockview = new DockviewComponent({ + parentElement: container, + components: { + default: PanelContentPartTest, + }, + tabComponents: { + test_tab_id: PanelTabPartTest, + }, + orientation: Orientation.HORIZONTAL, + }); + + dockview.layout(1000, 500); + + dockview.addPanel({ + id: 'panel_1', + component: 'default', + }); + + expect(dockview.groups.length).toBe(1); + expect(dockview.panels.length).toBe(1); + + dockview.fromJSON({ + grid: { + root: { + type: 'branch', + data: [ + { + type: 'leaf', + data: { + views: ['panelA'], + activeView: 'panelA', + id: '1', + }, + size: 841, + }, + { + type: 'leaf', + data: { + views: ['panelB'], + activeView: 'panelB', + id: '2', + }, + size: 842, + }, + ], + size: 530, + }, + width: 1683, + height: 530, + orientation: Orientation.HORIZONTAL, + }, + panels: { + panelA: { + id: 'panelA', + contentComponent: 'somethingBad', + title: 'Panel A', + }, + panelB: { + id: 'panelB', + contentComponent: 'panelB', + title: 'Panel B', + }, + }, + activeGroup: '1', + }); + + expect(dockview.groups.length).toBe(0); + expect(dockview.panels.length).toBe(0); + }); }); diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 04a0eb280..315772282 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -658,7 +658,25 @@ export class DockviewComponent this._onDidAddGroup.fire(group); for (const child of views) { - const panel = this._deserializer.fromJSON(panels[child], group); + let panel: IDockviewPanel; + try { + panel = this._deserializer.fromJSON(panels[child], group); + } catch (err) { + /** + * This is an odd case... we have failed to deserialize a view but we have already created a group, + * but we havn't registered that group with the gridview. + * We cannot use the removeGroup method because the group has only been partially added, we must + * manually dipose() of the view and remove it from being stored in the map. + */ + group.dispose(); + this._groups.delete(group.id); + + /** + * re-throw the error becasue we don't actually want to catch it, we just + * needed to do some clean-up before continuing + */ + throw err; + } const isActive = typeof activeView === 'string' && activeView === panel.id;