Fork me on GitHub
#shadow-cljs
<
2022-09-27
>
wombawomba10:09:28

I'm trying to require a lib (xterm.js) that the Clojure compiler refuses to compile (similar to https://github.com/thheller/shadow-cljs/issues/971). If I include the built library as a script directly in my HTML, everything works. However, I'd like to load the library dynamically, and am using require.js for this. The library loads fine and require.js gives me a handle to it, but the CLJS compiler is giving me "Cannot infer target type in expression" when I try to call functions in the library (e.g. (js/require ["xterm"] #(.Terminal %))). What's the recommended/proper way to solve this? Do I need to manually write an externs file?

thheller10:09:23

@wombawomba please include the actual error you get, otherwise I can't comment at all

thheller10:09:19

also no clue what (js/require ["xterm"] #(.Terminal %)) this is supposed to be? ah I guess require.js

wombawomba10:09:28

yeah that's require.js

thheller10:09:25

I have used xterm in the past without issues, so what is the actual problem?

wombawomba10:09:50

the literal error for the snippet I posted is Cannot infer target type in expression (. p1__240117# Terminal)

thheller11:09:06

the not-require.js version

wombawomba11:09:10

putting [xterm :refer [Terminal]] in my (:require ...) statement gives the following error (for xterm 5.0.0, which is the latest version):

Closure compilation failed with 1 errors
--- node_modules/xterm/lib/xterm.js:2
Illegal variable reference before declaration: e

thheller11:09:25

hmm yeah they seem to have changed their bundle method

wombawomba11:09:30

Perhaps this is because it's picking up the built and minified xterm.js at xterm/lib/xterm.js, and I should be requiring something else?

thheller11:09:31

can reproduce it locally

thheller11:09:50

no, there is only that version in the package

thheller11:09:55

apart from some .ts sources

wombawomba11:09:42

so anyway, do you have a recommended course of action here?

wombawomba11:09:30

Is there a way to force cljs to make the .Terminal call verbatim without bothering with externs, or do I need to add an externs file?

thheller11:09:03

thats what externs inference is for. you just help it with a ^js tag

thheller11:09:15

(js/require ["xterm"] #(.Terminal ^js %)) should be enough

wombawomba11:09:33

yeah that did the trick

wombawomba11:09:50

wait, crap, that gives me an error at runtime: Class constructors cannot be invoked without 'new'

wombawomba11:09:17

How do I combine new with this type hint/tag? (new Terminal. ^js %) gives me Use of undeclared Var my.ns/Terminal

wombawomba11:09:36

alright, I have no idea why, but doing (let [ctor (.-Terminal ^js %)] (new ctor)) works 😅

thheller11:09:17

maybe elimanate the #() function to make this more understandable?

wombawomba11:09:01

yeah, I actually already moved the constructor call out of the require.js callback

thheller11:09:01

(new Terminal. ^js %) is just invalid code and not related to ^js in any way 😛

wombawomba11:09:36

right yeah, but what threw me off is that (new (.-Terminal ^js %)) also doesn't work

wombawomba11:09:15

for whatever reason I had to bring the (.- Terminal ^js %) call out into a binding

jpmonettas13:09:13

is there a way of printing the dependency tree for shadow-cljs.edn dependencies? (like with clj -Stree)

thheller13:09:38

shadow-cljs info prints a basic info

thheller13:09:55

only if you use shadow-cljs.edn to manage deps though. if you use lein or deps.edn use those commands