Change:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: Yes/No <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --- VS Code Version: Head OS Version: Browser back and forth between the comments panel and some other panel. This will trigger this warning: The DOM nodes for each comment thread are recreated whenever the comment is displayed, see: The new nodes are registered for cleanup, however to the lifecycle of the CommentThreadBody: This means they are eventually cleaned up, but only when the entire comment thread is cleaned up. There is already a separate commentsDisposable, which seems to be used to dispose comments when they are deleted in updateCommentThread. But not when the display function recreates the elements.
the file is for the comment widget in the editor, not the "Comments" view that shows in the panel. If you share the full warning that you see then it might have some pointers wo where the leak is coming from.
Here is what I have: What the same problem not also occur for editors? I assume is also called when you switch between editors, maybe even when you scroll comment in and out of view. If that recreates the DOM, but does not ever clean up the listeners, should would that explain the error I see?
I think this is another menu listener leak: This is similar to the issue that will solve. The issue in both cases is that each node (tree nodes in the linked issue, individual comments here) creates a menu and then listens on the menu change event. The solution here is mostly likely similar to Don't listen on each menu's change event and instead collect all the relevant context names and have one listener on the thread or .
It looks like there is a second, more quickly occuring issue, with comment nodes not getting disposed properly too.
I found several leaks. To repro the leaks that I've fixed: Create a comment with the GitHub Pull Requests extension Add 10 replies to the comment. I did not address the "leak" (not so much a leak and intentionally having lots of listeners) in as it should only happen with you have over a hundred comments. please try with and see if your issue persists.
Thanks Alex for taking a look and sending a fix. I am happy to try it out, unfortunately you catch me on my way out for a week of vacation, so it will take me a good week to get back to you. Probably don't wait for me with your PR.
Thanks for the heads up and have a good vacation!
Hi Were you able to verify if this fixed works for you? Thanks!
you can also verify following the steps in !
Sorry for the delay. I did just run the test and can confirm that this seems to have solved our problem. Thanks!

Discussion:
super(); this._domNode = dom.$('div.review-comment'); <del> this._contextKeyService = contextKeyService.createScoped(this._domNode); </del> <ins> this._contextKeyService = this._register(contextKeyService.createScoped(this._domNode)); </ins> this._commentContextValue = CommentContextKeys.commentContext.bindTo(this._contextKeyService); if (this.comment.contextValue) { this._commentContextValue.set(this.comment.contextValue);

import * as dom from 'vs/base/browser/dom'; import * as nls from 'vs/nls'; <del> import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; </del> <ins> import { Disposable, DisposableMap, DisposableStore } from 'vs/base/common/lifecycle'; </ins> import * as languages from 'vs/editor/common/languages'; import { Emitter } from 'vs/base/common/event'; import { ICommentService } from 'vs/workbench/contrib/comments/browser/commentService';

private _onDidResize = new Emitter<dom.Dimension>(); onDidResize = this._onDidResize.event; <del> private _commentDisposable = new Map<CommentNode<T>, IDisposable>(); </del> <ins> private _commentDisposable = new DisposableMap<CommentNode<T>, DisposableStore>(); </ins> private _markdownRenderer: MarkdownRenderer; get length() {

} })); <ins> this._commentDisposable.clearAndDisposeAll(); </ins> this._commentElements = []; if (this._commentThread.comments) { for (const comment of this._commentThread.comments) {

// del removed elements for (let i = commentElementsToDel.length - 1; i >= 0; i--) { const commentToDelete = commentElementsToDel[i]; <del> this._commentDisposable.get(commentToDelete)?.dispose(); this._commentDisposable.delete(commentToDelete); </del> <ins> this._commentDisposable.deleteAndDispose(commentToDelete); </ins> this._commentElements.splice(commentElementsToDelIndex[i], 1); commentToDelete.domNode.remove();

this._parentCommentThreadWidget, this._markdownRenderer) as unknown as CommentNode<T>; <del> this._register(newCommentNode); this._commentDisposable.set(newCommentNode, newCommentNode.onDidClick(clickedNode => </del> <ins> const disposables: DisposableStore = new DisposableStore(); disposables.add(newCommentNode.onDidClick(clickedNode => </ins> this._setFocusedComment(this._commentElements.findIndex(commentNode => commentNode.comment.uniqueIdInThread === clickedNode.comment.uniqueIdInThread)) )); <ins> disposables.add(newCommentNode); this._commentDisposable.set(newCommentNode, disposables); </ins> return newCommentNode; }

this._resizeObserver = null; } <del> this._commentDisposable.forEach(v => v.dispose()); </del> <ins> this._commentDisposable.dispose(); </ins> } }