Fix two big DOM leaks which were locking Chrome solid.

pillifyLinks leaked Pill components, which if they contained a BaseAvatar
would leak a whole DOM tree retained by the BaseAvatar's onClientSync
event listener.  This tracks the Pill containers so they can be unmounted
via unmountPills.

BasicMessageComposer set an event listener on selectionchange in onFocus
which leaked if onBlur wasn't called.  This removes it in unmount.

We've also seen Velociraptor retaining full DOM trees from RRs, which
this doesn't address as the leak is probably within Velocity, and the plan
is to replace it with CSS animations.

Should fix https://github.com/vector-im/riot-web/issues/12417
This commit is contained in:
Matthew Hodgson 2020-02-22 23:51:30 +00:00
parent d088879c12
commit 7696f704b2
4 changed files with 44 additions and 7 deletions

View file

@ -30,7 +30,7 @@ import { _t } from '../../../languageHandler';
import * as ContextMenu from '../../structures/ContextMenu';
import SettingsStore from "../../../settings/SettingsStore";
import ReplyThread from "../elements/ReplyThread";
import {pillifyLinks} from '../../../utils/pillify';
import {pillifyLinks, unmountPills} from '../../../utils/pillify';
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
import {toRightOf} from "../../structures/ContextMenu";
@ -92,6 +92,7 @@ export default createReactClass({
componentDidMount: function() {
this._unmounted = false;
this._pills = [];
if (!this.props.editState) {
this._applyFormatting();
}
@ -103,7 +104,7 @@ export default createReactClass({
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
// are still sent as plaintext URLs. If these are ever pillified in the composer,
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
pillifyLinks([this._content.current], this.props.mxEvent);
pillifyLinks([this._content.current], this.props.mxEvent, this._pills);
HtmlUtils.linkifyElement(this._content.current);
this.calculateUrlPreview();
@ -146,6 +147,7 @@ export default createReactClass({
componentWillUnmount: function() {
this._unmounted = true;
unmountPills(this._pills);
},
shouldComponentUpdate: function(nextProps, nextState) {