Fix link event listener leak

The bug here is that _clearCurrentLink was being called only on the
line(s) that changed, but _askForLink was then being triggered
regardless. This caused more onRenderedViewportChange listeners to be
registered and for the thread blocking to get exponentially worse.

Fixes #4341
This commit is contained in:
Daniel Imms
2022-12-20 14:58:35 -08:00
parent 3142460db5
commit f28c21eb77
+16 -8
View File
@@ -309,19 +309,27 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
}
});
// Add listener for rerendering
// Listen to viewport changes re-render the link under the cursor when the viewport line
// changes
if (this._renderService) {
this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange(e => {
// Sanity check, this shouldn't happen in practice as this listener would be disposed
if (!this._currentLink) {
return;
}
// When start is 0 a scroll most likely occurred, make sure links above the fold also get
// cleared.
const start = e.start === 0 ? 0 : e.start + 1 + this._bufferService.buffer.ydisp;
const oldEvent = this._currentLink ? this._lastMouseEvent : undefined;
this._clearCurrentLink(start, e.end + 1 + this._bufferService.buffer.ydisp);
if (oldEvent && this._element) {
// re-eval previously active link after changes
const position = this._positionFromMouseEvent(oldEvent, this._element, this._mouseService!);
if (position) {
this._askForLink(position, false);
const end = this._bufferService.buffer.ydisp + 1 + e.end;
// Only clear the link if the viewport change happened on this line
if (this._currentLink.link.range.start.y >= start && this._currentLink.link.range.end.y <= end) {
this._clearCurrentLink(start, end);
if (this._lastMouseEvent && this._element) {
// re-eval previously active link after changes
const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element, this._mouseService!);
if (position) {
this._askForLink(position, false);
}
}
}
}));