summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/selectors/pause.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/debugger/src/selectors/pause.js')
-rw-r--r--devtools/client/debugger/src/selectors/pause.js267
1 files changed, 267 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/selectors/pause.js b/devtools/client/debugger/src/selectors/pause.js
new file mode 100644
index 0000000000..61900e9f8c
--- /dev/null
+++ b/devtools/client/debugger/src/selectors/pause.js
@@ -0,0 +1,267 @@
+/* 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 { getThreadPauseState } from "../reducers/pause";
+import { getSelectedSourceId, getSelectedLocation } from "./sources";
+
+import { isGeneratedId } from "devtools/client/shared/source-map-loader/index";
+
+// eslint-disable-next-line
+import { getSelectedLocation as _getSelectedLocation } from "../utils/selected-location";
+import { createSelector } from "reselect";
+
+export const getSelectedFrame = createSelector(
+ (state, thread) => state.pause.threads[thread],
+ threadPauseState => {
+ if (!threadPauseState) return null;
+ const { selectedFrameId, frames } = threadPauseState;
+ if (frames) {
+ return frames.find(frame => frame.id == selectedFrameId);
+ }
+ return null;
+ }
+);
+
+export const getVisibleSelectedFrame = createSelector(
+ getSelectedLocation,
+ state => getSelectedFrame(state, getCurrentThread(state)),
+ (selectedLocation, selectedFrame) => {
+ if (!selectedFrame) {
+ return null;
+ }
+
+ const { id, displayName } = selectedFrame;
+
+ return {
+ id,
+ displayName,
+ location: _getSelectedLocation(selectedFrame, selectedLocation),
+ };
+ }
+);
+
+export function getContext(state) {
+ return state.pause.cx;
+}
+
+export function getThreadContext(state) {
+ return state.pause.threadcx;
+}
+
+export function getPauseReason(state, thread) {
+ return getThreadPauseState(state.pause, thread).why;
+}
+
+export function getShouldBreakpointsPaneOpenOnPause(state, thread) {
+ return getThreadPauseState(state.pause, thread)
+ .shouldBreakpointsPaneOpenOnPause;
+}
+
+export function getPauseCommand(state, thread) {
+ return getThreadPauseState(state.pause, thread).command;
+}
+
+export function isStepping(state, thread) {
+ return ["stepIn", "stepOver", "stepOut"].includes(
+ getPauseCommand(state, thread)
+ );
+}
+
+export function getCurrentThread(state) {
+ return getThreadContext(state).thread;
+}
+
+export function getIsPaused(state, thread) {
+ return getThreadPauseState(state.pause, thread).isPaused;
+}
+
+export function getIsCurrentThreadPaused(state) {
+ return getIsPaused(state, getCurrentThread(state));
+}
+
+export function isEvaluatingExpression(state, thread) {
+ return getThreadPauseState(state.pause, thread).command === "expression";
+}
+
+export function getIsWaitingOnBreak(state, thread) {
+ return getThreadPauseState(state.pause, thread).isWaitingOnBreak;
+}
+
+export function getShouldPauseOnExceptions(state) {
+ return state.pause.shouldPauseOnExceptions;
+}
+
+export function getShouldPauseOnCaughtExceptions(state) {
+ return state.pause.shouldPauseOnCaughtExceptions;
+}
+
+export function getFrames(state, thread) {
+ const { frames, framesLoading } = getThreadPauseState(state.pause, thread);
+ return framesLoading ? null : frames;
+}
+
+export function getCurrentThreadFrames(state) {
+ const { frames, framesLoading } = getThreadPauseState(
+ state.pause,
+ getCurrentThread(state)
+ );
+ return framesLoading ? null : frames;
+}
+
+function getGeneratedFrameId(frameId) {
+ if (frameId.includes("-originalFrame")) {
+ // The mapFrames can add original stack frames -- get generated frameId.
+ return frameId.substr(0, frameId.lastIndexOf("-originalFrame"));
+ }
+ return frameId;
+}
+
+export function getGeneratedFrameScope(state, thread, frameId) {
+ if (!frameId) {
+ return null;
+ }
+
+ return getFrameScopes(state, thread).generated[getGeneratedFrameId(frameId)];
+}
+
+export function getOriginalFrameScope(state, thread, sourceId, frameId) {
+ if (!frameId || !sourceId) {
+ return null;
+ }
+
+ const isGenerated = isGeneratedId(sourceId);
+ const original = getFrameScopes(state, thread).original[
+ getGeneratedFrameId(frameId)
+ ];
+
+ if (!isGenerated && original && (original.pending || original.scope)) {
+ return original;
+ }
+
+ return null;
+}
+
+// This is only used by tests
+export function getFrameScopes(state, thread) {
+ return getThreadPauseState(state.pause, thread).frameScopes;
+}
+
+export function getSelectedFrameBindings(state, thread) {
+ const scopes = getFrameScopes(state, thread);
+ const selectedFrameId = getSelectedFrameId(state, thread);
+ if (!scopes || !selectedFrameId) {
+ return null;
+ }
+
+ const frameScope = scopes.generated[selectedFrameId];
+ if (!frameScope || frameScope.pending) {
+ return null;
+ }
+
+ let currentScope = frameScope.scope;
+ let frameBindings = [];
+ while (currentScope && currentScope.type != "object") {
+ if (currentScope.bindings) {
+ const bindings = Object.keys(currentScope.bindings.variables);
+ const args = [].concat(
+ ...currentScope.bindings.arguments.map(argument =>
+ Object.keys(argument)
+ )
+ );
+
+ frameBindings = [...frameBindings, ...bindings, ...args];
+ }
+ currentScope = currentScope.parent;
+ }
+
+ return frameBindings;
+}
+
+function getFrameScope(state, thread, sourceId, frameId) {
+ return (
+ getOriginalFrameScope(state, thread, sourceId, frameId) ||
+ getGeneratedFrameScope(state, thread, frameId)
+ );
+}
+
+// This is only used by tests
+export function getSelectedScope(state, thread) {
+ const sourceId = getSelectedSourceId(state);
+ const frameId = getSelectedFrameId(state, thread);
+
+ const frameScope = getFrameScope(state, thread, sourceId, frameId);
+ if (!frameScope) {
+ return null;
+ }
+
+ return frameScope.scope || null;
+}
+
+export function getSelectedOriginalScope(state, thread) {
+ const sourceId = getSelectedSourceId(state);
+ const frameId = getSelectedFrameId(state, thread);
+ return getOriginalFrameScope(state, thread, sourceId, frameId);
+}
+
+export function getSelectedGeneratedScope(state, thread) {
+ const frameId = getSelectedFrameId(state, thread);
+ return getGeneratedFrameScope(state, thread, frameId);
+}
+
+export function getSelectedScopeMappings(state, thread) {
+ const frameId = getSelectedFrameId(state, thread);
+ if (!frameId) {
+ return null;
+ }
+
+ return getFrameScopes(state, thread).mappings[frameId];
+}
+
+export function getSelectedFrameId(state, thread) {
+ return getThreadPauseState(state.pause, thread).selectedFrameId;
+}
+
+export function isTopFrameSelected(state, thread) {
+ const selectedFrameId = getSelectedFrameId(state, thread);
+ const topFrame = getTopFrame(state, thread);
+ return selectedFrameId == topFrame?.id;
+}
+
+export function getTopFrame(state, thread) {
+ const frames = getFrames(state, thread);
+ return frames?.[0];
+}
+
+export function getSkipPausing(state) {
+ return state.pause.skipPausing;
+}
+
+export function getHighlightedCalls(state, thread) {
+ return getThreadPauseState(state.pause, thread).highlightedCalls;
+}
+
+export function isMapScopesEnabled(state) {
+ return state.pause.mapScopes;
+}
+
+export function getInlinePreviews(state, thread, frameId) {
+ return getThreadPauseState(state.pause, thread).inlinePreview[
+ getGeneratedFrameId(frameId)
+ ];
+}
+
+// This is only used by tests
+export function getSelectedInlinePreviews(state) {
+ const thread = getCurrentThread(state);
+ const frameId = getSelectedFrameId(state, thread);
+ if (!frameId) {
+ return null;
+ }
+
+ return getInlinePreviews(state, thread, frameId);
+}
+
+export function getLastExpandedScopes(state, thread) {
+ return getThreadPauseState(state.pause, thread).lastExpandedScopes;
+}