Fork me on GitHub

I don't understand the AST in the compiler, so I don't understand its role in generalizing my hack into a general fix. I'll try to dig into it if I have a bit more time. I need to figure out how to have my own debug build of cljs so I can modify it while I'm using it to get some insight into how things work.

Sam Ritchie14:07:33

Hey all! I'm about a day in to a pretty brutal struggle, trying to generate a cljsjs dependency for Complex.js. I figured it was time to tap out and report here. I can repro all of this, but first let me sketch...

Sam Ritchie14:07:31

I'm using "lein doo node main once" to run my tests; everything works wonderfully with :optimizations :none with the jar I've generated containing the code for complex.js

Sam Ritchie14:07:00

but when I move to :optimizations :simple, I get an error stating that Complex does not exist; ie, the js/Complex reference is now failing to pick anything up

Sam Ritchie14:07:44

(I've tried repackaging the dependency using an npm bundle; unfortunately with this method I can't get js/Complex to resolve at all)

Sam Ritchie14:07:53

happy to provide more info, but has anyone seen anything like this before?


Is there any syntax for creating js objects with symbols for keys rather than string literals? E.g., like #js {:foo "bar"}, except yielding {foo: "bar"} instead of {"foo" : "bar"}


@isak there is no difference? all JS objects just have string keys


There is a difference for advanced compilation, no? @thheller


if you want foo to be renamed yes?


then you likely should just use (deftype Something [foo]) or so

AJ Jaro14:07:17

Is anyone using with puppeteer for UI-related tests? I’m struggling with getting a basic example working


Hmm, well since it is a parameter for a function defined in JS, it is easier to just create an object and call (set! (.-foo o) ...) on it, just wanted to know if there was syntax for it, but I guess not

Sam Ritchie15:07:08

If anyone does have any insight on the above... here is the code that gets built: 

Sam Ritchie15:07:10

the JS, that is

Sam Ritchie15:07:16

under simple optimizations

Sam Ritchie15:07:55

so, I DO see that there is no Complex object getting set...

Sam Ritchie15:07:53

I seem, actually, to not be able to get ANY cljsjs dependency to work

Sam Ritchie15:07:58

in more than :none mode

Sam Ritchie15:07:10

so, any tips or pointers to a project that can do this would be much appreciated!


@sritchie09 no pointers w/o something minimal - post something tiny that demonstrates your CLJSJS problem, I'm quite skeptical about that one


but maybe if someone can you straight about that, the rest will make more sense


also your problem seems tied up w/ testing - you haven't said if this only about testing and not in other cases

Sam Ritchie15:07:25

@dnolen yup, I've almost got a repro together

Sam Ritchie16:07:24

here's the cljsjs build;

Sam Ritchie16:07:39

and here's the minimal repro

Sam Ritchie16:07:12

@dnolen yes, so far this is only with the testing environment. only because I haven't yet tackled how to get a repl open pointing at an advanced compilation target


Not possible


For testing simple isn’t usually meaningful - advanced

Sam Ritchie16:07:48

yes, that fails as well, unfortunately. I've exported the top level function, let's see if I can get it running from phantomjs

Sam Ritchie16:07:48

no luck, just this test failure

Sam Ritchie16:07:51

@dnolen do you have any pointers to some other way I can attempt to run these tests? I promise I've been searching everywhere; it is not so obvious finding small examples. I suspect that I've got something busted in my project.clj, or the way I'm setting up the clojurescript compiler options;

Sam Ritchie16:07:12

this is because I see the same error with other dependencies that already exist on cljsjs, like cljsjs/bn when I pull that in instead as a test. In that case, BN is not defined

Sam Ritchie16:07:40

I'd be thrilled to use a different test runner, for example, if you think that might be the issue, and have a pointer to something more maintained / newer

Sam Ritchie16:07:59

ERROR: JSC_MISSING_MODULE_OR_PROVIDE. Required namespace "cljsjs.complex" never defined. at /Users/samritchie/code/clj/complex-failure/out/example/core.js line 4 : 0

Sam Ritchie16:07:06

here's the error from the headless chrome runner

Sam Ritchie16:07:40

LOG: 'Testing example.core-test' Chrome 84.0.4147.89 (Mac OS 10.15.5) example.core-test complex FAILED FAIL in (complex) (/Users/samritchie/code/clj/complex-failure/test/example/core_test.cljs:6:7) (= 1 (.-re (core/complex 1 2))) failed with ReferenceError: BN is not defined

Sam Ritchie16:07:38

with a different cljsjs library, same error when I try to reference the main object available as js/BN. cljsjs's documentation seems very clear that this is the way to reference anything made available through that dependency mechanism, and it does indeed work well with :none optimizations

Sam Ritchie16:07:32

I've been searching for any project with tests that uses any dependency from cljsjs, which I'm sure exist, but the search is not easy. does anyone have a pointer toward some project with advanced tests that is successfully using a cljsjs dependency? if I can get that specific dependency, which I KNOW should work, then i should be able to debug my cljsjs dep more easily

Sam Ritchie16:07:50

amazing, @dnolen they seem to both actually work when using the chrome headless runner


huh ok - like I was trying to imply above this sounded like it might be something to do w/ your testing setup


probably not ClojureScript

Sam Ritchie17:07:13

yeah, no doubt, it's more the difficulty of finding example setups to copy

Sam Ritchie18:07:56

@dnolen interesting update

Sam Ritchie18:07:04

my failing repro works fine with [org.clojure/clojurescript "1.9.946"]

Sam Ritchie18:07:43

fails to execute with [org.clojure/clojurescript "1.10.773"]

Sam Ritchie18:07:38

ERROR: doo was not loaded from the compiled script.

Make sure you start your tests using doo-tests or doo-all-tests
and that you include that file in your build

Subprocess failed (exit code: 1)
with this error, with the phantomjs runner

Sam Ritchie18:07:17

@dnolen let me find the version where it cuts over to failing


@sritchie09 I probably won't look at personally look at something like this until it's determined that it isn't actually a problem with doo

Sam Ritchie18:07:52

yes, that makes sense. I'm so rusty at all this that I figured I'd just gather what I can


I believe those two versions are more than 1 1/2 apart and with changes outside of our control in Closure Compiler and GCL

Sam Ritchie18:07:02

1.10.597 works, 1.10.741 fails


those two version are probably two years apart - this is not informative 🙂

Sam Ritchie18:07:08

@dnolen but I hear you! I'll drop to something that works for me and hold off for a while, here


it's likely someone else encountered this - I don't use doo myself so I really can't be of any help


at least around the part of determining if the problem is in doo in that it relies on something it can't rely on anymore around loading stuff, really who knows

Sam Ritchie18:07:05

sg, thanks for the comments, in any case! the current project is converting the engine behind Sussman's Structure and Interpretation of Classical Mechanics to cljs

Sam Ritchie18:07:31

so we can have an interactive advanced mechanics engine in the browser, with automatic differentiation in clojurescript coming along for the ride


my suggestion would be to just focus on what you're doing, unless you want to sink time into doo


if the logic is pure what is the point of running the tests in the browser

Sam Ritchie18:07:20

yes, node wasn't seeing any imported classes from cljsjs, ie, js/Complex, in anything other than :none compilation mode


running tests in any mode other than none is really only about one thing


that you didn't mess up externs somehow


but it's not really that meaningful otherwise

Sam Ritchie18:07:05

yes, for sure

Sam Ritchie18:07:26

oh, I see - you're saying, for tests, just stick to :none and move on


personally I never use anything but my own runners because whatever time is lost on setting that is less than the time to figure out what's wrong in my deps

Sam Ritchie18:07:41

I've learned that lesson viscerally today, I think


everybody has a different tolerance for this stuff, mine is very low


this isn't a knock against doo, it seems popular but I can't shed any light on it

Sam Ritchie18:07:33

I think I've discovered here that I can make it work if I need to with an older cljs version with no debugging, and I appreciate the time from you, really

Sam Ritchie18:07:53

and I did find one bug! I was doing some inspection of js-keys of functions to try and figure out function arity at runtime

Sam Ritchie18:07:05

which, of course, all gets munged away by the advanced compiler

Sam Ritchie18:07:36

I'm guessing that's not something that's possible to recover

Sam Ritchie18:07:01

without, say, a custom fn macro that snags the information at function definition time


yes you can't figure out arbitrary function arity at runtime


this is especially tricky because Clojure(Script) fns support more features than JS fns


(fn [f] (arity f ...))




(arity some-f) possible


because arity could be a macro that gets that info at compile time

👍 3
Sam Ritchie18:07:50

we're looking for the three cases of "exactly", "between", "at-least", so maxFixedArity gives us something, at least, with a fallback to assuming a single arg


another possible option is passing vars instead of direct fns


#'foo will dump something with the var meta - it will have a bunch of information

Sam Ritchie18:07:27

okay, that's excellent

Sam Ritchie18:07:00

thanks for the advice, and the larger, life advice of not spending too much time getting pulled into debugging build tools

Toni Dahl18:07:10

@sritchie09 I'm a bit late in this discussion, so I didn't read every bit of it. I wrote this blog post partially out of my own frustration. It might help you or not:


and I believe (#'foo) will work like in Clojure? I can't remember - if it doesn't that should be fixed

Sam Ritchie18:07:01

thanks, @toni.dahl , I think the bug I'm hitting is a more subtle problem with lein-doo

✔️ 3

@sritchie09 your js/Complex missing issue is coming from the js file itself not always creating that global as far as I can tell

Sam Ritchie20:07:42

@thheller that makes sense, of course... that particular issue only occurs when lein-doo uses the node runner


thats the common UMD style wrapper and in node it will take the typeof exports branch since it will exist


as such it will not take the last branch which creates the global

Sam Ritchie20:07:16

@thheller so this change needs to happen back in the original dependency, I suppose?

Sam Ritchie20:07:19

to work with node


to work with CLJSJS on node yes. it is not a fault in the library itself, it will likely work just fine in regular node.

Sam Ritchie20:07:06

got it! okay, that's a great note, and I'll cross that bridge in the future


Hi all! Does anyone have experience using xmpp.js (we’re going to be using with cljs? If so, what are your experiences? Any pitfalls you would advise others of? Thanks!