Fork me on GitHub
#shadow-cljs
<
2019-02-08
>
anmonteiro09:02:18

@thheller I’m seeing flaky builds on our build with shadow related to (I think) macroexpansion

anmonteiro09:02:49

in a macro we expect a Clojure var to exist (we resolve a symbol) but the result of resolve is coming up nil on and off

thheller10:02:23

that probably is related to parallel compilation (which is why resolve is a bad idea)

anmonteiro10:02:30

that makes sense

anmonteiro10:02:49

resolve is on the Clojure side btw

anmonteiro10:02:59

during macroexpansion

thheller10:02:00

if you have no explicit dependency on a namespace there is no guarantee it will be compiled when you expect it to

anmonteiro10:02:21

we have an explicit dependency on that namespace under a :clj reader conditional

anmonteiro10:02:35

which is why this feels puzzling to me

anmonteiro10:02:29

I’ll try with :parallel-build false

thheller10:02:01

that is not supported 😉

thheller10:02:21

hang on a sec and lets track this down properly 😉

thheller10:02:32

you call resolve in a macro to resolve a CLJ var?

anmonteiro10:02:48

how is that not supported? 😄

anmonteiro10:02:52

I thought it was

anmonteiro10:02:01

let me give you a proper example

anmonteiro10:02:13

(defmacro lazy-load
  [module-id comp-sym]
  (let [comp-var (ana/resolve-var (dissoc &env :locals) comp-sym)
        comp-name (with-meta (:name comp-var) {:cljs.analyzer/no-resolve true})]
    `(LazyComponent. ~(get-query @(resolve comp-sym))
                     (fn []
                       ;; shadow loader callback, not important right now
                       (-> (~(with-meta 'shadow.loader/load {:cljs.analyzer/no-resolve true})
                            ~(name module-id))
                           (.then (fn []
                                    (resolve# (cljs.core/js-obj "default" ~comp-name)))))))))

anmonteiro10:02:25

@thheller ^ this is literally the code I’m running

anmonteiro10:02:36

the important part is ~(get-query @(resolve comp-sym))

anmonteiro10:02:04

that’s a fully qualified symbol for which we have a require in the NS declaration (on the Clojure side)

anmonteiro10:02:47

the goal here is basically to inline the Om Next query to allow for code splitting - but that’s not important right now

thheller10:02:55

hmm I don't get it? why are you calling resolve? that looks like you are trying to resolve a CLJS var using CLJ resolve?

thheller10:02:24

(with-meta 'shadow.loader/load {:cljs.analyzer/no-resolve true}) this also doesn't make sense to me?

thheller10:02:51

and what is resolve#?

anmonteiro10:02:29

that’s not the part that’s throwing

anmonteiro10:02:44

I actually elided the code a little bit, resolve# is a js/Promise.resolve

thheller10:02:46

doesn't make it any more correct

anmonteiro10:02:55

~(get-query @(resolve comp-sym))

anmonteiro10:02:58

this is the part that runs in Clojure

thheller10:02:13

yes, but why?

thheller10:02:26

can you gimme an example of the use of that macro?

anmonteiro10:02:40

because we need that value without requiring the namespace where it’s in

anmonteiro10:02:04

Om Next needs to know the query for the entire app statically

anmonteiro10:02:10

which is at odds with code splitting

anmonteiro10:02:14

so we inline it at build time

anmonteiro10:02:09

open to other suggestions if you’re seeing something I’m not

thheller10:02:10

alright I don't think this is ever going to work properly

thheller10:02:24

the code-split means that you are relying on namespaces that are not available yet

thheller10:02:31

neither at runtime nor at compile time

anmonteiro10:02:42

they are available at compile time

anmonteiro10:02:46

these are all cljc files

anmonteiro10:02:54

or they should be available

thheller10:02:04

ah I was missing that part

thheller10:02:18

so these queries exist in CLJ land as well?

anmonteiro10:02:23

we have requires for all these namespace in the clj side

anmonteiro10:02:40

these builds are flaky, they’re not 100% wrong all the time

anmonteiro10:02:52

sometimes they work, sometimes they don’t ¯\(ツ)

thheller10:02:09

FWIW I'm using code-splitting in fulcro without issues regarding queries. they are just adjusting based on what the current route is

anmonteiro10:02:26

we use a different scheme

anmonteiro10:02:41

for historical reasons it’s too much code to move

anmonteiro10:02:46

we need to adapt

thheller10:02:43

do you have an example of a component that gets lazy loaded please?

anmonteiro10:02:05

I really don’t think that matters in this case

anmonteiro10:02:35

they’re standard (defui Component static om/IQuery (query [this] [:query :here]) ...

thheller10:02:49

hmm but how is the query handled at runtime when the idents are missing?

anmonteiro10:02:35

we have a different setup, it’s not really om next anymore

anmonteiro10:02:42

we don’t need any metadata

thheller10:02:17

so I'm assuming that you are calling (lazy-load :foo some.other.ns/foo) correct?

thheller10:02:26

(defmacro lazy-load
  [module-id comp-sym]
  {:pre [(keyword? module-id)
         (qualified-symbol? comp-sym)]}
  `(LazyComponent. ~(get-query @(resolve comp-sym))
     (fn []
       ;; shadow loader callback, not important right now
       (-> (shadow.loader/load ~(name module-id))
           (.then (fn []
                    (cljs.core/js-obj "default" ~(symbol "js" (comp/munge comp-sym)))))))))

thheller10:02:34

this is what I would do

thheller10:02:53

the flakiness may be due to reloading issues

thheller10:02:11

macro reload in general only loads namespaces with the macros themselves

thheller10:02:20

it doesn't track their dependencies or reload those

anmonteiro10:02:53

this shouldn’t be reloading anything actually

anmonteiro10:02:00

it’s just building the test builds from scratch

thheller10:02:17

then cache might get in your way

anmonteiro10:02:20

@thheller I think you missed what the issue was too

anmonteiro10:02:33

you changed the part that has the comment that says not important right now

thheller10:02:37

since the query data will just magically become part of the compilation

anmonteiro10:02:39

the part that’s actually failing is the othe rone

anmonteiro10:02:57

also in this build we have :build-options {:cache-level :off}

thheller10:02:13

hmm ok so no cache

anmonteiro10:02:20

I think I’m slowly disproving your theories, apologies

anmonteiro10:02:28

let me give you the entire build config

anmonteiro10:02:33

instead of throwing pieces at you

thheller10:02:37

how is it failing when it fails?

anmonteiro10:02:46

{:cache-root (str temp-dir "/.shadow-cljs")
         :builds {:karma {:target :karma
                          :output-to (str out-dir "/test.js")
                          :ns-regexp (str "^(" (string/join "|" namespaces) ")$")
                          :build-options {:cache-level :off}
                          :js-options {:node-modules-dir node-dir}}}}

thheller10:02:27

uhm I'm assuming you are generating the config somehow?

thheller10:02:41

since that isn't a valid config 😉

anmonteiro10:02:23

what’s missing?

thheller10:02:57

your confirmation that this is generating the actual shadow-cljs.edn 😉

thheller10:02:27

ok thats fine then

anmonteiro10:02:34

there’s definitely base-config (edn/read-string (slurp shadow-edn)) in here

anmonteiro10:02:00

yeah we’re merging that in

anmonteiro10:02:13

I think those are the relevant bits anyway

thheller10:02:31

so please expand on what you mean by flaky

thheller10:02:37

how is it failing?

anmonteiro10:02:13

ok so, relevant parts of the stack trace:

File: /var/lib/buildkite-agent/builds/buildkite-5dc4755b74-2mfgf-1/ladder-life/ladder/buck-out/gen/src/ladder/__views-next_cljs_cljs_classpath__/views-next_cljs_symlink_tree.jar/ladder/views_next.cljc
null
#:clojure.error{:source "ladder/views_next.cljc", :line 438, :column 32, :phase :macroexpansion, :symbol ladder.ui/lazy-load}
ExceptionInfo:
	cljs.analyzer/macroexpand-1*/fn--2050 (analyzer.cljc:3792)
	cljs.analyzer/macroexpand-1* (analyzer.cljc:3789)
	cljs.analyzer/macroexpand-1 (analyzer.cljc:3835)
	cljs.analyzer/analyze-seq (analyzer.cljc:3870)
	cljs.analyzer/analyze-form (analyzer.cljc:4061)
	cljs.analyzer/analyze* (analyzer.cljc:4109)
	cljs.analyzer/analyze (analyzer.cljc:4129)
	cljs.analyzer/analyze (analyzer.cljc:4114)

anmonteiro10:02:17

this is not very informative

anmonteiro10:02:26

Caused by:
NullPointerException:
	clojure.core/deref-future (core.clj:2300)
	clojure.core/deref (core.clj:2320)
	clojure.core/deref (core.clj:2306)
	ladder.ui/lazy-load (ui.cljc:344)
	ladder.ui/lazy-load (ui.cljc:336)

anmonteiro10:02:28

^ this is more

thheller10:02:55

ok I suspect that this is due to your namespace setup and parallel-build

thheller10:02:23

try :compiler-options {:parallel-build false}. forgot that I added support for that not too long ago

anmonteiro10:02:36

oh so that actually does something?

thheller10:02:07

yes it compiles in dependency order which should make things more predictable

anmonteiro10:02:22

do you think adding cache-blockers in this case would do anything?

thheller10:02:29

it still might fail though

thheller10:02:42

not if you already have all cache disabled anyways

anmonteiro10:02:44

yeah I’m gonna try something different too

anmonteiro10:02:52

related to our internal setup

thheller10:02:54

you may wanna try :cache-level :jars

anmonteiro10:02:01

if you say caching is affecting things here

thheller10:02:02

oh wait .. .nvm you don't have jars 😛

anmonteiro10:02:09

yeah we don’t

anmonteiro10:02:12

buck extracts them

thheller10:02:14

that was before you said it is disabled

anmonteiro10:02:34

I meant other type of caching

anmonteiro10:02:41

we have a “tainted clojure worker”

anmonteiro10:02:57

which is a type of clojure worker that we keep around in a pool

anmonteiro10:02:02

that has done other compilation stuff before

anmonteiro10:02:11

that we reuse, to avoid starting up

anmonteiro10:02:29

so if you say caching might be a problem here, I’m gonna force this to run in a regular worker

thheller10:02:35

well that may be a problem regarding the CLJ part of things

anmonteiro10:02:46

which is what’s happening here 🙂

thheller10:02:06

but if it is loading the same files that is not a problem

thheller10:02:36

only a problem if you have multiple versions of the same CLJ namespace

thheller10:02:06

the NPE likely happens when you try to (lazy-load :foo 'some.other/thing) and some.other/thing isn't loaded on the CLJ side

thheller10:02:35

which may be a missing require that would sometimes get loaded by other namespaces during parallel compile

thheller10:02:55

so it may appear to be available sometimes given how busy your compile threads are

thheller10:02:44

without parallel-build and a clean worker the build should always fail with the NPE in the case of a missing require on the CLJ side

anmonteiro10:02:20

@thheller the require is 100% not missing

anmonteiro10:02:29

and it’s in the classpath for sure too

anmonteiro10:02:31

I’ve triple checked

anmonteiro10:02:32

the thing I haven’t ruled out yet is the tainted persistent worker

thheller10:02:51

you can always add a (prn [:resolve (resolve comp-sym)]) in the macro

thheller10:02:10

that will only confirm that the symbol is nil but still

anmonteiro10:02:18

yeah the result of resolve is nil

thheller10:02:48

you can add the (prn [:loading-that-namespace]) to the namespace the resolve is referencing

thheller10:02:59

which will probably be missing

anmonteiro10:02:05

indeed, I’ll try that

thheller10:02:22

of you can fire a require for the sym to ensure

thheller10:02:59

although you gotta be careful with that or use the new require thing in 1.10

anmonteiro10:02:03

yeah that’s the last option

anmonteiro10:02:11

yeah requiring-resolve might help me here

thheller10:02:16

the one that locks the require

thheller10:02:19

yeah that one

anmonteiro10:02:20

or however it’s called

thheller10:02:45

otherwise one thread may start the require and another thread may start using it while it is still loading

anmonteiro11:02:19

@thheller I think moving it to the non-tainted worker made it work - even though the build is taking a lot longer (expected). so I’ll just use requiring-resolve, otherwise the build time is infeasible

thheller11:02:28

without any caching the build times can go up very significantly yes

thheller11:02:16

parallel-build shouldn't make that much of a difference overall, depends on how parallelizable your compile is

anmonteiro11:02:16

no I mean we have a bunch of “targets” that we build separately (because Buck)

anmonteiro11:02:46

so we really need to have some compile cache (especially on the Clojure side) between building and running those targets

anmonteiro11:02:56

that’s what the tainted worker does for us

anmonteiro11:02:36

btw this is also why we want Clojure to have a stable ABI

anmonteiro11:02:45

it would make all this much easier

anmonteiro11:02:01

@thheller maybe I can nerdsnipe you into making ClojureScript have a stable ABI 😛

anmonteiro11:02:12

e.g. through shadow

thheller11:02:38

what does that mean to you?

anmonteiro11:02:39

requiring-resolve made the build work instantly

anmonteiro11:02:57

it means that if you can have truly separate compilation

anmonteiro11:02:27

say you have namespaces:

A
  /   \
B     C

anmonteiro11:02:05

triggering a change in C shouldn’t need for A or B to get recompiled

anmonteiro11:02:14

and this goes further than having the transit cache too

thheller11:02:31

thats already how it works?

anmonteiro11:02:45

it’s not, really

thheller11:02:02

well I guess you want to isolate it more by keeping it entirely out of process

anmonteiro11:02:08

because if you compile A and exit

anmonteiro11:02:11

then compile B

anmonteiro11:02:23

the 2nd run still does some work for A

thheller11:02:36

well it reads the compiler cache for A

thheller11:02:38

but thats it?

thheller11:02:28

(assuming you have cache enabled of course)

anmonteiro11:02:31

I don’t think that’s the only work it does

thheller11:02:15

it doesn't do any compiler work, it does a bit to restore cache into the right places and stuff

anmonteiro11:02:18

maybe in the example I gave it is

anmonteiro11:02:42

but once you have a more complex dep graph there’s lots of work happening that wouldn’t need to happen

thheller11:02:06

hmm no not really. the caching stuff ensures that only the work that needs to happen actually does happen

thheller11:02:51

validating the cache and loading it is a bit of work yes but involves no actual compiler work

anmonteiro11:02:08

I’m pretty sure I’m forgetting something here

anmonteiro11:02:19

I’m fuzzy on the details

thheller11:02:44

well cache invalidation sometimes invalidates too much

anmonteiro11:02:03

the gist of the issue is: if you have a build tool that calculates your dep graph already, you don’t need the cljs compiler trying to do it for you too

anmonteiro11:02:13

and then all the consequences that that entails

thheller11:02:13

well but how does your tool compute the dep graph? that is a non trivial task?

thheller11:02:54

ie. parse all the ns forms of all namespaces, account for macros, npm dependencies, resolve all those with all the "browser" rules and stuff

anmonteiro11:02:14

we parse the NS deps

anmonteiro11:02:17

and hand it to buck

anmonteiro11:02:24

then we auto generate a file with all the deps

anmonteiro11:02:34

given it needs to be static

thheller11:02:34

a rather big chunk of shadow-cljs is determining when to cache and when to recompile

thheller11:02:58

so I don't quite unterstand why you'd want to repeat that in buck

anmonteiro11:02:47

it’s not that we want

anmonteiro11:02:06

it’s that Buck already does it for us

anmonteiro11:02:27

and has a distributed cache, so if we built something on CI, Buck just downloads it to our laptops

anmonteiro11:02:23

in fact we actually let Shadow take over when building CLJS

anmonteiro11:02:49

so we don’t actually enforce the Buck best practices when using Shadow

thheller11:02:02

is there some extra data I could output that would be useful for Buck?

anmonteiro11:02:04

simply because we’d need to get out of our way to do it with lots of custom / brittle code

anmonteiro11:02:20

I’m not sure. I’m gonna raise that question internally

anmonteiro11:02:54

I don’t think it’s that easy

anmonteiro11:02:05

the whole compilation model would need to be different

thheller11:02:46

is your Buck interface to CLJS something open source?

anmonteiro12:02:23

this is very outdated

anmonteiro12:02:32

but it’s how we used to do it with the bare CLJS compiler

anmonteiro12:02:36

shadow now takes over

thheller12:02:01

> The biggest benefits of using buck come from using the artifact cache. It's especially useful if you have several developers working on the same codebase since the cache can be distributed. You may also see better CI times with buck caching if you configure your CI to cache the buck-out directory between runs.

thheller12:02:16

cache .shadow-cljs/builds and you get that for CI as well

anmonteiro12:02:32

right but we already bought into buck

anmonteiro12:02:42

just so we get that for Clojure code too

anmonteiro12:02:59

to be fair this might be one of those things where you have to experience it to believe it

anmonteiro12:02:02

I was this way too

thheller12:02:22

yeah I don't know Buck at all so I don't know how it does things

thheller12:02:33

this is a verbose compile log of a test build that is fully cached

anmonteiro12:02:17

so rephrasing my earlier statement

thheller12:02:20

so those are pretty much the steps Buck would have to replicate

anmonteiro12:02:33

I believe that Shadow and the ClojureScript compiler do have intermediate caching and cached builds

anmonteiro12:02:48

my problem is that the ABIs are not stable or public

anmonteiro12:02:01

imagine that in my earlier A, B, C example

anmonteiro12:02:09

if you added one function to A that neither B or C used

anmonteiro12:02:15

those are gonna get recompiled anyway

anmonteiro12:02:39

that kind of fine grained control is something that we could implement if there was actually an ABI

thheller12:02:41

yes that is true. given the dynamic nature of CLJ(S) that is probably never going to change

thheller12:02:56

it is something I have been thinking about quite a bunch since it could also speed up live-reloads

thheller12:02:10

ie. you have (defn foo [] 1) in some namespace

thheller12:02:25

you change it to (defn foo [] 2) all namespaces that require this will be fully recompiled

thheller12:02:37

although the signature didn't change so its pointless to do that

thheller12:02:49

so during namespace compiling you track what signatures you used from other namespaces and check if they changed

thheller12:02:07

that is quite doable ... but then you add macros and everything goes completely crazy 🙂

thheller12:02:47

then you do a requiring-resolve in some macro and things get even more crazy 🙂

anmonteiro12:02:32

now you get it 🙂

thheller13:02:16

@anmonteiro this is somewhat related. how would you teach Buck that also depends on demo/test.md. https://clojureverse.org/t/using-none-code-resources-in-cljs-builds/3745

anmonteiro13:02:06

oh that’s trivial I think

thheller13:02:10

side-effecting macros is not something other languages have to deal with 🙂

anmonteiro13:02:21

Buck targets depend on other targets

anmonteiro13:02:40

so you’d make one target that encompasses the resources folder

anmonteiro13:02:55

and make your JS bundle target depend on that

jlmr15:02:12

Hi! When coding clojure I’m using a socket repl (in conjunction with REBL). Now I’m trying to add clojurescript using shadow-cljs, I’m a bit stuck on how to get everything working together. I’m using deps.edn. Can anyone point to a working example?

thheller15:02:54

@jlmr not sure that works yet. I haven't run REBL yet since it doesn't seem to like Java11 and Windows

thheller15:02:17

I'm not sure what it needs or if its even supposed to be supported

jlmr16:02:57

Ok, good to know. For now I got everything going, but without REBL

eccentric J18:02:16

Hello I’m trying to use clojure/tools.cli with shadow-cljs but I’m seeing a couple of warnings:

------ WARNING #1 - :undeclared-var --------------------------------------------
 Resource: clojure/tools/cli.cljc:126:17
--------------------------------------------------------------------------------
 123 |          (recur options (into extra-args (vec (rest args))) nil)
 124 |
 125 |          (and (opt? opt) (nil? spec))
 126 |          (throw (Exception. (str "'" opt "' is not a valid argument")))
-----------------------^--------------------------------------------------------
 Use of undeclared Var clojure.tools.cli/Exception
--------------------------------------------------------------------------------
 127 |
 128 |          (and (opt? opt) (spec :flag))
 129 |          (recur ((spec :assoc-fn) options (spec :name) (flag-for opt))
 130 |                 extra-args
--------------------------------------------------------------------------------

------ WARNING #2 - :undeclared-var --------------------------------------------
 Resource: clojure/tools/cli.cljc:228:25
--------------------------------------------------------------------------------
 225 |   (when *assert*
 226 |     (let [unknown-keys (keys (apply dissoc map spec-keys))]
 227 |       (when (seq unknown-keys)
 228 |         (binding [*out* *err*]
-------------------------------^------------------------------------------------
 Use of undeclared Var clojure.tools.cli/*err*
--------------------------------------------------------------------------------
 229 |           (println (str "Warning: The following options to parse-opts are unrecognized: "
 230 |                         (s/join ", " unknown-keys)))))))
 231 |
 232 |   (select-keys map spec-keys))
--------------------------------------------------------------------------------

thheller20:02:36

the warning looks legit. CLJS doesn't have a Exception class. I guess someone didn't actually test this much.

thheller20:02:05

cljs also doesn't have *err*

eccentric J20:02:28

Oof ok thanks again. I’ll see if an error was reported and report one if it doesn’t.

eccentric J18:02:03

Should I use a different library?

conan18:02:23

I'm getting a compilation error every time I run yarn shadow-cljs watch app:

[:app] Build failure:
------ ERROR -------------------------------------------------------------------
 File: jar:file:/mnt/c/Users/conan/.m2/repository/org/clojure/clojurescript/1.10.439/clojurescript-1.10.439.jar!/
cljs/core.cljs:999:14
--------------------------------------------------------------------------------
 996 |     (if (js/isFinite o)
 997 |       (js-mod (Math/floor o) 2147483647)
 998 |       (case o
 999 |         ##Inf
--------------------^-----------------------------------------------------------
No reader function for tag Inf

--------------------------------------------------------------------------------
1000 |         2146435072
1001 |         ##-Inf
1002 |         -1048576
1003 |         2146959360))
--------------------------------------------------------------------------------
Any ideas why? I found some discussion of this error that referred to tools.reader, but it's old and my lein deps :tree says I'm using [org.clojure/tools.reader "1.3.2"]. https://clojurians-log.clojureverse.org/shadow-cljs/2017-10-03

eccentric J18:02:12

What is your use case for tools.reader over the built-in read-string?

thheller20:02:12

cljs.reader/read-string actually uses tools.reader so there isn't any difference

eccentric J20:02:56

Oh I see, thanks.

conan12:02:12

It's a transitive dep pulled by shadow-cljs, I don't use it directly.

👍 5
idiomancy19:02:15

Anyone ever run into Invariant Violation: Target container is not a DOM element. with shadow? I do have the script tag after the root node in the body

lilactown19:02:09

guessing this is a React app?

lilactown19:02:29

what's the code you're using to render

idiomancy19:02:40

reframe. just a sec..

idiomancy19:02:16

I mean, reagent technically. but its... oh...

idiomancy19:02:37

(re/render [admin-panel] (.getElementById js/document "app")) lol, copypaste from old deps.edn code. should be "root" 😂

🎉 5
idiomancy19:02:37

(re/render [admin-panel] (.getElementById js/document "app")) lol, copypaste from old deps.edn code. should be "root" 😂

🎉 5
idiomancy19:02:02

works now, thanks for the sanity check @lilactown

👍 5
thheller20:02:43

@conan that is indeed a tools.reader conflict. you can check if you actually get the version you expect by using shadow-cljs clj-repl and ( "cljs/tools/reader.cljs")

conan12:02:28

Yep, here's the output:

[1:0]~shadow.user=> ( "cljs/tools/reader.cljs")
#object[java.net.URL 0x1d579f90 "jar:file:/mnt/c/Users/conan/.m2/repository/org/clojure/tools.reader/1.3.2/tools.reader-1.3.2.jar!/cljs/tools/reader.cljs"]

conan12:02:45

looks like 1.3.2, which I understand to be correct?

thheller20:02:52

do you have a profile or something else that may affect the classpath?

conan12:02:23

no profiles, I'm using :lein true and :target :node-library, maybe they affect the classpath? here's my shadow-cljs.edn:

{:lein true
 :builds {:app {:target :node-library
                :exports {:handler conan.core/handler}
                :output-dir "target"
                :output-to "target/main.js"}}}

thheller12:02:36

are you sure you are getting the correct versions of the other deps?

conan12:02:44

here's my project.clj:

(defproject conan "0.1.0-SNAPSHOT"
  :min-lein-version "2.7.0"
  :dependencies [[com.cemerick/url "0.1.1"]
                 [com.taoensso/timbre "4.10.0"]
                 [io.nervous/kvlt "0.1.4" :exclusions [org.clojure/clojurescript]]
                 [org.clojure/clojure "1.10.0"]
                 [org.clojure/core.async "0.4.490"]
                 [thheller/shadow-cljs "2.7.11"]]
  :source-paths ["src/cljs"])

thheller12:02:48

clojure 1.9+, clojurescript 1.10.516?

conan12:02:16

i have clojure 1.10 but clojurescript 1.10.439. i don't actually specify clojurescript in my deps as i assumed it would be better to let shadow-cljs choose, should i be explicit?

thheller12:02:58

2.7.11 with 439 is correct

conan12:02:13

yeah it all looks like it checks out

thheller12:02:19

I don't know honestly .. debugging dependency issues is hard. just don't use project.clj

thheller12:02:30

could be something in your .lein/profiles.clj

thheller12:02:10

if I use that project.clj the deps look ok

conan12:02:29

oh good idea, but i don't actually have a .lein/profiles.clj. didn't think of it though

thheller12:02:50

everything compiles and runs fine for me using your project.clj and config

thheller12:02:16

running npx shadow-cljs node-repl since I have none of you sources

thheller12:02:27

but that compiles cljs.core which fails for you

conan12:02:12

yeah that seems to be the problem. i'm guessing there are no compilation errors in there...

thheller12:02:04

the error you posted is a rather old one and was caused by invalid tools.reader versions

thheller12:02:10

but since you checked that you have the correct one

thheller12:02:15

I don't know what else to check

conan12:02:26

yeah i think there must be something else getting in the way

thheller12:02:51

if you remove lein and move the dependencies to shadow-cljs.edn and still run into this issue let me know

thheller12:02:08

otherwise I don't know

conan12:02:20

thanks very much for your help. i'll try starting a new project from scratch and slowly introducing stuff until it breaks (or doesn't). maybe it's just a gremlin ¯\(ツ)

thheller12:02:49

there isn't really anything you need to change

thheller12:02:57

just try it in your current state

thheller13:02:22

do NOT change anything other than removing :lein true and copying :dependencies to shadow-cljs.edn

thheller13:02:38

if that works you have at least isolated it to leiningen

thheller13:02:45

starting from scratch will tell you nothing

jstaab23:02:46

Hey there, I'm trying to get a quick turnaround when developing a library against another application I have by running watch on the library and copying the bundle over to my app's node_modules folder and restarting the (create-react-app, which wraps webpack) dev server there. It appears to work fine when I run release, but if I watch, I get Error: browser bootstrap used in incorrect target. Any reason for this or way I can get it to work? I'm using es6 modules, which I believe compile down to require calls. I tried the solution here: https://github.com/thheller/shadow-cljs/issues/376 but it's not exactly my situation and it seemed to make things worse.

currentoor23:02:13

I know in a macro definition we can use (boolean (:ns &env)) to detect if this macro is being used in CLJS code, but is there a way to detect, in a macro, that this macro is being called in regular browser cljs or nodejs?