Fork me on GitHub
#cljs-dev
<
2016-06-21
>
bhauman14:06:10

@dnolen: another thing to consider along these lines, is a simple build-api/input function to help supply the clojurescript source of a whole namespace directly to the compiler. AFAIK, currently, it's a little tricky to do this, so I'm creating a temp file. Being able to provide the raw source for a namespace, would make much easier to dynamically inject initialization without needing to create a file. Combining this with :preload should cover 99% of behavior injection.

darwin14:06:15

@bhauman: wondering why do you need clojurescript source of whole namespace?

bhauman14:06:57

@darwin: you mentioned config yesterday

bhauman14:06:36

right now you call the compiler with (cljs.build.api/inputs "src" "dev/cljs")

bhauman14:06:19

if we were able to inject the source code of a namespace there we could inject all the initialization config we need

darwin14:06:33

ah, now I see

bhauman14:06:40

this is a dynamic namespace that doesn't exist on disk

bhauman14:06:06

then with :preload you can require it in the right order

bhauman14:06:38

I'm pretty sure this can be done now, it just takes some futzing.

darwin14:06:56

I didn't have anything like lein plugin in mind, I think I can config my tool in two ways: a) closure-defines b) env variables

darwin14:06:28

in both ways one could encode JSON/edn in a variable with more complex config

darwin14:06:04

with lein plugin you could serialized whole :figwheel, pass it into closure-define and unserialize it in your init namepspace

darwin14:06:15

you would not need to generate temp files with some config injected

darwin14:06:54

env variables approach is more tricky, you could use clojure macro to read env setting and then emit it into cljs source code

darwin14:06:09

which has different implications

bhauman14:06:47

this works for simple config values, but wouldn't be as expressive as a whole namespace

bhauman14:06:26

but it works to be sure

bhauman14:06:22

the namespace can boot your different tools for you

bhauman14:06:36

and being able to inject it dynamically without needing a file is a big plus

darwin14:06:47

I agree, generated namespace would be very flexible, but I’m a bit afraid about error feedback when something goes wrong, fishing for non-existent files is no fun

darwin14:06:13

I hate Clojure for that (when working with REPL and dynamic evals ;)

bhauman14:06:36

so your tool could read the environment vars and then

"(ns mybooting.tools (:require cljs-devtools)) 
(cljsdevtools/start {:confg value-from-env})"

bhauman14:06:50

inject that right into the build

bhauman14:06:12

I hear you about the when something goes wrong

bhauman14:06:40

a temp file could be created

bhauman14:06:31

yeah that would work

darwin14:06:52

with closure defines, no macros would be needed

darwin14:06:08

the config would be passed via :compiler options directly by cljs compiler

darwin14:06:15

which is more predictable

darwin14:06:30

as I said, I could encode arbitrary complex config as json/edn, but then I would need a lein-plugin to make people’s lives easier to deal with it

dnolen14:06:09

@bhauman I think you can do what you want to today

dnolen14:06:20

if you pass a vector it should be a seq of forms

bhauman14:06:45

cool, I'll check it out

dnolen14:06:45

'[(ns foo) …]

bhauman14:06:20

darn I really thought I looked at the dispatch on that a while ago

dnolen14:06:21

this is why we don’t support passing a vector of source paths

darwin14:06:25

@dnolen: thinking about closure defines, would be handly if not only strings were supported, if you pass edn as a value, clojurescript compiler would serialize it as a string when emitting as CLOSURE_UNCOMPILED_DEFINES

darwin14:06:46

oh, wait, maybe it works? arbitrary nested edn will be just emitted as a corresponding json?

bhauman14:06:03

I'm psyched about :preload

darwin15:06:49

ah, goog defines require {string|number|boolean}, hmm

dnolen15:06:13

so not much benefit

darwin15:06:38

I would benefit from nested json under one key

darwin15:06:44

I would put there my whole config

dnolen15:06:53

@bhauman: glad to hear - that’s been sitting around since the earliest days

darwin15:06:59

and reduce risk of clash with other things

dnolen15:06:03

@darwin it’s a convenience thing I understand

dnolen15:06:12

but we already have too much config stuff and I’m about to add more

dnolen15:06:26

usually the answer to more config now is going to be no

darwin15:06:05

could we adopt a convention, something along these lines: for any [key value] in (:closure-defines opts) whose value does not serialize to {string|number|boolean} we emit two new goog defines with following convention: [key (pr-str value)] and [(str key “_edn”) true] this way I could do in my code test for devtools.config_edn, and if it is ideed edn, I can unserialize

dnolen15:06:31

I’d rather not

dnolen15:06:40

:closure-defines intentionally follows the rules

dnolen15:06:49

changing anything around it is unlikely

darwin15:06:19

I’m probably not going to write lein-plugin to do the string serialization on user’s behalf

bhauman15:06:34

I don't think you need to do that

bhauman15:06:44

I might be missing something

bhauman15:06:00

What is your specific situation?

darwin15:06:54

only bool, number and string are allowed as values

bhauman15:06:09

but the overall goal is to get user configuration to intitialize your tools right?

darwin15:06:20

I would like to see people use one key “devtools.config” to pass me whole devtools config

bhauman15:06:37

I'm suggesting that you don't do that

bhauman15:06:47

and don't write a plugin

darwin15:06:05

writing a lein plugin is the last thing I would want to do with my time 😉

dnolen15:06:31

@darwin overloading :closure-defines is just not the way to do this - :closure-defines is really for controlling Closure defines / dead code elimination

dnolen15:06:45

@darwin you might not know this but you can pass anything in compiler options

dnolen15:06:56

:cljs-devtools/config

darwin15:06:34

@dnolen: didn’t know this, thanks, how my cljs code then can access the information?

dnolen15:06:43

any macro can see it

dnolen15:06:54

so you can write a source file that just dumps that stuff

darwin15:06:56

then problem solved 🎉

darwin15:06:42

better than piggiebacking on closure-defines!

dnolen15:06:43

glad to hear it

dnolen15:06:55

so I’m getting pretty excited about specing the ClojureScript compiler

dnolen15:06:15

would be a pretty easy way to contribute and would greatly streamline onboarding new would be compiler hackers

dnolen15:06:25

will probably wait till 1.9.0 final before considering them seriously - but just putting it out there if anyone is interested in taking them on when we get there

darwin16:06:53

great I’m going to test it

dnolen16:06:56

I believe it should work with any optimization setting

dnolen16:06:03

though I didn’t test that

dnolen16:06:54

having played around with it over here it seems quite nice

dnolen17:06:16

I cut 1.9.85 for people who want to play around with :preloads

darwin17:06:39

I’m excited about it, btw. this is how easy it was to introduce preload ns in cljs-devtools

darwin17:06:48

btw. @bhauman proposed :tooling-config convention, so figwheel can be less strict about libraries under that key and still strictly validate everything else

dnolen17:06:34

@darwin awesome! Thanks

darwin17:06:22

I’m going to cut a new cljs-devtools release and document it a bit

darwin17:06:46

@dnolen: maybe I hit an issue with :preloads, if my preload namespace requires other namespaces those do not appear in cljs_deps.js, so goog module system does not know about them

darwin17:06:05

cljs_deps only contians reachable namespaces from :main namespace

dnolen17:06:08

@darwin: nice catch looking

dnolen20:06:44

@darwin try master, I fixed a bunch of things that would be broken

dnolen20:06:49

foreign libs etc.

dnolen20:06:59

it also seems to work fine under advanced optimization now

darwin20:06:14

thanks, will do

dnolen20:06:53

ClojureScript 1.9.88 cut

dnolen20:06:02

should be available via maven in a bit

darwin20:06:33

btw. just found a promising hack, how to enable long stack-traces in core.async + Chrome DevTools: https://dl.dropboxusercontent.com/u/559047/core-async-long-stack-traces.png

darwin20:06:00

the trick is to replace goog.async.nextTick with a promise-based implementation

darwin21:06:18

it is not super useful ATM, because maxAsyncStackChainDepth is currently hard-coded in DevTools and set to only 4, which is not enough for more complex core.asyn code: https://github.com/binaryage/dirac/blob/devtools/front_end/sdk/DebuggerModel.js#L200 but in Dirac I will able to lift in and maybe walk the call stack in a better way, so loops won’t create long stack traces

dnolen21:06:33

@darwin let me know if you hit any more issues, I’d like to use cljs-devtools w/ :preloads asap 😉

darwin21:06:14

@dnolen: v0.7.2 should be good, works in my sample project

darwin21:06:44

@dnolen: 1.9.88 fixed the issue in my sample app, good job!

dnolen21:06:48

@darwin: glad to hear it!

darwin21:06:17

I’m about to call it a day, we’ve made a good progress today, I’m thinking about publishing a tiny library, which would offer preload with (enable-console-print!), or make it as optional part of cljs-devtools, not sure if it is worth it tough