Skip to content

script: a callback's one-item reply re-enters the multiplexer, and :else acts on its value - #412

Merged
shreeve merged 1 commit into
mainfrom
script/multiplexer-replies
Sep 24, 2026
Merged

shreeve merged 1 commit into
mainfrom
script/multiplexer-replies

Conversation

@shreeve

@shreeve shreeve commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Three multiplexer bugs in packages/script, each confirmed with a pin that fails without the fix.

  • A callback's reply was measured after it was replaced by the text it sent. dispatchVal sent the reply, then checked back.length, which by then was the sent string. So -> ['abc'] counted as three items and left the multiplexer, while the same ['abc'] written in the table re-entered it (and -> ['a'] worked only because one character has length 1). The :pure form had the same flaw. The check now measures the reply list, as the static branch does.
  • :else threw away its value's result. The branch set back = :else and discarded what dispatchVal returned, so :else: :redo ended the multiplexer at the first pause instead of listening on. It now takes the result like any other key.
  • :else: null never fired. The branch was guarded by elseVal?, but hasElse still put every read on the fast timeout, so the multiplexer polled every 0.25 s forever and never reached slow or bomb. The guard is now hasElse, and null leaves the multiplexer, as the README's own :else: null example assumes.

All three now match the engine's Ruby ancestor, which measured the reply array and assigned the :else value's result.

One visible change: when :else fires, the multiplexer returns its handler's value rather than the :else symbol (a string :else value, as in replace(), still returns :else). The existing :else fires test now expects its handler's true. The README's :else row says what the value does.

Verification: bun run test in packages/script, 66 passed (63 before; the three new pins fail or hang without the fix). The old and new engines give identical transcripts and results on seven unchanged cases (multi-step callback replies, [text, :redo] and [:pure, text, :redo], callbacks returning true/:redo, static replies, :this, a string :else). em's full MVTS run driven by the fixed engine: 4,238 PASS, 0 FAIL, as before.

…lse acts on its value

A callback's reply was measured after being replaced by the text it sent,
so ['abc'] counted as three items and left the multiplexer. :else threw
away its value's result, so :else: :redo stopped listening, and
:else: null never fired at all: it polled the fast timeout forever.
Both now behave as a static reply and any other key's value do.
@shreeve
shreeve merged commit 76a34fb into main Sep 24, 2026
2 checks passed
@shreeve
shreeve deleted the script/multiplexer-replies branch September 24, 2026 18:07
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