Skip to content

fix(runtime): claim blocked select cases atomically - #180

Merged
paralin merged 1 commit into
masterfrom
fix/select-atomic
Sep 8, 2026
Merged

fix(runtime): claim blocked select cases atomically#180
paralin merged 1 commit into
masterfrom
fix/select-atomic

Conversation

@paralin

@paralin paralin commented Sep 8, 2026

Copy link
Copy Markdown
Member

Blocked select branches could consume multiple channel values before Promise.race chose a winner. Claim selection synchronously at channel transfer, cancel losing cases before further transfers, and prevent a select from rendezvousing with itself.

Validation: 33 runtime contract tests, compiled select compliance fixture, TypeScript typecheck, and JavaScript lint pass. The formerly intermittent downstream WebKit recovery test passes 50 repetitions in Chromium and WebKit. Go lint could not read the installed Go 1.27 export format; its binary supports an older format.

Signed-off-by: Christian Stewart <christian@aperture.us>
Copilot AI lite review requested due to automatic review settings September 8, 2026 07:38
@paralin
paralin merged commit 9f5f25f into master Sep 8, 2026
9 checks passed
@paralin
paralin deleted the fix/select-atomic branch September 8, 2026 07:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It changes core channel/select concurrency semantics and scheduling behavior in the runtime, which is high-impact and warrants final human verification beyond automated review.

Pull request overview

This PR fixes a race in the GoScript runtime select implementation where blocked branches could consume multiple channel values before Promise.race resolved, by claiming selection synchronously at the channel transfer point, aborting/withdrawing losing cases immediately, and preventing a select from rendezvousing with itself.

Changes:

  • Extend selectReceive/selectSend with an onCommit hook and use an AbortController to cancel/withdraw losing cases atomically at commit time.
  • Adjust channel rendezvous/wakeup scheduling to avoid extra microtask deferrals that allowed other transfers to slip in before commit.
  • Add regression coverage in both runtime contract tests and the select compliance fixture (plus expected output), and document the updated selectStatement behavior.
File summaries
File Description
gs/builtin/channel.ts Implements atomic commit for blocked select cases via onCommit + abort/withdrawal, and enforces “no self-rendezvous” within a single select.
gs/builtin/runtime-contract.test.ts Adds targeted runtime contract tests covering losing-branch preservation, send withdrawal, and self-rendezvous prevention.
tests/tests/select_statement/select_statement.go Extends the Go compliance fixture with concurrent send/select scenarios to detect value loss/double-consumption.
tests/tests/select_statement/select_statement.gs.ts Updates the compiled TypeScript fixture to match the new Go test and validate runtime behavior end-to-end.
tests/tests/select_statement/expected.log Adds the new expected compliance output line for the added test case.
design/DESIGN.md Documents the updated blocked-select claiming/cancellation behavior and self-rendezvous rule.
Review details
  • Files reviewed: 5/6 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants