Fork me on GitHub
#shadow-cljs
<
2022-07-22
>
john02:07:37

So for this webworker library, inmesh, I'm working on building a re-frame dashboard with the app logic moved into a webworker (similar to your split-todomvc, @thheller) - and the compile mode :none is working, but with :advanced release, I get a cryptic error. I made a repro branch in the inmesh repo here: https://github.com/johnmn3/in.mesh/tree/shadow-dashboard-repro/shadow_dashboard

john02:07:55

when I run npx shadow-cljs release core --debug and then npx shadow-cljs server I get this cryptic error:

Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')
    at alpha.cljs:430:5
    at screen.js:10293:4

john02:07:11

And that screen.js reference is just the last line of the file:

}
;
}).call(this); <- here
//# sourceMappingURL=screen.js.map
So I'm not sure which piece of code is calling spec erroneously in advanced mode

john02:07:02

That branch also has the latest future and =>> macros if anybody wants to play with them

john02:07:40

But I'm guessing my advanced build issue has to do with the npm additions rather than the webworker stuff

john02:07:22

Haven't really tried the advanced compile stuff until this real-world example

john02:07:01

I went with mui v5 for the interface for now just for iterating rapidly with a pre-existing set of components

john02:07:25

But I'm excited to try it out with shadow-grove soon, as I think grove's render architecture probably makes the most sense when pushing updates from a worker

thheller04:07:57

@john can't say much about this error. first guess is always externs. Cannot read properties of undefined (reading 'prototype') could just mean that somewhere you handed something a reference which is undefined, which could be due to trying to access (.foo thing) and that foo getting renamed making it (.aB thing) or something, thus accessing an undefined field and failing

thheller04:07:02

I don't know much interop you do or generate so can't say

thheller04:07:28

> But I'm guessing my advanced build issue has to do with the npm additions rather than the webworker stuff

thheller04:07:48

I'd say that is unlikely but certainly possible. Most of the time its interop in your code.

πŸ™ 1
john04:07:07

Even with --debug ? It the trace seems to end in the reify call of spec.alpha's map-spec-impl

thheller04:07:56

one thing that pops out by glancing at the code is this

1
thheller04:07:55

shadow will be undefined in :advanced so shadow.cljs would give you the Cannot read properties of undefined (although not the prototype). just giving an example of how :advanced changes the layout of the code

john04:07:56

Yeah, that makes sense

thheller04:07:14

and namespaces don't really exist anymore in :advanced

john04:07:32

ah right

john04:07:27

yeah, realized those those calls were failing when I tried advanced compile, so I just defaulted to the shadow configs for this test

thheller04:07:05

shadow-cljs defaults to not showing you inference warnings for library code

thheller04:07:20

so in the dashboard project you won't see inference warnings for inmesh

john04:07:22

I'll dig through and try to clean up the attr accesses

thheller04:07:56

you can set (set! *warn-on-infer* true) in the namespaces that do interop to always see them

thheller04:07:14

or just compile inmesh on its own via a test target or something

πŸ‘€ 1
thheller04:07:15

that also looks like something that is very unlikely to work in advanced. assuming this is turning a function into a string?

john04:07:11

I've had a similar thing working in advanced mode in the past, as long as the same advanced compiled artifacts exist on both sides of the io

thheller04:07:12

you can try setting :compiler-options {:output-wrapper false} in the build config

πŸ‘€ 1
thheller04:07:07

that isolates the code a little less and creates thousands of globals instead of locals

thheller04:07:36

(which may be necessary for the turn function into string thing)

john04:07:19

K, I'll try that

john04:07:23

Appreciate the pointers

john05:07:20

Yeah, the webworkers are setting up and talking to each other. It's something on the main thread, wrt the compile configurations. I think a combination of configs that are just super uncommon, with enabling webworkers

john05:07:28

I think it's the reitit router brings in spec-tools at runtime

john05:07:23

reitit is doing coercions at runtime

john05:07:33

Yeah, that was it

john05:07:55

Might try to use secretary instead

john05:07:13

Nah, just getting rid of the coercions was enough. And I had to ^:export the fns in the inmesh.re-frame ns to get things working

john05:07:45

but wow is it snappy in :advanced compile mode 😍 like you're not even using workers!

john05:07:49

Shipping minified code over the wire is basically like bytecode. Super lightweight

john05:07:35

Thanks for your help @thheller. Hoping to get this working on fig and plain cljs one day, but this is good enough to get stuff done with shadow for now. Big thanks for shadow!

john06:07:08

Unfortunately I haven't figured out how to get the service worker to work outside of the root folder, which you can't serve on with github project pages (has to be on /in.mesh/) but I don't need it for this demo

john06:07:28

Well, the sw is loading, but I don't think it can do intercepts

thheller07:07:31

@john it might break your setup but I'd generally recommend keeping service workers as their own build. seems better since it has its own lifecycle and should be independent of the page code itself only acting as a message passing relay of sorts

πŸ™ 1
Paul Hempel10:07:44

Hey @thheller. I encountered the following issue and was wondering if it was a shadow-cljs issue or more of an cljs-itself issue and hence where to open up a ticket. Problem The β€œunreachable code” error message showed up when I didn’t put in the (catch ...) statement for the (try) block. Yet, it pointed to the line of the (go) statement which wrapped the try/catch block. Only prints the error when executing npx shadow-cljs release app, not with watch app. Example code which resulted in the error > unreachable code

(defn foo []
  (go ;; <-- loc which error points to
    (let [res (<p! awaited-promise)]
      (try
         (do-stuff)))))
Fixed
(defn foo []
  (go 
    (let [res (<p! awaited-promise)]
      (try
         (do-stuff)
         (catch ...)))) ;; <-- no error

thheller10:07:15

@paul.hempel that error is coming from the closure compiler optimizations, which are only done for release builds. the unreachable part is probably due to the go macro generating something unreachable in case of try without catch? so core.async would be the place to report it?

Paul Hempel10:07:09

Good point. I’ll ask over there. Thanks πŸ™‚

thheller10:07:53

if you get the unreachable code outside of go as well it would be a CLJS issue I guess

Paul Hempel11:07:55

I’ll test that.

Paul Hempel11:07:39

Tested it, worked like a charm without the go and the catch.

thheller11:07:10

yeah the go macro does some wild rewriting so its probably just a case thats not covered

Nikolas Pafitis14:07:38

Hello I'm migrating a project from using shadow-cljs.edn for specifying deps to deps.edn and I'm getting this issue:

[2022-07-22 17:17:08.779 - WARNING] :shadow.build/hook-config-ex - {:hook-idx 0, :hook-sym build-css/start-watch-hook, :build-id :app}
Note: The following stack trace applies to the reader or compiler, your code was not executed.
CompilerException Syntax error compiling . at (cheshire/core.clj:170:6). {:clojure.error/phase :compile-syntax-check, :clojure.error/line 170, :clojure.error/column 6, :clojure.error/source "cheshire/core.clj", :clojure.error/symbol .}
	clojure.lang.Compiler.analyzeSeq (Compiler.java:7119)
	clojure.lang.Compiler.analyze (Compiler.java:6793)
	clojure.lang.Compiler.analyzeSeq (Compiler.java:7099)
	clojure.lang.Compiler.analyze (Compiler.java:6793)
	clojure.lang.Compiler.analyze (Compiler.java:6749)
	clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:6122)
	clojure.lang.Compiler$LetExpr$Parser.parse (Compiler.java:6440)
	clojure.lang.Compiler.analyzeSeq (Compiler.java:7111)
	clojure.lang.Compiler.analyze (Compiler.java:6793)
	clojure.lang.Compiler.analyzeSeq (Compiler.java:7099)
	clojure.lang.Compiler.analyze (Compiler.java:6793)
	clojure.lang.Compiler.analyze (Compiler.java:6749)
Caused by:
NoClassDefFoundError com/fasterxml/jackson/core/util/JacksonFeatureSet
	java.lang.Class.getDeclaredMethods0 (Class.java:-2)
	java.lang.Class.privateGetDeclaredMethods (Class.java:3166)
	java.lang.Class.privateGetPublicMethods (Class.java:3191)
	java.lang.Class.getMethods (Class.java:1904)
	clojure.lang.Reflector.getMethods (Reflector.java:498)
	clojure.lang.Compiler$HostExpr$Parser.parse (Compiler.java:996)
	clojure.lang.Compiler.analyzeSeq (Compiler.java:7111)
	clojure.lang.Compiler.analyze (Compiler.java:6793)
Caused by:
ClassNotFoundException com.fasterxml.jackson.core.util.JacksonFeatureSet
	jdk.internal.loader.BuiltinClassLoader.loadClass (BuiltinClassLoader.java:581)
	jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass (ClassLoaders.java:178)
	java.lang.ClassLoader.loadClass (ClassLoader.java:522)
	java.lang.Class.getDeclaredMethods0 (Class.java:-2)
	java.lang.Class.privateGetDeclaredMethods (Class.java:3166)
I don't have cheshire as an explicit dependency. I tried this on shadow-cljs v2.17.2 and v2.17.8. I also tried to add cheshire as an explicit dependency on it's latest version and the same thing happens. My builds build correctly though.

thheller14:07:24

if you use deps.edn to manage your dependencies then thats a deps.edn question and the shadow-cljs version doesn't matter

thheller14:07:01

make sure your :paths and aliases match what your shadow-cljs.edn setup was before

thheller14:07:45

looks like a build hook you are using wants to use cheshire?

Nikolas Pafitis14:07:32

I'm still using shadow-cljs.edn with :deps true option

Nikolas Pafitis14:07:12

In my deps.edn file i just specify deps and paths which are identical. I did this because Cursive cannot index libraries and deps from shadow-cljs.edn

thheller14:07:13

yes, but that means that all dependencies are managed by deps.edn and this is an error you get for a missing dependency

thheller14:07:40

can't guess whats in your deps.edn or if cheshire maybe needs something else in there

thheller14:07:07

there have been cases in the past where deps.edn didn't pick up something that lein/shadow-cljs did. can't remember details though.

Nikolas Pafitis15:07:51

I see, I've fixed it by using clj -X:deps tree and looked for the mismatches there. There were :exclusions that had to be added.

πŸ‘ 1
borkdude15:07:24

Does shadow-cljs allow to write an equivalent of this with target esm?

export default {
  port: 3000,
  fetch(request) {
    return new Response("Welcome to Bun!");
  },
};

borkdude15:07:39

I'm looking for prior art in this area

thheller15:07:15

sure. thats nothing special at all

thheller15:07:42

(def that-thing #js {:port 3000 :fetch (fn fetch [request] ...)})

thheller15:07:53

:exports {default your.ns/that-thing} in build config

borkdude15:07:12

but not in code itself right

borkdude15:07:39

not something like:

(defn ^:export default ...)

thheller15:07:05

no, exports are configured via build config

πŸ‘ 1
thheller15:07:43

kinda has to be since it has to map the closure/cljs namespace system to ESM exports somehow

borkdude15:07:53

yeah no problem, just was wondering if something like this existed

borkdude15:07:23

I'm playing around with something that transpiles .cljs directly to .mjs and it automatically exports public vars. But default isn't a valid name for a var.

borkdude15:07:58

I could just go with:

(js/export ...)

thheller15:07:11

not really since its not a function call

borkdude15:07:29

yeah with some special treatment

thheller15:07:01

(def default "whatever") is perfectly valid though

thheller15:07:14

so just need to account for it getting munged to export$?

borkdude15:07:05

you're right

borkdude15:07:18

that's a cleaner solution

jcoyle20:07:08

So glad you are making a lightweight cljs transpiler! Can’t wait to try it out