From cd2d71069225e40cc88778d248e502dbe47fe2f4 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 11 Oct 2023 21:03:43 +0200 Subject: [PATCH] Repair resolving of longer chains when reconnects happen --- packages/ws-relay/src/index.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/ws-relay/src/index.ts b/packages/ws-relay/src/index.ts index 03f7525..287eb43 100644 --- a/packages/ws-relay/src/index.ts +++ b/packages/ws-relay/src/index.ts @@ -193,7 +193,21 @@ export function boot(ds: Ref, debug: boolean = false, WebSocketConstructor?: typ }) when (e()) => { switch (resolved._variant) { case "accepted": - resolve(() => resolved.responderSession, more, k); + // Include a call to our e() in the e we pass in to the recursive + // call to resolve(). e() returning non-null is a precondition for + // the call; if that precondition ever changes, we want to NOT + // reevaluate the body of any assertion, so we should test it + // before we do. + // + // Concrete example of a problem that occurs if the `e() && ...` + // isn't there: connected all OK, the websocket disconnects, + // best.value gets set null, the previous assertion of ResolvePath + // at the end of the chain gets reevaluated because + // resolved.responderSession is still non-null, it includes + // best.value!, which is now null, boom. With the call to e(), we + // short circuit and so the assertion becomes null at that point. + // + resolve(() => e() && resolved.responderSession, more, k); break; case "Rejected": k(() => resolved);