Fork me on GitHub

Hello, how to convert JS exception into ClojuresScript exception?


What do you mean by "ClojureScript exception"?


I assumed that it is something different than JS exception... is it not? 😮


heve you tried to log JS exceptions with Timbre?


It is not. :) CLJS has ex-info that creates an instance of ExceptionInfo. But you don't have to use it - you can catch anything that you can throw. Including JS exceptions.


No, I don't think I've ever used Timbre.

😕 4

Is there a problem with Timbre and JS exceptions?


thows some protocol missing exception...


Can you paste the exception here?


oops can not reproduce and have to go to meeting now 😢 thanks for your help!!! 😉

👍 4

Has anyone had an issue importing vega libraries in clojurescript? I’m getting the following error in my browser when attempting to convert a vega spec into an actual graph:

failed to load module$node_modules$vega_lite$build$vega_lite.js SyntaxError: "missing ) after for-loop control"
Looks like something that the Google closure compiler is doing weirdly… Other warnings include:
failed to load cljsjs.vega_lite.js Module not provided: module$node_modules$vega_lite$build$vega_lite app.js:2218:15
shadow-cljs - failed to load module$node_modules$vega_embed$build$vega_embed /js/compiled/cljs-runtime/shadow.js.js:39:17
failed to load cljsjs.vega_embed.js Module not provided: module$node_modules$vega_lite$build$vega_lite
The exception is:
ReferenceError: vegaEmbed is not defined
We’re importing the vega components via ShadowCljs, relevant config in package.json:
      "vega": "^5.9.1",
      "vega-embed": "^6.2.2",
      "vega-lite": "^4.0.2"


"missing ) after for-loop control" sounds like your Vega spec is incorrect. I've used Vega with CLJS, although it was not the Vega-Lite version.


Weird thing is, the page renders fine (with the vega viz) in Safari, but not in Firefox or Chrome…


Oh. That is strange.


The spec itself is a very basic one using hanami


I didn’t apply too many transformations beyond a default one i took from his examples


@U2FRKM4TW what did you use for dependency management when you used vega?


Yeah, it's not your spec. Does that SyntaxError give any details about the line number? I used NPM + shadow-cljs + deps.edn.


Also, can you create a minimal reproducible example that I could check out?


here it is with line numbers included:

failed to load module$node_modules$vega_lite$build$vega_lite.js SyntaxError: "missing ) after for-loop control"       app.js:2218:15


I’ll work on an example


Ah, by default shadow-cljs uses :devtools {:loader-mode :eval} which messes up the line numbers since now the code is not in a separate file but in the same app.js.


ah… is there a way I can modify that to make it more friendly to you?


Yep, just set the :loader-mode to any value other than :eval.


But a reproducible example would be much better. :)


yup, I think we’re almost there


so after putting together a bare-bones example, it’s all working. I suspect that using lein with shadow got very messy, and compilation is stuffing up somewhere. I can send the lein config if you’re a glutton for punishment, but otherwise let’s leave it here 😄


How exactly do you use lein with shadow-cljs?


do you want the project.clj?


Nah, I mean the build process. Do you just set :lein true in your shadow-cljs.edn?


we use the lein-shadow plugin, and run with lein shadow watch app


OK. Well, the above exception doesn't sound like anything that would result from using lein. Try setting :loader-mode to some value other than :eval and see what line number it gives you, then see what's at that line. Should be a messed up for loop.


okay, will do


We got a different error output this time!

SyntaxError: missing ) after for-loop control module$node_modules$vega_lite$build$vega_lite.js:370:209
uncaught exception: Module not provided: module$node_modules$vega_lite$build$vega_lite js.js:88:4
    jsRequire js.js:88
    require js.js:100
    <anonymous> cljsjs.vega_lite.js:3
uncaught exception: Module not provided: module$node_modules$vega_lite$build$vega_lite js.js:88:4
    jsRequire js.js:88
    require js.js:100
    <anonymous> cljsjs.vega_embed.js:3


for what it’s worth, all the modules that are said not to be provided have been installed via npm and included as dependencies in lein


It says "not provided" probably because of that SyntaxError - the module was provided, it just couldn't be loaded. So, if you now open module$node_modules$vega_lite$build$vega_lite.js:370:209, what's in there?


It’s a bit hard to understand - I’m presented with a massive block of js text


I’ll paste it somewhere where I can get line numbers


Oh, what editor/IDE do you use that doesn't show line numbers?


I just opened it in my browser


I’m very sorry but need to head off - really appreciate your help! do you mind if I pick up this thread again tomorrow?


Don't mind at all - add more details whenever you can. Regardless of what we find at that particular line/column, my next steps would probably be: 1. Try to build the CLJS code using only shadow-cljs, with no lein and lein-shadow at all 2. Try to remove all of the app code except the one that creates the Vega chart 3. Remove CLJS dependencies that now aren't used, one by one Between all points, check whether the app works.


Since your app doesn't work but the minimal example does, this process would allow us to find that point of breakage. Of course, you can go the other way - try to build up on that minimal example till it breaks. Up to you.


Really appreciate it - great advice!!


@U2FRKM4TW quick update on this: I took all existing code and did the following differently: • ran it using shadow-cljs.edn instead of a project.clj • upgraded to reagent 0.9.1 from 0.8.0 due to a TypeError when using :> (see here: It all works now…

👍 4

The issue was not the reagent version, it was something in lein, or the config


are there any open source cljs+figwheel-main projects that build a Chrome extension?


or anyone that can provide a basic working example figwheel-main conf/setup that passes Chrome's security checks?


Hi, I have JS object that prints like that: #object[Error] How can I convert it to Clojure Exception? so I can use it with Timbre logging


@feikas If I remember correctly, if you pass the exception as the first argument to error it will log the stacktrace of that exception

Marko Horvatic17:01:07

Hi there. I'm new here. Anybody knows what is the best way to interop with (iterate over) Map object.


@marko.horvatic You could first translate it to a CLJS map with js->clj and then iterate over that, if performance is not that important


so like this:

cljs.user=> (seq (js->clj (js-obj "a" 1)))
(["a" 1])

Marko Horvatic17:01:24

@borkdude Well Map is I guess a bit tricky

(seq (js->clj (js/Map. (clj->js [["a" 1]]))))
#object[Error Error: [object Map] is not ISeqable]


hmm, I see. I read something about this: but I have no clue sorry 🙂

Marko Horvatic17:01:49

np, thanks anyway.


Given what borkdude has posted, you can do it like this:

cljs.user=> (vec (es6-iterator-seq (.entries (js/Map. #js [#js ["a" 1] #js ["b" 2]]))))
[#js ["a" 1] #js ["b" 2]]


If you work with js/Maps all the time and don't really care about both the performance and the advice to not extend built-in types, you can probably (extend-type js/Map IEncodeClojure (-js->clj [x opts] ...)).

Marko Horvatic18:01:27

@U2FRKM4TW Thanks for the answer. It is not that often. I have isolated case of external dependency that feeds me with js/Map data. About your response, I can see es6-iterator-seq is marked as experimental Does this pose any risk?


I doubt that it will be removed completely, maybe only changed somehow. It has been there for 6 years. Also, its implementation is so trivial, you can just copy-paste it into your own project (maybe just name it differently to avoid shadowing CLJS of the core symbol).


Hi, I have JS object that prints like that: #object[Error] How can I serialize it with pr-str so it can be read after with read-string ? js->clj does not help


To print it in some way that allows reconstructing the object later, you have to extend-type the js/Error to support the IPrintWithWriter protocol. To read it back (assuming, you're talking about cljs.reader/read-string), you need to add a custom reader to cljs.reader/*tag-table*.


I’ve been working with SPAs and re-frame for a bit, but I’m looking at reitit and front end routing for the first time. Other than making the app browser-friendly re: history, what else will a front end router do for me?


I use reitit-frontend to decide which view to render and to run initialization code on page change (controllers). There are also nice utils to coerce data from path and query parameters.


Aaand you can also navigate programmatically


It’s nice to be able to annotate your routes with arbitrary data: required roles for routes, layout info, attached view components etc. Also, as the route data accumulates from root to the leaves, you can have a "/admin" route fragments with user role requirements that effect all the child routes.

✔️ 4

(def router
    [["/" {:name ::home
           :icon "inbox"
           :view [:h1 "home!"]
           :title "Kotisivu"}]
     ["/gallery" {:name ::gallery
                  :icon "desktop"
                  :title "Gallery"
     ["/admin" {:roles #{:admin}}
       ["/users" {:name ::users
                  :view demo.admin/user-view}]
       ["/orders" {:name ::orders
                   :view demo.admin/order-view}]]
     ["/schema" {:name ::poc
                 :icon "line-chart"
                 :title "Schema"
                 :view [demo.schema/form-view]}]
     ["/user" {:name ::user
               :icon "user"
               :title "Käyttäjä"
               :view user-view}]]))


disclaimer: involved in developing the lib