clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
henrik42 2020-12-20T10:40:09.391100Z

Hey everyone! I'm running https://github.com/kanaka/cljs-bootstrap on a https://onion.io/omega2/ with https://openwrt.org/ & Node v8.10.0. Now I'd like to use Emacs/CIDER to connect to an nREPL server that does the evaluation in the Node/CLJS runtime. There is no way to run a JVM on the mirco. So I want to run a Clojure/JVM-nREPL server on my Windows box and have that JVM connect to the Node/CLJS. Any idea?

2020-12-20T10:50:53.395600Z

@henrikheine JVM+nREPL is meant to compile cljs to js, then the compiled forms can be sent to a web browser, a nodejs instance in the same machine or a nodejs in micro controller. I suspect if you need to run cljs-bootstrap in the first place. Why do you want cljs-bootstrap in the micro controller?

henrik42 2020-12-20T11:02:05.399900Z

@myguidingstar I'm probably just confused about cjls-bootstrap. I tried running it just to see if I could run CLJS without a JVM on the micro/Node. You're saying you can send the compiled CLJS/JS to a running Node? That's just what I need. What would I need on the JVM-side and what would run on the Node-side?

2020-12-20T11:05:24.401800Z

ok, I guess the confusing part is "bootstrap". It can either mean "boostraping the compiler" (as in cljs-bootstrap project you posted above), or only "bootstraping the js env for evaluation" (as seen in this script https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/bootstrap_nodejs.js)

2020-12-20T11:05:46.402200Z

in your case, you need the later, not the former

2020-12-20T11:13:52.403900Z

(you don't need to look into the above bootstrap_nodejs.js, that's only for reference)

2020-12-20T11:14:00.404100Z

look at this instead: https://github.com/nrepl/weasel

thheller 2020-12-20T11:22:57.409100Z

you can use shadow-cljs :node-script too. pretty easy to set up. extra easy if you can mount the files directly via sshfs or so

2020-12-20T11:25:41.410800Z

weasel will run on jvm desktop - it starts a websocket server and a nrepl server. You connect cider to the nrepl server, and in the readme you'll see the piece of code to put in the nodejs script. Don't forget to change the network address (from localhost to the local ip) and open firewall port

2020-12-20T11:29:18.411400Z

is it easy given that the nodejs instance is living in another machine?

thheller 2020-12-20T11:29:55.411600Z

yep

thheller 2020-12-20T11:31:10.411900Z

basically you set :output-dir "foo" :output-to "foo/script.js" :devtools {:devtools-url "<http://ip-of-machine-shadow-cljs.is.on:9630>"} and either mount the foo folder via sshfs or copy it over

thheller 2020-12-20T11:31:13.412100Z

best to mount though

thheller 2020-12-20T11:31:24.412300Z

but thats about it

2020-12-20T11:31:56.412600Z

so the important piece here is the devtools-url. Thanks

2020-12-20T11:33:18.413700Z

@henrikheine you may want to look at the shadow-cljs option instead. I haven't tried it myself, though

henrik42 2020-12-20T11:34:39.414700Z

@myguidingstar @thheller Thank you guys! That's the way to go. Got to go now. I'll do a write-up on this when things work out.

2020-12-20T11:50:07.415600Z

@thheller I'm a bit curious, what is devtools as in devtools-url?

thheller 2020-12-20T11:52:09.415800Z

configures dev related stuff from shadow-cljs?

thheller 2020-12-20T11:52:51.416Z

usually meant for this https://shadow-cljs.github.io/docs/UsersGuide.html#proxy-support but also works for other purposes. all it does it tell the code where it can find the shadow-cljs instance since that defaults to localhost or the current page url (which node of course doesn't have)

2020-12-20T11:53:46.416400Z

so it's "shadow's devtools", not "binaryage's devtools" 🙂

thheller 2020-12-20T11:53:53.416600Z

yes

2020-12-20T11:55:33.416800Z

do you think it is easy to support quickjs which is not nodejs-compatible and doesn't support websocket?

thheller 2020-12-20T11:59:35.417Z

there needs to be some way to remotely connect back to the shadow-cljs instance to get hot-reload/REPL. otherwise already works if you don't need that.

thheller 2020-12-20T12:02:41.417600Z

quickjs is fine with that output

2020-12-20T12:04:40.417800Z

I'll have a look. Thank you very much

clyfe 2020-12-20T12:16:24.418100Z

CrossPageChannel is deprecated in favor of MessageChannel https://google.github.io/closure-library/api/goog.net.xpc.CrossPageChannel.html

clyfe 2020-12-20T12:17:04.418300Z

maybe clojure.browser.repl should "upgrade"

GGfpc 2020-12-20T16:53:49.420300Z

How do I access a media query in clojure. The javascript code is this

// Create a media condition that targets viewports at least 768px wide
const mediaQuery = window.matchMedia('(min-width: 768px)')
// Check if the media query is true
if (mediaQuery.matches) {
  // Then trigger an alert
  alert('Media Query Matched!')
}
I tried this
(. (. js/window matchMedia "--breakpoint-not-small") matches)
but it returns
#object[TypeError TypeError: window.matchMedia (...) .matches is not a function]

valerauko 2020-12-20T16:56:18.420500Z

try with .- since it seems to be a property and not a function

p-himik 2020-12-20T17:49:34.420700Z

^ that's only for matches. matchMedia should still be used with . because it is a function.

1👍1💯
2020-12-20T18:33:33.421900Z

Can anyone explain why these docs don't seem to render in more recent versions? https://cljdoc.org/d/clojure-interop/cljs-web-api/1.0.0/api/web.Selection

clyfe 2020-12-20T18:49:26.422100Z

Seems to me some namespaces were moved, web.Selection is web.other.Selection in .10

2020-12-20T18:53:04.422400Z

@claudius.nicolae many thanks!

2020-12-20T19:23:04.423800Z

Followup to the above question... Once I get the selection with (. js/window getSelection), how do I then call methods like get-range-at on it? I see that I can do it like this, but it doesn't seem like it's the right way - it's not using the binding described in the docs:

{:onClick #(let [selection (. js/window getSelection)
                             ; srange (. selection get-range-at 0)
                             ; srange (.get-range-at selection 0)
                             srange (.getRangeAt selection 0)]

clyfe 2020-12-20T19:41:47.425600Z

(web.other.Selection/get-range-at (web.Window/get-selection js/window) 0)

2020-12-20T19:50:53.425800Z

I can't seem to require web.other.Selection.

2020-12-20T19:52:45.426Z

No such namespace: web.other.Selection, could not locate web/other/Selection.cljs, web/other/Selection.cljc, or JavaScript source providing "web.other.Selection"

henrik42 2020-12-20T19:54:30.426200Z

@thheller I followed https://github.com/thheller/shadow-cljs, did "npx create-cljs-project acme-app" and created a acme.core/foo.cljs - and "shadow-cljs watch my-app" (I'm using the Docker image theasp/clojurescript-nodejs:shadow-cljs-alpine). Now I try to connect the Node to the server (I do an exec into the container).

clyfe 2020-12-20T19:54:39.426500Z

what version are you on? the ".other" bit is in the latest

henrik42 2020-12-20T19:54:51.426700Z

node foo/my-app.js foo bar
this is acme.core/foo with args: ("foo" "bar")
REPL client error Error: connect EINVAL 0.0.37.158:80 - Local (0.0.0.0:0)
    at internalConnect (net.js:913:16)
    at defaultTriggerAsyncIdScope (internal/async_hooks.js:301:12)
    at GetAddrInfoReqWrap.emitLookup [as callback] (net.js:1056:9)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:65:10) {
  errno: -22,
  code: 'EINVAL',
  syscall: 'connect',
  address: '0.0.37.158',
  port: 80
}
REPL client disconnected

henrik42 2020-12-20T19:56:25.426900Z

Does this error message mean, that the NodeJS/CLJS tries to connect the server at 0.0.37.158:80 ? I have no idea where that could come from.

henrik42 2020-12-20T19:57:40.427100Z

acme.core/foo just does a println and returns. Does that hinder the connection from being established?

2020-12-20T19:59:18.427300Z

org.clojure/clojurescript {:mvn/version "1.10.742"}

clyfe 2020-12-20T20:00:00.427500Z

I meant clojure-interop version

2020-12-20T20:01:31.427700Z

Oh, shoot, that has to be installed separately? For some reason I assumed it's part of the cljs distro or something.

henrik42 2020-12-20T20:13:17.427900Z

My fault! Didn't put http:// in front of IP. Getting there ....

p-himik 2020-12-20T20:31:53.428100Z

cljs-web-api seems to be a thin wrapper around web API. You don't need to use it - your code above is the proper way to do it via JS interop. Well, maybe you'll need to sprinkle some ^js there if you have some problems after :advanced optimizations.

2020-12-20T20:57:18.428600Z

@p-himik so it's not "more correct" to use the wrapper? It's not the more idiomatic approach?

p-himik 2020-12-20T21:03:17.428800Z

Absolutely, thin wrappers aren't idiomatic.

p-himik 2020-12-20T21:03:58.429Z

IMO. :) But you can see a lot of prominent names in the Clojure community that are against thin wrappers. On the other hand, wrappers that actually do provide some useful functionality can be perfectly fine.

2020-12-20T21:09:49.429300Z

Thanks. This is my first bit of direct exposure to interop. I don't even know what that ^js stuff is about and I haven't done anything with :advanced, but I'll make a note of it for when it does come up.

p-himik 2020-12-20T21:14:39.429500Z

At least with shadow-cljs, ^js metadata on a symbol will tell the compiler to not mangle the names of fields/methods on that symbol that you access via JS interop. I'm pretty sure it works in the vanilla CLJS compiler. And :advanced is just an optimization level that's typically used for production builds. E.g. code like (.some_method x) might be turned into e.g. x.f() if GCC decides to shorten the name some_method to f. But it's not always appropriate because x might come not from your code (where such a rename would make sense because it would be throughout the whole codebase) but from some thirdparty API, like (.getSelection js/window). And (.some_method ^js x) will always result in x.some_method() (well, x might be renamed but it hardly matters).

p-himik 2020-12-20T21:15:00.429700Z

Same for

(let [^js x (somehow-get-x)]
  (.some_method x))

p-himik 2020-12-20T21:15:30.429900Z

Some details are available here: https://shadow-cljs.github.io/docs/UsersGuide.html#infer-externs

henrik42 2020-12-20T21:17:08.430100Z

AWESOME! It works. On my Windows box (git bash) I just did a "scp -r foo <micro-box>" and then on the mirco just "node foo/my-app.js". Had to add a rule to my Windows defender firewall so that the micro could connect back to the Windows box. This is greate. So thanks a lot!!

1😄
2020-12-20T21:25:23.430600Z

@p-himik thanks for the thorough explanation. That makes a lot of sense. The ^js basically forces the optimizer to leave that symbol alone.