Fork me on GitHub
Garrett Hopper04:06:34

Am I doing something wrong? clj -m cljs.main -co "{:foreign-libs [{:global-exports '{global.test global}}]}" -re node -r Exception in thread "main" java.lang.RuntimeException: Map literal must contain an even number of forms :global-exports is supposed to be a quoted map of namespaces to global exports, right?


@ghopper that single quote is screwing up the shell arg


you can safely get rid of it

Garrett Hopper04:06:25

...I was about to say that it does the same thing with a file. Then I tried the file without the quote. Thanks, @bhauman!


Bah. I should've solved the online requirement of cljsbuild earlier. Now I'm stuck working in a train with mobile connection that works... sometimes. If the problem is in the lein side (as I thought) and hairy to untangle, what are the alternatives for building cljs files?


Just gave figwheel-main a spin, good stuff 🙂


Noob question. Trying to build with lein-cljsbuild and all my deps seem to end up in app.js but not my own sources. What am I doing wrong?

{:id           "not-min"
     :source-paths ["src/cljs" "src/cljc"]
     :compiler     {:main            lipas.ui.core
                    :output-to       "resources/public/js/compiled/app.js"
                    :optimizations   :whitespace
                    :closure-defines {goog.DEBUG false}
                    :pretty-print    false}}


I’ve been developing this with figwheel so far and it works nicely. However I’m now trying to create a js-file that I can upload to server


lein clean && lein cljsbuild once not-min


It’s also very like that I’ve understood something wrong. I’m now assuming that all JS would be emitted to single file (app.js)


Now app.js contains thousands of rows from my deps but nothing from my own sources (checked with grep). However all my code + deps was compiled under target/cljsbuild-compiler-1/… into separate files. Why is my stuff missing from app.js?


I’m supposed to demo this in 10min 😄 It would’ve been cool to have it on internet so people could try with their own devices. But maybe I’ll stick with figwheel & screenshare this time.


@valtteri seems strange, did you try :simple?


Heh, updated to latest clojurescript and got better error message from the compiler. I had a file with bad name local-storage.cljs instead of local_storage.cljs. I guess that’s why it failed earlier.. though the last line in output was always “Successfully compiled ….” 😅


that result string is from cljsbuild, it’s odd that you didn’t get an exception during build though


Odd indeed

[email protected]:/usr/src/app# lein cljsbuild once not-min
Compiling ClojureScript...
[email protected]:/usr/src/app#


This was with 1.9.908 EDIT: looking at the output it doesn’t say ‘success’ even though I earlier claimed so. Now thinking about it.. It’s possible that my STDERR was going to /dev/null or something since I was playing with a bash session in Docker.


And with 1.10.238

Compiling ClojureScript...
Compiling "resources/public/js/compiled/app-min.js" from ["src/cljs" "src/cljc"]...
Jun 08, 2018 2:18:47 PM println
SEVERE: /Users/vaotjuha/lipas/lipas/webapp/target/cljsbuild-compiler-1/lipas/ui/core.js:5: ERROR - required "lipas.ui.local_storage" namespace never provided


But now advanced optimizations work which is sweeeet! 👍


Ahhh. Here’s another weird attempt when run on host (MacOS)

lein clean && lein cljsbuild once not-min
Compiling ClojureScript...
Compiling "resources/public/js/compiled/app.js" from ["src/cljs" "src/cljc"]...
Jun 08, 2018 12:41:26 PM println
SEVERE: /Users/vaotjuha/lipas/lipas/webapp/target/cljsbuild-compiler-1/cljs/core.js:3579: ERROR - Parse error. primary expression expected
case ##Inf:

Jun 08, 2018 12:41:26 PM printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_PARSE_ERROR. Parse error. primary expression expected at /Users/vaotjuha/lipas/lipas/webapp/target/cljsbuild-compiler-1/cljs/core.js line 3579 : 6
Successfully compiled "resources/public/js/compiled/app.js" in 18.084 seconds.


This was with 1.9.908.. and definitely the weirdest 🙂


But, in the above, it is as if ClojureScript is being put in your JavaScript file? Odd.


I’m not absolutely sure what was going on there because I didn’t know what I was doing. 🙂 But I think that the problem was indeed that there was a file with bad name and the latest clojurescript compiler was able to provide useful error which lead me to right direction. The confusion game from lein-cljsbuild telling that build was success even though it failed and error-message was really cryptic from 1.9xxx compiler.


HMmm isn’t tools.reader shipped with clojurescript? So there shouldn’t be version mismatch unless something pulled me another version somehow?


Hmm or is it actually shipped with clojure.. Anyways my clojure version is “1.9.0”


I probably need to figure out how this whole compliation process and related tooling actually works. 🙂


@valtteri Yeah, usually things work correctly with the tools.reader version that ClojureScript depends upon, and you really only run into trouble if something else in your build tooling causes an older version to be put on the classpath. But, the above sounds like ##Inf made it into JavaScript, and then Google Closure Compiler failed when it saw it.


Ok, thanks for the explanation.


I just lately realized that js-libs are nowadays HUGE and :advanced is really necessary. I added a ui-lib to my project and BOOM 2Mb of js. 🙀


(Actually, as you said, it is not "made it into JavaScript", but just a filenameing confusion)

👍 4

The JavaScript for cljs.core is about 1.2 Mb, but typically after :advanced you end up in the less than 100 Kb range.


I upgraded figwheel, and the code reloading is not working anymore (the compilation happens, but the new code is not loaded). has anyone experienced this?


@roti, try lein clean, remove target/ manually, shift-reload, different browser, roughly in that order


Hmh. How can I mark callback parameters in externs, or otherwise keep the names intact? So I want to pass a callback to external JS lib. That callback will get an object, which has a method I need to call (leaflet marker clusters and the function to create an icon for the cluster)


You could try putting a ^js type hint in front of the arg, if you have the :infer-externs compiler option enabled. Eg (fn [^js the-arg] ...)


Hm, true. I can do that and see what the generated extern looks like


Although based on the example I would need to supply the path to the object.


Ok, so what the inferred externs did was what I had hacked up: set up the methods on Object...


Whoa, If I manage to figure out the right object in the global namespace and extern that, closure compiler knows that the callback is going to get that object and keep the methods as is


So if I put a ^js type hint for a parameter, does that actually mean "This is of type Object" and not just "this is some kind of JS object", and therefore it forces the compiler to treat it as such, even though it's capable of inferring the exact type?


Hmm, no. If I misspell the object, the methods under it are still inferred. I suppose the compiler will just keep all method names under any object in externs, just in case


I'm starting to think that I will just stop thinking about how to make better externs (seems like the project which I inherited is in fact equivalent of having all methods defined on Object) I will just drop them completely and move to cljs-oops


For several months I have been using ^js hints whenever I encounter an issue with externs, and find that it "just works" and is a nice/lightweight approach. If you have warnings enabled, it will still show warnings for these cases (unless you use shadow-cljs, which directly supports ^js). cljs-oops works too. I just personally prefer to avoid extra libs.


Since the object is not in global scope, I can't do it the usual way


I tried getting the function with goog.object/get and call it then, but then it's called with null this


Is it possible in cljs or even just in JS to get a pem certificate delivered in code only (via ajax, etc) and automatically use that for further REST requests to a server?


I can't find any information suggesting certificates can be installed automatically or used in a browser without explicit user intervention


@ajs wouldn’t it be a security hole if code were able to install certs without user knowledge and/or approval?


i would think so, but i'm working with another team that seems to think this might be possible, even though they haven't done it before


Heh, even accessing goog.object gets munged


is it possible to use javascript’s async/await in cljs? I’m wanting to use it when writing an abstraction on top of amazon lambda


I’ve set my target to ecmascript2017, but i’m not sure how I can define a function as async (and it shows async/`await` here:


@dehli no, but you can use promises fairly conveniently with clojurescript. if I have something complicated, I use the alet macro from the promesa library which works quite well. that library also has a macro that emulates async/await, but I’ve found it to be a little fragile (and honestly you can do anything with alet)


big discussion thread on some of the challenges here:!topic/clojurescript/scUMhU-ctEM

👍 4

Thanks you guys! I’m currently using promises and just wanted to double check 🙂


So if I put a ^js type hint for a parameter, does that actually mean "This is of type Object" and not just "this is some kind of JS object", and therefore it forces the compiler to treat it as such, even though it's capable of inferring the exact type?


@lee.justin.m talking out of ignorance here, why not just use core.async for his async/await needs?


Also I am using core.async, however I needed promises (or async/await) for interop with amazon lambda. Basically just have to convert a core.async channel into something that lambda recognizes


nvm, you links explains some of it


@lockdown- for me personally, my reasons are (1) i do not like the exception handling semantics of core.async, (2) it produces tons of code that is hard to understand and debug, (3) it creates huge stack traces, (4) its way more complex than I need


@lee.justin.m ok, I'm starting to like JS 2018+ 😉 - is not that bad, and there is always lodash/fp


I think the difference in performance of doing immutability in JS(browser) but without the 'persistent' part is very low


FWIW I do not like princess, personally I don’t know why you would want to bother with async/await when you have core.async


If you use it at the edge and for coordination it really not hard to use nor do you encounter serious debugging issues


That’s promesa not princess :)


I’ve used it for a year on a client project along with nomadic macros


It’s not good IMO, certainly no easier to understand or debug than core.async


Erg sorry on phone, monadic macros


ran into issues using #?@ reader conditional in (:require ... section of ns form. Is this a known limitation/bug?


No issue has been reported before


Working with ServiceWorkers, they expect you to use async/await in some places

👍 4

seems to only happen when cljsjs/big is involved....


that's super strange


Yeah it has nothing to do with splicing but I can't make sense of it


(ns (:require [cognitect.transit :as t] [cljsjs.big])) is as small as I can get it


(require '
TypeError: Cannot load script from .cljs_nashorn_repl/goog/undefined
	 (NO_SOURCE_FILE <eval>:1:0)
	 (NO_SOURCE_FILE <eval>:1:0)
	 (NO_SOURCE_FILE <eval>:19:0)
	 <program> (.cljs_nashorn_repl/com/foo.cljc:5:0)
	 (NO_SOURCE_FILE <eval>:1:0)
	 (NO_SOURCE_FILE <eval>:1:0)
	 (NO_SOURCE_FILE <eval>:19:0)
	 (NO_SOURCE_FILE <eval>:1:0)


actually I can get it down to just big


@john to be clear nothing requires async/await as a language feature. You can always use promises


Yeah, but for a particular sort of control flow, when trying to hit the ServiceWorker's cache and blocking on the response, when trying to implement that in cljs... just seemed impossible. My understanding is that a cljs macro that does the same thing the polyfill does over generators, could accomplish something similar?


I ended up just tossing a js* in there, as I was mostly just exploring anyway.


Ah gotcha yea I understand what you’re saying.


Yeah, cause I think async/await (at least the polyfilled version) is rewriting the code flow, similar to core.async.


I'm starting to think that I will just stop thinking about how to make better externs (seems like the project which I inherited is in fact equivalent of having all methods defined on Object) I will just drop them completely and move to cljs-oops