nextjournal / clerk

⚡️ Moldable Live Programming for Clojure
https://clerk.vision
ISC License
1.79k stars 77 forks source link

Exceptions are not shown when watcher uses filter-fn #616

Closed zampino closed 8 months ago

zampino commented 8 months ago

When the watcher is started with a filter function e.g.

(clerk/serve! {:watch-paths ["notebooks" "src"] 
               :show-filter-fn #(clojure.string/starts-with? % "notebooks")})

when a notebook file is changed and contains e.g syntax or runtime errors then no exception is reported in the browser and the progress bar is stuck in analyzing state.

zampino commented 8 months ago

This happens (again) because of an unreadable expression is sent to the client as part of the document attached to the ex-data. This time, it is the printed value for the :show-filter-fn option:

{:type :set-state!,
 :doc {:path [],
       :nextjournal/value 
       {:toc {:path [], 
              :nextjournal/value […]}, 
        :error {:path [], 
                :nextjournal/value
                {:via [{:type clojure.lang.ExceptionInfo,
                        :message "`nextjournal.clerk/show!` encountered an eval error with: `\"notebooks/how_clerk_works.clj\"`",
                        :data {:nextjournal.clerk/doc
                               {:toc …
                                :footnotes []
                                :instance #object[org.httpkit.server.HttpServer 0x71c2782 "org.httpkit.server.HttpServer@71c2782"]
                                :git/url "https://github.com/nextjournal/clerk"
                                :blob->result {…}
                                :file "notebooks/how_clerk_works.clj"
                                :port 7777
                                :title "How Clerk Works 🕵🏻‍♀️"
                                :git/sha "b12aad2afe45690ecfd1b2619025cb0fab2dc77f"
                                :nav-path "notebooks/how_clerk_works"
                                :host "localhost"
                                :watch-paths ["notebooks" "src"]
                                :file-path "notebooks/how_clerk_works.clj"
                                :blocks […]

                                :show-filter-fn #function[user/eval60926/fn--60927]}}

                        :at [nextjournal.clerk$show_BANG_$fn__60588 invoke "clerk.clj" 74]} 

                       {:type clojure.lang.ExceptionInfo, :message "Execution error (ArithmeticException) at how-clerk-works/eval61174 (how_clerk_works.clj:11).\nDivide by zero\n", 
                        :data {:clojure.error/cause "Divide by zero", :clojure.error/phase :execution, :clojure.error/symbol how-clerk-works/eval61174, :clojure.error/line 11, :clojure.error/class java.lang.ArithmeticException, :clojure.error/source "how_clerk_works.clj", :line 11, :col 1, :clojure.core/eval-file "notebooks/how_clerk_works.clj", :form (/ 1 0)}, :at [nextjournal.clerk.eval$eval_PLUS_cache_BANG_ invokeStatic "eval.clj" 156]}], :trace [["nextjournal.clerk.eval/eval+cache!" invokeStatic "eval.clj" 156] ["nextjournal.clerk.eval/eval+cache!" invoke "eval.clj" 123] ["nextjournal.clerk.eval/read+eval-cached" invokeStatic "eval.clj" 195] ["nextjournal.clerk.eval/read+eval-cached" invoke "eval.clj" 166] ["nextjournal.clerk.eval/eval-analyzed-doc/fn--15710" invoke "eval.clj" 237] ["clojure.lang.PersistentVector" reduce "PersistentVector.java" 345] ["clojure.core/reduce" invokeStatic "core.clj" 6899] ["clojure.core/reduce" invoke "core.clj" 6882] ["nextjournal.clerk.eval/eval-analyzed-doc" invokeStatic "eval.clj" 230] ["nextjournal.clerk.eval/eval-analyzed-doc" invoke "eval.clj" 227] ["nextjournal.clerk.eval/+eval-results" invokeStatic "eval.clj" 258] ["nextjournal.clerk.eval/+eval-results" invoke "eval.clj" 251] ["nextjournal.clerk/show!/fn--60588/fn--60589" invoke "clerk.clj" 72] ["nextjournal.clerk/show!/fn--60588" invoke "clerk.clj" 71] ["nextjournal.clerk/show!" invokeStatic "clerk.clj" 71] ["nextjournal.clerk/show!" invoke "clerk.clj" 23] ["nextjournal.clerk/show!" invokeStatic "clerk.clj" 36] ["nextjournal.clerk/show!" invoke "clerk.clj" 23] ["nextjournal.clerk/file-event" invokeStatic "clerk.clj" 127] ["nextjournal.clerk/file-event" invoke "clerk.clj" 117] ["nextjournal.clerk/serve!/fn--60665" invoke "clerk.clj" 486] ["nextjournal.beholder/fn/reify--433" onEvent "beholder.clj" 13] ["io.methvin.watcher.DirectoryWatcher" onEvent "DirectoryWatcher.java" 402] ["io.methvin.watcher.DirectoryWatcher" runEventLoop "DirectoryWatcher.java" 349] ["io.methvin.watcher.DirectoryWatcher" lambda$watchAsync$1 "DirectoryWatcher.java" 232] ["java.util.concurrent.CompletableFuture/AsyncSupply" run "CompletableFuture.java" 1768] ["java.util.concurrent.CompletableFuture/AsyncSupply" exec "CompletableFuture.java" 1760] ["java.util.concurrent.ForkJoinTask" doExec "ForkJoinTask.java" 387] ["java.util.concurrent.ForkJoinPool/WorkQueue" topLevelExec "ForkJoinPool.java" 1312] ["java.util.concurrent.ForkJoinPool" scan "ForkJoinPool.java" 1843] ["java.util.concurrent.ForkJoinPool" runWorker "ForkJoinPool.java" 1808] ["java.util.concurrent.ForkJoinWorkerThread" run "ForkJoinWorkerThread.java" 188]], :cause "Execution error (ArithmeticException) at how-clerk-works/eval61174 (how_clerk_works.clj:11).\nDivide by zero\n", :data {:clojure.error/cause "Divide by zero", :clojure.error/phase :execution, :clojure.error/symbol how-clerk-works/eval61174, :clojure.error/line 11, :clojure.error/class java.lang.ArithmeticException, :clojure.error/source "how_clerk_works.clj", :line 11, :col 1, :clojure.core/eval-file "notebooks/how_clerk_works.clj", :form (/ 1 0)}}, :nextjournal/viewer {:name nextjournal.clerk.viewer/throwable-viewer, :render-fn #viewer-fn nextjournal.clerk.render/render-throwable, :hash "5dswADQUY2mBAupUjWd93PhFE3QG5s"}}}

       :nextjournal/viewer {:name nextjournal.clerk.viewer/notebook-viewer, :render-fn #viewer-fn nextjournal.clerk.render/render-notebook, :hash "5dsiHybTyGGTEpReRaV7nfNxoDgnKx"}}}

Does it make sense to have the whole clerk/serve! options be attached to the document? Or shall we actually control how functions get printed to EDN?