paused.js (3346B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 import { 6 getHiddenBreakpoint, 7 isEvaluatingExpression, 8 getSelectedFrame, 9 } from "../../selectors/index"; 10 11 import { mapFrames, fetchFrames, updateAllFrameDisplayNames } from "./index"; 12 import { removeBreakpoint } from "../breakpoints/index"; 13 import { evaluateExpressions } from "../expressions"; 14 import { selectLocation } from "../sources/index"; 15 import { validateSelectedFrame } from "../../utils/context"; 16 17 import { fetchScopes } from "./fetchScopes"; 18 19 /** 20 * Debugger has just paused 21 * 22 * @param {object} pauseInfo 23 * See `createPause` method. 24 */ 25 export function paused(pauseInfo) { 26 return async function ({ dispatch, getState }) { 27 const { thread, frame, why } = pauseInfo; 28 29 dispatch({ type: "PAUSED", thread, why, topFrame: frame }); 30 31 // When we use "continue to here" feature we register an "hidden" breakpoint 32 // that should be removed on the next paused, even if we didn't hit it and 33 // paused for any other reason. 34 const hiddenBreakpoint = getHiddenBreakpoint(getState()); 35 if (hiddenBreakpoint) { 36 dispatch(removeBreakpoint(hiddenBreakpoint)); 37 } 38 39 // The THREAD_STATE's "paused" resource only passes the top level stack frame, 40 // we dispatch the PAUSED action with it so that we can right away 41 // display it and update the UI to be paused. 42 // But we then fetch all the other frames: 43 await dispatch(fetchFrames(thread)); 44 // And map them to original source locations. 45 // Note that this will wait for all related original sources to be loaded in the reducers. 46 // So this step may pause for a little while. 47 await dispatch(mapFrames(thread)); 48 49 // If we paused on a particular frame, automatically select the related source 50 // and highlight the paused line 51 const selectedFrame = getSelectedFrame(getState(), thread); 52 if (selectedFrame) { 53 await dispatch(selectLocation(selectedFrame.location)); 54 // We might have resumed while opening the location. 55 // Prevent further computation if this happens. 56 validateSelectedFrame(getState(), selectedFrame); 57 58 // Update the display names of the original frames 59 // Note that this depends on the source editor's `getClosestFunctionName`. 60 // so it needs to be called after the source is selected (to make sure the source editor is fully initialized). 61 // This can happen when paused on initial load. 62 await dispatch(updateAllFrameDisplayNames(thread)); 63 64 // Fetch the previews for variables visible in the currently selected paused stackframe 65 await dispatch(fetchScopes()); 66 // We might have resumed while fetching the scopes 67 // Prevent further computation if this happens. 68 validateSelectedFrame(getState(), selectedFrame); 69 70 // Run after fetching scoping data so that it may make use of the sourcemap 71 // expression mappings for local variables. 72 const atException = why.type == "exception"; 73 if (!atException || !isEvaluatingExpression(getState(), thread)) { 74 await dispatch(evaluateExpressions(selectedFrame)); 75 validateSelectedFrame(getState(), selectedFrame); 76 } 77 } 78 }; 79 }