clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Gustavo Bertolino 2021-01-21T00:45:48.153600Z

Hi guys, I'm building a react demo appl with cljs (to practice cljs) and I'm thinking about changing this very appl on the fly via a remote repl. Is that possible? For example, suppose I want to change a component to correct it and re-rendering it with my appl running in production. Is it possible to make these things via repl?

Gustavo Bertolino 2021-01-21T13:29:26.024400Z

But if this appl is a Electron appl which runs in a single JS process (a node process), or even a controlled number of JS processes. So in this case, in theory, I could make changes on the fly via a remote repl to inject this change on the node process running my appl and all the clients would take this change, wouldn't they? @dpsutton

Gustavo Bertolino 2021-01-21T13:34:04.024600Z

obs.: in the case of a controlled number of node processes, each one running an appl's instance, I'd enter in the repl of each instance to make the change

Gustavo Bertolino 2021-01-21T00:51:49.155800Z

obs.: the repl I'd connect with remotely is the one fired by the start of my appl

dpsutton 2021-01-21T01:01:26.158300Z

A repl can only change the running instance. For a long running clj process this would be fine. But a cljs process is just someone’s browser. So if you repld to a particular users browser you could change it but the next load of a page would just get the originally compiled code without any changes. The same as restarting a clj process.

👍 1
👀 1
p-himik 2021-01-21T01:08:30.000100Z

Seems to work just fine for me. Try clearing all the cache and build artifacts, including the .shadow-cljs dir.

Gustavo Bertolino 2021-01-21T03:05:15.000600Z

Yes, I see. I made some tests here with my appl and re-rendering its component via repl and it works but only for one particular browser's tab or window that opens my appl. And after reloading the page, the browser takes the initial compiled code. Opening other tabs/windows and calling my appl also cause the same effect. I didn't notice that in the case of setting the browser as the target means that the repl (fired during the build) will be connected to that instance/process of the browser through I eventually open my appl.

zendevil 2021-01-21T04:15:23.001100Z

I am uploading a video to the server like so:

zendevil 2021-01-21T04:16:11.001900Z

(reg-event-fx
 :upload-shot-video
 (fn [coeffects _]
   (prn "uploading video")
   (let [video {:uri (-> coeffects :db :shot-video-uri)}
         body (js/FormData.)]
     (prn "uri is " (-> coeffects :db :shot-video-uri))
     (.append body "video" video)
     {:http-xhrio {:method :post
                   :uri (str "<http://d18a6571c2e5.ngrok.io>" "/api/upload-shot-video")
                   :body body
                   :on-success [:upload-success]
                   :on-failure [:upload-error]
                   :response-format (edn/edn-response-format)}})))
where (-> coeffects :db :shot-video-uri) is the temporary uri of the image in the ios device

zendevil 2021-01-21T04:16:49.002400Z

the handler that I have is the following:

zendevil 2021-01-21T04:17:51.003200Z

For saving the input stream into a file video.mov

(defn upload-shot-video [req]
  (prn "uploading video")
  (prn "video is! " (-&gt; req :params))
  (prn "video is " (-&gt; req :body))
  (<http://clojure.java.io/copy|clojure.java.io/copy> (-&gt; req :body) (<http://clojure.java.io/file|clojure.java.io/file> "./resources/public/video.mov"))


  (r/response {:res "okay!"}))

zendevil 2021-01-21T04:18:19.003900Z

But the size of the file is turning out to be 0 bytes, whereas I expect a size greater than 0 bytes

zendevil 2021-01-21T04:18:37.004300Z

How to correctly send the video to the server?

dpsutton 2021-01-21T04:31:11.004900Z

did you look into the extensive info noisesmith provided about the middleware? How it takes the body and creates a temporary file for you?

zendevil 2021-01-21T04:31:41.005400Z

@dpsutton I removed the middleware and created a copy manually/

zendevil 2021-01-21T04:33:08.005900Z

the video is in (-> req :body). At least there’s an inputstream in there

zendevil 2021-01-21T04:33:33.006500Z

copying that input stream to the file system as a file is giving a file of 0 bytes

dpsutton 2021-01-21T04:34:09.007100Z

add a prn statement on your request. just see what's in there. i suspect you've got more middleware going on. there might be more information

zendevil 2021-01-21T04:37:16.007500Z

@dpsutton Here’s the request:

zendevil 2021-01-21T04:37:16.007600Z

{:reitit.core/match #reitit.core.Match{:template "/api/upload-shot-video", :data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :result #reitit.ring.Methods{:get #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :get, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :head #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :head, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :post #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :post, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :put #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :put, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :delete #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :delete, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :connect #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :connect, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :options #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :options, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :trace #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :trace, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}, :patch #reitit.ring.Endpoint{:data {:middleware [#function[humboiserver.middleware/wrap-formats]], :handler #function[humboiserver.routes.home/upload-shot-video]}, :handler #function[humboiserver.middleware/wrap-formats/fn--9418], :path "/api/upload-shot-video", :method :patch, :middleware [#reitit.middleware.Middleware{:name nil, :wrap #function[humboiserver.middleware/wrap-formats], :spec nil}]}}, :path-params {}, :path "/api/upload-shot-video"}, :reitit.core/router #object[reitit.core$lookup_router$reify__11769 0x667531a6 "reitit.core$lookup_router$reify__11769@667531a6"], :aleph/request-arrived 166349045051244, :aleph/keep-alive? true, :cookies {}, :remote-addr "0:0:0:0:0:0:0:1", :params {:video ""}, :flash nil, :headers {"host" "<http://d18a6571c2e5.ngrok.io|d18a6571c2e5.ngrok.io>", "user-agent" "Humboi/1 CFNetwork/1206 Darwin/20.1.0", "content-type" "multipart/form-data; boundary=BrxekIJ39.PWpQVKqWBWuBAz5KUTH7jhXk67qEssuW4LZbO4Df535XFNLmYDbDGWT73QsP", "content-length" "200", "accept" "application/edn", "accept-language" "en-us", "x-forwarded-for" "110.225.238.196", "accept-encoding" "gzip, deflate"}, :server-port 3000, :muuntaja/request #FormatAndCharset{:format nil, :charset "utf-8", :raw-format "multipart/form-data"}, :form-params {}, :session/key nil, :query-params {}, :uri "/api/upload-shot-video", :server-name "localhost", :query-string nil, :path-params {}, :muuntaja/response #FormatAndCharset{:format "application/edn", :charset "utf-8", :raw-format "application/edn"}, :body #object[java.io.ByteArrayInputStream 0x222b0412 "java.io.ByteArrayInputStream@222b0412"], :multipart-params {"video" ""}, :scheme :http, :request-method :post, :session {}}

zendevil 2021-01-21T04:40:32.007900Z

The only middleware is wrap-formats

dpsutton 2021-01-21T04:41:09.008500Z

can you open up the browser network pane and make sure you're actually sending bytes across the wire?

zendevil 2021-01-21T04:41:49.009100Z

I don’t know how to do that. How does one open a browser network pane?

seancorfield 2021-01-21T04:42:48.009400Z

@ps What browser are you using?

zendevil 2021-01-21T04:43:08.009800Z

safari

seancorfield 2021-01-21T04:43:41.010700Z

Ah... been many years since I used that... I'm sure it has developer tools but no memory of how to get at them...

zendevil 2021-01-21T04:43:53.011200Z

@dpsutton You mean open the developer console here?: http://localhost:8081/debugger-ui/

seancorfield 2021-01-21T04:44:05.011500Z

Chrome has "dev tools" (as does Microsoft Edge for macOS).

dpsutton 2021-01-21T04:45:08.012400Z

Develop > Show Web Inspector. then click on the network tab

zendevil 2021-01-21T04:46:38.013200Z

wouldn’t http://localhost:8081/debugger-ui/ open the simulator debugging and not the device? I’m recording the video on the device

zendevil 2021-01-21T04:47:05.013700Z

which is supposed to be sent to the server after video stops recording

zendevil 2021-01-21T04:52:22.014500Z

I have a feeling that http://localhost:8081/debugger-ui/ doesn’t open debugging for the device

zendevil 2021-01-21T04:53:49.014600Z

command option I

zendevil 2021-01-21T04:54:39.015Z

no actually the debugger is working with the device

zendevil 2021-01-21T04:55:13.015500Z

but @dpsutton what should I be looking for in the network tab?

dpsutton 2021-01-21T04:55:36.016Z

the request that has a big video payload. look for it having some form data, try to find the size of the request, etc

dpsutton 2021-01-21T04:57:40.017100Z

identify if the video is getting to your backend and the problem is finding it in the request or if the frontend is sending it and you need to fix that first. just general debugging steps. cut the problem in half and then figure out a way to cut that remaining problem in half, etc

seancorfield 2021-01-21T04:59:27.017200Z

I have been using Microsoft Edge on macOS for ages -- and cmd-opt-i is what Edge uses to open dev tools 🙂

zendevil 2021-01-21T05:03:19.017900Z

I don’t see any new requests in the console, whereas the server is receiving the request

dpsutton 2021-01-21T05:05:43.018600Z

if you're on the network pane and its correctly hooked up and you hit refresh you should see requests to load your js and html. i don't know what you're looking at so can't help you further

zendevil 2021-01-21T05:07:37.018900Z

I do see the other requests

zendevil 2021-01-21T05:08:09.019Z

zendevil 2021-01-21T05:09:47.019700Z

but apparently not the one with the video

zendevil 2021-01-21T05:13:46.020Z

and the number of requests isn’t increased either

zendevil 2021-01-21T05:28:26.020700Z

I read this on cljs-ajax which the http-xhrio library wraps

zendevil 2021-01-21T05:28:35.020900Z

cljs-ajax doesn’t have any other support for file uploads (although pull requests are welcome).

zendevil 2021-01-21T05:29:48.021400Z

but in this issue the user successfully uploads the file: https://github.com/JulianBirch/cljs-ajax/issues/122

zendevil 2021-01-21T05:30:10.021800Z

This is confusing

fmnoise 2021-01-21T14:34:14.025700Z

hi everyone, probably stupid question asked million times but

(= (hash 1) (hash 1.7))
;; =&gt; true
is that expected?

fmnoise 2021-01-21T14:34:52.026200Z

Clojure has different behavior

alexmiller 2021-01-21T14:56:16.026500Z

hashes are not guaranteed consistent across platforms

dnolen 2021-01-21T14:56:55.027400Z

you can fudge that a little bit with ClojureScript

alexmiller 2021-01-21T14:56:56.027600Z

and having hashes collide is certainly normal

dnolen 2021-01-21T14:57:11.028100Z

for various reasons we do try to generate identical hashes where practical

dnolen 2021-01-21T14:59:55.028700Z

numbers are problematic of course because JavaScript only has double

dnolen 2021-01-21T15:00:39.029200Z

so aligning things here is not really worth the other complications

2021-01-21T15:11:40.030200Z

A quick cljs REPL experiment shows that cljs vectors appear to be more like Clojure 1.5.1 and earlier, in that they collide often for a set of vectors like:

(def grid-keys (for [x (range 100), y (range 100)]
                        [x y]))

2021-01-21T15:12:31.030500Z

That was one example of the kind of hash collisions that led Clojure to change its hash function in Clojure 1.6.0

2021-01-21T15:13:55.030700Z

I don't know whether the performance tradeoffs for fancier hashing is the same in cljs -- just thought I'd mention the results of that experiment, since the code demonstrating the problem with older Clojure versions was easy to copy and paste.

Gustavo Bertolino 2021-01-21T15:51:52.033Z

Hi guys, could someone validate this scenario for me? I was thinking if it's correct or feasible The context is to see if it make sense my thought of accessing the JS process on which is running my cljs appl so that I can make changes in it on the fly

dnolen 2021-01-21T16:04:47.034Z

@andy.fingerhut we use the same hashing functions as Clojure at the bottom

dnolen 2021-01-21T16:05:14.034600Z

so we have the post 1.6 stuff, whether we have the vector specific tweaks is another investigation

2021-01-21T16:08:37.034700Z

Is a CLJS ticket that at first simply collects some observations on latest CLJS version hash behavior as compared to latest Clojure version perhaps useful?

dnolen 2021-01-21T16:43:37.035100Z

sure

p-himik 2021-01-21T18:15:29.038200Z

There are special channels for that - #jobs and #remote-jobs

p-himik 2021-01-21T18:15:48.038400Z

Make sure to read the channels' descriptions.

Brian Kelly 2021-01-21T18:26:56.038600Z

Absolutely and this will be my only post in here. 2 members asked me to do it to help others in the community that may be looking for work !

👍 1
seancorfield 2021-01-21T18:49:35.039Z

@bkelly This is the second time you've been told not to post jobs in general channels -- and the second time I've deleted your post. If you want to post a job, do it in the appropriate channel and provide details about location/remote and any other criteria. Just saying "DM me for more details" just wastes people's time. /admin

☝️ 1
fmnoise 2021-01-21T19:09:58.039200Z

thanks for explanation :thumbsup::skin-tone-3: