-
Notifications
You must be signed in to change notification settings - Fork 58
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
CPLAT-7606 Improve handling of “repeat” errors thrown from components wrapped by an ErrorBoundary #350
Conversation
Security InsightsThe items listed below may not capture all security relevant changes. Before providing a security review, be sure to review the entire PR for security impact. (3) Security relevant changes were detectedinnerHtml in lib/src/component/error_boundary.dart line(s) ['323'] addedInnerHtml in lib/src/component/error_boundary.dart line(s) ['347'] addeddangerouslySetInnerHTML in lib/src/component/error_boundary.dart line(s) ['348'] addedAction Items
Questions or Comments? Reach out on Slack: #support-infosec. |
+1 security
|
return (Dom.div() | ||
..key = 'ohnoes' | ||
..addTestId('ErrorBoundary.unrecoverableErrorInnerHtmlContainerNode') | ||
..['dangerouslySetInnerHTML'] = {'__html': _domAtTimeOfError} ?? '' |
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.
What are the cases when the null check will return ''
? Because the Map
is always set with a key, won't it always be non-null?
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.
Is this supposed to be on _domAtTimeOfError
?
..['dangerouslySetInnerHTML'] = {'__html': _domAtTimeOfError} ?? '' | |
..['dangerouslySetInnerHTML'] = {'__html': _domAtTimeOfError ?? ''} |
Maybe we should add a test where the child component is a or renders a fragment, which would represent a case where _domAtTimeOfError
would be null
:
ErrorBoundary([ // Can't use variadic children or the fragment will be interpreted as two separate children
// A list-style "fragment" as the single child.
[
(Dom.div()..key = 1)(),
(FaultyComponent()..key = 2)(),
],
])
Or actually, maybe even an empty component would do...
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.
Nice catch on this typo @joebingham-wk !!!
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.
Fixed the typo, added edge case test coverage in a9e864e
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.
Mostly nits and then a few questions/comments. Overall, looks really solid!
+ and add more test coverage for edge cases involving `dangerouslySetInnerHTML`
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.
+1
expect(() => component.setState(component.newState()..hasError = true), throws); | ||
expect(getByTestId(jacket.getInstance(), 'dummyChild'), isNull, | ||
reason: 'The child component tree should have been removed from the dom'); | ||
expect(jacket.getNode(), hasAttr(defaultTestIdKey, 'ErrorBoundary.unrecoverableErrorInnerHtmlContainerNode')); |
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.
Can we assert here that the static HTML got rendered? I'm not seeing that tested anywhere
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.
It is tested in the "gracefully handles errors in its tree when props.fallbackUIRenderer
is not set" section:
https://github.com/Workiva/over_react/pull/350/files#diff-820fada62e348ea7fccc19d5cc72d0f6R342
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.
Ah, sorry, I missed that. Thanks!
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.
+1
Works well in WVC and over_react example QA +1 @Workiva/release-management-p |
+1 security refresh |
Motivation
While testing the recent
3.0.0-alpha.0
release in a consumer library, a problem was discovered.Currently, our
ErrorBoundary
component - whenprops.fallbackUIRenderer
is not specified - will attempt to remount its child component tree when an error is caught. In most cases, this is a sane default - however - if a component in that tree throws every time it mounts - this causes a huge problem, since it creates a sort of "infinite loop" ofcomponent throws in componentDidMount -> ErrorBoundary remounts the componnet -> component throws in componentDidMount -> ...
. This infinite loop has the potential to completely lock up the main CPU thread.Changes
ErrorBoundaryComponent
that keep track of the error that was thrown, and the "component stack" from theinfo
object made available from ReactJS when a component wrapped in an error boundary throws.reset
instance method.Release Notes
Improve handling of “repeat” errors thrown from components wrapped by an ErrorBoundary component.
Review
See CONTRIBUTING.md for more details on review types (+1 / QA +1 / +10) and code review process.
Please review: @greglittlefield-wf @kealjones-wk @joebingham-wk @sydneyjodon-wk
QA Checklist
Merge Checklist
While we perform many automated checks before auto-merging, some manual checks are needed: