Repository: microsoft/vscode (TypeScript)
Date: 2023-02-08 15:35:24+00:00
Task type: Bug Fix

Issue:
 TypeError: we is not iterable
* today's insiders
* seeing the errors below
* this is [this `e`](https://github.com/microsoft/vscode/blob/990a496681948ec274da5503b35cd49a7d06c0a2/src/vs/workbench/browser/parts/editor/editorStatus.ts#L627) being not an array

```
 ERR we is not iterable: TypeError: we is not iterable
    at vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2282:1203
    at f.invoke (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:145)
    at n.deliver (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:2066)
    at c.fire (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:1704)
    at Ce (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:84:27982)
    at Object.onWillRemoveListener (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:84:28130)
    at vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:1378
    at o.dispose (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:19:31457)
    at u (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:19:29530)
    at h.clear (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:19:30160)
    at ne.X (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2282:762)
    at vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2281:27650
    at f.invoke (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:145)
    at n.deliver (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:2066)
    at c.fire (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:1704)
    at k.z (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2296:99809)
    at k.y (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2296:99717)
    at vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2296:99961
    at f.invoke (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:145)
    at n.deliver (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:2066)
    at c.fire (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:86:1704)
    at vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:2468:13571
    at async E.D (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:1204:28435)
    at async E.openCodeEditor (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:687:39070)
    at async pr.m (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:742:63389)
    at async pr.l (vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js:742:63150)
```


Issue discussion:
Repro is to change editors:

![image](https://user-images.githubusercontent.com/2193314/217574320-e40dc2f2-9054-4685-8b7d-fd5d84d2eb1f.png)


Solution patch:
diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts
--- a/src/vs/base/common/event.ts
+++ b/src/vs/base/common/event.ts
@@ -254,7 +254,7 @@ export namespace Event {
 				});
 			},
 			onWillRemoveListener() {
-				if (flushOnListenerRemove) {
+				if (flushOnListenerRemove && numDebouncedCalls > 0) {
 					doFire?.();
 				}
 			},


Test patch:
diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts
--- a/src/vs/base/test/common/event.test.ts
+++ b/src/vs/base/test/common/event.test.ts
@@ -1048,6 +1048,26 @@ suite('Event utils', () => {
 	});
 
 	suite('accumulate', () => {
+		test('should not fire after a listener is disposed with undefined or []', async () => {
+			const eventEmitter = new Emitter<number>();
+			const event = eventEmitter.event;
+			const accumulated = Event.accumulate(event, 0);
+
+			const calls1: number[][] = [];
+			const calls2: number[][] = [];
+			const listener1 = accumulated((e) => calls1.push(e));
+			accumulated((e) => calls2.push(e));
+
+			eventEmitter.fire(1);
+			await timeout(1);
+			assert.deepStrictEqual(calls1, [[1]]);
+			assert.deepStrictEqual(calls2, [[1]]);
+
+			listener1.dispose();
+			await timeout(1);
+			assert.deepStrictEqual(calls1, [[1]]);
+			assert.deepStrictEqual(calls2, [[1]], 'should not fire after a listener is disposed with undefined or []');
+		});
 		test('should accumulate a single event', async () => {
 			const eventEmitter = new Emitter<number>();
 			const event = eventEmitter.event;
@@ -1234,7 +1254,6 @@ suite('Event utils', () => {
 			assert.deepStrictEqual(calls, [1], 'should fire with the first event, not the second (after listener dispose)');
 		});
 
-
 		test('should flush events when the emitter is disposed', async () => {
 			const emitter = new Emitter<number>();
 			const debounced = Event.debounce(emitter.event, (l, e) => l ? l + 1 : 1, 0);