bhauman / figwheel-main

Figwheel Main provides tooling for developing ClojureScript applications
https://figwheel.org
Eclipse Public License 1.0
640 stars 93 forks source link

Missing :host key in Figwheel's repl-env causes vim-fireplace to hang on CLJS exception #339

Open krajj7 opened 1 year ago

krajj7 commented 1 year ago

When developing ClojureScript with figwheel-main and vim-fireplace, I encountered a bug where my Piggiebacked REPL session would hang whenever a ClojureScript evaluation launched from Vim throws an exception.

I believe the issue lies in figwheel-main's repl-env, which doesn't set the :host key. This leads to improper handling of stacktraces containing URLs, which ultimately causes an exception that hangs the Piggiebacked REPL.

To reproduce:

Get the figwheel demo project: git clone 'https://github.com/bhauman/flappy-bird-demo-new.git'

Update the following dependencies in project.clj: [org.clojure/clojurescript "1.11.60"] [com.bhauman/figwheel-main "0.2.18"]

At least for my setup I also have to add this dependency to resolve a conflict: [com.google.guava/guava "24.0-jre"]

Add this dependency to the dev profile: [cider/piggieback "0.5.3"]

Now run lein repl and start figwheel from there:

(require 'figwheel.main.api)
(figwheel.main.api/start {:mode :serve} "flappy")

Then in vim (with vim-fireplace installed) open src/flappy_bird_demo/core.cljs and run these commands:

:Piggieback (figwheel.main.api/repl-env "flappy")
:CljsEval (println "check that this works")
:CljsEval (throw (ex-info "a" {}))

After running the last command, vim shows the exception #error {:message "a", :data {}}, but hangs. After interrupting with Ctrl+C, subsequent evaluations in that session also hang.

The following exception is printed in the lein repl console:

Exception in thread "nREPL-session-1c658774-d115-4677-ab3e-4d06778c0a4d" java.lang.IllegalArgumentException: Not a file: http://localhost:9500/cljs-out/flappy/cljs/core.js (full stacktrace: https://paste.rs/Hu1so.txt)

The cause:

The function cljs.stacktrace/parse-stacktrace, which is used by the Figwheel repl-env to parse stacktraces, expects the :host and :port keys. These are used to transform URLs to file paths in stacktraces.

(See the parse-stacktrace docstring: https://github.com/clojure/clojurescript/blob/219951678b16575ec29bb9b88047356cf1437aec/src/main/cljs/cljs/stacktrace.cljc#L21 and the transformation itself: https://github.com/clojure/clojurescript/blob/219951678b16575ec29bb9b88047356cf1437aec/src/main/cljs/cljs/stacktrace.cljc#L81 )

The Figwheel repl-env doesn't set the :host key, it only sets the :port.

(This is where it is constructed: https://github.com/bhauman/figwheel-repl/blob/1571a6374d9b38ffdc072fbc850ec0110368f64d/src/figwheel/repl.cljc#L1353 )

Consequently, when an exception occurs in the CLJS REPL and the :host key is missing from the repl-env, the resulting parsed stacktrace representation still contains URLs in the :file values, which violates the expectation that it either contains file paths, or an identifier in angle brackets.

(This expectation is documented here: https://github.com/clojure/clojurescript/blob/219951678b16575ec29bb9b88047356cf1437aec/src/main/clojure/cljs/repl.cljc#L374 )

The improperly parsed stacktrace eventually causes the exception above that hangs the piggiebacked REPL session.

(The exception occurs here: https://github.com/clojure/clojurescript/blob/219951678b16575ec29bb9b88047356cf1437aec/src/main/clojure/cljs/repl.cljc#L332 )

The fix:

As a workaround, I manually set the :host key to "localhost" in the repl-env before passing it to Piggieback. Stacktraces are then processed and displayed correctly, the above exception no longer occurs and my Piggieback session keeps working even when evaluations throw exceptions.

To add the :host key to the repl-env I use the following vim-fireplace command: :CljEval (cider.piggieback/cljs-repl (assoc (figwheel.main.api/repl-env "flappy") :host "localhost")) instead of the usual :Piggieback (figwheel.main.api/repl-env "flappy")

Therefore, I suggest adding the :host key to FigwheelReplEnv by default.