Fork me on GitHub
#shadow-cljs
<
2020-05-30
>
sergey.shvets05:05:18

Hi, getting some very weird issue, when trying to run a "Getting Started" guide of Slate.js. It seems like something with closure compiler but I'm completely lost. Anyone saw this before?

index.js:404 Uncaught TypeError: Cannot read property 'prototype' of undefined
    at Object.$jscomp.generator.createGenerator (generator_engine] :879)
    at Object.levels (index.js:755)
    at Object.above (index.js:380)
    at Object.void (index.js:2233)
    at eval (index.js:2092)
    at HTMLUnknownElement.callCallback (react-dom.development.js:189)
    at Object.invokeGuardedCallbackImpl (react-dom.development.js:238)
    at invokeGuardedCallback (react-dom.development.js:293)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:307)
    at executeDispatch (react-dom.development.js:390)
I've been only able to find this issue thus far: https://github.com/google/closure-compiler/issues/2910 which might be or not be similar. The component renders but when I try to edit anything, the error above happens.

rberger06:05:46

Just when I think my mental model of Javascript interop is in sync with reality, the javascript world sends me another cureveball. Especially after being spoiled by npm and shadow-cljs. I have a lame javascript “library that only comes as a javascript file that seems to be intended only to be consumed via a <script> tag, not imported. It’s not an NPM library. If I inject it via the script file it comes in as a nice js function:

WebRTCAdaptor:  λ[mediaConstraints audioConstraint stream]
                jsƒ WebRTCAdaptor(initialValues)
I can then instantiate the main object with a (new js/WebRTCAdapter jsparams) and all is well, until it is :advanced compiled and all the names get munged. I could go thru all the function and property calls and use cljs-oops to ensure they don’t get munged, but it seems like I should be able to figure out how to import /require the js file and shadow-cljs should take care of things (I hope that assumption is correct!) Then I find out I don’t know how to deal with the object that get’s imported/ required. It’s not coming in as a function or an object with a constructor. If I try to :require it like ["./antmedia/webrtc_adaptor.js" :as WebRTCAdaptor] I get the object but, its just an js object:
WebRTCAdaptor:  
{}
__proto__:
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
And I can’t do a new (new WebRTCAdaptor jsparams) Uncaught TypeError: module$visx$dashboard$antmedia$webrtc_adaptor is not a constructor or execute it as a function (WebRTCAdaptor jsparams) Uncaught TypeError: module$visx$dashboard$antmedia$webrtc_adaptor is not a function So I come back to the fount of knowledge to humbly ask for guidance. Is there a nice clean way to do this with shadow-cljs or should I just apply some cljs-oops elbow grease to the <script> imported js?

thheller07:05:01

@rberger first of all delete cljs-oops from your mind as an option. NEVER use it. turn on :infer-extern :auto and let the compiler tell you about things it needs externs for. you can just stick a regular CLJS syntax, no need for a library.

thheller07:05:53

would help to see the code. the library seems to have an exported value, otherwise you'd get nothing. looks like that is already an instance of the class it provides.

thheller07:05:22

really up to you if you want to bring the code into your build or leave it in a script

thheller07:05:42

externs inference will probably well you which externs you need. if the JS does too much dynamic stuff it might not survive :advanced because of that. externs aren't enough to fix that, so it just might not be compatible.

thheller07:05:41

@bear-z my guess would be that you are looking at this incorrectly. in general my first guess when something is undefined is that you didn't pass a value that was expected correctly.

sergey.shvets17:05:37

Thank you for your time. I'll start with a minimal example to triple check myself. Can I share the code if it doesn't work?

sergey.shvets18:05:44

Thank you so much. I just completed the example and it has the same error. Here is the repo with the code: https://github.com/bearz/slate-cljs-minimal-example I'm trying to run an example from here: https://docs.slatejs.org/walkthroughs/01-installing-slate And here is the working javascript code: https://codesandbox.io/s/cranky-currying-vl7ik?file=/src/App.js Thank you again for looking into it. I'm lost and don't know where to dig next.

thheller18:05:27

hmm the problem seems to go away if you set :compiler-options {:output-feature-set :es6}

sergey.shvets18:05:33

Is this affects anything else that I should be aware of?

thheller18:05:08

well yeah the code doesn't run in browsers that don't support ES6 (dunno which feature slate uses exactly that causes the error otherwise)

thheller18:05:28

the default is :es5 so the closure compiler will trying to transpile it down

thheller18:05:33

which seems to be causing the issue

thheller18:05:56

but if you don't care about pre 2015 browsers then thats probably fine

sergey.shvets18:05:24

Yes. Doesnt' really matter to me. Thank you so much! I wouldn't find this any time soon without your help

sergey.shvets18:05:52

Slate is in typescript since recently, probably they target es6 with their compile.

thheller07:05:12

depending on when the library checks what you passed the resulting error might be deep in the code

thheller07:05:50

so first make sure that the arguments you are passing to slate are what they are supposed to be. meaning don't pass CLJS data if it expects JS objects, etc.

rberger08:05:54

I’m curious as to why it works if the webRTCAdapter code is brought in globally with the <script> tag but doesn’t work as an import. If you do have the time to glance at the code it is at https://github.com/ant-media/StreamApp/blob/master/src/main/webapp/js/webrtc_adaptor.js

thheller08:05:28

this has no exports so it can't possibly work

rberger08:05:21

Ah, If I were to add something like export WebRTCAdaptor it would work?

thheller08:05:38

you can just add export { WebRTCAdaptor } at the bottom yes

thheller08:05:58

that gives you a :refer (WebRTCAdaptor) in CLJS

rberger08:05:14

Cool, really appreciate your time

thheller08:05:28

quick warning though. the code is not exactly idiomatic JS and closure might have issues with this

thheller08:05:10

you can also add exports.WebRTCAdaptor = WebRTCAdaptor; at the bottom instead of the exports

thheller08:05:31

that turns the code into commonjs, meaning it doesn't go through :advanced and instead uses the same style as node_modules code

thheller08:05:40

so if you have :advanced issues that might be worth trying

EmmanuelOga11:05:19

sup, does anybody know where's the right place to change :watch-ext ? I'm trying to make shadow reload my static html file changes but can't figure out where to put that config key. Ref: https://github.com/thheller/shadow-cljs/blob/7428c212b246f2ce179b2da39678f5d32931b772/src/main/shadow/cljs/devtools/server/worker.clj#L262-L264 I tried: https://shadow-cljs.github.io/docs/UsersGuide.html#_css_reloading

{...
    {:builds
      {:app {...
             :devtools {:watch-exts #{"css" "html"}}}}}
... but not luck. Btw, this is not documented afaict.

thheller12:05:33

@emmanueloga that isn't supported. even if you make it watch the html it won't reload it.

EmmanuelOga20:05:25

that explains it 🙂

Pavel Klavík21:05:48

Hi, I have a problem in advance compilation of NodeJS, probably due to missing extern. I am using Macchiato which has the following line:

(.createServer (node/require "http") http-handler)
When running in advance, I get this:
function mo(a,b,c){var d=null!=b&&(b.h&64||r===b.P)?J.b(dh,b):b,e=E.b(d,oj);b=E.b(d,Si);var f=E.b(d,Zh);if(x(Wk.a(f)))return null;try{var g=e.j?e.j():e.call(null);hf.c(c,sd,a);var k=g}catch(l){throw b=l,Error([["could not start [",C.a(a),"] due to"].join("")," ",C.a(b)].join(""));}c=k;d=null!=d&&(d.h&64||r===d.P)?J.b(dh,d):d;d=E.b(d,wm);gf(d,c);hf.H(ko,W,a,new v(null,1,[Si,b],null));return hf.H(jo,xf,new X(null,2,5,Y,[a,Zh],null),new mh(null,new v(null,1,[Wk,null],null),null))}
                                                                                                                                                                                                 ^

Error: could not start [#'orgpad.screenshot.core/server] due to TypeError: (intermediate value)(intermediate value)(intermediate value).rd is not a function
    at mo (C:\Shared\orgpad\screenshot\screenshot.js:443:204)
    at Function.so.l (C:\Shared\orgpad\screenshot\screenshot.js:449:21)
    at so (C:\Shared\orgpad\screenshot\screenshot.js:447:276)
    at Function.<anonymous> (C:\Shared\orgpad\screenshot\screenshot.js:556:154)
    at Function.J.b (C:\Shared\orgpad\screenshot\screenshot.js:169:112)
    at C:\Shared\orgpad\screenshot\screenshot.js:556:119
    at Object.<anonymous> (C:\Shared\orgpad\screenshot\screenshot.js:557:3)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
When switching to :simple compilation, everything works fine.

mauricio.szabo21:05:44

Hi, I'm trying to compile a project (that was working on 2.8.109) with the current version 2.9.10. Something strange is happening: when I try to watch my node-library project, it's printing the following on terminal:

[:dev] Configuring build.
[:dev] Compiling ...
[:dev] Build completed. (213 files, 212 compiled, 0 warnings, 33.38s)
[:dev] Compiling ...
[:dev] Build completed. (213 files, 0 compiled, 0 warnings, 0.07s)
[:dev] Compiling ...
[:dev] Build completed. (213 files, 58 compiled, 0 warnings, 1.21s)
[:dev] Compiling ...
[:dev] Build completed. (213 files, 92 compiled, 0 warnings, 7.22s)
[:dev] Compiling ...
[:dev] Build failure:
The required namespace "shadow.umd-helper" is not available.

dpsutton21:05:45

Why are you using advanced compilation?

Pavel Klavík21:05:29

Not sure, it was the default. The file is little bit smaller, might be faster. Not really that important in the end, since the server is really tiny.

dpsutton21:05:15

I’m surprised it’s the default. What build target are you using?

dpsutton21:05:54

What does you shadow-cljs.edn file look like?

mauricio.szabo21:05:06

I believe all targets on shadow-cljs defaults to :advanced...

Pavel Klavík21:05:11

The entire build config looks like this:

:screenshot {:target           :node-script
                             :main             orgpad.screenshot.core/main
                             :output-to        "screenshot/screenshot.js"
                             :devtools         {:autoload true}
                             :compiler-options {:optimizations :simple}}

dpsutton21:05:34

Delete those compiler options. Shadow uses sensible defaults

dpsutton21:05:04

Node doesn’t I don’t believe

dpsutton21:05:12

No benefit to advanced

dpsutton21:05:18

Oh does it?

Pavel Klavík21:05:26

it was broken without them, so I added them to make it work for now

thheller21:05:01

everything defaults to :advanced

thheller21:05:34

it is broken because of machiato doing nonsense

thheller21:05:03

(.createServer (node/require "http") http-handler) this I mean ...

Pavel Klavík13:05:16

how should this be changed to make it work with Shadow-cljs?

thheller14:05:03

it works just fine. it just isn't recognized by externs inference

thheller14:05:34

should be (:require ["http" :as http]) in the ns and then (http/createServer ...) but that might have issue with regular cljs

Pavel Klavík20:05:17

so how could this be solved if one wants to be compatible with regular cljs?

thheller20:05:55

add externs inference hints in the code

thheller20:05:31

and maybe others .. whatever else fails

thheller21:05:32

but yeah if you are fine with :simple then use it

mauricio.szabo21:05:01

@thheller any tips on debugging The required namespace "shadow.umd-helper" is not available. happening?

dpsutton21:05:22

i apologize. i thought i remember reading that a few targets did not use advanced. the node ones in particular. i was wrong

thheller21:05:03

not really. can you narrow it down when it happens?

thheller21:05:36

like editing a specific file or so? it is a generated namespace so not sure how it could be missing

mauricio.szabo21:05:53

When I try to compile Chlorine source. Just compile, nothing fancy happening

thheller21:05:13

seems to work a couple of times and then doesn't

mauricio.szabo21:05:26

Like, I just watch the file, it says 3 times that build is complete, but then tries to compile again

thheller21:05:30

so something must happen that is causing it to stop working

thheller21:05:51

you mean it compiles 3 times on its own without you doing anything?

thheller21:05:19

and you are sure that NOTHING is touching any files or so?

thheller21:05:41

wouldn't be the first time that some editor setup just does stuff. like running a linter, formatter or whatever

thheller21:05:07

you can set :log {:level :debug} in shadow-cljs.edn that will give you a little more log output

mauricio.szabo21:05:57

Okay, I just closed all editors, everything that can touch files, removed old compilation files, and added that option to shadow, the error still happens... Still says "Build completed" twice, then fails 😞

mauricio.szabo21:05:55

Wait... there's something strange indeed on my config

mauricio.szabo21:05:29

Nevermind - the output-dir was included on source-files.

mauricio.szabo21:05:36

If I remove it, it works

mauricio.szabo21:05:57

Thanks a lot! With :level :debug I saw:

[2020-05-30 18:44:37.353 - FINE] :shadow.cljs.devtools.server.reload-classpath/classpath-js-update - {:dir #object[java.io.File 0xbbe1be95 "/home/mauricio/.atom/packages/chlorine/lib"], :name "js/cljs-runtime/sci.impl.max_or_throw.js", :ext "js", :file #object[java.io.File 0xa45ec655 "/home/mauricio/.atom/packages/chlorine/lib/js/cljs-runtime/sci.impl.max_or_throw.js"], :event :mod}
And that gave me clues on what's wrong 👍

thheller21:05:24

hmm weird. those are supposed to be filtered. it shouldn't be watching cljs-runtime folders.

thheller21:05:52

but yeah output dirs on the classpath is not a great idea

thheller22:05:07

fighting with nrepl again ... one day I'll make it my mission to kill nrepl. so extremely annoying to work with for CLJS ...

mauricio.szabo22:05:03

Do shadow-cljs have a ClojureScript nREPL? Or it works the same as piggieback, for example?

thheller22:05:54

it has its own nrepl middleware. piggieback exists but isn't used. only there because other middleware expects it.

mauricio.szabo22:05:21

Is there any documentation that tooling authors can follow? Or do you not recommend using it?

thheller22:05:57

no extra docs, you just use nrepl as normal

👍 1
thheller22:05:18

I mean you can read piggieback docs or whatever