tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

EagerEvaluation.js (4377B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  Component,
      9 } = require("resource://devtools/client/shared/vendor/react.mjs");
     10 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     11 const {
     12  connect,
     13 } = require("resource://devtools/client/shared/vendor/react-redux.js");
     14 
     15 const {
     16  getTerminalEagerResult,
     17 } = require("resource://devtools/client/webconsole/selectors/history.js");
     18 
     19 const actions = require("resource://devtools/client/webconsole/actions/index.js");
     20 
     21 loader.lazyGetter(this, "REPS", function () {
     22  return ChromeUtils.importESModule(
     23    "resource://devtools/client/shared/components/reps/index.mjs",
     24    { global: "current" }
     25  ).REPS;
     26 });
     27 loader.lazyGetter(this, "MODE", function () {
     28  return ChromeUtils.importESModule(
     29    "resource://devtools/client/shared/components/reps/index.mjs",
     30    { global: "current" }
     31  ).MODE;
     32 });
     33 loader.lazyRequireGetter(
     34  this,
     35  "PropTypes",
     36  "resource://devtools/client/shared/vendor/react-prop-types.js"
     37 );
     38 
     39 /**
     40 * Show the results of evaluating the current terminal text, if possible.
     41 */
     42 class EagerEvaluation extends Component {
     43  static get propTypes() {
     44    return {
     45      terminalEagerResult: PropTypes.any,
     46      highlightDomElement: PropTypes.func.isRequired,
     47      unHighlightDomElement: PropTypes.func.isRequired,
     48    };
     49  }
     50 
     51  static getDerivedStateFromError() {
     52    return { hasError: true };
     53  }
     54 
     55  componentDidUpdate(prevProps) {
     56    const { highlightDomElement, unHighlightDomElement, terminalEagerResult } =
     57      this.props;
     58 
     59    if (canHighlightObject(prevProps.terminalEagerResult)) {
     60      unHighlightDomElement(prevProps.terminalEagerResult.getGrip());
     61    }
     62 
     63    if (canHighlightObject(terminalEagerResult)) {
     64      highlightDomElement(terminalEagerResult.getGrip());
     65    }
     66 
     67    if (this.state?.hasError) {
     68      // If the render function threw at some point, clear the error after 1s so the
     69      // component has a chance to render again.
     70      // This way, we don't block instant evaluation for the whole session, in case the
     71      // input changed in the meantime. If the input didn't change, we'll hit
     72      // getDerivatedStateFromError again (and this won't render anything), so it's safe.
     73      setTimeout(() => {
     74        this.setState({ hasError: false });
     75      }, 1000);
     76    }
     77  }
     78 
     79  componentWillUnmount() {
     80    const { unHighlightDomElement, terminalEagerResult } = this.props;
     81 
     82    if (canHighlightObject(terminalEagerResult)) {
     83      unHighlightDomElement(terminalEagerResult.getGrip());
     84    }
     85  }
     86 
     87  renderRepsResult() {
     88    const { terminalEagerResult } = this.props;
     89 
     90    const result = terminalEagerResult.getGrip
     91      ? terminalEagerResult.getGrip()
     92      : terminalEagerResult;
     93    const { isError } = result || {};
     94 
     95    return REPS.Rep({
     96      key: "rep",
     97      object: result,
     98      mode: isError ? MODE.SHORT : MODE.LONG,
     99    });
    100  }
    101 
    102  render() {
    103    const hasResult =
    104      this.props.terminalEagerResult !== null &&
    105      this.props.terminalEagerResult !== undefined &&
    106      !this.state?.hasError;
    107 
    108    return dom.div(
    109      { className: "eager-evaluation-result", key: "eager-evaluation-result" },
    110      hasResult
    111        ? dom.span(
    112            { className: "eager-evaluation-result__row" },
    113            dom.span({
    114              className: "eager-evaluation-result__icon",
    115              key: "icon",
    116            }),
    117            dom.span(
    118              { className: "eager-evaluation-result__text", key: "text" },
    119              this.renderRepsResult()
    120            )
    121          )
    122        : null
    123    );
    124  }
    125 }
    126 
    127 function canHighlightObject(obj) {
    128  const grip = obj?.getGrip && obj.getGrip();
    129  return (
    130    grip &&
    131    (REPS.ElementNode.supportsObject(grip) ||
    132      REPS.TextNode.supportsObject(grip)) &&
    133    grip.preview.isConnected
    134  );
    135 }
    136 
    137 function mapStateToProps(state) {
    138  return {
    139    terminalEagerResult: getTerminalEagerResult(state),
    140  };
    141 }
    142 
    143 function mapDispatchToProps(dispatch) {
    144  return {
    145    highlightDomElement: grip => dispatch(actions.highlightDomElement(grip)),
    146    unHighlightDomElement: grip =>
    147      dispatch(actions.unHighlightDomElement(grip)),
    148  };
    149 }
    150 module.exports = connect(mapStateToProps, mapDispatchToProps)(EagerEvaluation);