Skip to content

Fix the compatibility problems proof found - #1

Merged
bbatsov merged 6 commits into
mainfrom
proof-fixes
Oct 23, 2026
Merged

bbatsov merged 6 commits into
mainfrom
proof-fixes

Conversation

@bbatsov

@bbatsov bbatsov commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Running proof against dialtone and repartee turned up a few places where they behave differently from what clients expect: close didn't reply with session-closed, unknown-op replies didn't echo the op, an eval without code was reported as an eval-error, and evaluating several Erlang forms returned only the last value. Fixing those also uncovered a race after close, temporary sessions that never stopped, and a crash on load-file of a file without code. With all of this both servers pass everything in proof except stderr capture, which is a separate PR.

vim-fireplace only forgets a session once it sees session-closed, and
nREPL replies with it too. Closing a session that's already gone (or no
session at all) gets session-closed as well, like Babashka, nbb and
ClojureCLR do, so clients that wait for it don't loop.

The session now leaves the registry before it replies. Otherwise a
request sent right after session-closed could still be routed to the
session while it shut down and never get an answer.
Calva builds its "the server doesn't support this" message from the op
in the reply, and nREPL includes it as well. All unknown-op replies now
come from one helper, including those for optional ops a backend doesn't
implement.
Nothing gets evaluated in that case, so eval-error was misleading, and
nREPL answers with no-code as well. A code field that isn't a string is
still reported as a malformed request.
A request without a session gets a session of its own, which stops once
its eval finishes. Requests that were answered right away (an eval
without code, completions, lookup and the like) never got that far, so
their sessions stayed around for good.
Evaluating "1. 2." used to report only the last value, so clients showed
one result and silently dropped the rest. Now each form's value goes to
the client as soon as the form is done, like the shell prints them. The
values travel through the session's IO server, the same way output does,
so they arrive in step with it, and an error in a later form no longer
swallows the earlier values. Other backends can do the same through
dialtone_backend:emit_value/1. load-file still reports only the last
value, as nREPL does.
A file with nothing but comments (or nothing at all) crashed while looking for a module attribute. It's now treated like an empty eval.
@bbatsov
bbatsov merged commit 93ee97a into main Oct 23, 2026
10 checks passed
@bbatsov
bbatsov deleted the proof-fixes branch October 23, 2026 10:03
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