Skip to content

fix(popup): keep draining the port backlog after a handler throws - #111

Open
xgreenx wants to merge 2 commits into
mainfrom
fix/popup-backlog-drain
Open

xgreenx wants to merge 2 commits into
mainfrom
fix/popup-backlog-drain

Conversation

@xgreenx

@xgreenx xgreenx commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

A caller handler that threw during the backlog drain lost the rest of the backlog while later port values still arrived, breaking REQ-POPUP-MSG-03/04 and REQ-POPUP-CONT-02/06.

Changes

  • Drain survives a throw (ts/packages/popup/src/port.ts:261): a finally requeues the rest in a fresh microtask, still ahead of the port's tasks. The exception propagates untouched.
  • Handoff kept: the requeue runs only while this carrier still owns the port, so a handler that detaches hands the rest on.
  • Backlog test (port.test.ts:382): two throws, values delivered in order before the port's queued value. Fails on main.
  • Detach-then-throw test (port.test.ts:424): the rest goes to the next owner, one exception, no further delivery.
  • Bounded harness (port.test.ts:80): runs captured microtasks and fails on a self-requeueing loop instead of hanging.

Verified

  • pnpm test in ts/packages/popup: 156/156 pass. On main's port.ts, the backlog test fails, 1 of 21.
  • Dropping the ownership check from the finally fails the detach test with "microtasks never settle".
  • pnpm typecheck (popup), pnpm lint and pnpm fmt:check (ts) pass. Lint keeps one pre-existing info in packages/ceremony.

Not verified / known issues

  • No browser e2e run.
  • Microtasks a handler queued before it threw now run between backlog values. Port values still follow the whole backlog.

🤖 Generated with Claude Code

PortCarrier delivered its backlog in one microtask loop, so a caller
handler that threw ended the loop. The remaining backlog values were
never delivered while later port values still arrived, which breaks
REQ-POPUP-MSG-03/04 and REQ-POPUP-CONT-02/06. The rest now drains in a
fresh microtask, still ahead of the port's tasks, while the exception
propagates untouched.

Assisted-by: Claude Opus 5.5
Signed-off-by: xgreenx <xgreenx9999@gmail.com>
That path is the only one where the drain's finally sees another owner
of the port; without its ownership check the drain requeues itself
forever. The microtask harness moves into a shared, bounded helper so
such a loop fails the test instead of hanging the suite. The backlog
test also cites POPUP-KEEPER-001, which orders it ahead of the port.

Assisted-by: Claude Opus 5.5
Signed-off-by: xgreenx <xgreenx9999@gmail.com>

This branch has not been deployed

No deployments
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.

1 participant