joyride

pez 2023-10-28T20:25:59.794089Z

I am trying to give myself a JS repl. Having some success, but since I am just doing (js/eval <selectionText>), the evals are run in a context that is then forgotten, so I can’t define a variable in one evaluation and use it in the next one. Any ideas how to overcome this? Is there something in SCI that can facilitate it, @borkdude?

borkdude 2023-10-28T20:32:05.431439Z

This should help somewhat I think:

(js/eval.apply js/globalThis #js ["var x = 1"])

borkdude 2023-10-28T20:32:37.403289Z

There is nothing in SCI that will help you evaluate JS

borkdude 2023-10-28T20:34:01.225599Z

const won't work for defining global things using eval: https://stackoverflow.com/a/50099981/6264

pez 2023-10-28T20:47:33.094739Z

Thanks! Seems eval and the apply on globalThis work similarly. Both behave like this in this case at least. Very good to know about the const -> strict thing.

borkdude 2023-10-28T20:48:54.498619Z

I did a similar thing in clerk, let me look it up

borkdude 2023-10-28T20:50:10.906529Z

ah yes, you need to attach that function to the global object first:

(j/assoc! js/globalThis :global_eval (fn [x]
                                       (js/eval.apply js/globalThis #js [x])))

borkdude 2023-10-28T20:50:52.548319Z

without j/:

(set! (.-global_eval js/globalThis) (fn [x] (js/eval.apply js/globalThis #js [x]))))

borkdude 2023-10-28T20:51:04.351459Z

and then call that js/global_eval function

pez 2023-10-28T23:48:06.011109Z

I could get const declarations work using the node repl:

(defonce node-repl (.start repl))

(defn eval+ [code]
  (p/create (fn [resolve reject]
              (.eval node-repl
                     code
                     (.-context node-repl)
                     ""
                     (fn [err, result]
                       (if err
                         (reject err)
                         (resolve result)))))))

pez 2023-10-29T13:12:30.891569Z

Progress. No top level await and no es6, yet. But for quick js experiments this is pretty useful already, I think.

borkdude 2023-10-29T13:18:00.174449Z

in squint repl I hack around the limitation of eval + await by evaluating everything inside of a self-calling async anonymous function

borkdude 2023-10-29T13:18:13.800579Z

but in that case, const etc won't work I guess

pez 2023-10-29T13:42:45.446589Z

Maybe I could detect if there is a top level await there and then wrap it like that, with the limitation that it strict assignments will be scoped in those cases. But maybe that defeats the purpose…

borkdude 2023-10-29T13:45:14.324259Z

or rewrite const to var ;)

borkdude 2023-10-29T13:45:44.690849Z

only when it appears on the top level

borkdude 2023-10-29T13:45:47.433409Z

dunno

borkdude 2023-10-29T13:46:04.173999Z

I guess you need to evaluate everything in the scope of what file/module it is in as well

borkdude 2023-10-29T13:46:07.882519Z

sounds like a mess

pez 2023-10-29T13:48:17.554759Z

The evaluator knows which file thing are evaluated in. But maybe it mostly uses that for error messages. Idk. Maybe I could test that some way…

pez 2023-10-29T13:49:14.133409Z

Rewriting the code sounds pretty difficult.

borkdude 2023-10-29T13:58:31.006049Z

I mean, there are some tools to parse JS as an AST, then you could walk this by rewriting only the top level stuff and print it back to a string, but this sounds like a future rabbit-hole optimization ;)

🐇 1