tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

visibleColumnBreakpoints.js (5342B)


      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 { createSelector } from "devtools/client/shared/vendor/reselect";
      6 
      7 import {
      8  getViewport,
      9  getSelectedSource,
     10  getSelectedSourceTextContent,
     11  getBreakpointPositionsForSource,
     12 } from "./index";
     13 import { getVisibleBreakpoints } from "./visibleBreakpoints";
     14 import { getSelectedLocation } from "../utils/selected-location";
     15 import { sortSelectedLocations } from "../utils/location";
     16 import { getLineText } from "../utils/source";
     17 
     18 function contains(location, range) {
     19  // If the location is within the viewport lines or if the location is on the first or last line
     20  // and the columns are within the start or end line content.
     21  return (
     22    (location.line > range.start.line && location.line < range.end.line) ||
     23    (location.line == range.start.line &&
     24      location.column >= range.start.column) ||
     25    (location.line == range.end.line && location.column <= range.end.column)
     26  );
     27 }
     28 
     29 function convertToList(breakpointPositions) {
     30  return [].concat(...Object.values(breakpointPositions));
     31 }
     32 
     33 /**
     34 * Retrieve the list of column breakpoints to be displayed.
     35 * This ignores lines without any breakpoint, but also lines with a single possible breakpoint.
     36 * So that we only return breakpoints where there is at least two possible breakpoint on a given line.
     37 * Also, this only consider lines currently visible in CodeMirror editor.
     38 *
     39 * This method returns an array whose elements are objects having two attributes:
     40 *  - breakpoint: A breakpoint object refering to a precise column location
     41 *  - location: The location object in an active source where the breakpoint location matched.
     42 *              This location may be the generated or original source based on the currently selected source type.
     43 *
     44 * See `visibleColumnBreakpoints()` for the definition of arguments.
     45 */
     46 export function getColumnBreakpoints(
     47  positions,
     48  breakpoints,
     49  viewport,
     50  selectedSource,
     51  selectedSourceTextContent
     52 ) {
     53  if (!positions || !selectedSource || !breakpoints.length || !viewport) {
     54    return [];
     55  }
     56 
     57  const breakpointsPerLine = new Map();
     58  for (const breakpoint of breakpoints) {
     59    if (breakpoint.options.hidden) {
     60      continue;
     61    }
     62    const location = getSelectedLocation(breakpoint, selectedSource);
     63    const { line } = location;
     64    let breakpointsPerColumn = breakpointsPerLine.get(line);
     65    if (!breakpointsPerColumn) {
     66      breakpointsPerColumn = new Map();
     67      breakpointsPerLine.set(line, breakpointsPerColumn);
     68    }
     69    breakpointsPerColumn.set(location.column, breakpoint);
     70  }
     71 
     72  const columnBreakpoints = [];
     73  for (const keyLine in positions) {
     74    const positionsPerLine = positions[keyLine];
     75    // Only consider positions where there is more than one breakable position per line.
     76    // When there is only one breakpoint, this isn't a column breakpoint.
     77    if (positionsPerLine.length <= 1) {
     78      continue;
     79    }
     80    for (const breakpointPosition of positionsPerLine) {
     81      // For minified sources we want to limit the amount of displayed column breakpoints
     82      // This is nice to have for perf reasons
     83      if (columnBreakpoints.length >= 100) {
     84        continue;
     85      }
     86 
     87      const location = getSelectedLocation(breakpointPosition, selectedSource);
     88      // Only consider positions visible in the current CodeMirror viewport
     89      if (!contains(location, viewport)) {
     90        continue;
     91      }
     92 
     93      const { line } = location;
     94      // Ignore any further computation if there is no breakpoint on that line.
     95      const breakpointsPerColumn = breakpointsPerLine.get(line);
     96      if (!breakpointsPerColumn) {
     97        continue;
     98      }
     99 
    100      // Filters out breakpoints to the right of the line. (bug 1552039)
    101      // XXX Not really clear why we get such positions??
    102      const { column } = location;
    103      if (column) {
    104        const lineText = getLineText(
    105          selectedSource.id,
    106          selectedSourceTextContent,
    107          line
    108        );
    109        if (column > lineText.length) {
    110          continue;
    111        }
    112      }
    113 
    114      // Finally, return the expected format output for this selector.
    115      // Location of each column breakpoint + a reference to the breakpoint object (if one is set on that column, it can be null).
    116      const breakpoint = breakpointsPerColumn.get(column);
    117 
    118      columnBreakpoints.push({
    119        location,
    120        breakpoint,
    121      });
    122    }
    123  }
    124 
    125  return columnBreakpoints;
    126 }
    127 
    128 function getVisibleBreakpointPositions(state) {
    129  const source = getSelectedSource(state);
    130  if (!source) {
    131    return null;
    132  }
    133  return getBreakpointPositionsForSource(state, source.id);
    134 }
    135 
    136 export const visibleColumnBreakpoints = createSelector(
    137  getVisibleBreakpointPositions,
    138  getVisibleBreakpoints,
    139  getViewport,
    140  getSelectedSource,
    141  getSelectedSourceTextContent,
    142  getColumnBreakpoints
    143 );
    144 
    145 export function getFirstBreakpointPosition(state, location) {
    146  const positions = getBreakpointPositionsForSource(state, location.source.id);
    147  if (!positions) {
    148    return null;
    149  }
    150 
    151  return sortSelectedLocations(convertToList(positions), location.source).find(
    152    position =>
    153      getSelectedLocation(position, location.source).line == location.line
    154  );
    155 }