breakpoints.js (4730B)
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 /** 6 * Breakpoints reducer 7 * 8 * @module reducers/breakpoints 9 */ 10 11 import { createBreakpoint } from "../client/firefox/create"; 12 import { makeBreakpointId } from "../utils/breakpoint/index"; 13 14 export function initialBreakpointsState(xhrBreakpoints = []) { 15 return { 16 breakpoints: {}, 17 xhrBreakpoints, 18 }; 19 } 20 21 function update(state = initialBreakpointsState(), action) { 22 switch (action.type) { 23 case "SET_BREAKPOINT": { 24 if (action.status === "start") { 25 return setBreakpoint(state, action); 26 } 27 return state; 28 } 29 30 case "REMOVE_BREAKPOINT": { 31 if (action.status === "start") { 32 return removeBreakpoint(state, action); 33 } 34 return state; 35 } 36 37 case "CLEAR_BREAKPOINTS": { 38 return { ...state, breakpoints: {} }; 39 } 40 41 case "REMOVE_SOURCES": { 42 return removeBreakpointsForSources(state, action.sources); 43 } 44 45 case "SET_XHR_BREAKPOINT": { 46 return addXHRBreakpoint(state, action); 47 } 48 49 case "REMOVE_XHR_BREAKPOINT": { 50 return removeXHRBreakpoint(state, action); 51 } 52 53 case "UPDATE_XHR_BREAKPOINT": { 54 return updateXHRBreakpoint(state, action); 55 } 56 57 case "ENABLE_XHR_BREAKPOINT": { 58 return updateXHRBreakpoint(state, action); 59 } 60 61 case "DISABLE_XHR_BREAKPOINT": { 62 return updateXHRBreakpoint(state, action); 63 } 64 case "CLEAR_XHR_BREAKPOINTS": { 65 if (action.status == "start") { 66 return state; 67 } 68 return { ...state, xhrBreakpoints: [] }; 69 } 70 } 71 72 return state; 73 } 74 75 function addXHRBreakpoint(state, action) { 76 const { xhrBreakpoints } = state; 77 const { breakpoint } = action; 78 const { path, method } = breakpoint; 79 80 const existingBreakpointIndex = state.xhrBreakpoints.findIndex( 81 bp => bp.path === path && bp.method === method 82 ); 83 84 if (existingBreakpointIndex === -1) { 85 return { 86 ...state, 87 xhrBreakpoints: [...xhrBreakpoints, breakpoint], 88 }; 89 } else if (xhrBreakpoints[existingBreakpointIndex] !== breakpoint) { 90 const newXhrBreakpoints = [...xhrBreakpoints]; 91 newXhrBreakpoints[existingBreakpointIndex] = breakpoint; 92 return { 93 ...state, 94 xhrBreakpoints: newXhrBreakpoints, 95 }; 96 } 97 98 return state; 99 } 100 101 function removeXHRBreakpoint(state, action) { 102 const { breakpoint } = action; 103 const { xhrBreakpoints } = state; 104 105 if (action.status === "start") { 106 return state; 107 } 108 109 return { 110 ...state, 111 xhrBreakpoints: xhrBreakpoints.filter( 112 bp => bp.path !== breakpoint.path || bp.method !== breakpoint.method 113 ), 114 }; 115 } 116 117 function updateXHRBreakpoint(state, action) { 118 const { breakpoint, index } = action; 119 const { xhrBreakpoints } = state; 120 const newXhrBreakpoints = [...xhrBreakpoints]; 121 newXhrBreakpoints[index] = breakpoint; 122 return { 123 ...state, 124 xhrBreakpoints: newXhrBreakpoints, 125 }; 126 } 127 128 function setBreakpoint(state, { breakpoint }) { 129 const id = makeBreakpointId(breakpoint.location); 130 const breakpoints = { ...state.breakpoints, [id]: breakpoint }; 131 return { ...state, breakpoints }; 132 } 133 134 function removeBreakpoint(state, { breakpoint }) { 135 const id = makeBreakpointId(breakpoint.location); 136 const breakpoints = { ...state.breakpoints }; 137 delete breakpoints[id]; 138 return { ...state, breakpoints }; 139 } 140 141 function removeBreakpointsForSources(state, sources) { 142 if (!sources.length) { 143 return state; 144 } 145 const remainingBreakpoints = {}; 146 let changed = false; 147 for (const [id, breakpoint] of Object.entries(state.breakpoints)) { 148 if (!sources.includes(breakpoint.location.source)) { 149 remainingBreakpoints[id] = breakpoint; 150 } else if ( 151 breakpoint.location.source.isOriginal && 152 !sources.includes(breakpoint.generatedLocation.source) 153 ) { 154 // If we are removing an original source (which can be a pretty printed source), without removing its related generated/bundle/minimized source, 155 // the breakpoint is kept and replaced with an identical one but only against the generated source. 156 // We don't have to map the location, but instead only strip the references to original location. 157 const generatedId = makeBreakpointId(breakpoint.generatedLocation); 158 remainingBreakpoints[generatedId] = createBreakpoint({ 159 ...breakpoint, 160 id: generatedId, 161 location: breakpoint.generatedLocation, 162 originalText: breakpoint.text, 163 }); 164 changed = true; 165 } else { 166 changed = true; 167 } 168 } 169 return changed ? { ...state, breakpoints: remainingBreakpoints } : state; 170 } 171 172 export default update;