chore: memory leak fixes and tests

This commit is contained in:
mathuo 2024-12-21 14:21:28 +00:00
parent c216d70354
commit f749372eb2
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
4 changed files with 101 additions and 87 deletions

View File

@ -21,7 +21,6 @@ import { DockviewApi } from '../../api/component.api';
import { DockviewDndOverlayEvent } from '../../dockview/options'; import { DockviewDndOverlayEvent } from '../../dockview/options';
import { SizeEvent } from '../../api/gridviewPanelApi'; import { SizeEvent } from '../../api/gridviewPanelApi';
import { setupMockWindow } from '../__mocks__/mockWindow'; import { setupMockWindow } from '../__mocks__/mockWindow';
import { exhaustMicrotaskQueue } from '../__test_utils__/utils';
class PanelContentPartTest implements IContentRenderer { class PanelContentPartTest implements IContentRenderer {
element: HTMLElement = document.createElement('div'); element: HTMLElement = document.createElement('div');
@ -141,109 +140,114 @@ describe('dockviewComponent', () => {
expect(dockview.element.className).toBe('test-b test-c'); expect(dockview.element.className).toBe('test-b test-c');
}); });
// describe('memory leakage', () => { describe('memory leakage', () => {
// beforeEach(() => { beforeEach(() => {
// window.open = () => fromPartial<Window>({ window.open = () => setupMockWindow();
// addEventListener: jest.fn(), });
// close: jest.fn(),
// });
// });
// test('event leakage', () => { test('event leakage', async () => {
// Emitter.setLeakageMonitorEnabled(true); Emitter.setLeakageMonitorEnabled(true);
// dockview = new DockviewComponent({ dockview = new DockviewComponent(container, {
// parentElement: container, createComponent(options) {
// components: { switch (options.name) {
// default: PanelContentPartTest, case 'default':
// }, return new PanelContentPartTest(
// }); options.id,
options.name
);
default:
throw new Error(`unsupported`);
}
},
className: 'test-a test-b',
});
// dockview.layout(500, 1000); dockview.layout(500, 1000);
// const panel1 = dockview.addPanel({ const panel1 = dockview.addPanel({
// id: 'panel1', id: 'panel1',
// component: 'default', component: 'default',
// }); });
// const panel2 = dockview.addPanel({ const panel2 = dockview.addPanel({
// id: 'panel2', id: 'panel2',
// component: 'default', component: 'default',
// }); });
// dockview.removePanel(panel2); dockview.removePanel(panel2);
// const panel3 = dockview.addPanel({ const panel3 = dockview.addPanel({
// id: 'panel3', id: 'panel3',
// component: 'default', component: 'default',
// position: { position: {
// direction: 'right', direction: 'right',
// referencePanel: 'panel1', referencePanel: 'panel1',
// }, },
// }); });
// const panel4 = dockview.addPanel({ const panel4 = dockview.addPanel({
// id: 'panel4', id: 'panel4',
// component: 'default', component: 'default',
// position: { position: {
// direction: 'above', direction: 'above',
// }, },
// }); });
// dockview.moveGroupOrPanel( panel4.api.group.api.moveTo({
// panel4.group, group: panel3.api.group,
// panel3.group.id, position: 'center',
// panel3.id, });
// 'center'
// );
// dockview.addPanel({ dockview.addPanel({
// id: 'panel5', id: 'panel5',
// component: 'default', component: 'default',
// floating: true, floating: true,
// }); });
// const panel6 = dockview.addPanel({ const panel6 = dockview.addPanel({
// id: 'panel6', id: 'panel6',
// component: 'default', component: 'default',
// position: { position: {
// referencePanel: 'panel5', referencePanel: 'panel5',
// direction: 'within', direction: 'within',
// }, },
// }); });
// dockview.addFloatingGroup(panel4.api.group); dockview.addFloatingGroup(panel4.api.group);
// dockview.addPopoutGroup(panel6); await dockview.addPopoutGroup(panel2);
// dockview.moveGroupOrPanel( panel1.api.group.api.moveTo({
// panel1.group, group: panel6.api.group,
// panel6.group.id, position: 'center',
// panel6.id, });
// 'center'
// );
// dockview.moveGroupOrPanel( panel4.api.group.api.moveTo({
// panel4.group, group: panel6.api.group,
// panel6.group.id, position: 'center',
// panel6.id, });
// 'center'
// );
// dockview.dispose(); dockview.dispose();
// if (Emitter.MEMORY_LEAK_WATCHER.size > 0) { if (Emitter.MEMORY_LEAK_WATCHER.size > 0) {
// for (const entry of Array.from( console.warn(
// Emitter.MEMORY_LEAK_WATCHER.events `${Emitter.MEMORY_LEAK_WATCHER.size} undisposed resources`
// )) { );
// console.log('disposal', entry[1]);
// }
// throw new Error('not all listeners disposed');
// }
// Emitter.setLeakageMonitorEnabled(false); for (const entry of Array.from(
// }); Emitter.MEMORY_LEAK_WATCHER.events
// }); )) {
console.log('disposal', entry[1]);
}
throw new Error(
`${Emitter.MEMORY_LEAK_WATCHER.size} undisposed resources`
);
}
Emitter.setLeakageMonitorEnabled(false);
});
});
test('duplicate panel', () => { test('duplicate panel', () => {
dockview.layout(500, 1000); dockview.layout(500, 1000);

View File

@ -409,6 +409,7 @@ export class DockviewComponent
this._onDidRemoveGroup, this._onDidRemoveGroup,
this._onDidActiveGroupChange, this._onDidActiveGroupChange,
this._onUnhandledDragOverEvent, this._onUnhandledDragOverEvent,
this._onDidMaximizedGroupChange,
this.onDidViewVisibilityChangeMicroTaskQueue(() => { this.onDidViewVisibilityChangeMicroTaskQueue(() => {
this.updateWatermark(); this.updateWatermark();
}), }),
@ -576,6 +577,11 @@ export class DockviewComponent
this.updateWatermark(); this.updateWatermark();
} }
override dispose(): void {
this.clear(); // explicitly clear the layout before cleaning up
super.dispose();
}
override setVisible(panel: DockviewGroupPanel, visible: boolean): void { override setVisible(panel: DockviewGroupPanel, visible: boolean): void {
switch (panel.api.location.type) { switch (panel.api.location.type) {
case 'grid': case 'grid':

View File

@ -506,7 +506,9 @@ export class DockviewGroupPanelModel
this._onDidAddPanel, this._onDidAddPanel,
this._onDidRemovePanel, this._onDidRemovePanel,
this._onDidActivePanelChange, this._onDidActivePanelChange,
this._onUnhandledDragOverEvent this._onUnhandledDragOverEvent,
this._onDidPanelTitleChange,
this._onDidPanelParametersChange
); );
} }

View File

@ -205,6 +205,8 @@ export abstract class BaseGrid<T extends IGridPanelView>
)(() => { )(() => {
this._bufferOnDidLayoutChange.fire(); this._bufferOnDidLayoutChange.fire();
}), }),
this._onDidMaximizedChange,
this._onDidViewVisibilityChangeMicroTaskQueue,
this._bufferOnDidLayoutChange this._bufferOnDidLayoutChange
); );
} }