Reputation: 26135
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.
Upvotes: 2
Views: 403
Reputation: 1878
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.
Emulate the browser sourcemap resolution with StackTraceJS or filter your errors by their prototype or any of their properties (like Error.message
for example)
JS Errors stacktrace are a mess, and so unreliable:
setTimeout
for example)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)
*/
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.
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.
Upvotes: 1