bug: duplicate container HTML Element

This commit is contained in:
mathuo 2025-01-10 20:55:25 +00:00
parent 872ec7cba9
commit 1a3c6ea7db
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
13 changed files with 91 additions and 106 deletions

View File

@ -105,6 +105,21 @@ class ClassUnderTest extends BaseGrid<TestPanel> {
} }
describe('baseComponentGridview', () => { describe('baseComponentGridview', () => {
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const cut = new ClassUnderTest(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: true,
});
cut.dispose();
expect(container.parentElement).toBe(root);
});
test('that .layout(...) force flag works', () => { test('that .layout(...) force flag works', () => {
const cut = new ClassUnderTest(document.createElement('div'), { const cut = new ClassUnderTest(document.createElement('div'), {
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,

View File

@ -67,6 +67,27 @@ describe('componentPaneview', () => {
container.className = 'container'; container.className = 'container';
}); });
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.dispose();
expect(container.parentElement).toBe(root);
});
test('vertical panels', () => { test('vertical panels', () => {
const disposables = new CompositeDisposable(); const disposables = new CompositeDisposable();
@ -293,40 +314,6 @@ describe('componentPaneview', () => {
disposable.dispose(); disposable.dispose();
}); });
test('dispose of paneviewComponent', () => {
expect(container.childNodes.length).toBe(0);
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(1000, 1000);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel 2',
});
expect(container.childNodes.length).toBeGreaterThan(0);
paneview.dispose();
expect(container.childNodes.length).toBe(0);
});
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const paneview = new PaneviewComponent(container, { const paneview = new PaneviewComponent(container, {
createComponent: (options) => { createComponent: (options) => {
@ -606,10 +593,10 @@ describe('componentPaneview', () => {
className: 'test-a test-b', className: 'test-a test-b',
}); });
expect(paneview.element.className).toBe('container test-a test-b'); expect(paneview.element.className).toBe('test-a test-b');
paneview.updateOptions({ className: 'test-b test-c' }); paneview.updateOptions({ className: 'test-b test-c' });
expect(paneview.element.className).toBe('container test-b test-c'); expect(paneview.element.className).toBe('test-b test-c');
}); });
}); });

View File

@ -26,6 +26,28 @@ describe('componentSplitview', () => {
container.className = 'container'; container.className = 'container';
}); });
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.dispose();
expect(container.parentElement).toBe(root);
});
test('event leakage', () => { test('event leakage', () => {
Emitter.setLeakageMonitorEnabled(true); Emitter.setLeakageMonitorEnabled(true);
@ -451,39 +473,6 @@ describe('componentSplitview', () => {
disposable.dispose(); disposable.dispose();
}); });
test('dispose of splitviewComponent', () => {
expect(container.childNodes.length).toBe(0);
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
splitview.addPanel({
id: 'panel1',
component: 'default',
});
splitview.addPanel({
id: 'panel2',
component: 'default',
});
expect(container.childNodes.length).toBeGreaterThan(0);
splitview.dispose();
expect(container.childNodes.length).toBe(0);
});
test('panel is disposed of when component is disposed', () => { test('panel is disposed of when component is disposed', () => {
const splitview = new SplitviewComponent(container, { const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
@ -736,10 +725,10 @@ describe('componentSplitview', () => {
className: 'test-a test-b', className: 'test-a test-b',
}); });
expect(splitview.element.className).toBe('container test-a test-b'); expect(splitview.element.className).toBe('test-a test-b');
splitview.updateOptions({ className: 'test-b test-c' }); splitview.updateOptions({ className: 'test-b test-c' });
expect(splitview.element.className).toBe('container test-b test-c'); expect(splitview.element.className).toBe('test-b test-c');
}); });
}); });

View File

@ -368,8 +368,8 @@ export class DockviewComponent
return this._floatingGroups; return this._floatingGroups;
} }
constructor(parentElement: HTMLElement, options: DockviewComponentOptions) { constructor(container: HTMLElement, options: DockviewComponentOptions) {
super(parentElement, { super(container, {
proportionalLayout: true, proportionalLayout: true,
orientation: Orientation.HORIZONTAL, orientation: Orientation.HORIZONTAL,
styles: options.hideBorders styles: options.hideBorders

View File

@ -155,14 +155,17 @@ export abstract class BaseGrid<T extends IGridPanelView>
this.gridview.locked = value; this.gridview.locked = value;
} }
constructor(parentElement: HTMLElement, options: BaseGridOptions) { constructor(container: HTMLElement, options: BaseGridOptions) {
super(parentElement, options.disableAutoResizing); super(document.createElement('div'), options.disableAutoResizing);
this.element.style.height = '100%'; this.element.style.height = '100%';
this.element.style.width = '100%'; this.element.style.width = '100%';
this._classNames = new Classnames(this.element); this._classNames = new Classnames(this.element);
this._classNames.setClassNames(options.className ?? ''); this._classNames.setClassNames(options.className ?? '');
// the container is owned by the third-party, do not modify/delete it
container.appendChild(this.element);
this.gridview = new Gridview( this.gridview = new Gridview(
!!options.proportionalLayout, !!options.proportionalLayout,
options.styles, options.styles,

View File

@ -113,8 +113,8 @@ export class GridviewComponent
this._deserializer = value; this._deserializer = value;
} }
constructor(parentElement: HTMLElement, options: GridviewComponentOptions) { constructor(container: HTMLElement, options: GridviewComponentOptions) {
super(parentElement, { super(container, {
proportionalLayout: options.proportionalLayout ?? true, proportionalLayout: options.proportionalLayout ?? true,
orientation: options.orientation, orientation: options.orientation,
styles: options.hideBorders styles: options.hideBorders

View File

@ -195,8 +195,10 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent {
return this._options; return this._options;
} }
constructor(parentElement: HTMLElement, options: PaneviewComponentOptions) { constructor(container: HTMLElement, options: PaneviewComponentOptions) {
super(parentElement, options.disableAutoResizing); super(document.createElement('div'), options.disableAutoResizing);
this.element.style.height = '100%';
this.element.style.width = '100%';
this.addDisposables( this.addDisposables(
this._onDidLayoutChange, this._onDidLayoutChange,
@ -210,6 +212,9 @@ export class PaneviewComponent extends Resizable implements IPaneviewComponent {
this._classNames = new Classnames(this.element); this._classNames = new Classnames(this.element);
this._classNames.setClassNames(options.className ?? ''); this._classNames.setClassNames(options.className ?? '');
// the container is owned by the third-party, do not modify/delete it
container.appendChild(this.element);
this._options = options; this._options = options;
this.paneview = new Paneview(this.element, { this.paneview = new Paneview(this.element, {

View File

@ -32,7 +32,7 @@ export interface ISplitviewStyles {
} }
export interface SplitViewOptions { export interface SplitViewOptions {
orientation: Orientation; orientation?: Orientation;
descriptor?: ISplitViewDescriptor; descriptor?: ISplitViewDescriptor;
proportionalLayout?: boolean; proportionalLayout?: boolean;
styles?: ISplitviewStyles; styles?: ISplitviewStyles;
@ -225,7 +225,7 @@ export class Splitview {
private readonly container: HTMLElement, private readonly container: HTMLElement,
options: SplitViewOptions options: SplitViewOptions
) { ) {
this._orientation = options.orientation; this._orientation = options.orientation ?? Orientation.VERTICAL;
this.element = this.createContainer(); this.element = this.createContainer();
this.margin = options.margin ?? 0; this.margin = options.margin ?? 0;

View File

@ -155,15 +155,17 @@ export class SplitviewComponent
: this.splitview.orthogonalSize; : this.splitview.orthogonalSize;
} }
constructor( constructor(container: HTMLElement, options: SplitviewComponentOptions) {
parentElement: HTMLElement, super(document.createElement('div'), options.disableAutoResizing);
options: SplitviewComponentOptions this.element.style.height = '100%';
) { this.element.style.width = '100%';
super(parentElement, options.disableAutoResizing);
this._classNames = new Classnames(this.element); this._classNames = new Classnames(this.element);
this._classNames.setClassNames(options.className ?? ''); this._classNames.setClassNames(options.className ?? '');
// the container is owned by the third-party, do not modify/delete it
container.appendChild(this.element);
this._options = options; this._options = options;
this.splitview = new Splitview(this.element, options); this.splitview = new Splitview(this.element, options);

View File

@ -318,11 +318,7 @@ export const DockviewReact = React.forwardRef(
}, [props.prefixHeaderActionsComponent]); }, [props.prefixHeaderActionsComponent]);
return ( return (
<div <div style={{ height: '100%', width: '100%' }} ref={domRef}>
className={props.className}
style={{ height: '100%', width: '100%' }}
ref={domRef}
>
{portals} {portals}
</div> </div>
); );

View File

@ -126,11 +126,7 @@ export const GridviewReact = React.forwardRef(
}, [props.components]); }, [props.components]);
return ( return (
<div <div style={{ height: '100%', width: '100%' }} ref={domRef}>
className={props.className}
style={{ height: '100%', width: '100%' }}
ref={domRef}
>
{portals} {portals}
</div> </div>
); );

View File

@ -176,11 +176,7 @@ export const PaneviewReact = React.forwardRef(
}, [props.onDidDrop]); }, [props.onDidDrop]);
return ( return (
<div <div style={{ height: '100%', width: '100%' }} ref={domRef}>
className={props.className}
style={{ height: '100%', width: '100%' }}
ref={domRef}
>
{portals} {portals}
</div> </div>
); );

View File

@ -126,11 +126,7 @@ export const SplitviewReact = React.forwardRef(
}, [props.components]); }, [props.components]);
return ( return (
<div <div style={{ height: '100%', width: '100%' }} ref={domRef}>
className={props.className}
style={{ height: '100%', width: '100%' }}
ref={domRef}
>
{portals} {portals}
</div> </div>
); );