summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/components/Editor/Breakpoint.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/debugger/src/components/Editor/Breakpoint.js')
-rw-r--r--devtools/client/debugger/src/components/Editor/Breakpoint.js183
1 files changed, 183 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/components/Editor/Breakpoint.js b/devtools/client/debugger/src/components/Editor/Breakpoint.js
new file mode 100644
index 0000000000..cce23c199f
--- /dev/null
+++ b/devtools/client/debugger/src/components/Editor/Breakpoint.js
@@ -0,0 +1,183 @@
+/* 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 <http://mozilla.org/MPL/2.0/>. */
+
+import { PureComponent } from "react";
+import PropTypes from "prop-types";
+
+import { getDocument, toEditorLine } from "../../utils/editor";
+import { getSelectedLocation } from "../../utils/selected-location";
+import { features } from "../../utils/prefs";
+import { showMenu } from "../../context-menu/menu";
+import { breakpointItems } from "./menus/breakpoints";
+const classnames = require("devtools/client/shared/classnames.js");
+
+const breakpointSvg = document.createElement("div");
+breakpointSvg.innerHTML =
+ '<svg viewBox="0 0 60 15" width="60" height="15"><path d="M53.07.5H1.5c-.54 0-1 .46-1 1v12c0 .54.46 1 1 1h51.57c.58 0 1.15-.26 1.53-.7l4.7-6.3-4.7-6.3c-.38-.44-.95-.7-1.53-.7z"/></svg>';
+
+class Breakpoint extends PureComponent {
+ static get propTypes() {
+ return {
+ cx: PropTypes.object.isRequired,
+ breakpoint: PropTypes.object.isRequired,
+ breakpointActions: PropTypes.object.isRequired,
+ editor: PropTypes.object.isRequired,
+ editorActions: PropTypes.object.isRequired,
+ selectedSource: PropTypes.object,
+ blackboxedRangesForSelectedSource: PropTypes.array,
+ isSelectedSourceOnIgnoreList: PropTypes.bool.isRequired,
+ };
+ }
+
+ componentDidMount() {
+ this.addBreakpoint(this.props);
+ }
+
+ componentDidUpdate(prevProps) {
+ this.removeBreakpoint(prevProps);
+ this.addBreakpoint(this.props);
+ }
+
+ componentWillUnmount() {
+ this.removeBreakpoint(this.props);
+ }
+
+ makeMarker() {
+ const { breakpoint } = this.props;
+ const bp = breakpointSvg.cloneNode(true);
+
+ bp.className = classnames("editor new-breakpoint", {
+ "breakpoint-disabled": breakpoint.disabled,
+ "folding-enabled": features.codeFolding,
+ });
+ bp.onmousedown = this.onClick;
+ bp.oncontextmenu = this.onContextMenu;
+
+ return bp;
+ }
+
+ onClick = event => {
+ const { cx, breakpointActions, editorActions, breakpoint, selectedSource } =
+ this.props;
+
+ // ignore right clicks
+ if ((event.ctrlKey && event.button === 0) || event.button === 2) {
+ return;
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+
+ const selectedLocation = getSelectedLocation(breakpoint, selectedSource);
+ if (event.metaKey) {
+ editorActions.continueToHere(cx, selectedLocation);
+ return;
+ }
+
+ if (event.shiftKey) {
+ breakpointActions.toggleBreakpointsAtLine(
+ cx,
+ !breakpoint.disabled,
+ selectedLocation.line
+ );
+ return;
+ }
+
+ breakpointActions.removeBreakpointsAtLine(
+ cx,
+ selectedLocation.sourceId,
+ selectedLocation.line
+ );
+ };
+
+ onContextMenu = event => {
+ const {
+ cx,
+ breakpoint,
+ selectedSource,
+ breakpointActions,
+ blackboxedRangesForSelectedSource,
+ isSelectedSourceOnIgnoreList,
+ } = this.props;
+ event.stopPropagation();
+ event.preventDefault();
+ const selectedLocation = getSelectedLocation(breakpoint, selectedSource);
+
+ showMenu(
+ event,
+ breakpointItems(
+ cx,
+ breakpoint,
+ selectedLocation,
+ breakpointActions,
+ blackboxedRangesForSelectedSource,
+ isSelectedSourceOnIgnoreList
+ )
+ );
+ };
+
+ addBreakpoint(props) {
+ const { breakpoint, editor, selectedSource } = props;
+ const selectedLocation = getSelectedLocation(breakpoint, selectedSource);
+
+ // Hidden Breakpoints are never rendered on the client
+ if (breakpoint.options.hidden) {
+ return;
+ }
+
+ if (!selectedSource) {
+ return;
+ }
+
+ const sourceId = selectedSource.id;
+ const line = toEditorLine(sourceId, selectedLocation.line);
+ const doc = getDocument(sourceId);
+
+ doc.setGutterMarker(line, "breakpoints", this.makeMarker());
+
+ editor.codeMirror.addLineClass(line, "wrap", "new-breakpoint");
+ editor.codeMirror.removeLineClass(line, "wrap", "breakpoint-disabled");
+ editor.codeMirror.removeLineClass(line, "wrap", "has-condition");
+ editor.codeMirror.removeLineClass(line, "wrap", "has-log");
+
+ if (breakpoint.disabled) {
+ editor.codeMirror.addLineClass(line, "wrap", "breakpoint-disabled");
+ }
+
+ if (breakpoint.options.logValue) {
+ editor.codeMirror.addLineClass(line, "wrap", "has-log");
+ } else if (breakpoint.options.condition) {
+ editor.codeMirror.addLineClass(line, "wrap", "has-condition");
+ }
+ }
+
+ removeBreakpoint(props) {
+ const { selectedSource, breakpoint } = props;
+ if (!selectedSource) {
+ return;
+ }
+
+ const sourceId = selectedSource.id;
+ const doc = getDocument(sourceId);
+
+ if (!doc) {
+ return;
+ }
+
+ const selectedLocation = getSelectedLocation(breakpoint, selectedSource);
+ const line = toEditorLine(sourceId, selectedLocation.line);
+
+ doc.setGutterMarker(line, "breakpoints", null);
+ doc.removeLineClass(line, "wrap", "new-breakpoint");
+ doc.removeLineClass(line, "wrap", "breakpoint-disabled");
+ doc.removeLineClass(line, "wrap", "has-condition");
+ doc.removeLineClass(line, "wrap", "has-log");
+ }
+
+ render() {
+ return null;
+ }
+}
+
+export default Breakpoint;