shadow-cljs icon indicating copy to clipboard operation
shadow-cljs copied to clipboard

Deno repl

Open didiercrunch opened this issue 2 years ago • 5 comments

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.

didiercrunch avatar Aug 17 '21 21:08 didiercrunch

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

  • https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/cljs/devtools/client/browser.cljs
  • https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/cljs/devtools/client/react_native.cljs
  • https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/cljs/devtools/client/node.cljs

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.

thheller avatar Aug 17 '21 21:08 thheller

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.

dgb23 avatar Oct 03 '21 21:10 dgb23

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 avatar Jul 19 '22 21:07 ranfdev

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

ranfdev avatar Aug 02 '22 17:08 ranfdev

@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:

  • https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/cljs/devtools/client/node.cljs
  • https://github.com/thheller/shadow-cljs/blob/629406b2029825dcafc8b53f58da3252d3b4a1b5/src/main/shadow/cljs/node_bootstrap.txt

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).

maxweber avatar Oct 01 '23 18:10 maxweber