Shadow-cljs: Watch gets stuck if trying to eval code in cljs.user namespace while building

Created on 15 Mar 2020  路  10Comments  路  Source: thheller/shadow-cljs

I believe I've narrowed down what's happening here. Here's my repro:

  1. Install a Vim plugin that attempts to use an nrepl eval via Fireplace on save
  2. Start up a watch with shadow-cljs watch app
  3. Open a browser for the app target
  4. Open a new instance of Vim
  5. Connect Fireplace to the shadow-cljs repl in the usual way
  6. Save the file, triggering shadow to build and the plugin to attempt the eval op via Fireplace
  7. The watch process fails to build forever, complaining of:
Build failure:
The required namespace "cljs.user" is not available.

At this point, I have to end and restart the watch process for it to start building successfully again鈥攁ny and every build attempt by the current watch process (triggered by a file write, usually) will result in the same Build failure message as above.

Here's what happens:

Fireplace has some internal state to track which namespaces have been loaded. When using fireplace#message or similar to send an nrepl op (or if using .Eval() to evaluate code, which is equivalent to sending {:op "eval"} in the buffer's namespace), fireplace will first attempt to "preload" the namespace associated with the requested op, if any. For clojurescript, this looks like sending an nrepl op like so:

{:op "eval", :code "(ns cljs.user (:require my.namespace))", :ns "cljs.user"}

If fireplace thinks it has already required the namespace in question (eg my.namespace above) it will skip this step. If I manually edit fireplace's state so it thinks it has already required the namespace before sending the op, the above build failure does not occur, so I believe something in there is the cause. In addition, when manually executing the plugin code when there is no build running, the error is not triggered, so I believe the ops the plugin performs to be safe.

Another observation that supports my suspicion is that if I restart the shadow watch process without restarting vim, I can reconnect and save that file without any problems. In an experiment just now, I was able to subsequently save a second file successfully, but saving a third file failed as above. Both namespaces needed the preload, so perhaps there is a race condition of sorts?

Thank you for your time!

Most helpful comment

Just pushed 2.8.95 which should fix this.

All 10 comments

I have the same problem and same repro steps.

Can you post how you edit fireplace's state, so i can maybe fiddle with it myself too? (not really fluent with vimscript, but can deduct a lot from reading the code).

Cheers

Can you post how you edit fireplace's state, so i can maybe fiddle with it myself too? (not really fluent with vimscript, but can deduct a lot from reading the code).

Sure! Something like this:

let client = fireplace#platform().Client()
let client.requires['my.namespace'] = 1

May I add that I have this problem without any external vim plugin, same repro steps but just evaling code in cljs buffer with regular fireplace cpp, cqp or just :Eval will contaminate shadow-cljs watch process forever which will not correctly build anything until restarted.

Any ideas where to look?

I recently encountered this issue testing out shadow-cljs over Figwheel with my vim setup, it looks like this issue doesn't occur in version 2.8.91 and prior, suggesting it was something introduced in 2.8.92. I'm downgrading for now while I continue to test out the platform.

Edit: I spoke too soon, I thought I had eliminated the problem when I stepped the version down to 2.8.90, and I walked it back up to 2.8.91 and it was still gone, but it's happening again.

Ok so I was previously starting up with shadow-cljs watch app, so I decided to try starting up the shadow-cljs clj-repl and then running (shadow/watch :app) in the repl. Now when I connect fireplace in vim and do :CljEval (shadow/repl :app) I can eval cljs again, save the file and I haven't seen the cljs.user error again yet, so maybe that will help?

Edit: not working again. I'm... going to stop trying to help now. I can't figure out why it seems to be working sometimes and then no longer works when I try to go through the same steps to reproduce.

I haven't been able to reproduce this. I suspect that this is something related to the order of command sent by vim-fireplace. Since I don't use vim I don't have that available.

Would be tremendously helpful if someone was able to reproduce this with a plain shadow-cljs cljs-repl app.

I do not know whats going on and I can eval the mentioned (ns cljs.user (:require my.namespace)) just fine and everything keeps working.

I threw together this script which seems to reproduce it for me in a running dev build (IE: shadow-cljs watch :app).

Usage, eg:

shadow-test.clj path/to/file.clj my.namespace 1234 app

Basically it just simulates writing to the path/to/file.clj by updating its modified timestamp, then connects to the shadow-cljs nrepl (with the given build ID) and evaluates that ns form shortly after.

Thanks, that helped a lot. I'm now able to reproduce this. No clue whats going on but I'll find it.

Just pushed 2.8.95 which should fix this.

Awesome, thank you鈥攍ooks good here :)

Was this page helpful?
0 / 5 - 0 ratings