shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
flowthing 2021-04-14T07:46:05.172400Z

Does shadow-cljs have an API for getting the ClojureScript compiler environment? I'm asking because I'm considering implementing basic ClojureScript auto-completion support from scratch and I believe I need to get a hold of the compiler environment for that.

flowthing 2021-04-14T07:46:52.173Z

I found this comment: https://github.com/thheller/shadow-cljs/issues/76#issuecomment-318763762 But that snippet doesn't seem to return the compiler env anymore (unless I messed something up).

thheller 2021-04-14T07:49:37.173500Z

(shadow.cljs.devtools.api/compiler-env :the-build)

flowthing 2021-04-14T07:49:50.173900Z

How did I not find that... 🤦 thanks!

thheller 2021-04-14T07:49:58.174100Z

watch needs to be running for that to work

flowthing 2021-04-14T07:50:02.174300Z

Sure.

flowthing 2021-04-14T08:28:13.179200Z

Another (maybe too vague) question: I'd like to start a nested REPL using clojure.main/repl that leverages shadow-cljs to evaluate ClojureScript. I'm wondering whether there's any prior art on this sort of thing I ought to be looking at? I tried quickly hacking something together and came up with this:

;; *out-fn* is bound to a function that prints to the socket output stream
(let [out-fn tutkain.repl.runtime.repl/*out-fn*]
  (clojure.main/repl
    :read clojure.core.server/repl-read ;; add :repl/quit support
    :need-prompt (constantly false) ;; don't want prompt
    :prompt (constantly "") ;; don't want prompt
    ;; eval is code -> value -- cljs-eval is string -> string, so need to pr-str the input form
    :eval #((requiring-resolve 'shadow.cljs.devtools.api/cljs-eval) :app (pr-str %) {})
    :print (fn [{:keys [results out err ns]}]
             (when (seq out) (out-fn {:tag :out :val out}))
             (when (seq err) (out-fn {:tag :err :val err}))
             (run! #(out-fn {:tag :ret :val % :ns ns}) results))))
This seems to work as far as very basic use goes. Does this seem like a reasonable approach? I know that's not enough to have special things like in-ns work -- need to look into that some more.

thheller 2021-04-14T08:31:24.179500Z

(shadow.cljs.devtools.api/repl :the-build {:prompt false})

thheller 2021-04-14T08:34:07.179900Z

if you want more control over what the REPL does you could use what it internally uses

thheller 2021-04-14T08:34:32.181Z

but would be better to make an issue for it with a proper description so I can add an actual API fn for it

flowthing 2021-04-14T08:34:51.181800Z

Yeah, that's what I was looking for. Thanks! I'll dive into it and make an issue if something turns up.

thheller 2021-04-14T08:34:56.181900Z

digging into internals too much is not recommended because I might break it at any point 😛

flowthing 2021-04-14T08:35:01.182200Z

Sure. 🙂

flowthing 2021-04-14T12:34:05.185300Z

One more: if I do this:

(when file
    (let [{:keys [results err]} ((requiring-resolve 'shadow.cljs.devtools.api/cljs-eval)
                                 :app
                                 (format "(cljs.core/load-file \"%s\" %s)" file code) {})]
      (when err
        (out-fn (response-for message {:tag :err :val err}))
        (run! #(out-fn (response-for message {:tag :ret :val %})) results))))
And the code is a ClojureScript namespace that uses an auto-qualified keyword like ::db/reset, I get this error:
repl-input.cljs [line 23, col 38] Invalid keyword: ::db/reset.
The namespace has a require like this: [app.client.db :as db]. Are auto-qualified keywords not supported? This might also be more of a general ClojureScript question, but if I've understood correctly, shadow-cljs implements its own load-file kind of thing.

thheller 2021-04-14T12:35:50.186600Z

it is much easier for me to answer stuff if you show the actual REPL code

thheller 2021-04-14T12:36:04.187Z

shadow-cljs node-repl or browser-repl and then the actual command

thheller 2021-04-14T12:36:15.187300Z

I don't know if you are escaping the strings properly etc

thheller 2021-04-14T12:36:38.187900Z

the aliases should work just fine, assuming they actually exist

flowthing 2021-04-14T12:36:43.188Z

Oh, string escaping is a good point. Gotta double-check that.

flowthing 2021-04-14T12:37:13.188600Z

They do exist, the code itself works. But yeah, I'll come back with a better repro if it's something else than string escapes.

thheller 2021-04-14T12:37:56.189Z

load-file also only take one argument?

flowthing 2021-04-14T12:39:06.189500Z

Oh, that's right. I must've gotten it mixed up... good catch, thanks. :thumbsup::skin-tone-2:

orestis 2021-04-14T17:22:09.192200Z

Is there a way to generate the "build report" html file when doing a proper release? Right now it seems that it takes as much time to do the release as it takes to generate the report. Would be nice to cut our CI times in half.

thheller 2021-04-14T17:25:21.193Z

not currently no. it could in theory but currently it is separate since it changes a bunch of stuff in the config to make things easier. needs to be able to access source maps and stuff

thheller 2021-04-14T17:25:43.193400Z

(which are not enabled by default for release for example)

orestis 2021-04-14T17:30:05.194300Z

Makes sense. I've enabled source maps in release mode now (I'm trying to integrate Sentry), but I guess it's not that simple.

thheller 2021-04-14T17:32:20.194700Z

should be simple but no clue 🙂

Alys Brooks 2021-04-14T20:49:16.197800Z

I've tried enabling the babel integration to compile my output for IE11, but it doesn't seem to be working. Here's my shadow-cljs.edn:

{:builds {:main 
          {:js-options {:babel-preset-config {:ie 11}}
...}}
...}

Alys Brooks 2021-04-14T20:51:07.198400Z

I tried enabling a verbose build log, and babel doesn't seem to be anywhere.

thheller 2021-04-14T20:53:02.199100Z

babel is not applied to all JS sources, the more reliable option is :compiler-options {:output-feature-set :es3}

thheller 2021-04-14T20:53:20.199500Z

what exactly doesn't work in IE11? I mean typically es5 should be fine for that?

Alys Brooks 2021-04-14T21:02:22.201Z

I think the issue is that IE11 doesn't support String.includes . The code is for a client and not open source, so I'd have to see if the error is in the application code or one of the libraries we're using.

thheller 2021-04-14T21:06:15.201500Z

you can try setting :compiler-options {:force-library-injection #{"es6/string/includes"}} in your build config

thheller 2021-04-14T21:06:36.202Z

that will inject the polyfill if needed

Alys Brooks 2021-04-15T18:54:05.246Z

Oh, that works now, thanks! I'm not sure there's a Google Closure polyfill for URLSearchParams, though.

thheller 2021-04-15T19:03:22.246200Z

you can always use https://polyfill.io/v3/ to get whatever standard polyfills you need for IE

Alys Brooks 2021-04-15T19:34:08.246500Z

That looks like a good resource! I have seen references to babel, but it seems like it might lag behind in terms of polyfill support.

thheller 2021-04-15T19:34:53.246700Z

babel doesn't lag behind. babel isn't used.

thheller 2021-04-15T19:35:08.246900Z

it has one specific purpose in shadow-cljs but that is not polyfilling. in fact we don't want it to polyfill at all and I'll likely remove that aspect of it completely

Alys Brooks 2021-04-15T19:38:18.247200Z

Oh, gotcha

Alys Brooks 2021-04-15T19:42:54.247400Z

I think I'm going to use goog.uri instead of http://polyfill.io. (Probably why Google Closure doesn't have a polyfill for URLSearchParams)

Alys Brooks 2021-04-15T19:44:16.247600Z

Would you be interested in a PR adding documentation around :force-library-injection? It seems like it's a fallback/last resort, but the documentation could definitely note that.

thheller 2021-04-15T19:45:38.247800Z

under normal circumstances it is never required to set it

thheller 2021-04-15T19:46:00.248Z

just under some weird circumstances that I have not been able to reproduce it needs to be manually added

thheller 2021-04-15T19:46:22.248400Z

sure it would be worth documenting but I'd rather identify why its not detected properly 😉

Alys Brooks 2021-04-15T19:52:51.250200Z

Makes sense. I can try to reproduce with a minimal sample project, if that would help.

thheller 2021-04-15T20:06:01.250400Z

it would

Alys Brooks 2021-04-16T20:02:21.278600Z

You might not be surprised to hear that I'm not having a lot of luck reproducing in a simpler sample project. I thought maybe something about Glögi was confusing it or perhaps Glögi plus separate modules, but both of those are working fine. I'll keep trying today.

thheller 2021-04-16T20:08:28.278800Z

yeah it has proven difficult to reproduce 😛

Alys Brooks 2021-04-14T21:53:40.204600Z

I'm not having any luck with that either. 😕 . I'm putting it in :builds . It also looks like the issue is coming from one of the libraries I'm using. I don't think that should make a difference, as it's also ClojureScript that would need to be compiled, though?

Alys Brooks 2021-04-14T22:20:42.205100Z

The build log does say it's generating polyfills

Alys Brooks 2021-04-14T22:31:10.205400Z

I fixed one of the issues upstream with glögi, but now URLSearchParams is causing a problem.