Fork me on GitHub
#cljs-dev
<
2016-09-04
>
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?

darwin14:09:01

no way, IMO

dnolen17:09:57

@viebel JS is single threaded

dnolen17:09:03

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?

darwin17:09:15

@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

darwin17:09:42

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)

darwin17:09:58

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

darwin17:09:12

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

darwin17:09:55

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

darwin17:09:53

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

darwin18:09:48

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

darwin18:09:26

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

darwin18:09:22

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

darwin18:09:19

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?

darwin18:09:42

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

darwin18:09:26

> 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?

darwin18:09:39

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)

darwin18:09:03

I’m 99.99% sure