I'm trying to debug a bunch of functions that redirect the user. I want to "kill" the script while it's running to to read the output of console.log(). I can't just use a simple return because there are many functions that work together.
Set a breakpoint at the spot in your code where you want to pause. If you add a debugger statement in your code browsers that support it will automatically stop at that point and open the debugger (actually I think some browsers (Chrome?) may ignore the statement unless you already have the console/dev tools open, but obviously you can just start with the dev tools open if necessary).
There are a few options, not all of them applicable to your case:
Throw an exception; that will stop the function and any caller function as well;
Use an alert(), as ismaelga suggested;
Set a breakpoint, as nnnnnn suggested; you can either use the debugger keyword or use your browser´s GUI if present;
Redefine console.log to an empty function; this way nothing will be logged from then on, so you can read what was logged so far without interference.
Some situations where the options will not be possible:
If your code is responding to events, or using things like setInterval, even if the "main loop" stops other code can still run and log stuff;
The alert window may make difficult to see the log, depending on how obtrusive it is for your browser;
There's no suitable debugger, or you can't install one;
Some functions have stored a local copy of console.log, so redefining it won't affect them.
Of all option, I'd sugest the 4th, since you can read your logs calmly without "breaking" the page. If you want to "filter" the logs, you can also have some functions call the "correct" log (a saved copy of console.log), while the rest calling the "fake" one (the one you redefined).
Declare a global variable that is outside of any function, and add code within each function or long-running loop that checks the value of that variable and only proceeds if the value is set a certain way. This way the variable serves as a semaphore and you can change its value from anywhere and terminate all processing in accordance with its value.
For example, a simple Boolean variable called stopProcessing that is initialized as false but can be set to true to let all functions know to return and all loops to break ASAP.
Related
So this is more of a curiosity, rather than a problem I'm facing. I've come across a website that calls window.location.reload() before the load event fires. How would you break out of this refresh loop, as a user? Can it even be done?
Anyways, I've tried the following:
Replacing window.location.reload (via greasemonkey)
This is not possible since window.location is read-only.
Listening for window.onbeforeunload and hitting cancel (via greasemonkey)
The reload call happens before the document loads. This means the beforeunload event is never fired due to lack of transient activation, so there's no prompting for you to cancel the reload.
Block JavaScript (or: block all network requests)
This does disable the reload. And also the entire site, so it's not ideal.
Block the request to the specific file with the reload call (via devtools)
Same as above, since the file in question is a Webpack bundle, containing the majority of the site's functionality.
Inject a userscript that replaces the function calling windows.location.reload() with an equivalent function that doesn't call windows.location.reload() (via greasemonkey)
I don't think it's possible for this site. Webpack loads every function in an IIFE, so it's not obvious how to modify the function in question before it gets passed as a callback and becomes untouchable. In any case, this approach doesn't generalize.
Place a breakpoint at the window.location.reload call, and modify some local function to throw an error before it can call reload (via devtools)
This didn't work (on Firefox, at least) -- try it out, (function() {throw new Error(), window.location.reload()})(). Due to the comma operator, it'll reload despite the thrown error, and every Webpack expression seems to be a string of comma-separated statements so there's no avoiding this. This approach also doesn't generalize.
Manually modify the construction of the global Webpack window.webpackChunk_N_E table (via greasemonkey)
I don't know about modern Webpack to know if this could be done, but I tried replacing the particular method in question in that table with a ()=>{}. It didn't work -- I believe the method was already passed as a callback before the tire change. We are dealing with a function that is far too powerful to care about its replaced reference in some mere global table.
Close the tab
I gave up.
Did I miss anything obvious, or is it impossible by design to break this particular kind of refresh loop in the browser (short of disabling JavaScript)?
From Chrome Devtool Example https://googlechrome.github.io/devtools-samples/debug-js/get-started
While adding breakpoint on first line of inputsAreEmpty function, inputsAreEmpty() into Watch, inputsAreEmpty() in watch will invoke.
log will print more times if insert log into inputsAreEmpty function, why is this happening?
If you mean you have inputsAreEmpty() as a Watch expression, that expression will get evaluated (calling inputsAreEmpty) any time the Watch needs to update its display. If you put a breakpoint in inputsAreEmpty, Watch needs to update its display when it hits the breakpoint — which means calling inputsAreEmpty, which will hit the breakpoint, and so on, and so on, and so on.
In general, it's best not to have function calls in Watch expressions (though there are exceptions to that). But you definitely need to avoid having function calls in Watch expressions you have breakpoints in, because it creates the vicious cycle above.
I want to debug a website that is built from millions of lines of js code, and I want to find the function that will receive a specific value as one of the arguments. Is it possible to break the execution when any function receive a specific value as one of the arguments?
You could add a conditional breakpoint in
Chrome's debugger
Firefox' debugger
Alternatively, if the browser of your choice does not have similar functionality, you could invoke the debugger statement conditionally (if you can modify the code):
if(value === "wanted") debugger;
however that only works if you know the functions that might receive a specific parameter
Is it possible to break the execution when any function receive a specific value as one of the arguments?
No, that's close to impossible. Adding a breakpoint to "any function" will probably slow down execution a lot, if it's even possible. Doing so programmatically might work somehow, though it seems like a lot of work for little benefit. If you know the value, you probably also know the source and can debug from there.
I recently started to swap out all my debugger statements with eval('debugger') statements. The reason is that with the plain version, not all "factually/theoretically" visible variables are "practically" visible. This happens because of optimization (see earlier SO question).
With this trick, the problem is like "90% solved" - there are some drawbacks. Apart from longer source code, those are:
When third party libraries are involved, it is not feasible, maybe not even possible to have the debugger -> eval('debugger') transformation done there also.
When I would rather set a break point in the debugger itself, instead of changing the code, that cannot be done - or can it?
When I'm already stopped at a "normal" debugger statement (in third party code, or where I forgot one), there is no way to switch to the desired mode - certainly typing eval('debugger') on the console doesn't help. If I want the functionality, I have to change the debugger statement, and run the code again, which might be a whole lot of work
When I stopped at an eval('debugger') statement, but then use the debugger 'step over/into/out' functionality, I 'lost my special status'.
How can I work around this? Is there a way to tell v8 to interpret all debugger statements by eval('debugger')? Is there a trick with which you can 'go into the other mode' - as if the eval('debugger') statement would magically appear as the next statement after the debugger statement where you're stopped? Do command line options to the chrome executable help? Maybe there is a way in firefox?
I learned about the eval('debugger') trick in an answer to a recent SO question of my own
ANNOUNCEMENT
What I'm going to do next is write a little transpiler for usage within node webserver. The transpiler will insert eval('') statements all over the place (by default once at the beginning/body of every function, and more or fewer of them if so specified in the query string.) Then I can set a breakpoint where the eval statement is, do "step into" and then I got what I want. Then I'm going to answer my own question.
Unless of course, someone will beat me to it. That would be most delightful, as I do have other things to do.
V8 developer here.
Is there a way to tell v8 to interpret all debugger statements by eval('debugger')?
There is currently no way to treat debugger statements or breakpoints as eval("debugger"), but it might be feasible to add a flag that does this. You can file a "feature request" bug at crbug.com/v8/new and ask for a flag that forcibly context-allocates all variables for debugging purposes.
(Side note 1: It's the eval part that has an effect here. Instead of eval('debugger') you could write eval(""); debugger; or debugger; other_code(); eval("");, so long as you have eval somewhere in the function.)
(Side note 2: the tension here is that on the one hand, it's Good™ when the behavior of a program when it is being debugged is the same as when it is not being debugged -- otherwise there might be issues that only show up when debugging, or un-debuggable failures in production mode. On the other hand, sometimes certain deviations are explicitly necessary in order to make debugging possible. I'm not sure on which side of the line this one falls. Context-allocating all variables will reduce performance and increase memory consumption, so if/when such a mode becomes available, you will probably have to (or want to) switch back and forth during your development work; which in particular means that this couldn't simply be the default when DevTools are open.)
Is there a trick with which you can 'go into the other mode' - as if the eval('debugger') statement would magically appear as the next statement after the debugger statement where you're stopped?
No, and there can't be. It's not a "mode" or "special status", it's a decision that has to be made when first parsing/compiling the outer function (the one that contained the variable you want to see within an inner function). Once that time has passed, it's too late to change anything (non-context-allocated variables are just gone), and the only option is to reload.
[EDIT in response to comments:
To clarify what I mean by "not a mode, but a decision": from the scope chain's point of view, the situation is essentially the same as:
var inner;
function outer() {
var foo = "foo";
var bar = "bar";
inner = function() {
console.log(bar);
debugger;
}
// "inner();" here is moved below
}
outer();
inner();
at the point when inner() is called, foo is either still there like bar (if it's context-allocated because at compile time of outer V8 determined that inner will need it), or gone (if V8 determined that it's local to outer and nobody else will need it). If inner contains eval, then it might need all outer-scope variables.
--end of EDIT]
This happens because of optimization
Well... because of an optimization, namely being smart about whether to allocate variables on the stack or in the "context object". This is completely unrelated to what is typically referred to as "optimization of a function", i.e. running them through the optimizing compiler. That's why the %NeverOptimizeFunction hack discussed in the other issue had no effect -- it's an unrelated mechanism.
i want track error in my javascript code.Some times javascript automatically executes and hangs my browser i want to track which part of javascript is executing automatically and hangs ....
For tracking errors using console.log
Or use an alert as your first line of code with the variable's inside it and this should help,
I would recommend console.log as alerts become annoying, Console log also makes it easier to view variables, objects and arrays. I personally use chrome you should try it :)
This might also help Console log question