Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/devtools/client/debugger/src/reducers/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  pause.js   Sprache: JAVA

 
/* 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/>. */


/* eslint complexity: ["error", 36]*/

/**
 * Pause reducer
 * @module reducers/pause
 */


import { prefs } from "../utils/prefs";

// Pause state associated with an individual thread.

// Pause state describing all threads.

export function initialPauseState(thread = "UnknownThread") {
  return {
    cx: {
      navigateCounter: 0,
    },
    // This `threadcx` is the `cx` variable we pass around in components and actions.
    // This is pulled via getThreadContext().
    // This stores information about the currently selected thread and its paused state.
    threadcx: {
      navigateCounter: 0,
      thread,
      pauseCounter: 0,
    },
    threads: {},
    skipPausing: prefs.skipPausing,
    mapScopes: prefs.mapScopes,
    shouldPauseOnDebuggerStatement: prefs.pauseOnDebuggerStatement,
    shouldPauseOnExceptions: prefs.pauseOnExceptions,
    shouldPauseOnCaughtExceptions: prefs.pauseOnCaughtExceptions,
  };
}

const resumedPauseState = {
  isPaused: false,
  frames: null,
  framesLoading: false,
  frameScopes: {
    generated: {},
    original: {},
    mappings: {},
  },
  selectedFrameId: null,
  why: null,
  inlinePreview: {},
};

const createInitialPauseState = () => ({
  ...resumedPauseState,
  isWaitingOnBreak: false,
  command: null,
  previousLocation: null,
  expandedScopes: new Set(),
  lastExpandedScopes: [],
  shouldBreakpointsPaneOpenOnPause: false,
});

export function getThreadPauseState(state, thread) {
  // Thread state is lazily initialized so that we don't have to keep track of
  // the current set of worker threads.
  return state.threads[thread] || createInitialPauseState();
}

function update(state = initialPauseState(), action) {
  // All the actions updating pause state must pass an object which designate
  // the related thread.
  const getActionThread = () => {
    const thread =
      action.thread || action.selectedFrame?.thread || action.frame?.thread;
    if (!thread) {
      throw new Error(`Missing thread in action ${action.type}`);
    }
    return thread;
  };

  // `threadState` and `updateThreadState` help easily get and update
  // the pause state for a given thread.
  const threadState = () => {
    return getThreadPauseState(state, getActionThread());
  };
  const updateThreadState = newThreadState => {
    return {
      ...state,
      threads: {
        ...state.threads,
        [getActionThread()]: { ...threadState(), ...newThreadState },
      },
    };
  };

  switch (action.type) {
    case "SELECT_THREAD": {
      // Ignore the action if the related thread doesn't exist.
      if (!state.threads[action.thread]) {
        console.warn(
          `Trying to select a destroyed or non-existent thread '${action.thread}'`
        );
        return state;
      }

      return {
        ...state,
        threadcx: {
          ...state.threadcx,
          thread: action.thread,
          pauseCounter: state.threadcx.pauseCounter + 1,
        },
      };
    }

    case "INSERT_THREAD": {
      // When navigating to a new location,
      // we receive NAVIGATE early, which clear things
      // then we have REMOVE_THREAD of the previous thread.
      // INSERT_THREAD will be the very first event with the new thread actor ID.
      // Automatically select the new top level thread.
      if (action.newThread.isTopLevel) {
        return {
          ...state,
          threadcx: {
            ...state.threadcx,
            thread: action.newThread.actor,
            pauseCounter: state.threadcx.pauseCounter + 1,
          },
          threads: {
            ...state.threads,
            [action.newThread.actor]: createInitialPauseState(),
          },
        };
      }

      return {
        ...state,
        threads: {
          ...state.threads,
          [action.newThread.actor]: createInitialPauseState(),
        },
      };
    }

    case "REMOVE_THREAD": {
      if (
        action.threadActorID in state.threads ||
        action.threadActorID == state.threadcx.thread
      ) {
        // Remove the thread from the cached list
        const threads = { ...state.threads };
        delete threads[action.threadActorID];
        let threadcx = state.threadcx;

        // And also switch to another thread if this was the currently selected one.
        // As we don't store thread objects in this reducer, and only store thread actor IDs,
        // we can't try to find the top level thread. So we pick the first available thread,
        // and hope that's the top level one.
        if (state.threadcx.thread == action.threadActorID) {
          threadcx = {
            ...threadcx,
            thread: Object.keys(threads)[0],
            pauseCounter: threadcx.pauseCounter + 1,
          };
        }
        return {
          ...state,
          threadcx,
          threads,
        };
      }
      break;
    }

    case "PAUSED": {
      const { thread, topFrame, why } = action;
      state = {
        ...state,
        threadcx: {
          ...state.threadcx,
          pauseCounter: state.threadcx.pauseCounter + 1,
          thread,
        },
      };

      return updateThreadState({
        isWaitingOnBreak: false,
        selectedFrameId: topFrame.id,
        isPaused: true,
        // On pause, we only receive the top frame, all subsequent ones
        // will be asynchronously populated via `fetchFrames` action
        frames: [topFrame],
        framesLoading: true,
        frameScopes: { ...resumedPauseState.frameScopes },
        why,
        shouldBreakpointsPaneOpenOnPause: why.type === "breakpoint",
      });
    }

    case "FETCHED_FRAMES": {
      const { frames } = action;

      // We typically receive a PAUSED action before this one,
      // with only the first frame. Here, we avoid replacing it
      // with a copy of it in order to avoid triggerring selectors
      // uncessarily
      // (note that in jest, action's frames might be empty)
      // (and if we resume in between PAUSED and FETCHED_FRAMES
      //  threadState().frames might be null)
      if (threadState().frames) {
        const previousFirstFrame = threadState().frames[0];
        if (previousFirstFrame.id == frames[0]?.id) {
          frames.splice(0, 1, previousFirstFrame);
        }
      }
      return updateThreadState({ frames, framesLoading: false });
    }

    case "MAP_FRAMES": {
      const { selectedFrameId, frames } = action;
      return updateThreadState({ frames, selectedFrameId });
    }

    case "ADD_SCOPES": {
      const { status, value } = action;
      const selectedFrameId = action.selectedFrame.id;

      const generated = {
        ...threadState().frameScopes.generated,
        [selectedFrameId]: {
          pending: status !== "done",
          scope: value,
        },
      };

      return updateThreadState({
        frameScopes: {
          ...threadState().frameScopes,
          generated,
        },
      });
    }

    case "MAP_SCOPES": {
      const { status, value } = action;
      const selectedFrameId = action.selectedFrame.id;

      const original = {
        ...threadState().frameScopes.original,
        [selectedFrameId]: {
          pending: status !== "done",
          scope: value?.scope,
        },
      };

      const mappings = {
        ...threadState().frameScopes.mappings,
        [selectedFrameId]: value?.mappings,
      };

      return updateThreadState({
        frameScopes: {
          ...threadState().frameScopes,
          original,
          mappings,
        },
      });
    }

    case "BREAK_ON_NEXT":
      return updateThreadState({ isWaitingOnBreak: true });

    case "SELECT_FRAME":
      return updateThreadState({ selectedFrameId: action.frame.id });

    case "PAUSE_ON_DEBUGGER_STATEMENT": {
      const { shouldPauseOnDebuggerStatement } = action;

      prefs.pauseOnDebuggerStatement = shouldPauseOnDebuggerStatement;

      return {
        ...state,
        shouldPauseOnDebuggerStatement,
      };
    }

    case "PAUSE_ON_EXCEPTIONS": {
      const { shouldPauseOnExceptions, shouldPauseOnCaughtExceptions } = action;

      prefs.pauseOnExceptions = shouldPauseOnExceptions;
      prefs.pauseOnCaughtExceptions = shouldPauseOnCaughtExceptions;

      // Preserving for the old debugger
      prefs.ignoreCaughtExceptions = !shouldPauseOnCaughtExceptions;

      return {
        ...state,
        shouldPauseOnExceptions,
        shouldPauseOnCaughtExceptions,
      };
    }

    case "COMMAND":
      if (action.status === "start") {
        return updateThreadState({
          ...resumedPauseState,
          command: action.command,
          previousLocation: getPauseLocation(threadState(), action),
        });
      }
      return updateThreadState({ command: null });

    case "RESUME": {
      if (action.thread == state.threadcx.thread) {
        state = {
          ...state,
          threadcx: {
            ...state.threadcx,
            pauseCounter: state.threadcx.pauseCounter + 1,
          },
        };
      }

      return updateThreadState({
        ...resumedPauseState,
        expandedScopes: new Set(),
        lastExpandedScopes: [...threadState().expandedScopes],
        shouldBreakpointsPaneOpenOnPause: false,
      });
    }

    case "EVALUATE_EXPRESSION":
      return updateThreadState({
        command: action.status === "start" ? "expression" : null,
      });

    case "NAVIGATE": {
      const navigateCounter = state.cx.navigateCounter + 1;
      return {
        ...state,
        cx: {
          navigateCounter,
        },
        threadcx: {
          navigateCounter,
          thread: action.mainThread.actor,
          pauseCounter: 0,
        },
        threads: {
          ...state.threads,
          [action.mainThread.actor]: {
            ...getThreadPauseState(state, action.mainThread.actor),
            ...resumedPauseState,
          },
        },
      };
    }

    case "TOGGLE_SKIP_PAUSING": {
      const { skipPausing } = action;
      prefs.skipPausing = skipPausing;

      return { ...state, skipPausing };
    }

    case "TOGGLE_MAP_SCOPES": {
      const { mapScopes } = action;
      prefs.mapScopes = mapScopes;
      return { ...state, mapScopes };
    }

    case "SET_EXPANDED_SCOPE": {
      const { path, expanded } = action;
      const expandedScopes = new Set(threadState().expandedScopes);
      if (expanded) {
        expandedScopes.add(path);
      } else {
        expandedScopes.delete(path);
      }
      return updateThreadState({ expandedScopes });
    }

    case "ADD_INLINE_PREVIEW": {
      const { selectedFrame, previews } = action;
      const selectedFrameId = selectedFrame.id;

      return updateThreadState({
        inlinePreview: {
          ...threadState().inlinePreview,
          [selectedFrameId]: previews,
        },
      });
    }

    case "RESET_BREAKPOINTS_PANE_STATE": {
      return updateThreadState({
        ...threadState(),
        shouldBreakpointsPaneOpenOnPause: false,
      });
    }
  }

  return state;
}

function getPauseLocation(state, action) {
  const { frames, previousLocation } = state;

  // NOTE: We store the previous location so that we ensure that we
  // do not stop at the same location twice when we step over.
  if (action.command !== "stepOver") {
    return null;
  }

  const frame = frames?.[0];
  if (!frame) {
    return previousLocation;
  }

  return {
    location: frame.location,
    generatedLocation: frame.generatedLocation,
  };
}

export default update;

87%


¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.