From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../src/components/SecondaryPanes/WhyPaused.js | 218 +++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 devtools/client/debugger/src/components/SecondaryPanes/WhyPaused.js (limited to 'devtools/client/debugger/src/components/SecondaryPanes/WhyPaused.js') diff --git a/devtools/client/debugger/src/components/SecondaryPanes/WhyPaused.js b/devtools/client/debugger/src/components/SecondaryPanes/WhyPaused.js new file mode 100644 index 0000000000..fabd75a7ce --- /dev/null +++ b/devtools/client/debugger/src/components/SecondaryPanes/WhyPaused.js @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +const { + LocalizationProvider, + Localized, +} = require("resource://devtools/client/shared/vendor/fluent-react.js"); + +import React, { PureComponent } from "devtools/client/shared/vendor/react"; +import { div, span } from "devtools/client/shared/vendor/react-dom-factories"; +import PropTypes from "devtools/client/shared/vendor/react-prop-types"; +import { connect } from "devtools/client/shared/vendor/react-redux"; +import AccessibleImage from "../shared/AccessibleImage"; +import actions from "../../actions/index"; + +import Reps from "devtools/client/shared/components/reps/index"; +const { + REPS: { Rep }, + MODE, +} = Reps; + +import { getPauseReason } from "../../utils/pause/index"; +import { + getCurrentThread, + getPaneCollapse, + getPauseReason as getWhy, +} from "../../selectors/index"; + +class WhyPaused extends PureComponent { + constructor(props) { + super(props); + this.state = { hideWhyPaused: "" }; + } + + static get propTypes() { + return { + delay: PropTypes.number.isRequired, + endPanelCollapsed: PropTypes.bool.isRequired, + highlightDomElement: PropTypes.func.isRequired, + openElementInInspector: PropTypes.func.isRequired, + unHighlightDomElement: PropTypes.func.isRequired, + why: PropTypes.object, + }; + } + + componentDidUpdate() { + const { delay } = this.props; + + if (delay) { + setTimeout(() => { + this.setState({ hideWhyPaused: "" }); + }, delay); + } else { + this.setState({ hideWhyPaused: "pane why-paused" }); + } + } + + renderExceptionSummary(exception) { + if (typeof exception === "string") { + return exception; + } + + const { preview } = exception; + if (!preview || !preview.name || !preview.message) { + return null; + } + + return `${preview.name}: ${preview.message}`; + } + + renderMessage(why) { + const { type, exception, message } = why; + + if (type == "exception" && exception) { + // Our types for 'Why' are too general because 'type' can be 'string'. + // $FlowFixMe - We should have a proper discriminating union of reasons. + const summary = this.renderExceptionSummary(exception); + return div( + { + className: "message warning", + }, + summary + ); + } + + if (type === "mutationBreakpoint" && why.nodeGrip) { + const { nodeGrip, ancestorGrip, action } = why; + const { + openElementInInspector, + highlightDomElement, + unHighlightDomElement, + } = this.props; + + const targetRep = Rep({ + object: nodeGrip, + mode: MODE.TINY, + onDOMNodeClick: () => openElementInInspector(nodeGrip), + onInspectIconClick: () => openElementInInspector(nodeGrip), + onDOMNodeMouseOver: () => highlightDomElement(nodeGrip), + onDOMNodeMouseOut: () => unHighlightDomElement(), + }); + + const ancestorRep = ancestorGrip + ? Rep({ + object: ancestorGrip, + mode: MODE.TINY, + onDOMNodeClick: () => openElementInInspector(ancestorGrip), + onInspectIconClick: () => openElementInInspector(ancestorGrip), + onDOMNodeMouseOver: () => highlightDomElement(ancestorGrip), + onDOMNodeMouseOut: () => unHighlightDomElement(), + }) + : null; + return div( + null, + div( + { + className: "message", + }, + why.message + ), + div( + { + className: "mutationNode", + }, + ancestorRep, + ancestorGrip + ? span( + { + className: "why-paused-ancestor", + }, + React.createElement(Localized, { + id: + action === "remove" + ? "whypaused-mutation-breakpoint-removed" + : "whypaused-mutation-breakpoint-added", + }), + targetRep + ) + : targetRep + ) + ); + } + + if (typeof message == "string") { + return div( + { + className: "message", + }, + message + ); + } + + return null; + } + + render() { + const { endPanelCollapsed, why } = this.props; + const { fluentBundles } = this.context; + const reason = getPauseReason(why); + + if (!why || !reason || endPanelCollapsed) { + return div({ + className: this.state.hideWhyPaused, + }); + } + return ( + // We're rendering the LocalizationProvider component from here and not in an upper + // component because it does set a new context, overriding the context that we set + // in the first place in , which breaks some components. + // This should be fixed in Bug 1743155. + React.createElement( + LocalizationProvider, + { + bundles: fluentBundles || [], + }, + div( + { + className: "pane why-paused", + }, + div( + null, + div( + { + className: "info icon", + }, + React.createElement(AccessibleImage, { + className: "info", + }) + ), + div( + { + className: "pause reason", + }, + React.createElement(Localized, { + id: reason, + }), + this.renderMessage(why) + ) + ) + ) + ) + ); + } +} + +WhyPaused.contextTypes = { fluentBundles: PropTypes.array }; + +const mapStateToProps = state => ({ + endPanelCollapsed: getPaneCollapse(state, "end"), + why: getWhy(state, getCurrentThread(state)), +}); + +export default connect(mapStateToProps, { + openElementInInspector: actions.openElementInInspectorCommand, + highlightDomElement: actions.highlightDomElement, + unHighlightDomElement: actions.unHighlightDomElement, +})(WhyPaused); -- cgit v1.2.3