How do you stop an infinite loop in Javascript? - javascript

Let's say I accidentally wrote this:
do { } while (true);
...and then ran it. Apart from killing your browser, is there a way to stop javascript execution (the equivalent of Ctrl+Break in basic, or Ctrl+C)?
Normally, after about 30 seconds your browser asks if you want to stop the long-running script, but this doesn't always happen (as I just found out)!
FYI: A simple loop such as this: for (i=1; i > 0; ++i); will cause my browser to crash (Firefox 3.5b4). I don't feel much like testing to see if it's any of my add-ons. Continuously restarting my browser isn't my idea of a fun Monday night.

2018 update:
In Chrome 67, if you have the DevTools open (F12), you can end the infinite loop without killing the whole tab:
Go to the Sources panel and click "Pause script execution".
Hold that same button and now select the "Stop" icon.
https://developers.google.com/web/updates/2018/04/devtools#stop

I'm using Chome Version 45.0.2454.101
At the top right hand corner, at the hamburger menu, click on More Tools > Task Manager, and then kill the tab from there. This is if attempting to close the tab fails. Otherwise a simple 'X' on the tab kills it.

At least with Chrome, you may be able to kill off the individual tab and not the whole application.
Randolpho has also informed me that IE8 has similar functionality.

If you are using Chrome you can easily kill not responding tab:
Switch to any other tab
Press Shift + Esc to open Chrome's Task Manager
Find your tab in the list (Should be the most memory consumer)
Click End Process
Important: Navigating to another tab is important, because if you are on the original tab JavaScript will make the browser unable to process your key press and do nothing because of its infinite loop.

ref: https://superuser.com/questions/92617/stop-never-ending-popup-alerts-in-firefox
Firefox is particularly problematic ...
Warning! Caveat! Do NOT run this!
javascript:
while (true) alert("irritated and exhausted - yet?");
This will go "infinite" and will NOT exhaust an internal timeout since the script will not chew up CPU time fast enough. In FF 11 this guarantees there will be no "unresponsive script" abortion opportunities.
Gracefully stopping just the offending script was possible and trivial in early browser versions, using manual intervention, without croaking and aborting the whole browser. To not have such control is a major browser software design flaw. Unreasonable dexterity and reflex are required to effect the manual motor mechanics of the "solutions" described in the reference.
Caveat: It is possible for scripts to go "infinite" w/o timing out AND w/o alert type prompts. These are particularly pernicious and annoying. Basically, the scripts run slowly enough so that the CPU time cycle allotment of say 20 sec. is stretched out over several minutes or hours or ..., before timing out, by suspension of execution pending resumption on an event trigger. Instead of timing CPU cycles it would be far better for scripts to timeout on real world clocking. (Ever notice how you cannot abort a script that is trying to retrieve content - but unsuccessfully - for constructing a page? In FF both the address bar buttons reload and cancel/stop are disabled though the tab at least can be closed.) Normal javascript Timeout() and setInterval() calls do not suffer from this and are conditioned so that while suspended, manual intervention is possible to abort them "gracefully".
Test environment for empirical observations:
window.navigator.userAgent=
Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:11.0) Gecko/20100101 Firefox/11.0
PS. the script
for (i=1; i > 0; ++i);
will eventually trap on an overflow error when i exceeds the maximum value allowed.

Most browsers have a "slow script performance" warning that comes up when an out of control javascript is taking a very long time to execute. This warning dialog usually gives the option to kill the offending script.

Depends on the browser. Some let you click the "stop" button to stop javascript execution. Others don't.
I suggest the best way is to just kill the browser or tab entirely.

In Firefox
Go to Developer Tools > Debugger, and click pause button.
In Chrome
Go to Developer Tools > Sources, and click pause button.

most decent browsers do show an "unresponsive script" warning... If not, I guess your best course of action would be to find out why the warning is not popping up.

From https://superuser.com/questions/92617/stop-never-ending-popup-alerts-in-firefox#comment93927_92617, by anonymous:
This isn't a satisfactory general-purpose solution, but with Greasmonkey (or maybe Ubiquity or Jetpack) you could overwrite window.alert with a function that calls window.confirm and optionally throw(s) an error, stopping all script execution, or toggles a flag to stop alerts. That might be useful if a site you keep going back to presents this behavior.

What I do when using Chrome and this happens is hitting shift+ctrl+esc to bring up the windows taskmanager. Then switch to the processes-tab and scroll through the chrome.exe processes(chrome has one process for each open tab) till I find one with significantly higher cpu usage than the oters. It tends to have around 30% for me while all others have like 0-2%
Then I'll just end that process.
Actually the same can be done by going to tools>taskmanager or shift+esc in chrome to open its custom taskmanager for its processes. Might be easier to use that since it shows more info of the tabs.

Last resort: close the browser from the OS. I had good results closing Chrome from the taskbar in Windows 10 while an infinite loop ran. If that didn't work I would have killed the browser in Task Manager as above. On other OS's, of course the exact technique would vary.
Infinite recursions are less a problem. All systems I've seen limit the size of the execution stack, and interrupt with a runtime error eventually once infinite recursion leads to stack overflow (no pun intended).

Related

Force all execution to pause using Javascript

I am making a chrome extension that aims to pause execution of a tab if it inactive after some time in order to stop if from consuming resources.
By "Pause", I mean something like debugger, however, debugger does not seem to work unless the developer inspector tool is open.
Is there anyway to stop a tab from consuming resources until the user goes to that tab and click on something (like the play button on debugger)
PS: I want to make this because there a synonym/dictionary website that slowly consumes 5GB of RAM even if it is left inactive for half an hour.
The only way is using alert() or prompt(). Enter may be used to confirm and continue executing.
Chrome extension has API for this.
Tab discard
chrome.tabs.discard(
tabId?: number,
callback?: function,
)
Add permission tabs if required.

Webpage freezes in Safari on both iOS and OSX when the page reloads?

I'm using an iPhone 11 Pro with iOS 15.3.1.
I'm trying to figure out why when visiting my website, Safari is freezing most of the time when the page loads. Sometimes the page loads the first time I visit it, but on reload it basically freezes with no interaction.
When I connect the iPhone to a Mac and use the Safari inspector to connect to the webpage on the iPhone, the inspector is basically blank on all screens. If I go to the "Elements" tab, nothing shows. If I go to the "Console" tab and try to execute some Javascript, nothing happens when I press enter.
On OSX, I can see similar behavior, except I can actually open the inspector before I visit the page. In this case, when it freezes I can see a few elements in the "Elements" tab, but that's about it. Any sort of interaction I try to do in the inspector results in nothing happening.
I'm at kind of a loss. How can the development experience for such a popular OS/Browser be so terrible, and how do I work around the inspector itself not working? I can't replicate this freezing on anything besides Safari.
To be absolutely clear on my question:
What is your process to debug a webpage in Safari when it is in a state where the inspector no longer interacts with the webpage?
I did a broad divide and conquer of my app, commenting out top level code and working my way down uncommenting until I found the exact line that causes the freeze.
It seems calling HTMLInputElement.setSelectionRange() inside an onfocus event handler function caused an infinite synchronous loop in Safari, perhaps Safari synchronously blurs the input and refocuses for some reason when that function is called. And on page reload Safari was trying to focus on an input with that code automatically. That is my guess at least, removing the setSelectionRange() resolves the freezing problem.
Luckily, the freezing was fairly consistent so the divide and conquer approach worked. Unluckily, the inspector really should have done its job and picked up on the fact that the page was hanging and told me which function code execution broke at when Javascript was forced to stop, like Chrome or Firefox would.
If anyone has any better ideas for debugging these kinds of issues in Safari besides the programming equivalent of a short circuit test, I'll gladly accept the answer.

Does Chrome deprioritize Javascript execution extensions?

I have been developing a simple browser extension, and I have ran into a very strange behavior that happens on Chrome while it doesn't happen on Firefox. Basically, the extension runs much slower in Chrome than in Firefox, and it takes 3+ seconds to add a single class to a button, while it happens in milliseconds in Firefox.
This repo contains a demonstration of the issue. What is supposed to happen is, when the input box is not empty, the button should change color, this is almost instantaneous in Firefox, but it takes seconds to update in Chrome.
I have noticed that:
Further observations:
The problem goes away if I remove the TailwindCSS import in App.vue file.
The problem goes away if I remove the background script from the manifest.json file.
The problem goes away if I run performance profiling in Chrome Performance tab on the inspect window.
If I visit the extension page directly in the browser, like chrome-extension://extension-id/popup/popup.html#/ it is totally fine, there is no lag or anything.
For the first two, Webpack seems to be including a lot of extra code into the bundle, and removing any of these seems to be reduce the bundle size significantly.
For the third one, I imagine Chrome is prioritizing the extension execution when the performance profiling is enabled, therefore it is fast back again. This is probably the case for the last one as well because the page is in focus and it is probably the most important page to run for Chrome at that point. I believe this problem has something to do with the way Chrome runs Javascript in extensions or the way it redraws the UI.
This seems to be a very weird behavior, and I couldn't find any prior reports regarding this behavior. Any help is appreciated, I cannot think of anything else to add but I can add more details as requested.

How can I debug "Back Navigation Caching" in IE?

I'm seeing an odd bug in IE that I'm not seeing in Chrome. Specifically, this involves some JS code not firing when a (Telerik) wizard is navigated back to it's first step.
When the user clicks their "Previous" button, some data isn't being properly loaded. Hitting F12 and bringing up the developer console has shown me the following Warning:
DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
Ok, so I go to the link provided and I noticed the documentation states:
In order to be cached, webpages must meet these conditions:
...
- The F12 Developer tools window isn't open
This is a problem, because when I use the navigation buttons within my wizard WHILE the dev window is open, it behaves properly, just as it does in Chrome.
How can I debug my related Javascript so I can figure out what's going on? Also, I understand what caching is but I'm not exactly sure what this is about and I have no idea why Chrome behaves differently. Is there a way that I can force IE to behave like chrome and cut on (or off) whatever features that are causing this issue?
Yuck. Back to old school debugging for you.
Short of putting the whole browser into a Windows debugger, you can pretty much forget about setting breakpoints. All you can do is log.
If you are lucky and your problem isn't too deep, you can use a sprinkling of simple alert() statements to let you know the state of things at various stages in your code. One nice thing is that you can serialize objects now pretty nicely; for example, you can do JSON.stringify(this), which will probably give you a giant output, which you can copy and paste into your IDE and unpack. A major upside to doing this is that the alert will block, so you can take your time studying the output. A major downside to this is that race conditions are now much more likely.
Alternatively, you can add a <textarea> to the page and throw your JSON.stringify(this) results into that. Because this means extra DOM mutations, it also increases the odds of race conditions, but not by much. (If race conditions are a possibility, you can do this:
(function () {
var currentState = JSON.stringify(this);
setTimeout(function () {
document.querySelector('textarea').value = currentState;
}, 1000);
})()
Even though these are now asynchronous, if you use this multiple times in sequence, these will execute in that same sequence (unless you change the timeout period).
If you are doing actual page navigations (and not just changing the URL with pushState()), then actually reading those logs is going to be a problem. The solution is to put the page in a frame and write the content out to a sibling frame. As long as both frames are running on the same domain, you will have no problem pushing the data into the sibling frame. If you can't put them on the same domain, you are kind of screwed.

profiler for slow javascript (jquery) on page event? "Unresponsive Script" error

I am troubleshooting some slow jquery code on a drupal module. After the page loads on a configuration form, you click on an area to expand out a fieldform. However, this expansion takes forever, and most browser give a warning "The script has become unresponsive, do you want to stop it?"
I'm looking for a profiler that will give output like that from xdebug, where I can see the statistics of the entire execution path, just for that one javascript event.
The debugger in firebug will drop me in on the exact line where firefox decides that the script is taking too long; but there is no single line that is the problem (at least I don't think so at this point). I believe that the slowdown comes from some poorly-architectured looping or iteration that spans multiple lines, which is why I want the profiler stats to show me in what parts of the code its spending most of the time.
The Firebug add-on has a profiler built into it. I don't have Firebug installed on the machine I'm using right now, but if I recall it's accessed from a pull-down menu in the "Console" view. (I could be wrong; it's there somewhere.) I can't say that I'm super-fond of it, but you might want to give it a try.
Chrome's developer tools also has a profiler, which is a little fancier.
For IE, there's a product called dynaTrace AJAX edition, which has a really fancy profiler. Of course it only works with IE, but you're going to have to test in IE anyway — if you've got a page that's slow in other browsers, it's going to be even worse in IE :-)

Categories

Resources