Fork me on GitHub
#shadow-cljs
<
2019-02-18
>
flowthing08:02:29

The specs in shadow.cljs.devtools.cljs-specs don't seem to allow destructuring like this: (defn foo [{:keys [baz/quux] :or {baz/quux :quuz}}]). In particular, it seems to be the combination of :or and destructuring a namespaced keyword that's the problem. The specs allow (defn foo [{:keys [quux] :or {quux :quuz}}]), for instance. I'm on shadow-cljs v2.8.0.

thheller08:02:20

(defn foo [{:keys [baz/quux] :or {baz/quux :quuz}}] this is not valid. (defn foo [{:keys [baz/quux] :or {quux :quuz}}] should be.

flowthing08:02:10

Well, I'll be damned. I guess my code's never actually hit the :or path. Thanks!

thheller08:02:23

it may work due to the way destructuring is implemented

flowthing08:02:38

I tried it out in the REPL, it doesn't seem to work.

thheller08:02:42

they are somewhat "open" to interpretation

flowthing08:02:22

$ clj -Srepro -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "RELEASE"}}}' -m cljs.main
ClojureScript 1.10.520
cljs.user=> (defn foo [{:keys [baz/quux] :or {baz/quux :quuz}}] quux)
#'cljs.user/foo
cljs.user=> (foo {})
nil
cljs.user=> (defn foo* [{:keys [baz/quux] :or {quux :quuz}}] quux)
#'cljs.user/foo*
cljs.user=> (foo* {})
:quuz

flowthing08:02:40

I guess it seems kinda logical that :or {baz/quux ,,,} would work, but on the other hand, I guess you could argue that quux is the name of the variable the value is bound to and therefore makes more sense.

flowthing08:02:12

Anyway, TIL! Not the first time I've gotten destructuring wrong without any indication that it's not actually working...

thheller08:02:39

yeah the core specs aren't enabled in CLJS by default yet so it lets some things slide

ouvasam09:02:55

Hi, Has someone already used AirBnB DateRangePicker with reagent ? Can't make it work ... thanks

thheller10:02:57

what have you tried? what error do you get?

r0man10:02:41

@thheller I'm testing 2.8.0 on one of my projects and get an error from the babel worker trying to process a file from @material/textfield

r0man10:02:14

any idea?

thheller10:02:20

hmm looks like something got renamed that shouldn't have been

thheller10:02:06

did that work previously?

r0man10:02:27

yes, it worked with previous versions of shadow-cljs

thheller10:02:13

ok I'll check it out

r0man10:02:39

ok, thanks. if you need more info. let me know.

thheller11:02:41

ok I can reproduce it but not exaclty sure why anything changed. will investigate

thheller12:02:12

@r0man should be fixed in 2.8.1. still unsure why this wasn't a problem previously but I can't reproduce the problem anymore

r0man12:02:00

ok, thanks. I'll try ...

r0man12:02:03

@thheller yes, this fixed the issue. thanks!

r0man12:02:16

but I run into another issue with my nodejs server. πŸ˜•

r0man12:02:59

do I need to change anything for the new module manager. I'm using the cljs.loader namespace at the moment

thheller12:02:29

why or how are you using cljs.loader in a node env?

thheller12:02:35

(cljs.loader is now aliased to use shadow.loader, but cljs.loader would have the same issue above)

r0man12:02:04

I have some files that use the module manager in the frontend. I guarded the calls to loader/set-loaded with this:

thheller12:02:20

the underlying goog module loader stuff changed a bunch in the new release so I'm not surprised there are issues

r0man12:02:25

so on node I only require the cljs.loader namespace

thheller12:02:38

please paste the contents of /home/roman/workspace/burningswell/web/.shadow-cljs/builds/server/dev/out/cljs-runtime/goog.loader.activemodulemanager.js

r0man12:02:06

when I look at goog.loader.activemodulemanager.js I see a require for the "asserts"

r0man12:02:10

yes, 1 mom

thheller12:02:16

should be starting with goog.loadModule(...)

thheller12:02:46

hmm yeah thats how it supposed to look

r0man12:02:04

is this comment before the require a problem? shouldn't, right?

r0man12:02:09

on line 6

thheller12:02:12

I didn't test this in a node env so I suppose something is weird there

thheller12:02:27

ah .. I know

thheller12:02:46

nah thats all fine

thheller12:02:14

the node builds replace goog.require with one that isn't aware of goog.loadModule stuff

thheller12:02:35

so var asserts = goog.require("goog.asserts"); just ends up as nil

thheller12:02:47

since goog.require usually doesn't return anything

thheller12:02:48

can you try adding this to your src/shadow/cljs/node_bootstrap.txt and recompile

thheller12:02:08

var SHADOW_REQUIRE = function(name) {
  if (goog.isInModuleLoader_()) {
    return goog.module.getInternal_(name);
  }
  return true;
};

r0man12:02:14

in my project?

thheller12:02:22

that used to only be

var SHADOW_REQUIRE = function(name) {
  return true;
};

r0man12:02:57

πŸ‘ yes, that worked!

r0man12:02:20

also module loading seems fine now

thheller12:02:45

ok thx. I'll see if the goog.require override is required at all anymore. maybe I can just remove that hack entirely.

r0man12:02:33

ok, thanks for you help. I just recently switched to shadow and it is really nice!

thheller12:02:18

@r0man btw in shadow-cljs you don't need to call set-loaded!. the tool takes care of that for you

r0man12:02:04

only the shadow.loader or also for cljs.loader?

thheller12:02:35

cljs.loader is aliased to shadow.loader regardless of what you require πŸ˜‰

thheller12:02:43

so you are always using shadow.loader πŸ˜‰

thheller12:02:06

cljs.loader doesn't work with the new closure library at all yet

thheller12:02:27

you can keep the call if you want, you just don't need it

thheller12:02:52

I never liked that you had to add it manually in normal CLJS

r0man12:02:56

alright. didn't know that.

r0man12:02:29

one more question regarding modules. at the moment I have 1 module for each of my routes, like /signin, /signup etc. those module depend at the moment on 1 shared modue which contains most of the cljs code and all stuff that is shared among more than 1 module. the shared module is quite big at the moment and also contains stuff like vega & d3 which is not needed on the /signin and /signup pages. it's still moved into the shared module because 2 other modules depend on it. does shadow or the closure module loader support multiple shared modules?

thheller12:02:26

yes you can construct pretty much any graph

thheller12:02:00

you can even create "pseudo" modules

orestis12:02:26

I’m seeing Error building classpath. Specified aliases are undeclared: [:shadow-cljs-inject["r""e""b""l""-""1""1"]] when using -A:rebl-11 or -A rebl-11 in recent shadow 2.8.1

r0man12:02:41

ok, I'll try again. I run into issues in the past.

thheller12:02:33

@r0man say you have 2 pages that you know have common deps which should not be in :shared

thheller12:02:24

:modules {:foo {:entries [] :depends-on #{:shared} :uses-foo {:entries [your.page.foo] :depends-on #{:shared :foo} ....}

thheller12:02:30

ugh that gets ugly

thheller12:02:48

:modules
{:shared
 {:entries []}
 :foo-shared
 {:entries []
  :depends-on #{:shared}}
 :page-a
 {:entries [your.app.page-a]
  :depends-on #{:shared}}
 :page-b
 {:entries [your.app.page-b]
  :depends-on #{:shared :foo-shared}}
 :page-c
 {:entries [your.app.page-c]
  :depends-on #{:shared :foo-shared}}
 }

thheller12:02:09

things that are used in all 3 pages are moved to :shared

thheller12:02:26

things that are only used by b+c are moved to :foo-shared

thheller12:02:02

the :entries [] is a shortcut when you don't have any specific namespaces that should be moved there

thheller12:02:41

@orestis hmm that looks weird πŸ™‚

orestis12:02:30

./node_modules/.bin/shadow-cljs -A:rebl-11 clj-run ... is the actual command line

thheller12:02:24

yeah the merging is just messed up due to the user-config stuff I added

r0man13:02:36

@thheller yes, that was my understanding. I just run into problems. I'm trying again. I think I also need to add :default true to my main module, right?

thheller13:02:04

no, only if you have 2 modules that both have no :depends-on

thheller13:02:09

you can pin dependencies to certain modules and shadow-cljs will warn you if they are moved out due to some requires

thheller13:02:11

ie. in :foo-shared {:entries [cljs.core] ...} will warn you since :page-a needs cljs.core

thheller13:02:32

its a bit annoying that this has to be setup to manually currently

r0man13:02:01

ok, I'll try again with this information. thanks for your guidance

thheller13:02:26

@orestis should be fixed in 2.8.2

πŸ™ 5
r0man13:02:58

@thheller I run into another issue with my nodejs release build. I'm using "simple" optimizations. the code that breaks is the following:

r0man13:02:19

and the error:

r0man13:02:32

the compiled code looks the same in shadow-cljs 2.7.36 and 2.8.2:

r0man13:02:35

I'm setting Document to a polyfill for server side rendering

r0man13:02:21

maybe another tweak needed for the nodejs require?

thheller14:02:11

hmm looks identical to me too

thheller14:02:22

@r0man what does the use look like? the definition looks fine but where is it used?

r0man14:02:59

what do you mean by "use"?

thheller14:02:15

how is Document used? by what?

thheller14:02:29

ReferenceError: Document is not defined
    at /home/roman/workspace/burningswell/web/out/burningswell/server.js:2663:800

thheller14:02:33

what happens there?

r0man14:02:46

I think it's this line: (set! js/Document html/Document)

thheller14:02:55

please verify

thheller14:02:40

just look at the actual source please

r0man14:02:07

so it blows up on the set! call.

thheller14:02:32

add (prn html) please

thheller14:02:42

I'm confused by this worked before and not now. I don't see any obvious difference?

r0man14:02:40

this is what I have for html

thheller14:02:57

looks fine to me

thheller14:02:55

(set! js/Document ...) is kinda questionable and should probably be (set! js/goog.global.Document ...) but I don't see a reason why it shouldn't work now if it did work before

r0man14:02:35

let me try the goog.global

thheller14:02:47

try (prn html/Document) while you are at it

r0man14:02:35

this fixed it: (set! js/goog.global.Document html/Document)

r0man14:02:20

and printing (prn html/Document) ;=> #object[Document]

thheller14:02:22

weird. I have no clue why that was fine previously?

r0man14:02:26

as before

r0man14:02:43

ok, so is goog.global the recommended way to set globals in closure?

r0man14:02:24

alright. thanks again! I hope I didn't ruin your day

thheller14:02:26

kinda curious to find out why it worked before πŸ˜›

r0man14:02:26

hehe, let me know if you have an idea

r0man15:02:07

@thheller I'm afraid I found another issue with the module manager in advanced compilation

r0man15:02:31

it happens when I load a module

r0man15:02:58

it looks like the module info is not available

r0man15:02:15

(prn (.-moduleInfoMap (loader/getModuleManager))) ;=> #js {}

r0man15:02:34

to me it looks like the module infos are not available. if I type shadow$loader into the browser console it prints {}

r0man15:02:24

with a "none" build the module info is available

r0man15:02:11

I looked at my main module and I do find the populated shadow$loader object at the very beginning.

r0man15:02:25

however, somewhere later in the same file this gets reset by the following code: var shadow$loader = {}

r0man15:02:21

so I guess the first var shadow$loader = {"uris": { ... }}; is emitted by shadow-cljs to make the module info available. but the 2nd var shadow$loader = {} comes from the goog.provide("shadow.loader"); call in loader.js, which unfortunatly resets this information again

thheller17:02:56

@r0man shadow.loader isn't really supposed to work on a node env. how do you see a populated shadow$loader object in the beginning?

thheller17:02:08

I can probably shim some functions so that is just treats all modules as loaded given there is only ever going to be one for node

metacritical19:02:31

@thheller I am trying to use cljs.analyzer namespace specially a Γ nalyze-file` defn in it, but while building it seems to be giving a error!

metacritical19:02:44

Any ideas i should try?

thheller19:02:02

what is the error?

thheller19:02:11

how are you using it?

metacritical19:02:51

I am trying to analyze a cljs file on demand.the error is Use of undeclared Var cljs.analyzer/analyze-file `

thheller19:02:58

analyze-file is only available in CLJ

heyarne19:02:00

So I have a pretty minimal cljs file with reagent, but somehow the reload hook is ignored. I can't spot the error, am I missing something?

(ns reagent-movable.core
  (:require [reagent.core :as r]
            ["react-movable" :refer [List]]))

(defn reload! []
  (.. js/window -location reload))

(defonce state (r/atom (vec (map #(str "Item " %) (range 1 11)))))

(defn movable []
  (let [items @state]
    [:ul
     (for [[idx item] (map-indexed vector items)]
       ^{:key idx} [:li item])]))

(defn app []
  [:div
   [:h1 "Movable list below"]
   [movable]])

(defn ^:export ^:dev/after-load start []
  (println "Mounting component...")
  (r/render [app] (.getElementById js/document "app")))

thheller19:02:21

uhm I don't think you can add two metadata hints that way?

thheller19:02:00

try

(defn start
  {:export true
   :dev/after-load true}
  []
  (println "Mounting component...")
  (r/render [app] (.getElementById js/document "app")))

heyarne19:02:01

doesn't change anything?

heyarne19:02:07

also as per the docs:

thheller19:02:08

hmm no seems fine in clojure

heyarne19:02:14

> It is possible to add multiple pieces of metadata by chaining the metadata reader macros together. For example: ^:dynamic ^ints obj would apply both the :dynamic flag and ints type-hint to obj. Metadata chains from right to left (left takes precedence).

thheller19:02:21

yeah I wasn't sure

heyarne19:02:23

pretty sure it worked in another project

thheller19:02:43

what happens on compile? any warnings?

thheller19:02:54

it should get picked up as far as I can tell?

heyarne19:02:15

this is the repo

metacritical19:02:35

@thheller aah i guess copying that function and manually analyzing should do the trick! Thanks!

lilactown19:02:21

(defn
  ^{:export true
    :dev/after-load true}
  start
  []
  (println "Mounting component...")
  (r/render [app] (.getElementById js/document "app")))

lilactown19:02:12

does that fix it?

thheller19:02:15

@arne-clojurians that repo doesn't contain the code you posted?

heyarne19:02:32

i pushed it seconds after, sorry

heyarne19:02:00

just stopped the watcher and rmrfed /.shadow-cljs, now it's working πŸ˜•

heyarne19:02:47

with the ^:export ^:dev/after-load syntax btw. πŸ™‚ if anyone wants to save a few keystrokes in the future

heyarne19:02:09

the meta data wasn't getting picked up at all. also when I removed the export. so maybe it was some kind of cache invalidation bug? it'll be hard to reproduce though

thheller20:02:39

no that can't affect the cache invalidation

thheller20:02:23

I wish people would stop deleting .shadow-cljs as the first instinct πŸ˜›

thheller20:02:00

destroys all chances of ever finding out what was happening and fixing it 😞

heyarne21:02:02

oops. next time i'll mv it

thheller21:02:21

a restart would have been enough probably

thheller21:02:07

I'd guess that the watch maybe just got into a weird situation and either stopped recompiled completely

thheller21:02:18

or had some stuck state that wasn't cleaned properly

thheller21:02:29

either would have been fixed by simply restarting the watch