Open smee opened 7 years ago
During what deserialization is this happening and how messages from cider middleware end up on DIRAC side in the first place?
I can only guess that this happens during the first eval response when a map of clojure.core is sent back by track-state middleware:
arglists "([protocol])")
.. (dict
arglists "([x form] [x form & more])"
doc "\"form => fieldName-symbol or (instanceMethodName-symbol args*)\\n\\n Expands into a member access (.) of the first member on the first\\n argument, followed by the next member on the result, etc. For\\n instance:\\n\\n (.. System (getProperties) (get \\\"os.name\\\"))\\n\\n expands to:\\n\\n (. (. System (getProperties)) (get \\\"os.name\\\"))\\n\\n but is easier to write, read, and understand.\""
macro "true")
/ (dict
arglists "([x] [x y] [x y & more])"
doc "\"If no denominators are supplied, returns 1/numerator,\\n else returns numerator divided by all of the denominators.\"")
< (dict
but that dict's keys are string symbols (no :
in front).
My best guess is that's the issue is on the DIRAC's side (or whatever comes before it). Something prepends ":" to the dict's keys and then DIRAC tries to read those transformed keys. In that case there is nothing that could be done on cider's side.
cc @darwin
@vspinu Dirac implemented an nREPL client in Javascript (using ClojureScript). This page could help understanding the architecture: https://github.com/binaryage/dirac/blob/master/docs/about-repls.md#dirac
I think the problem @smee described is real. When someone serializes arbitrary data using clojure and then tries to deserialize them using cljs.reader, here is a minor risk of running into incompatibilities like the one described above.
But fixing this is would not really fix his setup as I wrote here. Because Dirac's nREPL client does not understand Cider nREPL messages.
Proper solution would be to run two nREPL servers with two separate sets of middleware. First one with Dirac middleware available for Dirac nREPL client(s) in Chrome. And second one with Cider middleware available for Cider nREPL client(s) in Emacs. This should work, but could introduce another issue of "syncing" nREPL state (Clojure(Script) compiler state) between those two servers. I'm not familiar with Cider and have never tried a similar setup myself.
If anyone still cares, you can maybe hack your way around this by disabling the track-state middleware. Emacs shouldn't complain much (you'll just miss out on some small features).
To do that you would have to redefine the function cider.nrepl.middleware.track-state/make-transport
to something like this.
(defn make-transport
"NOOP to just return transport."
[{:keys [^Transport transport]}]
transport)
It might be enough to simply run this on the repl after it's loaded.
Proper solution would be to run two nREPL servers with two separate sets of middleware. First one with Dirac middleware available for Dirac nREPL client(s) in Chrome. And second one with Cider middleware available for Cider nREPL client(s) in Emacs. This should work, but could introduce another issue of "syncing" nREPL state (Clojure(Script) compiler state) between those two servers. I'm not familiar with Cider and have never tried a similar setup myself.
@darwin Why would the unknown messages be problematic? I assume most clients would simply drop unknown responses.
@bbatsov You are correct. In sane world clients should drop unknown messages and this would make them less fragile and add interoperability. But on the other hand they might silently fail in some scenarios when server misbehaves - maybe client would drop messages without giving user any error feedback.
Unfortunately messages don't have nice "tags" that they belong to specific middleware. My process-message
is quite hairy as you can see here:
https://github.com/binaryage/dirac/blob/aa2a66f8302f039c53ebc88a84869d51f79637d7/src/implant/dirac/implant/nrepl_tunnel_client.cljs#L75-L98
Message is a gray "goo of stuff". Maybe it is because I had to layer several nREPL hacks and the whole thing is a mess.
Anyways, I can put some effort into it and make it less fragile by tagging all dirac-related messages consistently and dropping everything else.
I'm developing a clojurescript application, so I'm using DIRAC as a clojurescript REPL in the browser. Since cider adds the
cider.nrepl.middleware.track-state
middleware to NREPL, dirac receives its messages in clojurescript. When it then parses the message viacljs.reader
it chokes on the serialized form of the/
symbol, the keyword:/
(for details please see https://github.com/binaryage/dirac/issues/52).Since clojurescript adheres to the EDN standard,
:/
is explicitely named as an invalid keyword. Clojure itself doesn't say the same thing, so a:/
keyword in clojure seems to be fine.So my question is: What can I do in this situation?