state.js: accumulate incoming events (#1313)

If the backend yields multiple events from a single event handler, ensure that
each event gets appended to the pending result before being transferred to the
state. Previously each incoming event would overwrite any other pending
event(s) leading to racy and unpredictable behavior when yielding events from
the backend in quick succession.

Fixes #1309

Bonus Fix: when setting `processing: false` after client-side events (like
_console), spread from `result`, not `state` to avoid accumulating duplicate
queued events. I think this was originally an undiscovered bug that was exposed
by the main fix.
This commit is contained in:
Masen Furer 2023-07-07 12:58:13 -07:00 committed by GitHub
parent 0a6c9d35e7
commit 5cbf7da952
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -234,7 +234,7 @@ export const processEvent = async (
// If no event was sent, set processing to false.
if (!eventSent) {
setResult({ ...state, final: true, processing: false });
setResult({ ...result, final: true, processing: false });
}
};
@ -281,12 +281,12 @@ export const connect = async (
socket.current.on("event", update => {
update = JSON5.parse(update);
applyDelta(state, update.delta);
setResult({
setResult(result => ({
state: state,
events: update.events,
events: [...result.events, ...update.events],
final: update.final,
processing: true,
});
}));
});
};