6 ms·
Do you, or the broader community, have any ideas about solving infinite loops? I'm on mobile so I can't test this at the moment, but I imagine that while(1) cra
by angleofrepose 6y ago
Do you, or the broader community, have any ideas about solving infinite loops? I'm on mobile so I can't test this at the moment, but I imagine that while(1) crashes the tab.
What would an MVP operating system like ctrl-C functionality look like for execution environments in the browser?
- mattigames 6y agoYou could modify the AST tree using something like jscodeshift to add a function that is called in every loop (and maybe every function) and there you can "break" the loop in a pretty clean way.
- protoduction 6y agoA determined user will still be able to figure out something that blocks forever, for instance run a WASM program that has an infinite loop in it.
- angleofrepose 6y agoI am aware of multiple hacky solutions, such as loop detection and adding timeouts. This fails in most non-trivial creative coding applications due to long running code. I'm interested what it would take to come up with a general escape hatch like any shell user has.
- jraph 6y agoA timeout would most certainly not trigger during a busy loop in JS. Timeouts can only trigger when the main thread is not running code. Browsers will complain against code running for too long without interruption though.
- angleofrepose 6y agoYes, as the other comments get at the "hack" I'm referring to is a loop transform that adds a timer check to the condition.
- jraph 6y agoOh, right, I was not there at all. Wow, that seems hard to do. One would need to take a lot of things in account, including recursive calls, asynchronous functions / calls and, indeed, even long strings of instructions that are not necessarily part of a loop or recursive calls. Would a transform that adds the check between every JS instructions where it is possible theoretically solve the problem? is there a solution that does not slow down the code too much and interrupts the code within an acceptable margin?
- angleofrepose 6y agoYeah! The general case of this is the halting problem... The best solution I know of is stopify, which the other comments have talked about. I just wonder if there's another take on the situation, something akin to OS task management.
- protoduction 6y agoOn Starboard[0] I approached this by sandboxing the notebook code in an iframe on a different origin. This sandboxing has to be done anyway to prevent XSS. If you type while(true){} in a notebook only the iframe will break (and usually your browser will prompt you after a while to kill it). When you do only the iframe is no longer functional. I don't think there's an elegant way to solve it any differently in the browser. [0]: https://starboard.gg https://starboard.gg
- jraph 6y agoThat's clever. Do you know if there is something possible using web workers? maybe running the "sandboxed code" in the worker? I don't really know how they work and if it is possible to interrupt them from the main thread.
- protoduction 6y agoI think so, but a worker won't have access to the DOM and a bunch of other APIs, so the code would be fairly limited in what it can do. Which may be fine for some usecases!
- angleofrepose 6y agoHi, yes! I like your project. I chatted about similar things on your launch post here. You also address this explicitly on your product which I appreciate. What I'm getting at is that these browser notebooks try to get at the desire and feeling for rapid exploration and iteration. Losing context by having a crashing logic error is a massive blow to that ideal. I'm not saying that your or anyone elses product is only for "rapid prototyping" but it's still true that larger projects could be bit by the same errors. When I crash my native code I C-c and I'm back in an instant. When I crash browser notebook code I lose a bit of time and unsaved code. I crash browsers often in creative coding where I write many loops and don't always do them right. It may also be that my chrome and firefox experience on linus is worse than standard, I don't know. But I have crashed my entire browser in chrome when using observable, and I thought that wasn't supposed to be possible.
- chkas 6y agoI have made something similar (https://easylang.online/ide/ https://easylang.online/ide/). It is a language of its own, which is compiled and interpreted by WASM. The problem with hanging in endless loops is solved by running the interpreter in a "web worker" that can be killed and restarted at any time.
- angleofrepose 6y agoLooks interesting, I'll do some digging around. Thank you for sharing.
- 1-more 6y agoWe started with a blacklist to match against while(1), while(true), for(;;), etc, but we eventually found an eslint plugin (goedel.js) that nicely tells you if the code contains an infinite loop or recursion.
- emmanueloga_ 6y agohttps://www.stopify.org/ https://www.stopify.org/
- rng_civ 6y agoTo add to this comment, Stopify is a JS-to-JS compiler that instruments sync JS code to make them interruptible at set points. The paper [0] can explain it better than I ever could. I work on an experimental Pyret [1] runtime that uses Stopify to instrument compiled Pyret code (plain old JS) so that we can run Pyret code on the main page thread without hanging it up. Main thread execution is important for quick/easy DOM access. In terms of performance cost, we haven't measured too extensively, but so far, on average, we're seeing a 2x slow down compared to un-Stopified programs. (Disclaimer: paid contributor for Pyret). [0] https://www.stopify.org/research.html https://www.stopify.org/research.html [1] https://www.pyret.org/ https://www.pyret.org/
- angleofrepose 6y agoDo you see any other solutions in the same domain as Stopify? Another method that might provide a way to keep UI unblocked but still have user executable code?
- rng_civ 6y agoIf you need the user code to execute on the main thread, then unfortunately I am aware of none besides bundling your own tailored system. Pyret used to use its own runtime system [0] but Stopify was created in part to replace it due to the maintenance burden and complexity of "vanilla" JS interoperability. [0] https://www.pyret.org/docs/latest/s_running.html https://www.pyret.org/docs/latest/s_running.html
- angleofrepose 6y agoThis is what I use. Seems to be the only option, and it works.
- shortercode 6y agoCodepen uses a system that measures loop duration, and it's a giant pain. Having done some pens that do ray tracing and image transforms which can have long running loops. Given the variable execution time of JS it can be quite random. It just exits the loop without warning, causing weird failures in your code. 2 theoretical solutions ( with significant overhead ) are: Run the code in a VM ( maybe quick.js compiled to WASM would work ) that suspends code execution periodically if it exceeds a certain duration. This has the advantage that long running code in general won't block rendering, not just loops. Transform the AST to use async generator that yields once per loop. This would allow the loop to be suspended and resumed. But it would require a lot of modification to the AST, making effectively the entire call tree async.
- artifact_44 6y agoI've done this and it works surprisingly well. I made a timesliced js scripting system this way.. it looked imperative with tight loops but it was all asynchronous. It felt like a threaded app.
- gitgud 6y agoWell you can easily detect trivial examples like "while(1)" and "for(i=0;true;i++)". But otherwise how would know some is an infinite loop? Put a bit more simply, to work out if a problem is unsolvable (infinitly looping) you need to evaluate the problem... By trying to solve it. Checkout the halting problem for more details. https://en.m.wikipedia.org/wiki/Halting_problem https://en.m.wikipedia.org/wiki/Halting_problem
- teraflop 6y ago"Solving" infinite loops doesn't necessarily mean accurately predicting a priori whether a piece of code will terminate. It can just mean ensuring that if the code does try to run indefinitely, it doesn't have unfortunate effects such as blocking the UI thread without the possibility of being interrupted.
- gitgud 6y ago> It can just mean ensuring that if the code does try to run indefinitely, it doesn't have unfortunate effects such as blocking the UI thread without the possibility of being interrupted. Well that can be achieved by executing the code in a background worker thread. Which doesn't affect the UI thread in browsers... no sure how it's managed but I think you could terminate it after a certain amount of time too
- angleofrepose 6y ago> ctrl-C functionality OS implementations dont solve the halting problem. I agree with the sibling comment.