Fix RemoveEventDispatch using wrong index in multi-listener branch (#7796)

The outer loop binds `i` as the index into the `ids` array and derives the dispatch key as `id = ids[i]`. The single-listener cleanup branch correctly uses `id`, but the multi-listener branch indexed `obj.eventsDispatch[i]` instead of `obj.eventsDispatch[id]`. `obj.eventsDispatch[i]` is undefined (`i` is "0", "1", ...), so the inner `for...in` iterates zero times, `newList` stays empty, and the final assignment writes the empty array to a bogus numeric key. The real `obj.eventsDispatch[id]` array is left untouched, so the target that was supposed to be removed keeps receiving events. Bogus numeric keys also accumulate over time. Single-listener case (`length == 1`, `delete obj.eventsDispatch[id]`) was already correct, so the bug only triggers when two or more callers have subscribed to the same dispatch id. The sibling `RemoveAllEventDispatch` is not affected -- its outer loop already binds `i` to the dispatch key.

Adam DeWolf committed May 15, 2026 at 11:40 UTC c3ea0ed574ad5974e695a52a55a47fec9cb1e178
1 file changed +2 -2
meshcentral.js
+2 -2
@@ -2418,8 +2418,8 @@ function CreateMeshCentralServer(config, args) {
2418 delete obj.eventsDispatch[id];
2419 } else {
2420 const newList = []; // We create a new list so not to modify the original list. Allows this function to be called during an event dispatch.
2421 - for (var k in obj.eventsDispatch[i]) { if (obj.eventsDispatch[i][k] != target) { newList.push(obj.eventsDispatch[i][k]); } }
2422 - obj.eventsDispatch[i] = newList;
2421 + for (var k in obj.eventsDispatch[id]) { if (obj.eventsDispatch[id][k] != target) { newList.push(obj.eventsDispatch[id][k]); } }
2422 + obj.eventsDispatch[id] = newList;
2423 }
2424 }
2425 }