fix(widget): guard async continuations against post-disconnect null access#257
Draft
tiagozip wants to merge 1 commit into
Draft
fix(widget): guard async continuations against post-disconnect null access#257tiagozip wants to merge 1 commit into
tiagozip wants to merge 1 commit into
Conversation
…ccess When the widget is unmounted while an async proof-of-work or speculative redeem is in flight, disconnectedCallback nullifies #speculative before those async continuations resume. Add null guards at every await point in #speculativeSolveAll, #speculativeRedeem, and the solve() progress interval so that any in-flight work becomes a no-op after disconnect instead of throwing an unhandled TypeError. Fixes #252 https://claude.ai/code/session_01Mo2kqFdchfDXXsJsenvxJ6
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
cap | e4b0ed6 | May 16 2026, 09:12 AM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
Closes #252.
When
<cap-widget>is unmounted (or remounted via a Reactkeychange) while an async proof-of-work solve or speculative redeem is in flight,disconnectedCallback→cleanup()nullifiesthis.#speculativebefore those async continuations resume. Because the cleanup also callsnotify()(which resolves any pendingonSettledpromises), the subsequent microtasks resume withthis.#speculative === nulland throw:How I reproduced it
What I changed
Added
if (!this.#speculative) return;guards at every async resumption point across three methods:#speculativeSolveAll— afterawait Promise.all(...)(the batch solve), after the speculative yieldsetTimeout, after the while loop, and inside the per-result.then()callback.#speculativeRedeem— at method entry, after the instrumentationawait, after thecapFetchawait, after.json(), and at the top of thecatchblock.solve()— in thesetIntervalprogress callback (clears the interval and returns early), and immediately afterawait new Promise(resolve => this.#speculative.onSettled(resolve)).No new fields are introduced; the existing
cleanup()already nullifies#speculative, which acts as the disconnection sentinel.Caveats / edge cases
solve()main path (non-speculative branch) doesn't access#speculativeafter its awaits, so it didn't need changes.finally { this.#solving = false; }block insolve()still runs correctly on an earlyreturn.— Claude, on behalf of Tiago
Generated by Claude Code