Fix xterm.js resource leaks in split pane (#3409)

This commit is contained in:
Igor Sadikov 2019-01-18 17:58:09 -05:00 committed by CHaBou
parent ee8e95b8f1
commit 3881703e01
2 changed files with 25 additions and 19 deletions

View file

@ -76,13 +76,11 @@ export default class Term extends React.PureComponent {
constructor(props) {
super(props);
props.ref_(props.uid, this);
this.termRef = null;
this.termWrapperRef = null;
this.termRect = null;
this.onOpen = this.onOpen.bind(this);
this.onWindowResize = this.onWindowResize.bind(this);
this.onWindowPaste = this.onWindowPaste.bind(this);
this.onTermRef = this.onTermRef.bind(this);
this.onTermWrapperRef = this.onTermWrapperRef.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.termOptions = {};
@ -94,15 +92,21 @@ export default class Term extends React.PureComponent {
this.termOptions = getTermOptions(props);
this.term = props.term || new Terminal(this.termOptions);
this.term.attachCustomKeyEventHandler(this.keyboardHandler);
this.term.open(this.termRef);
this.term.webLinksInit();
this.term.winptyCompatInit();
if (props.term) {
//We need to set options again after reattaching an existing term
Object.keys(this.termOptions).forEach(option => this.term.setOption(option, this.termOptions[option]));
// The parent element for the terminal is attached and removed manually so
// that we can preserve it across mounts and unmounts of the component
let parent = props.term ? props.term._core._parent : document.createElement('div');
parent.className = 'term_fit term_term';
this.termWrapperRef.appendChild(parent);
if (!props.term) {
this.term.attachCustomKeyEventHandler(this.keyboardHandler);
this.term.open(parent);
this.term.webLinksInit();
this.term.winptyCompatInit();
}
if (this.props.isTermActive) {
this.term.focus();
}
@ -302,12 +306,9 @@ export default class Term extends React.PureComponent {
this.termWrapperRef = component;
}
onTermRef(component) {
this.termRef = component;
}
componentWillUnmount() {
terms[this.props.uid] = null;
this.termWrapperRef.removeChild(this.term._core._parent);
this.props.ref_(this.props.uid, null);
// to clean up the terminal, we remove the listeners
@ -334,12 +335,10 @@ export default class Term extends React.PureComponent {
onMouseUp={this.onMouseUp}
>
{this.props.customChildrenBefore}
<div ref={this.onTermWrapperRef} className="term_fit term_wrapper">
<div ref={this.onTermRef} className="term_fit term_term" />
</div>
<div ref={this.onTermWrapperRef} className="term_fit term_wrapper" />
{this.props.customChildren}
<style jsx>{`
<style jsx global>{`
.term_fit {
display: block;
width: 100%;

View file

@ -42,8 +42,6 @@ export default class Terms extends React.Component {
onRef(uid, term) {
if (term) {
this.terms[uid] = term;
} else if (!this.props.sessions[uid]) {
delete this.terms[uid];
}
}
@ -71,6 +69,15 @@ export default class Terms extends React.Component {
});
}
componentDidUpdate(prevProps) {
for (let uid in prevProps.sessions) {
if (!this.props.sessions[uid]) {
this.terms[uid].term.dispose();
delete this.terms[uid];
}
}
}
componentWillUnmount() {
this.props.ref_(null);
}