Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cider.nrepl.middleware.track-state serializes the division function as :/ #393

Open
smee opened this issue Jan 13, 2017 · 5 comments
Open

Comments

@smee
Copy link

smee commented Jan 13, 2017

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 via cljs.reader it chokes on the serialized form of the / symbol, the keyword :/ (for details please see binaryage/dirac#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?

@vspinu
Copy link
Contributor

vspinu commented Aug 27, 2017

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

@darwin
Copy link

darwin commented Aug 27, 2017

@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.

@Malabarba
Copy link
Member

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.

@bbatsov
Copy link
Member

bbatsov commented Dec 9, 2017

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.

@darwin
Copy link

darwin commented Dec 9, 2017

@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.

@clojure-emacs clojure-emacs deleted a comment from MalloZup Oct 2, 2023
@vemv vemv pinned this issue Oct 2, 2023
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

No branches or pull requests

5 participants