This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-24
Channels
- # announcements (1)
- # aws (140)
- # beginners (41)
- # calva (47)
- # cider (43)
- # clj-kondo (36)
- # clojure (178)
- # clojure-europe (12)
- # clojure-gamedev (2)
- # clojure-italy (1)
- # clojure-nl (17)
- # clojure-russia (3)
- # clojure-spec (37)
- # clojure-uk (97)
- # clojurescript (173)
- # core-async (16)
- # cursive (18)
- # data-science (2)
- # datascript (6)
- # datomic (32)
- # dirac (16)
- # duct (16)
- # events (2)
- # figwheel-main (7)
- # fulcro (8)
- # graalvm (18)
- # immutant (3)
- # joker (2)
- # kaocha (8)
- # nrepl (6)
- # nyc (2)
- # off-topic (62)
- # quil (3)
- # re-frame (18)
- # reitit (6)
- # ring-swagger (1)
- # shadow-cljs (119)
- # spacemacs (4)
- # specter (2)
- # tools-deps (10)
- # vim (58)
- # xtdb (9)
This is a crazy good new feature!! I will love it. (Can you maybe put colors in pretty print?)
Awesome feature. Thanks for your efforts @thheller! 🙂 We'll look at feasibility of direct integration of shadow-cljs in re-frame-10x at some point.
@superstructor although I'm working on this inside the shadow-cljs project for now all the underlying shadow.remote stuff is actually meant to be standalone at some point.
but I'll get into more details on that in the future. just wanted to show an early preview 🙂
Anyone here has experience making shadow-cljs working together with dirac ? They seems not "compatible" with each other ...
I don't know what it needs but currently is makes direct use of the cljs.analyzer
API I believe which means shadow-cljs can't intercept anything
@thheller I have very shallow knowledge about both, AFAIK 1) shadow-cljs has its own nrepl middleware (not using piggieback) to bootstrap a CLJS repl 2) and so does diract - it uses its own implementation Is that the major blocker?
@thheller IIUC
1. for a normal cljs repl, it's like clj repl -> piggleback mw (or whatever) -> websocket in browser/node
.
2. For diract its clj repl -> dirac mw -> dirac agent -> websocket in chrome devtools -> program being debugged
The thing makes dirac shine is it can evaluate exprs even when a breakpoint is hit and the program suspended, because its eval goes through chrome devtools. While others like shadow-cljs/figwheel can't do that because their eval are based on "user-mode" websocket code which is a no-go when bp is hit Ofc there are other stuff from diract like pretty-printing cljs var names, but this is the biggest sell for me
but given that it doesn't use any of the default cljs.repl
stuff that might be a lot of work
the stuff I'm currently working on may actually be relevant for this but it is a bit too early
the shadow.remote
stuff would be relevant for dirac. right now it isn't capable of eval
but it will hopefully be soon.
This looks awesome!!!! Going to try out this afternoon hopefully, think it will be a game changer for react native debugging
I haven't actually tested react-native yet since the test project I had for this doesn't work anymore for some reason
[SOLVED] I'm trying to require static resources like this
https://facebook.github.io/react-native/docs/images#static-image-resources
Should I use js/require
or import "as a library" in :require
from ns?
- Use (js/require "./../../resources/img.png")
@thheller works on react native a treat - got our whole re-frame db in there, it’s bloody brilliant!!
Is it possible to write a NodeJS server with Shadow-CLJS?
@thheller I would like to look into integrating dirac with shadow at some point, basically all I need is access to cljs compiler which is used by shadow-cljs - with figwheel I run dirac nrepl middleware in the same JVM as figwheel, so it can query figwheel’s state and use all “builds” and their relevant :compiler-env
states
it is a bit fragile and hacky, because I touch internal figwheel’s state, but it works: https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/figwheel.clj
yeah I looked at that in the past but couldn't quite figure out how it all worked together
btw. that code is a bit more involved because I also let user call figwheel repl api through dirac
repl command:
https://github.com/binaryage/dirac/tree/master/examples/figwheel-main#you-can-control-figwheel-main-via-dirac
yeah thats the main issue. if you use the compiler directly shadow-cljs can't do anything
please note that I use compiler API at lower level, because compilation env could be affected by locals on stack, so I don’t only give it cljs code string, but also prepare env with locals on stack (when stopped on a breakpoint)
I need to do something like this: https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/eval.clj#L52-L62
wouldn't it be easier to just eval (fn [the locals listed as args] (whatever-you-need-to-eval-using locals))
I wrote a simple health-checker using Serverless Framework and shadow-cljs. https://github.com/vharmain/serverless-healthcheck
not sure if this would work well, at least it would mess with stack, in case of another breakpoint in that code, user would see that wrapper function
but :locals
is supported cljs state config, why not use it? I have to mess with env anyways, for example to set current ns
that wrapper function could also interfere with return
statements maybe, not sure if this would be a real issue
it is using repl api here: https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/eval.clj#L252
here it is passing the compiler-env, which it got from figwheel (or created by dirac): https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/eval.clj#L238
ok, let me ask differnt way, when you receive user input as string, you have to turn it into js code, and then send it back to client for js eval - turning it into js code could be some fn call [cljs-code-string env] -> js-code-string
in your current impl env is probably always empty, but you can pass-through it for me down to cljs-compiler
https://github.com/thheller/shadow-cljs/blob/master/src/repl/shadow/cljs/repl_test.clj#L143-L149
there is no actual "eval" anywhere the REPL code .. you can process a bajillion things without ever evaling anything
to save you the time to eval. this is what you'd get back
:repl-actions
[{:type :repl/invoke,
:name "<eval>",
:js "(function (foo){\r\nreturn foo;\r\n})",
:source "(fn [foo] foo)",
:source-map-json
"{\"version\":3,\r\n \"file\":\"<eval>\",\r\n \"sources\":[\"<eval>\"],\r\n \"lineCount\":1,\r\n \"mappings\":\"AAAA,AAAKA;AAAL,AAAUA\",\r\n \"names\":[\"foo\"],\r\n \"sourcesContent\":[\"(fn [foo] foo)\"]}\r\n",
:warnings []}]}
I could probably use this api, but I would need some additional support. Current ns could be “emulated” by emitting in-ns
code, but :locals
would be better than wrapping it with fn, also need support for source maps somehow
{:shadow.cljs.repl/repl-state true,
:current-ns cljs.user,
:repl-sources
[[:shadow.build.classpath/resource "goog/base.js"]
[:shadow.build.classpath/resource "goog/debug/error.js"]
[:shadow.build.classpath/resource "goog/dom/nodetype.js"]
[:shadow.build.classpath/resource "goog/asserts/asserts.js"]
[:shadow.build.classpath/resource "goog/reflect/reflect.js"]
[:shadow.build.classpath/resource "goog/math/long.js"]
[:shadow.build.classpath/resource "goog/math/integer.js"]
[:shadow.build.classpath/resource "goog/string/internal.js"]
[:shadow.build.classpath/resource "goog/string/string.js"]
[:shadow.build.classpath/resource "goog/object/object.js"]
[:shadow.build.classpath/resource "goog/array/array.js"]
[:shadow.build.classpath/resource "goog/structs/structs.js"]
[:shadow.build.classpath/resource "goog/functions/functions.js"]
[:shadow.build.classpath/resource "goog/math/math.js"]
[:shadow.build.classpath/resource "goog/iter/iter.js"]
[:shadow.build.classpath/resource "goog/structs/map.js"]
[:shadow.build.classpath/resource "goog/uri/utils.js"]
[:shadow.build.classpath/resource "goog/uri/uri.js"]
[:shadow.build.classpath/resource "goog/string/stringbuffer.js"]
[:shadow.build.classpath/resource "cljs/core.cljs"]
[:shadow.build.classpath/resource "clojure/walk.cljs"]
[:shadow.build.classpath/resource "cljs/spec/gen/alpha.cljs"]
[:shadow.build.classpath/resource "clojure/string.cljs"]
[:shadow.build.classpath/resource "cljs/spec/alpha.cljs"]
[:shadow.build.classpath/resource "goog/string/stringformat.js"]
[:shadow.build.classpath/resource "cljs/repl.cljs"]
[:shadow.cljs.repl/resource "cljs/user.cljs"]],
:repl-actions
[{:type :repl/invoke,
:name "<eval>",
:js "(function (foo){\r\nreturn foo;\r\n})",
:source "(fn [foo] foo)",
:source-map-json
"{\"version\":3,\r\n \"file\":\"<eval>\",\r\n \"sources\":[\"<eval>\"],\r\n \"lineCount\":1,\r\n \"mappings\":\"AAAA,AAAKA;AAAL,AAAUA\",\r\n \"names\":[\"foo\"],\r\n \"sourcesContent\":[\"(fn [foo] foo)\"]}\r\n",
:warnings []}]}
that is the full repl-state. note the :current-ns
. you can just assoc :current-ns 'whatever.sym
so what about adding :locals
support in your repl? IMO you should just pass it through to analyzer
and maybe something else I’m not aware of right now, I wrote this code 3+ years ago, and I don’t have the context in my head
talking directly to the cljs.compiler just isn't going to work since shadow-cljs can't do its stuff that way
you could potentially even strip them from completely using https://shadow-cljs.github.io/docs/UsersGuide.html#_code_stripping