Fork me on GitHub
#shadow-cljs
<
2018-05-06
>
cjsauer00:05:55

Is there a way to set the initial namespace when running shadow-cljs clj-repl? I'd like to set it to user instead of shadow.user as I have some helper functions defined there.

lwhorton02:05:55

is this something shadow-cljs might support, since it has a finite number of supported :compiler-options

mjmeintjes06:05:59

Can you think of a reason that an app would work when building release with :pseudo-names true, but then throw an exception when released without that option?

mjmeintjes07:05:48

Turned out to be an externs issue causing a naming conflict.

thheller08:05:53

@lwhorton no. why would you need that?

lwhorton19:05:53

http://Sentry.io doesnt seem to handle indexed sourcemaps in their parser

lwhorton19:05:20

I wonder if mozillas sourcemap has a way to reformat a map... didnt seem to

thheller19:05:40

hmm the reason it is using an index map is because of the npm stuff

thheller19:05:46

CLJS + goog is all one map

thheller19:05:02

and then one per node_modules .js file

thheller20:05:08

don't know how to turn it into one merged one either

lwhorton21:05:06

it’s a bummer that we can’t let another tool make the map at the end. wouldn’t want to miss out on the compiler’s optimizations just for sake of sourcemaps

thheller21:05:13

wonder why sentry doesnt support index map. seems pretty common and https://github.com/mozilla/source-map supports it as well

thheller08:05:36

@mjmeintjes yes externs. with :pseudo-names you get long variable names that are less likely to clash, so it sometimes fixes things.

mjmeintjes08:05:08

The weird thing is that I've been releasing and compiling without externs for a couple of months, but then just randomly today it started crashing. Probably just lucky/unlucky with name conflicts.

thheller08:05:51

hehe yeah I had this happen before. works one day but then breaks suddenly. Closure picks variable names sort of incrementally so it starts with a,b,c,d,... and then picks aa,ab,ac,... and so on. if you have enough vars you eventually get to ga which google analytics already uses and clashes

thheller08:05:57

or similar things

tianshu09:05:51

some function called static function which is just a simple ES6 module export.

// a.js
module.exports = {
  setString: xxx
}
If a is an export of module b, and I require like this (:require ["b" :refer [a]]) I can use setString with following code:
(def a-set-string (aget a "setString"))
(a-set-string xxx)
but this won't work
(a.setString xxx)
is this an expected behavior?

thheller10:05:34

a/setString

thheller10:05:01

and yes that is expected

tianshu10:05:09

if use a/setString, it will say can't find variable a.

thheller10:05:00

I'm confused now. what is b?

thheller10:05:16

(:require ["b" :refer [a]]) this doesn't make sense?

thheller10:05:01

how is a.js involved in that?

tianshu10:05:19

in my case, "b" is "react-native" and a is Clipboard.

thheller10:05:20

(:require ["react-native" :refer (Clipboard)]) (.setString Clipboard "foo")

tianshu10:05:26

yes, this works

tianshu10:05:42

but how to distinguish these situations?

thheller10:05:10

which situations?

thheller10:05:23

ah you mean a.setString working sometimes? well ... blame weird choices in the CLJS compiler. it only works for locals not ns aliases

tianshu10:05:05

so .setString a and a.setString is different?

thheller10:05:21

from the code that gets emitted it is the same

thheller10:05:26

but they are analyzed differently

thheller10:05:31

no idea why.

thheller10:05:12

I guess I could tweak the code for this to make it work

thheller10:05:45

but I don't think its a good idea to do this anways

tianshu11:05:38

i think it's better to always use (.setString a)

tianshu11:05:44

whats the difference between (a/b) and (.b a) here for npm module?

thheller11:05:02

:as sets up a namespace alias so it acts like any other CLJS namespace

thheller11:05:33

the (.b a) is not valid for CLJS namespaces and you must use a/b there

thheller11:05:49

it just works for JS namespace since you are also allowed to use them directly

thheller11:05:26

eg. (:require [clojure.string :as foo]) then foo is not a variable and you can only use (foo/upper-case ...) not (.upper-case foo)

thheller11:05:05

for JS :as must create a variable since some CommonJS uses module.exports = function() ... which would not be callable otherwise

tianshu11:05:24

clear for me

tianshu11:05:40

i should always use a/b when a is a alias of npm module.

thheller11:05:46

basically you should NEVER use a.setString in any circumstance. the only exception to this is anything in the js/ namespace (eg. (js/console.log "foo")) IMHO.

thheller11:05:17

thats my rule for this.

thheller11:05:37

a.setString would not be valid in Clojure so I never do it.

tianshu11:05:36

best practice is not obvious for begginer, this is bad i think.

thheller13:05:39

pretty sure that no official docs ever mention that a.setString is even possible or allowed

thheller13:05:00

so not sure where this is even coming from

javi13:05:27

I am writing some tests to explore how the cljs compiler works, Given

...
:test                         {:target    :node-test
                                                 :output-to "out/node-tests.js"
                                                 :ns-regexp "-test$"
                                                 :autorun   true}
                  :bootstrapped-assets-for-test {:target    :bootstrap
                                                 :output-dir "out/bootstrap"
                                                 :entries [eval-and-parse.botstrapped-libs]
                                                 :exclude #{cljs.js}}
....
and...
(ns eval-and-parse.core-test
  (:require
    [cljs.js :as cljs]
    [cljs.env :as env]
    [shadow.cljs.bootstrap.browser :as boot]
    [cljs.test :refer-macros [deftest is testing run-tests async]]))

(deftest library-gets-loaded-and-accesible-on-bootstrap-mode
         (async done
                (let [c-state (cljs/empty-state)]
                     (boot/init c-state
                                  {:path         "/bootstrap"
                                   :load-on-init '#{eval-and-parse.bootstrapped-libs}}
                                  (fn []
                                   ;; --------------- tests
                                      (done))))))
I am getting ...
SHADOW import error ... ... ... .shadow-cljs/builds/test/dev/out/cljs-runtime/shadow.module.main.append.js

........shadow-cljs/builds/test/dev/out/cljs-runtime/goog.net.xmlhttp.js:175
    return new XMLHttpRequest();
Is this because of the env where the tests are running? ie: :target :node-test

thheller13:05:44

not sure what your question is going to be but :entries [eval-and-parse.botstrapped-libs] seems to be missing an o

javi13:05:35

hey, sorry, pressed send by mistake before finishing the message

thheller13:05:31

c-state should be a comiler env. not an analyzer env. eg. (cljs.env/default-compiler-env)

thheller13:05:42

oh wait you are running node

thheller13:05:09

shadow.cljs.bootstrap.browser only works in the browser .. hence the name

javi13:05:41

I have an editor, compiles and consumes all libs great.

javi13:05:26

Now i am setting up tests to fill in my conceptual blanks and get a whole picture of compilation

javi13:05:15

so i am getting that message with test profile

{:target    :node-test
                                                 :output-to "out/node-tests.js"
                                                 :ns-regexp "-test$"
                                                 :autorun   true}

thheller13:05:20

you can use :browser-test instead of :node-test

thheller13:05:00

it should be pretty simple to write a shadow.cljs.bootstrap.node that works the same

javi13:05:22

what do you mean?

javi13:05:38

the same as :browser?

thheller13:05:51

(ns eval-and-parse.core-test
  (:require
    [cljs.js :as cljs]
    [cljs.env :as env]
    [shadow.cljs.bootstrap.browser :as boot]
    [cljs.test :refer-macros [deftest is testing run-tests async]]))

thheller13:05:11

you are requiring shadow.cljs.bootstrap.browser which clearly has "browser" in the name

thheller13:05:18

but then run it in node

thheller13:05:51

the boot/init utility function assumes it is running in a browser

javi13:05:12

OK! makes sense now. 🙂 gonna give it a try. thanks

thheller13:05:13

you can write a similar function for node. I just have not written that yet.

thheller13:05:37

would actually be substantially easier in node since you can use fs/readFileSync

javi13:05:18

I understand. the whole picture is becoming clearer now

thheller13:05:42

the :bootstrap target basically just pre-compiles files so they can be loaded at runtime

thheller13:05:18

the other option is to no precompile anything and just making the sources accessible directly

thheller13:05:56

:bootstrap then creates a index.transit.json containing all the information for the compiled files

thheller13:05:17

boot/init loads that index and then loads whichever namespaces are required

javi13:05:20

yeah, i followed your post on that

javi13:05:54

i am poking to see where cljs places things in the environment etc...

thheller13:05:30

well that all works a bit differently in self-host CLJS

thheller13:05:41

but for the most part it is all in cljs.env/*compiler*

thheller13:05:05

ie. c-state

thheller13:05:54

info about cljs.core you would find in (get-in @c-state [:cljs.analyzer/namespaces 'cljs.core])

thheller13:05:14

(after init completes)

javi13:05:14

I have a little viz of the compiler env and i can see things being added etc... makes sense ... one thing... when i do

(:require .....
   ["an-npm-lib" :as an-npm-lib]
...)
where does that go in the cljs.env/*compiler*

thheller13:05:00

or rather I have no idea where it goes. shadow-cljs handles that very differently

thheller13:05:08

no idea how it works in standard CLJS

thheller13:05:24

I think :js-module-index is involved

javi13:05:46

ok, so you use your dependecy resolution mechanism to look that up? Sorry, i am sure some of these questions are a bit stupid... 🙂

thheller13:05:08

not stupid at all

thheller13:05:20

yes shadow-cljs has its own resolve mechanism

thheller13:05:39

in fact it replaces the entire parser for ns

javi13:05:30

makes sense, where in the source can i look to begin to understand this?

thheller13:05:43

CLJS or shadow-cljs?

javi13:05:42

shadow-cljs

thheller13:05:00

that part is replaced by shadow.build.ns-form and shadow.build.resolve

javi13:05:18

wow. thanks!

thheller13:05:46

this is the starting point. so if you have a browser build with :entries [foo.bar] it get called with (resolve-entries state [foo.bar])

thheller13:05:17

but most of the resolve magic is in that file. shadow.build.npm has the npm specific stuff

thheller13:05:25

but everything starts in shadow.build.resolve

thheller13:05:49

all of this works very very differently in CLJS though so none of this applies if you are looking into self-hosted stuff

javi13:05:03

can i access it like when i do this?

(->> "
		(do
     (ns my.somns (:require [clojure.string :as string])) 
     (def g 90)
     
     (ns my.r (:require [clojure.string :as string])) 
     (def lo 90)
     )
     "
     cljs.tools.reader/read-string
     (cljs.analyzer/analyze user-env)
     cljs.compiler/emit-str
     )

thheller13:05:36

well, not with those API calls

thheller13:05:46

you can access everything yes

thheller13:05:09

but shadow-cljs is a build tool for building files. so some of the more dynamic stuff like evaling strings works differently as well

javi13:05:39

ha ha yes!! gonna try it.

thheller14:05:21

you are probably better off looking at the official cljs.analyzer stuff though

thheller14:05:31

the shadow-cljs stuff is pretty specific to shadow-cljs

javi14:05:10

thanks!! I will look at both little by little so i can see the different approches and learn from that. one last question... at the browser console module$node_modules$codemirror$addon$edit$closebrackets is that how shadow builds a look up for the bootstrapped libs?

thheller14:05:17

that is the ns alias created for the node_modules/codemirror/addon/edit/closebrackets.js file yes

javi14:05:13

ok thanks! gonna look into those resources you sent me. thanks so much!

thheller14:05:33

try looking at the index.transit.json data

thheller14:05:59

should make sense how it all comes together there

thheller14:05:58

in shadow-cljs everything is treated as a resource. each resource can provide one or more namespace and and can require zero or more

thheller14:05:31

(ns foo.bar) would be :provides #{foo.bar} :requires #{cljs.core} and so on

thheller14:05:20

(ns foo.bar (:require ["react" :as r])) basically gets rewritten to (ns foo.bar (:require [module$node_modules$react... :as r]))

javi14:05:42

> in shadow-cljs everything is treated as a resource At some point (it is sunday...) ( .. and as a beginner on the compiler bits ...) i would love to hear your view on the deps.edn/requiring from github and codeq etc... thanks for the help. have a great rest of sunday!

thheller14:05:37

I think it is interesting but not sold on actuallly using git deps

thheller14:05:06

not possible to use shadow-cljs as a git dep for example since it has some java code that needs to be compiled first

thheller14:05:55

thinking about this stuff is a gigantic rabbit hole ... It is interesting to think about but I do no have enough time to do anything about it 🙂

😀 4
🍺 4
Pontus19:05:59

I just setup shadow-cljs for my project, and I was wondering something. I've got om-next as a dependency and I think that's using a cljsjs packaged react. Then I've installed React with npm as it was needed as a dependency for another react-library. Do I know use two versions of React or does shadow-cljs somehow make om-next use the npm installed React?

wilkerlucio19:05:24

@pontus.colliander you are using the npm version, when you use a cljsjs dependency with shadow, you are actually loading this file: https://github.com/thheller/shadow-cljsjs/blob/master/src/main/cljsjs/react.cljs

👍 8
wilkerlucio19:05:02

these are the common ones because people already rely on cljsjs, but you can just create your cljsjs.my-package and make a shim like the one in the link I send before

Pontus19:05:50

okay, so that changes all references om-next had to the cljsjs-react to the npm version? Pretty cool