bhauman / lein-figwheel

Figwheel builds your ClojureScript code and hot loads it into the browser as you are coding!
Eclipse Public License 1.0
2.88k stars 208 forks source link

Send JS exception stack traces through piggieback #563

Open cjhowedev opened 7 years ago

cjhowedev commented 7 years ago

With the latest piggieback (0.2.2) and cider-nrepl, causing an exception in a piggieback REPL will send the exception back to cider to show it in the stack trace window. You can cause these errors in figwheel by typing some invalid syntax, like #fail, which will pop up the stack trace window. However, normal Javascript errors, like (throw "fail"), don't cause a stack trace to be sent back. I'm assuming this is because it's a Javascript error and not a Clojure exception. Could we make figwheel support translating Javascript errors into Clojure exceptions with a stack trace so they can be sent through piggieback to show up in the cider stacktrace window?

EDIT:

As an example,

cljs.user> (defn whatever-man [] (let [arr [1 4]] (arr 3)))
#'cljs.user/whatever-man
cljs.user> (whatever-man)
#object[Error Error: No item 3 in vector of length 2]
Error: No item 3 in vector of length 2
    at Object.cljs$core$vector_index_out_of_bounds [as vector_index_out_of_bounds] (http://localhost:3449/js/compiled/out/cljs/core.js:18933:8)
    at Object.cljs$core$array_for [as array_for] (http://localhost:3449/js/compiled/out/cljs/core.js:18975:18)
    at cljs.core.PersistentVector.cljs$core$IIndexed$_nth$arity$2 (http://localhost:3449/js/compiled/out/cljs/core.js:19264:19)
    at cljs.core.PersistentVector.G__10745__2 (http://localhost:3449/js/compiled/out/cljs/core.js:19581:13)
    at cljs.core.PersistentVector.G__10745 [as call] (http://localhost:3449/js/compiled/out/cljs/core.js:19592:20)
    at cljs$user$whatever_man (eval at figwheel$client$utils$eval_helper (http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8), <anonymous>:4:12)
    at eval (eval at figwheel$client$utils$eval_helper (http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8), <anonymous>:1:249)
    at eval (eval at figwheel$client$utils$eval_helper (http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8), <anonymous>:9:3)
    at eval (eval at figwheel$client$utils$eval_helper (http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8), <anonymous>:14:4)
    at figwheel$client$utils$eval_helper (http://localhost:3449/js/compiled/out/figwheel/client/utils.js:174:8)
nil
cljs.user> #fail
clojure.lang.ExceptionInfo: No reader function for tag fail {:type :reader-exception, :line 1, :column 6, :file "NO_SOURCE_FILE"}
    at clojure.core$ex_info.invokeStatic(core.clj:4617)
    at clojure.core$ex_info.invoke(core.clj:4617)
    at clojure.tools.reader.reader_types$reader_error.invokeStatic(reader_types.clj:389)
    at clojure.tools.reader.reader_types$reader_error.doInvoke(reader_types.clj:385)
    at clojure.lang.RestFn.invoke(RestFn.java:439)
    at clojure.tools.reader$read_tagged.invokeStatic(reader.clj:851)
    at clojure.tools.reader$read_tagged.invoke(reader.clj:838)
    at clojure.tools.reader$read_dispatch.invokeStatic(reader.clj:71)
    at clojure.tools.reader$read_dispatch.invoke(reader.clj:66)
    at clojure.tools.reader$read_STAR_$fn__8660.invoke(reader.clj:916)
    at clojure.tools.reader.reader_types$log_source_STAR_$fn__8344.invoke(reader_types.clj:294)
    at clojure.lang.AFn.applyToHelper(AFn.java:152)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invokeStatic(core.clj:646)
    at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1881)
    at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1881)
    at clojure.lang.RestFn.invoke(RestFn.java:425)
    at clojure.tools.reader.reader_types$log_source_STAR_.invokeStatic(reader_types.clj:293)
    at clojure.tools.reader.reader_types$log_source_STAR_.invoke(reader_types.clj:288)
    at clojure.tools.reader$read_STAR_.invokeStatic(reader.clj:905)
    at clojure.tools.reader$read_STAR_.invoke(reader.clj:897)
    at clojure.tools.reader$read.invokeStatic(reader.clj:965)
    at clojure.tools.reader$read.invoke(reader.clj:942)
    at cljs.repl$repl_read.invokeStatic(repl.cljc:107)
    at cljs.repl$repl_read.invoke(repl.cljc:86)
    at cljs.repl$repl_read.invokeStatic(repl.cljc:98)
    at cljs.repl$repl_read.invoke(repl.cljc:86)
    at cljs.repl$repl_STAR_$read_eval_print__22113$fn__22114.invoke(repl.cljc:851)
    at cljs.repl$repl_STAR_$read_eval_print__22113.invoke(repl.cljc:844)
    at cljs.repl$repl_STAR_$fn__22119$fn__22128.invoke(repl.cljc:900)
    at cljs.repl$repl_STAR_$fn__22119.invoke(repl.cljc:899)
    at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1180)
    at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1169)
    at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:861)
    at cljs.repl$repl_STAR_.invoke(repl.cljc:737)
    at cemerick.piggieback$run_cljs_repl.invokeStatic(piggieback.clj:169)
    at cemerick.piggieback$run_cljs_repl.invoke(piggieback.clj:155)
    at clojure.lang.AFn.applyToHelper(AFn.java:171)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invokeStatic(core.clj:650)
    at clojure.core$apply.invoke(core.clj:641)
    at cemerick.piggieback$evaluate.invokeStatic(piggieback.clj:259)
    at cemerick.piggieback$evaluate.invoke(piggieback.clj:255)
    at clojure.lang.Var.invoke(Var.java:379)
    at cemerick.piggieback$wrap_cljs_repl$fn__35364$fn__35366$fn__35367.invoke(piggieback.clj:291)
    at cemerick.piggieback$enqueue$fn__35350.invoke(piggieback.clj:247)
    at clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__30699.invoke(interruptible_eval.clj:190)
    at clojure.lang.AFn.run(AFn.java:22)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

The first exception does not get sent through piggieback and forwarded to cider's stack trace display, while the second does.

bhauman commented 7 years ago

I remember trying to make this work, I forget what the show stopper was.