Ignore throw $break in Chrome JavaScript debugger - javascript

I'm using Prototype in a web app, and I'd like to break when exceptions are thrown (including handled ones). However, I don't want to break on exception used for flow control, specifically the throw $break pattern used in Prototype's each implementation.
function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break; // I want to ignore this one
}
});
return result;
}
Does anyone know how to get Chrome's debugger to ignore specific exceptions? Or to get it to ignore exceptions thrown from specific lines? Or even to get it to not break in specific files?

I'm fairly certain there is no such feature. The documentation, which seems fairly complete, doesn't mention it. Also, the Chrome Developer Tool uses the Remote Debugging protocol, whose Debugger.setPauseOnExceptions command does not have a "file" parameter. That said, I have not grokked the source code.
Getting Chrome's debugger to ignore specific exceptions or files would also help when working with jQuery. It catches and re-throws any exception in an event callback (search for "resolveWith"), making the message in the console essentially useless. jQuery throws and catches exceptions internally all the time, so breaking on all exceptions produces too much noise.

Related

Chrome automatically formats Error stacks, how does this work?

The content of (new Error('foo')).stack looks something like this:
Error: foo
at Object.notifier (http://localhost:6969/js/main.js:12705:37)
at trackHookChanges (http://localhost:6969/js/main.js:1813:27)
at UseState (http://localhost:6969/js/main.js:1982:13)
at K._.data (http://localhost:6969/js/main.js:70174:6005)
at K (http://localhost:6969/js/main.js:70174:6380)
at Z (http://localhost:6969/js/main.js:70174:9187)
However, when I console.log it, it looks like:
Error: foo
at Object.notifier (wdyr.ts:10)
at trackHookChanges (whyDidYouRender.js:1306)
at UseState (whyDidYouRender.js:1475)
at K._.data (index.esm.js:1)
at K (index.esm.js:1)
at Z (index.esm.js:1)
Is Chrome devtools is using sourcemaps to automatically change the string being logged? Is it there an easy way to access the source file names in my code? I want to ignore errors originating from certain NPM module.
Unfortunately (but luckly for devs) yes, Chrome uses sourcemaps to format errors in the console and there is (still) no way to access the same function it uses or output it produces. Even if it was possible, it would work only on a specific browser/platform.
TLDR
Emulate the browser sourcemap resolution with StackTraceJS or filter your errors by their prototype or any of their properties (like Error.message for example)
Discussion
JS Errors stacktrace are a mess, and so unreliable:
they are very dependant on the running environment, if you run code on Chrome you could end up with a different stack with respect of running it on Firefox, IE or node (even if in the latest times they are reaching to a "stacktrace agreement" between environments).
The maximum length of the error stacktrace is (almost always) 10 lines, so if your function (hook) was called before that time you will never catch it.
internal or delayed callbacks can erase/change/augment the stacktrace of a function in certain environments (it can be very hard, sometimes impossible, to catch the full stacktrace of a callback called inside a setTimeout for example)
Partial solution (StackTraceJS)
If you can afford to make a http request for a sourcemap, you can exploit the same mechanism that Chrome (or any other browser) uses to parse and map the error stacktrace files into the original files and filter those you don't like. The downside of this operation is that your code must be completely reworked with promise-like chain (because of the http request).
Luckly there is already a library which makes this process much much easier: StackTraceJS, you can give it a try.
This would be its usage (from library docs):
var error = new Error('BOOM!');
StackTrace.fromError(error).then(callback).catch(errback)
/*
==> Promise([
{functionName: 'fn', fileName: 'file.js', lineNumber: 32, columnNumber: 1},
{functionName: 'fn2', fileName: 'file.js', lineNumber: 543, columnNumber: 32},
{functionName: 'fn3', fileName: 'file.js', lineNumber: 8, columnNumber: 1}
], Error)
*/
Side Note
As you stated in the question comment, you are using React, and the usual working pipeline is using wepack or other js bundler to output a single JS file from all the dependencies. During developing you could encounter no problems to find out the file from the errors stack, but in production you could omit sourcemap informations from the bundle or either have some internal/uglified filenames which are not linked with the original file. This means that the behaviour of your code could change between dev/prod configuration depending on your building pipeline.
Theoretical solution
The (proto-OOP) theory states to use prototype to discriminate between Error types in order to filter unwanted behaviours.
So first of all you should use a custom class to define the errors thrown by your application/library (see Custom Error - MDN section). By doing so you must throw or extend only your CustomError(s) in your code.
Secondly you should filter the error by its type/properties and not by its source file, so (if you can) check what classes of Error the 3rd party function can throw.
In this way it's easy to isolate only those 3rd party errors, you can do just a simple check of inheritance within the try/catch block:
try { /* dangerous code */ }
catch (ex) {
if (ex instanceof MyError) { /* handle your errors */ }
else if (ex instanceof The3rdPartyCustomError) { /* handle specific 3rd party CustomError */ }
else if (ex.__proto__ instanceof Error) { /* handle generic 3rd party CustomErrors */ }
else { /* handle native errors (or bad practice 3rd party errors) */ }
}
But all of this theory can be difficult to implement, especially because 3rd party libraries very rarely implement their CustomError classes, so you will end up to handle only native errors and your defined classes.
Give it a try and check what kind of errors can throw your 3rd parties libs.
Maybe the simpler solution is to filter the erros by Error.message or any other properties which could work better than expected in your domain case.

How to fix 'thrown exception caught locally' when using instanceof to determine internal errors type

I have a block of code that loads a set of plugins. For each plugin, a list of functions is called inside of a try catch block to determine if the plugin has failed or not and act accordingly. At the same time, one of the multiple functions of the plugin can return a specific error that mean that the plugin has not failed but is not valid to execute the next functions with the data.
Let's see an example (the code is Typescript, but I am going to make it as language agnostic as possible):
for each plugin:
try:
plugin.function1(data)
plugin.function2(data)
plugin.function3(data)
try:
plugin.function4(data)
catch error:
if error instanceof PluginNotValidForThisKindOfDataError:
continue
else:
throw error
plugin.function5(data)
plugin.function6(data)
catch error:
log(plugin has failed)
(I hope the code is clear enough. I'll update it if required)
As can be seen, I execute function4 and I parse the possible errors because one of them (there are multiple) is "tolerable" and just means that it is not valid for function5 and function6 with that specific set of data. However, I still have to throw the other errors because they are not good. At the end, I catch the global set of errors to determine if the plugin has crashed or not.
What I get in my IDE, JetBrains (WebStorm specifically) is a thrown exception caught locally warning. But I am not able to reimagine how to redo that block to act differently. I am not using throws as flow control but just passing the error.
I admit that the main problem is that in Javascript I can not do catch PluginNotValidForThisKindOfDataError, which would be the optimal situation (hope its added some day). But, with the tools I have, how can I refactor this?
Thank you very much.
Added to both language-agnostic and javascript because of the specific Javascript try-catch method
I see three options:
Ideally, the plugin wouldn't throw an error for a non-error condition like that. Instead, have it return a value that tells the code in your question whether it should run functions 5 and 6.
If you want to keep it the way it is, though, you can either:
Ignore the warning (and probably there's a way to disable it for one line), or
Don't re-throw; instead, do the same thing you're doing in the outer catch (log(plugin has failed)) followed by continue. Provided that's just a single function call or similar, the duplication isn't ideal, but isn't horrible either. If there's any complexity to that step, isolate it into a function (perhaps even a local function) and call that from both places.

Difference between console.log enabled verification

I have seen jquery-ui-1.8.11.js verify console.log functionality by doing
if (this.debug)
console.log()
I have also seen people define an anonymous function that is a no-op for browsers with no console logging like IE7.
if(typeof console === "undefined") {
console = { log: function() { } };
}
Is there a technical difference or are both functionally equivalent?
In the first example you've given, this.debug will be a reference to a debug variable in the jQueryUI code. This debug variable will have been set elsewhere, possibly by checking whether console is defined, but also possibly with other settings.
In any case, the first example is specific to the application; if you want to do a generic check to see whether the console is available, you'll need to use the second technique. You don't have to define an empty console object as per the example, but doing it that way does mean that you won't have to do the if() condition every time you want to call console.log().
Having said all of that, I would counsel you strongly to avoid putting any code into production which contains calls to the console. The console should only be used for debugging purposes while you are working on the code. It should not be necessary in final release, and doing so can be a sign that either your code is unstable or you're unconfident of it, neither of which is a good sign if you're releasing the code for live use.
(libraries such as jQueryUI are an exception to this rule, as they need to provide functionality for developers to do debugging while writing code using their library)
Both of those do something else. The first code suppresses logging messages unless a flag is set. The people who develop jQuery UI need logging when working on it, and turn it on. But people using the library don't want to have their console cluttered by log messages from libraries, so it's off by default. It lets you turn off logging even when the browser supports it – that regular users on IE7 don't get script errors is a (possibly intended) side effect.
The second code defines a dummy console.log(), so you can call the method without checking if it exists everywhere. It will not suppress logging on browsers where it's supported.
The second of the two is standalone, not relying on jQuery. In my opinion, that makes it better.

Stop suppressing JavaScript errors

I'm using Firebug to view JavaScript errors. But I'm also using jQuery. For some reason, I never see JavaScript errors when using jQuery and this is one of the biggest problems with working with jQuery in the first place.
There's no particular code to show, just imagine alert(areareg); where areareg is undefined or any sort of JavaScript error, and Firebug won't tell me about it. The JavaScript will simply fail without warning or notification of any sort. This is always the case, in any project where I've used jQuery and it's the only reason I don't like jQuery; because it's notoriously difficult to debug when something goes wrong.
For some reason I've even had trouble finding this question raised online, let alone answered. But I figured I'd give it a try here:
Is there any way to make jQuery stop suppressing error messages?
Am I the only one in the world who has always had this problem with jQuery?
EDIT:
I use both Firefox (with Firebug) and Chrome, and I only use the non-minified version of jQuery. Still, I have never in my entire life seen a jQuery error message of any kind, neither useful nor useless, nor in fact normal JavaScript errors, when using jQuery.
Well, despite your impression, jQuery itself doesn't do anything to "suppress" error messages. Now, Firefox does tend to throw away certain kinds of exceptions, notably like what you describe. I often find that wrapping a whole Javascript block in a try ... catch with an alert call should an exception happen is a useful way to deal with it, but it's still irritating.
I use google Chrome for my debugging, and it's pretty good, it shows all the jquery errors as well (as Alfred said, if you use minified version, you wont get any meaningful name in your errors, so it's better to use the raw source)
I am having the same problem in FF 18. I am using JSF and JQuery, though it happens even for plain JS code on the page. I intentionally put javascript code that should throw a syntax error without a word in Firebug. FF 18 has its own built-in console that looks similar to firebug. When I disabled the firebug plug-in the console.log messages started showing up. However, the errors are still not showing up. I just tried Chrome and the errors do appear there.
I've run into this problem several times. It's quite inconsistent and hard to replicate, sometimes it seems related to version issues. Settings rarely seem to make a difference, though "Break on next" sometimes (not always) identifies errors that otherwise slip through.
One thing I've noticed is, it tends to happen for code that is triggered inside a callback function, e.g. from a UI event or from an AJAX call. Sometimes Firefox / Firebug will behave like other browsers and show errors in the console, sometimes it gives nothing at all even for incredibly clear-cut cases like:
console.log('something'); // Shows up in console fine
fail // Other browsers give undefined variable error, Firefox gives nothing
console.log('something else'); // Never reached, so silent error clearly happens
The best approach I've found to this is:
Once you've found a no-show error, work back using console.trace() until you reach a point where inside a function, the error is hidden, outside, it shows, adding some code snippet like:
console.trace();
fail // cause the error, look out for a trace followed by nothing
If it's an AJAX call, manually add a basic error handler, because for some reason Firefox/Firebug is losing the default:
$.ajax({
error: function(a,b,c){
throw c;
},
other: '...settings'
}
If it's something you can't add an error handling function to, wrap it in a try... catch, for example:
try {
// whatever the code is within which there are no errors
} catch( err ){
throw err;
}
This should be enough to catch all errors where-ever they are within the scope where Firefox is losing them. Beware of cases where you have a callback within a callback though, you might need to do this twice...

Robust Javascript Exception Handling

I am developing a DHTML/Javascript application which relies on some advanced features (DOM manipulation, AJAX, Flash communication, and more). I'm very concerned about functionality -- if problems occur, even after the application is deployed, I want to make sure I know why and how to fix them -- and also, I want to make sure the user is able to continue using the application, possibly with reduced functionality if the exception was severe.
I currently have a logging and exception handling system built whereby functions can generate logs, and if an exception is caught, all logs are emailed to me. The system works well but I'd like to make it more robust. I'm looking for suggestions.
One idea I have is to wrap the body of every javascript function in a try/catch block and upon catching an exception, log the name of the function and then throw the error to the global handler. But that's a lot of code just to track down the function the exception occurred in.
Any ideas to make runtime exceptions easier to find and reproduce?
Rather than dealing with adding N try/catch blocks to N functions, it might be easier to use the window.onerror event.
JavaScript Kit has a series of examples you could use. Especially the 3rd:
window.onerror = function (msg, url, line) {
alert('Error message: ' + msg + '\nURL: ' + url + '\nLine Number: ' + line);
return true;
}
If you'd prefer a stack trace, you might check out Eric Wendelin's (or Luke Smith's update). It's one of the few I know of that attempts to work cross-browser.

Categories

Resources