Bug 1640572 - Add Error boundaries to Eager Evaluation component. r=bomsy.
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Mon, 25 May 2020 19:16:36 +0000
changeset 532122 000aac572ccf422961bd09f9aa0a966be50ebc01
parent 532121 cd5c87a1700881582a938bff5d653b48eb82d0bc
child 532123 9298de7e11dd1a8b7cf408d1f3fba6f0edb6c55e
push id37450
push usercbrindusan@mozilla.com
push dateTue, 26 May 2020 15:44:42 +0000
treeherdermozilla-central@4da52a3b8dfd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbomsy
bugs1640572
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1640572 - Add Error boundaries to Eager Evaluation component. r=bomsy. This will prevent the Eager Evaluation component to crash the whole console when there's an issue in its render function. Differential Revision: https://phabricator.services.mozilla.com/D76673
devtools/client/webconsole/components/Input/EagerEvaluation.js
--- a/devtools/client/webconsole/components/Input/EagerEvaluation.js
+++ b/devtools/client/webconsole/components/Input/EagerEvaluation.js
@@ -34,30 +34,45 @@ class EagerEvaluation extends Component 
     return {
       terminalEagerResult: PropTypes.any,
       serviceContainer: PropTypes.object.isRequired,
       highlightDomElement: PropTypes.func.isRequired,
       unHighlightDomElement: PropTypes.func.isRequired,
     };
   }
 
+  static getDerivedStateFromError(error) {
+    return { hasError: true };
+  }
+
   componentDidUpdate(prevProps) {
     const {
       highlightDomElement,
       unHighlightDomElement,
       terminalEagerResult,
     } = this.props;
 
     if (canHighlightObject(prevProps.terminalEagerResult)) {
       unHighlightDomElement(prevProps.terminalEagerResult.getGrip());
     }
 
     if (canHighlightObject(terminalEagerResult)) {
       highlightDomElement(terminalEagerResult.getGrip());
     }
+
+    if (this.state?.hasError) {
+      // If the render function threw at some point, clear the error after 1s so the
+      // component has a chance to render again.
+      // This way, we don't block instant evaluation for the whole session, in case the
+      // input changed in the meantime. If the input didn't change, we'll hit
+      // getDerivatedStateFromError again (and this won't render anything), so it's safe.
+      setTimeout(() => {
+        this.setState({ hasError: false });
+      }, 1000);
+    }
   }
 
   componentWillUnmount() {
     const { unHighlightDomElement, terminalEagerResult } = this.props;
 
     if (canHighlightObject(terminalEagerResult)) {
       unHighlightDomElement(terminalEagerResult.getGrip());
     }
@@ -74,17 +89,18 @@ class EagerEvaluation extends Component 
     return REPS.Rep({
       key: "rep",
       object: result,
       mode: isError ? MODE.SHORT : MODE.LONG,
     });
   }
 
   render() {
-    const hasResult = this.props.terminalEagerResult !== null;
+    const hasResult =
+      this.props.terminalEagerResult !== null && !this.state?.hasError;
 
     return dom.div(
       { className: "eager-evaluation-result", key: "eager-evaluation-result" },
       hasResult
         ? dom.span(
             { className: "eager-evaluation-result__row" },
             dom.span({
               className: "eager-evaluation-result__icon",