main.js (5324B)
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 * as firefox from "./client/firefox"; 6 7 import { asyncStore, verifyPrefSchema, prefs } from "./utils/prefs"; 8 import { setupHelper } from "./utils/dbg"; 9 import { setToolboxTelemetry } from "./utils/telemetry"; 10 11 import { 12 bootstrapApp, 13 bootstrapStore, 14 bootstrapWorkers, 15 unmountRoot, 16 teardownWorkers, 17 } from "./utils/bootstrap"; 18 19 import { initialTabState } from "./reducers/tabs"; 20 import { initialBreakpointsState } from "./reducers/breakpoints"; 21 import { initialSourcesState } from "./reducers/sources"; 22 import { initialSourcesTreeState } from "./reducers/sources-tree"; 23 import { initialUIState } from "./reducers/ui"; 24 import { initialSourceBlackBoxState } from "./reducers/source-blackbox"; 25 import { initialEventListenerState } from "./reducers/event-listeners"; 26 27 const { 28 sanitizeBreakpoints, 29 } = require("resource://devtools/client/shared/thread-utils.js"); 30 const { 31 START_IGNORE_ACTION, 32 } = require("resource://devtools/client/shared/redux/middleware/ignore.js"); 33 34 let gStore; 35 36 async function syncBreakpoints() { 37 const breakpoints = await asyncStore.pendingBreakpoints; 38 const breakpointValues = Object.values(sanitizeBreakpoints(breakpoints)); 39 return Promise.all( 40 breakpointValues.map(({ disabled, options, generatedLocation }) => { 41 if (disabled) { 42 return Promise.resolve(); 43 } 44 // Set the breakpoint on the server using the generated location as generated 45 // sources are known on server, not original sources. 46 return firefox.clientCommands.setBreakpoint(generatedLocation, options); 47 }) 48 ); 49 } 50 51 async function syncXHRBreakpoints() { 52 const breakpoints = await asyncStore.xhrBreakpoints; 53 return Promise.all( 54 breakpoints.map(({ path, method, disabled }) => { 55 if (!disabled) { 56 firefox.clientCommands.setXHRBreakpoint(path, method); 57 } 58 }) 59 ); 60 } 61 62 function setPauseOnDebuggerStatement() { 63 const { pauseOnDebuggerStatement } = prefs; 64 return firefox.clientCommands.pauseOnDebuggerStatement( 65 pauseOnDebuggerStatement 66 ); 67 } 68 69 function setPauseOnExceptions() { 70 const { pauseOnExceptions, pauseOnCaughtExceptions } = prefs; 71 return firefox.clientCommands.pauseOnExceptions( 72 pauseOnExceptions, 73 pauseOnCaughtExceptions 74 ); 75 } 76 77 async function loadInitialState(commands) { 78 const pendingBreakpoints = sanitizeBreakpoints( 79 await asyncStore.pendingBreakpoints 80 ); 81 const tabs = initialTabState({ 82 urls: await asyncStore.openedURLs, 83 prettyPrintedURLs: new Set(await asyncStore.prettyPrintedURLs), 84 }); 85 const xhrBreakpoints = await asyncStore.xhrBreakpoints; 86 const blackboxedRanges = await asyncStore.blackboxedRanges; 87 const eventListenerBreakpoints = await asyncStore.eventListenerBreakpoints; 88 if (eventListenerBreakpoints && !eventListenerBreakpoints.byPanel) { 89 // Firefox 132 changed the layout of the event listener data to support both breakpoints and tracer 90 eventListenerBreakpoints.byPanel = initialEventListenerState().byPanel; 91 } 92 93 const breakpoints = initialBreakpointsState(xhrBreakpoints); 94 const sourceBlackBox = initialSourceBlackBoxState({ blackboxedRanges }); 95 const sources = initialSourcesState(); 96 const sourcesTree = initialSourcesTreeState({ 97 mainThreadProjectDirectoryRoots: await asyncStore.directoryRoots, 98 isWebExtension: commands.descriptorFront.isWebExtensionDescriptor, 99 }); 100 const ui = initialUIState(); 101 102 return { 103 pendingBreakpoints, 104 tabs, 105 breakpoints, 106 eventListenerBreakpoints, 107 sources, 108 sourcesTree, 109 sourceBlackBox, 110 ui, 111 }; 112 } 113 114 export async function bootstrap({ 115 commands, 116 fluentBundles, 117 resourceCommand, 118 workers: panelWorkers, 119 panel, 120 }) { 121 verifyPrefSchema(); 122 123 // Set telemetry at the very beginning as some actions fired from this function might 124 // record events. 125 setToolboxTelemetry(panel.toolbox.telemetry); 126 127 const initialState = await loadInitialState(commands); 128 const workers = bootstrapWorkers(panelWorkers); 129 130 const { store, actions, selectors } = bootstrapStore( 131 firefox.clientCommands, 132 workers, 133 panel, 134 initialState 135 ); 136 gStore = store; 137 138 const connected = firefox.onConnect( 139 commands, 140 resourceCommand, 141 actions, 142 store 143 ); 144 145 await syncBreakpoints(); 146 await syncXHRBreakpoints(); 147 await setPauseOnDebuggerStatement(); 148 await setPauseOnExceptions(); 149 150 setupHelper({ 151 store, 152 actions, 153 selectors, 154 workers, 155 targetCommand: commands.targetCommand, 156 client: firefox.clientCommands, 157 }); 158 159 bootstrapApp(store, panel.getToolboxStore(), { 160 fluentBundles, 161 toolboxDoc: panel.panelWin.parent.document, 162 }); 163 await connected; 164 return { store, actions, selectors, client: firefox.clientCommands }; 165 } 166 167 export async function destroy() { 168 // Instruct redux to start ignoring any further action 169 if (gStore) { 170 gStore.dispatch(START_IGNORE_ACTION); 171 gStore = null; 172 } 173 174 // Unregister all listeners set on DevTools RDP client 175 firefox.onDisconnect(); 176 177 // Unmount all React components 178 unmountRoot(); 179 180 // Unregister and cleanup everything about parser, pretty print and source map workers 181 teardownWorkers(); 182 }