breakableLines.js (3844B)
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 getBreakableLines, 7 getSourceActorBreakableLines, 8 getSourceActorsForSource, 9 } from "../../selectors/index"; 10 import { setBreakpointPositions } from "../breakpoints/breakpointPositions"; 11 12 function calculateBreakableLines(positions) { 13 const lines = []; 14 for (const line in positions) { 15 if (positions[line].length) { 16 lines.push(Number(line)); 17 } 18 } 19 20 return lines; 21 } 22 23 /** 24 * Ensure that breakable lines for a given source are fetched. 25 * 26 * This method is memoized, so that if concurrent calls are dispatched, 27 * it will return the first async promise processing the breakable lines. 28 * 29 * @param Object location 30 */ 31 export function setBreakableLines(location) { 32 return async ({ getState, dispatch, client }) => { 33 if (location.source.isOriginal) { 34 // Original sources have a dedicated codepath to fetch locations 35 // from the generated source actor and then map them to "positions" 36 // in the original source. 37 let promise = getBreakableLines(getState(), location.source.id); 38 if (promise) { 39 return promise; 40 } 41 promise = (async () => { 42 const positions = await dispatch(setBreakpointPositions(location)); 43 return calculateBreakableLines(positions); 44 })(); 45 dispatch({ 46 type: "SET_ORIGINAL_BREAKABLE_LINES", 47 source: location.source, 48 promise, 49 }); 50 const breakableLines = await promise; 51 dispatch({ 52 type: "SET_ORIGINAL_BREAKABLE_LINES", 53 source: location.source, 54 breakableLines, 55 }); 56 } else if (location.source.isHTML) { 57 // For a given HTML page, we get a unique Source (for the html page), 58 // but many Source Actors (one per inline <script> tag and inlined event listeners). 59 // So that we have to get the breakable lines for each of them. 60 // 61 // Whereas, for regular source (with a url), when we have more than one source actor, 62 // it means that we evaled the source more than once. 63 const sourceActors = getSourceActorsForSource( 64 getState(), 65 location.source.id 66 ); 67 if (!sourceActors) { 68 return null; 69 } 70 for (const sourceActor of sourceActors) { 71 let promise = getSourceActorBreakableLines(getState(), sourceActor.id); 72 if (promise) { 73 await promise; 74 } else { 75 promise = client.getSourceActorBreakableLines(sourceActor); 76 dispatch({ 77 type: "SET_SOURCE_ACTOR_BREAKABLE_LINES", 78 sourceActor, 79 promise, 80 }); 81 const breakableLines = await promise; 82 dispatch({ 83 type: "SET_SOURCE_ACTOR_BREAKABLE_LINES", 84 sourceActor, 85 breakableLines, 86 }); 87 } 88 } 89 } else { 90 // Here is the handling of regular non-source-mapped non-html sources. 91 // We do fetch the breakable position for the specific source actor passed as argument. 92 // In case there is many source actors for the same URL, it will only affect one instance. 93 let promise = getSourceActorBreakableLines( 94 getState(), 95 location.sourceActor.id 96 ); 97 if (promise) { 98 return promise; 99 } 100 promise = client.getSourceActorBreakableLines(location.sourceActor); 101 dispatch({ 102 type: "SET_SOURCE_ACTOR_BREAKABLE_LINES", 103 sourceActor: location.sourceActor, 104 promise, 105 }); 106 const breakableLines = await promise; 107 dispatch({ 108 type: "SET_SOURCE_ACTOR_BREAKABLE_LINES", 109 sourceActor: location.sourceActor, 110 breakableLines, 111 }); 112 } 113 return null; 114 }; 115 }