summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js')
-rw-r--r--devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js112
1 files changed, 112 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js b/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js
new file mode 100644
index 0000000000..d535a4b19e
--- /dev/null
+++ b/devtools/client/debugger/src/components/SecondaryPanes/Frames/FrameMenu.js
@@ -0,0 +1,112 @@
+/* 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/>. */
+
+// @flow
+import { showMenu } from "../../../context-menu/menu";
+import { copyToTheClipboard } from "../../../utils/clipboard";
+import type { ContextMenuItem, Frame, ThreadContext } from "../../../types";
+import { kebabCase } from "lodash";
+
+const blackboxString = "ignoreContextItem.ignore";
+const unblackboxString = "ignoreContextItem.unignore";
+
+function formatMenuElement(
+ labelString: string,
+ click: Function,
+ disabled: boolean = false
+): ContextMenuItem {
+ const label = L10N.getStr(labelString);
+ const accesskey = L10N.getStr(`${labelString}.accesskey`);
+ const id = `node-menu-${kebabCase(label)}`;
+ return {
+ id,
+ label,
+ accesskey,
+ disabled,
+ click,
+ };
+}
+
+function copySourceElement(url) {
+ return formatMenuElement("copySourceUri2", () => copyToTheClipboard(url));
+}
+
+function copyStackTraceElement(copyStackTrace) {
+ return formatMenuElement("copyStackTrace", () => copyStackTrace());
+}
+
+function toggleFrameworkGroupingElement(
+ toggleFrameworkGrouping,
+ frameworkGroupingOn
+) {
+ const actionType = frameworkGroupingOn
+ ? "framework.disableGrouping"
+ : "framework.enableGrouping";
+
+ return formatMenuElement(actionType, () => toggleFrameworkGrouping());
+}
+
+function blackBoxSource(cx, source, toggleBlackBox) {
+ const toggleBlackBoxString = source.isBlackBoxed
+ ? unblackboxString
+ : blackboxString;
+
+ return formatMenuElement(toggleBlackBoxString, () =>
+ toggleBlackBox(cx, source)
+ );
+}
+
+function restartFrame(cx, frame, restart) {
+ return formatMenuElement("restartFrame", () => restart(cx, frame));
+}
+
+function isValidRestartFrame(frame: Frame, callbacks: Object) {
+ // Hides 'Restart Frame' item for call stack groups context menu,
+ // otherwise can be misleading for the user which frame gets restarted.
+ if (!callbacks.restart) {
+ return false;
+ }
+
+ // Any frame state than 'on-stack' is either dismissed by the server
+ // or can potentially cause unexpected errors.
+ // Global frame has frame.callee equal to null and can't be restarted.
+ return frame.type === "call" && frame.state === "on-stack";
+}
+
+export default function FrameMenu(
+ frame: Frame,
+ frameworkGroupingOn: boolean,
+ callbacks: Object,
+ event: SyntheticMouseEvent<HTMLElement>,
+ cx: ThreadContext
+) {
+ event.stopPropagation();
+ event.preventDefault();
+
+ const menuOptions = [];
+
+ if (isValidRestartFrame(frame, callbacks)) {
+ const restartFrameItem = restartFrame(cx, frame, callbacks.restart);
+ menuOptions.push(restartFrameItem);
+ }
+
+ const toggleFrameworkElement = toggleFrameworkGroupingElement(
+ callbacks.toggleFrameworkGrouping,
+ frameworkGroupingOn
+ );
+ menuOptions.push(toggleFrameworkElement);
+
+ const { source } = frame;
+ if (source) {
+ const copySourceUri2 = copySourceElement(source.url);
+ menuOptions.push(copySourceUri2);
+ menuOptions.push(blackBoxSource(cx, source, callbacks.toggleBlackBox));
+ }
+
+ const copyStackTraceItem = copyStackTraceElement(callbacks.copyStackTrace);
+
+ menuOptions.push(copyStackTraceItem);
+
+ showMenu(event, menuOptions);
+}