Fork me on GitHub
#shadow-cljs
<
2022-06-21
>
simongray09:06:30

quick question about inferring externs. The documentation says: > No hint required, externs inferred automatically >

(js/Some.Thing.coolFunction)
but does this also extend to objects create via js/f calls? e.g. in (let [d (js/Date. x)] (.toLocaleDateString d)) would d be correctly inferred to be a js object in the let clause?

thheller09:06:59

yes, but only in the scope of the let

🙏 1
simongray09:06:49

any more general advice on how to find places where externs are needed? :S the advanced compilation output is difficult to get information out of

simongray10:06:39

I’m making externs for manually added files, this stuff doesn’t exist on NPM

thheller10:06:33

well, thats what externs inference warnings are for?

thheller10:06:41

also what does "manually added files" mean? dunno what npm has to do with this?

simongray10:06:47

I have a bunch of JS files from an ancient JS lib and I have a Clojure namespace that is wrapping parts of them

simongray10:06:55

I get runtime errors such as

main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:145 TypeError: f.Sf is not a function
    at c.<anonymous> (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:2192:336)
    at c.componentDidMount (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:1647:332)
    at uj (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:147:464)
    at Ej (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:183:21)
    at ea.unstable_runWithPriority (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:27:21)
    at Ac (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:80:117)
    at bd (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:176:83)
    at Fg (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:168:106)
    at main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:80:407
    at ea.unstable_runWithPriority (main.0943529B7909B0E1E5BADC7C3B265449.js?-2052149777:27:21)
so I get the general area and I have tried annotating js/BlabBla where needed, but to no avail.

simongray10:06:48

I guess I’m just gonna keep trying things out, but it’s a shame that this externs inference step seems to revert my workflow to “fix bugs, recompile, repeat ad infinitum” like in the old days :P

thheller10:06:37

to debug this use shadow-cljs release app --pseudo-names

thheller10:06:55

that will at least make this more debuggable TypeError: f.Sf is not a function

thheller10:06:30

I'd be curios to see the code snippet causing this

thheller10:06:46

maybe its just a case missed by externs inference

thheller10:06:20

but you didn't really answer my question. "I have a bunch of JS files from an ancient JS lib". how are you including them?

thheller10:06:41

just entirely separately outside of the shadow-cljs build? or included in the build somehow? depending on how they are included affects how and what externs are needed

simongray10:06:41

the only way I know how: using <script> in <head>

thheller10:06:16

ok, thats fine. so all access is via js/...

simongray10:06:54

and (.methodName …)

thheller10:06:13

those should be covered by externs inference

simongray10:06:23

I guess, but I guess some are missed, likely by my own efforts. Gonna try your suggestion and add pseduo-names

thheller10:06:55

should be easy to identify with pseudo names enabled. it'll just rename .methodName properties to .$methodName$ or so

thheller10:06:02

still renaming it, but with a recognizable name

simongray10:06:15

yes, it’s already helping me locate the issues. Thanks a lot!

simongray10:06:58

JS is confusing…

simongray11:06:21

can I annotate using ^js/Timeline._Impl (Timeline._Impl.prototype is where the troublesome methods are defined in the JS files) or do I need to use ^js only like is used in the shadow-cljs documentation?

thheller12:06:41

@simongray you can annotate like that but the end result is exactly the same as just ^js. nothing else is gained. it doesn't magically gain knowledge of more properties or something

thheller12:06:34

do you have examples of where you need to add typehints but don't get warnings?

simongray12:06:21

this namespace

simongray12:06:48

I’ve tried adding ^js everywhere it makes sense, but it doesn’t seem to do anything

simongray12:06:57

in this case

thheller12:06:21

I personally prefer adding the ^js hint on declaration

thheller12:06:31

but you should be getting inference warnings for all of those cases?

thheller12:06:50

which shadow-cljs version do you use? or did you explicitly turn it off?

thheller12:06:17

meaning tl (draw-timeline! new-state) becomes ^js tl (draw-timeline! new-state)

thheller12:06:35

(when-let [tl* (and tl @tl)] (when-let [^js tl* (and tl @tl)]

simongray12:06:30

I don’t think I’ve turned it off. I do get a warning for something in tick-rc6, but that doesn’t seem to affect the project.

thheller12:06:07

hmm yeah I just checked

thheller12:06:14

there should definitely be warnings but they are missing somehow

thheller12:06:20

and even though you are adding js hints the externs are still missing

simongray12:06:16

tried pretty much adding every type of extern everywhere I could

thheller12:06:33

hmm yeah something is definitely off in this project. If I just add

(defn yo [x]
  (.whyUNOINFER x))
anywhere I don't get any inference warnings. on all my other projects I do

thheller12:06:48

so not sure what is going on 😛

thheller12:06:47

hmm removing :compiler-options {:data-readers true} turns them back on

thheller12:06:50

not sure why though

simongray12:06:31

well, the issue surfaced when I recently updated the deps and I think I had to add that line due to some conflict between shadow-cljs and the latest version of tick

thheller12:06:11

I don't get why that even affects inference in any way. its not even remotely close code wise

thheller12:06:30

must be something weird or obvious 😉

simongray12:06:43

hah, yeah that does seem quite strange

simongray12:06:32

well, it’s only weird until it’s completely obvious 😛

thheller13:06:38

doh, yeah found it

simongray13:06:07

Are you saying that for once it wasn’t myself who fucked up, but it was actually a bug in shadow-cljs??

simongray13:06:36

That is a first. Well, glad to be of service :P

thheller13:06:57

@simongray try 2.19.4. at the very least you should be getting inference warnings again. and the tags should be respected and actually generate externs.

1
simongray13:06:50

I think that did the trick.

Alys Brooks18:06:38

When the manual says shadow-cljs doesn't support CLJSJS "at all", does that mean it doesn't support dependencies that themselves rely on CLJSJS? Or does shadow-cljsjs take care of that?

Alys Brooks18:06:03

Never mind, reading the section again, it appears shadow-cljsjs does take care of that.

thheller18:06:38

yes, that is the intent

Alys Brooks18:06:59

If I want to add a file to shadow-cljsjs, is adding a dependency to a local copy and an exclusion enough or does shadow-cljsjs do something special to pull in shadow-cljsjs?

thheller/shadow-cljsjs {:local/root "../../../shadow-cljsjs"} 
thheller/shadow-cljs {:mvn/version "2.11.23" :exclusions [thheller/shadow-cljsjs]  }
(Eventually I'll submit a PR but I want to get it working first)

Alys Brooks18:06:11

Okay, it appears that does work, I just forgot to replace the hyphen in my new file's name with an underscore.

thheller19:06:20

@actuallyalys_slack you don't need to add files to shadow-cljsjs. just add the file to your own classpath (ie. one of your :paths)

Drew Verlee21:06:33

if my shadow project has a .cljc file on the path that contains the expression (println "x") should i expect to see "x" my terminal when i watch the build?

Drew Verlee21:06:57

I feel like the answer is defiantly yes, yet i feel like that more or less what i'm not seeing in my current project so i'm trying to sanity check some concepts....

Drew Verlee21:06:06

if i put a clj or cljc file on shadows path, it reads it because it's compiling the cljs to js using clj (correct me if i'm wrong). So it should absolutely see that file, and execute any expressions in it.

isak21:06:55

I think you'd need to require the namespace somewhere for that to be true, no?

Drew Verlee21:06:32

It is required. But yea, i assume so to.

isak21:06:51

Ah ok. Have you tried changing it to spit out a file or something instead? It could be something with the out being redirected or something. I would test something that won't be affected by that.

thheller21:06:58

@U0DJ4T5U1 .cljc means nothing. the question you need to answer in which context the thing is eval'd

thheller21:06:16

when it is compiled as CLJS you will see the println when it is loaded in the JS runtime (eg. browser)

thheller21:06:52

when it is compiled in CLJ you will see it during compilation (although where is not entirely clear since it goes to *out*, which may not be where you are looking)

thheller22:06:09

it is only loaded in CLJ when required as a macro namespace, ie :require-macros

1
Drew Verlee22:06:09

I'll check again, i don't see it in either context so i must have a path issue. I'll check what *out* is bound to. Thanks I'll check how it's loaded again to.

thheller22:06:02

I'd say your assumption of "definitely yes" seems wrong

thheller22:06:41

since regular CLJS compilation will not actually eval any CLJS code, it is just translated to JS

thheller22:06:41

as for *out* it defaults to wherever shadow-cljs was started. dunno how you are starting it

Drew Verlee22:06:07

It runs via my terminal with the cmd line shadow-cljs watch app. When it compiles (println "hello") into js won't that run when the browser gets the .js file and interprets it?

thheller22:06:02

yes it will. but those prints end up in the browser console not the terminal

Drew Verlee22:06:27

Yep, that's what i understand happens as well. Ty. In the morning this will all seem as clear as day I'm sure