Fork me on GitHub
Yehonathan Sharvit09:09:48

Is there a way to prevent infinite loop in self-host cljs

Yehonathan Sharvit09:09:38

For instance, on the browser evaluating (range) stucks forever...

Yehonathan Sharvit11:09:36

Is there a way to pass a timeout?


no way, IMO


@viebel JS is single threaded


this has nothing to do with self-host

Yehonathan Sharvit17:09:45

@dnolen what about *print-length*?

Yehonathan Sharvit17:09:29

could it help to wrap eval-str with a (with-redefs [*print-length* 1000] …) block?


@viebel a wild idea: you could wrap whole expression in a go-like macro, then do a deep code walk and decorate all looping constructs with some interruptible helper code - this won’t solve it for general case (e.g. external js fn looping forever), but could solve it for code entered by klipse users


ah, but still this would not solve the range problem

Yehonathan Sharvit17:09:53

My main use case is for the klipse plugin where code is evaluated “instantaneously” (i.e. after 20 msec of inactivity)


range is an “external” function from the point of view of your expression

Yehonathan Sharvit17:09:05

And the user is typing (range 10)

Yehonathan Sharvit17:09:29

but between range and 10 there is a small delay (> 20 msec), so the evaluation is triggered with (range)

Yehonathan Sharvit17:09:37

and the browser gets stuck


thinking about it more, you have full control over self-host cljs compiler in klipse, could hack cljs compiler to emit interruptible code


another idea is to do execution in a webworker and instrument it from the main frame (e.g kill it after some time)

Yehonathan Sharvit17:09:52

Yeah, the webworker is probably the cleanest solution


yes, but there are other challenges, once you allow people to interact with DOM and other browser APIs you have another huge issue


I think first idea has a merit to it too, it could be as easy as tweaking how recur/loop gets emitted, with each recur you would call a callback, which would “sleep” for other browser code to run and then check a flag and throw if program should be interrupted


and by “sleep” I mean running callbacks from a parallel even loop you would manage by hand

Yehonathan Sharvit18:09:57

Yeah. But my main concern is the (range) issue


range must have recur or loop inside

Yehonathan Sharvit18:09:50

I just tried to wrap eval-str with a (with-redefs [*print-length* 1000] …) and it worked


I can easily give you another code example which will loop forever without printing

Yehonathan Sharvit18:09:31

because (str …) of the Range type calls pr-str

Yehonathan Sharvit18:09:46

@darwin I know that there are other obvious cases...

Yehonathan Sharvit18:09:22

Now that I found a solution to my main pain, I’m available to solve the real issue

Yehonathan Sharvit18:09:49

What is the way to tweak how recur/loop gets emitted?

Yehonathan Sharvit18:09:00

I mean - how do I do it technically?


another (#3) idea: use an iframe instead of webworker, it will have full DOM access and clean “environment” as a bonus, with proper content-origin you will be able to drive it from your klipse app


> how do I do it technically? I can’t help here, have never done anything similar, just throwing ideas around

Yehonathan Sharvit18:09:39

@darwin is it possible to kill an iframe that is stuck in an infinite loop?


I believe so, you are closing it from another javascript context, which can tell browser to close iframe “window” (regardless of state of the javascript runtime inside)


I’m 99.99% sure