thheller / shadow-cljs

ClojureScript compilation made easy
https://github.com/thheller/shadow-cljs
Eclipse Public License 1.0
2.24k stars 175 forks source link

Deno repl #923

Open didiercrunch opened 3 years ago

didiercrunch commented 3 years ago

I am trying to develop an application with clojurescript and deno. The trivial sources are here. It works great until I tried to run a repl.

To run the repl, I..

  1. Run the shadow-cljs repl via node_modules/.bin/shadow-cljs clj-repl
  2. The I start the deno repl using a command such as
    
    (shadow/node-repl {:build-id :app ;; my application
                   :node-command "/home/didier/.bin/deno"  ;; the deno bin directly 
                   :node-args ["repl"]  ;; `deno repl` is very similar to `node`
                   :verbose true})

Result: The underlying deno program exit and I have the following error.

[2021-08-17 16:59:18.741 - INFO] :shadow.cljs.devtools.server.repl-impl/node-repl-exit - {:code 0}

Expected: The repl should switch to deno process.

My two cents..

I believe the stdin of the deno process is closed. If I manually tail -f main.js | deno repl it works.

thheller commented 3 years ago

deno repl is something else entirely and is not related to how a CLJS REPL works in any way.

Currently there is no support for a CLJS REPL in deno since I have not implemented it yet. I have only played very briefly with deno when I created :target :esm. node-repl is not a suitable implementation here and won't work.

In essence there are 3 implemented REPL types currently. Browser, react-native and node

A deno CLJS REPL would need an implementation like these. They control how code actually connectes back to shadow-cljs and how code is loaded. You could attempt to write an implementation yourself and configure your build via {:target :esm :runtime :custom :devtools {:client-ns your.impl} ...}.

I don't currently have time to work out how to do this in deno myself but I can answer questions here if you want to try yourself (or anyone else interested). If deno supports websockets the port should be straightforward. I'm unsure how it handles dynamic code loading but I believe eval was available, just might have some scoping issues maybe.

dgb23 commented 2 years ago

I'm very interested in this feature and would like to at least tip my toes into contributing if that's OK.

Skimming the code I got confused by how the node client implements eval. The function is defined in this text file here which is loaded here. This stuff is a bit over my head at this point without further exploration, pointers or explanation.

Would it be feasible to just ignore the source-map-json in the call to do-invoke to get something running and explore from there what I can do?


And as a bit of an aside:

Happy to know if there are already any resources such as discussions/blog posts/documentation/videos and so on that give a bit of a high level overview of how shadow-cljs works internally, how I can think of the different parts and the REPL specifically. The things I found are more about the usage and less about how the thing works or how it is designed.

ranfdev commented 2 years ago

An external deno implementation would be useful also as a guidance to implement the REPL for other runtimes, like gjs or bun.

Specifically, gjs already has shadow-cljs support with an external target https://github.com/titonbarua/shadow-cljs-gjs-target and it also has a WebSocket implementation. It's only missing the code to run the REPL,

ranfdev commented 2 years ago

I've successfully implemented the REPL for the gjs runtime. The code may help you get the REPL working on deno: https://github.com/ranfdev/shadow-cljs-gjs-target

maxweber commented 11 months ago

@thheller, thank you so much for creating shadow-cljs :+1::+1:

I hacked a bit on a prototype to create a shadow-cljs REPL for Deno:

https://github.com/maxweber/cljs-deno-example

It is working 🥳 But I still don't know what I'm doing 😅 So I'm very grateful for any input on how to improve it. Currently, you can only evaluate forms. Loading/compiling the complete namespace does not work yet.

I used these as starting points:

I couldn't use eval since the evaluated code cannot use import. I used dynamic imports instead:

https://medium.com/deno-the-complete-reference/dynamic-imports-in-deno-5e9eb7f66238

SHADOW_WRAP in deno_bootstrap.js is not used anymore. I had trouble understanding it and transferring it to the dynamic imports approach. I also had to make the SHADOW_IMPORT function async, but if I remember correctly, the code that invokes it does not support this yet.

The content of the deno_bootstrap.js is not used directly. For the sake of the example, I copied it as :prepend into the shadow-cljs.edn (I know this is not the desired purpose :prepend).