-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for aggregate errors #87
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments, thoughts, questions – but most importantly: A note that this is susceptible to infinite recursion. Only the latter is why I set "Request changes" :)
Do note though: I'm not a maintainer of this module
lib/err.js
Outdated
@@ -50,6 +56,10 @@ function errSerializer (err) { | |||
: err.name | |||
_err.message = messageWithCauses(err) | |||
_err.stack = stackWithCauses(err) | |||
// eslint-disable-next-line no-undef | |||
if (hasAggregateError && err instanceof AggregateError && err.errors && Array.isArray(err.errors)) { | |||
_err.aggregateErrors = err.errors.map(errSerializer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bypasses the if (!val.hasOwnProperty(seen)) {
check and thus is susceptible to infinite recursion if an aggregate error includes itself in the list of errors.
We should add a prevents infinite aggregate recursion
test + either add a check right here or in the beginning of errSerializer
to ensure that infinite is aborted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@voxpelli I agree that infinite recursion is possible if the aggregate error includes itself in the list of errors but can you provide a scenario where this could happen? I think creating a new aggregate error requires you to provide an iterable of already existing errors so the list of errors cannot contain a reference to the aggregate error itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sameer-coder I'm kind of lost on why it's impossible to write a unit test that cover this case. Can you add one anyway?
test/err.test.js
Outdated
t.plan(7) | ||
const foo = new Error('foo') | ||
const agg1 = new AggregateError([foo], 'aggregated message') // eslint-disable-line no-undef | ||
agg1.inner = agg1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really sure if this test is written correctly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this be agg1.errors.push(agg1)
? Although, I agree with you. I'd like to have a clear explanation of when we think this would actually happen, @voxpelli. An AggregateError
must be initialized with an array of existing errors. Thus, it cannot be initialized with itself in the aggregate. Anyone appending to the aggregate to its errors
list seems a Bad Idea, and a scenario we should just classify as unsupported.
http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError
Also, the spec requires at least the array of errors be present when creating a new aggregate -- https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-aggregate-error-constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@voxpelli Did you get a chance to look at this again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyone appending to the aggregate to its errors list seems a Bad Idea, and a scenario we should just classify as unsupported.
I agree, but since the consequences are catastrophic, I think we should still prevent it.
Same would apply for Error Causes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mcollina do you have any thoughts on this? @davidmarkclements ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think cycles are a problem. It will be catastrophic but also very easy to debug and fix.
They will need to modify the .errors
property manually.
To prevernt this, I would just wrap the function in a try/catch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, to be clear, we are agreeing to remove the edge case detection in this code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And if someone jumps on eg. huntr.dev and reports this as a potential DDoS vector, then we'll simply say that its not valid?
I'm okay with that 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. As stated, it's unsupported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
Example
Produces the following serialized output:
Note: AggregateError is only supported by node 15+
Closes #86