Repository: vscode
Issue: Events and registered commands on TreeView are unreliable when refreshing treeview
Labels: bug,tree-views

<!-- ⚠️⚠️ Do Not Delete This! bug_report_template ⚠️⚠️ -->
<!-- Please read our Rules of Conduct: https://opensource.microsoft.com/codeofconduct/ -->
<!-- 🕮 Read our guide about submitting issues: https://github.com/microsoft/vscode/wiki/Submitting-Bugs-and-Suggestions -->
<!-- 🔎 Search existing issues to avoid creating duplicates. -->
<!-- 🧪 Test using the latest Insiders build to see if your issue has already been fixed: https://code.visualstudio.com/insiders/ -->
<!-- 💡 Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. -->
<!-- 🔧 Launch with `code --disable-extensions` to check. -->
Does this issue occur when all extensions are disabled?: No/unknown, because I need an extension to show the behavior in the first place.

<!-- 🪓 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: vscode-1.68.1
- OS Version: NixOS, with nixpkgs at revision `95e79164be1f7d883ed9ffda8b7d4ad3a17e6c1e`. Also seen with Ubuntu 20.04.

### Steps to Reproduce:

- Create an extension with a tree view as per the basic instructions at https://code.visualstudio.com/api/extension-guides/tree-view
- Refresh the tree _very_ often, by using some function like this (this makes it easier to reproduce):
    ```typescript
    async function refreshVeryOften(provider: NodeDependenciesProvider) {
        while (true) {
            await new Promise(f => setTimeout(f, 10)); // Wait 10ms, or some other small amount of time
            provider._onDidChangeTreeData.fire();
        }
    }
    ```
- Register some view actions, as per https://code.visualstudio.com/api/extension-guides/tree-view#view-actions
  - Let's say we add the `nodeDependencies.editEntry` command and add it to the `view/item/context`, as per the example.
- Register an `onDidExpandElement` and `onDidCollapseElement` listener that just run `console.log`. e.g.:
  ```typescript
  treeView.onDidExpandElement(event => console.log("onDidExpandElement", event));
  treeView.onDidCollapseElement(event => console.log("onDidCollapseElement", event));
  ```
- Start VS Code with the extension
- Try to run the added view action a couple of times
- Try to expand/collapse some tree items. It might take some times to reproduce


### Expected results

Despite the refreshes, I would expect the `onDidExpandElement` and `onDidCollapseElement` listeners to run and `console.log` the event. I would also expect the `nodeDependencies.editEntry` command to always run, and the function is passed a `TreeItem`.


### Actual result

- `onDidExpandElement` often does not get called, even though in the UI, I see that the tree view item is expanded
- `onDidCollapseElement` often does not get called, even though in the UI, I see that the tree view item is collapsed
- The `nodeDependencies.editEntry` registered command sometimes gets called with no arguments, i.e. no `TreeItem` is passed.

### Video example

This is in a different project, namely my [Semaphore CI extension](https://github.com/FPtje/vscode-semaphore-ci). Note that I have set the refresh delay to 2 seconds (2000ms).

![reproduce-buttonpress](https://user-images.githubusercontent.com/1202014/177007236-b1a8adc6-1f03-4de7-b7ab-3dd85b09cac5.gif)

Same for collapsing/expanding events. In the video you can see the element being expanded and collapsed, but not every change in the UI is shown in the events.
![collapsing](https://user-images.githubusercontent.com/1202014/177007314-901b57eb-ca78-486b-a3fb-d508c6adb2fe.gif)

### Speculated cause

I think some part of the tree view is removed before the new one is finished rendering, during a refresh. Either way it seems like some race/timing condition, because it sometimes happens and sometimes doesn't, even though the code path on the extension side should be exactly the same.