tor-browser

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

getApplicableBindingsForOriginalPosition.js (3458B)


      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 { positionCmp } from "./positionCmp";
      6 import { filterSortedArray } from "./filtering";
      7 import { mappingContains } from "./mappingContains";
      8 import { getGeneratedLocation } from "../../source-maps";
      9 
     10 export async function originalRangeStartsInside({ start, end }, thunkArgs) {
     11  const endPosition = await getGeneratedLocation(end, thunkArgs);
     12  const startPosition = await getGeneratedLocation(start, thunkArgs);
     13 
     14  // If the start and end positions collapse into eachother, it means that
     15  // the range in the original content didn't _start_ at the start position.
     16  // Since this likely means that the range doesn't logically apply to this
     17  // binding location, we skip it.
     18  return positionCmp(startPosition, endPosition) !== 0;
     19 }
     20 
     21 export async function getApplicableBindingsForOriginalPosition(
     22  generatedAstBindings,
     23  source,
     24  { start, end },
     25  bindingType,
     26  locationType,
     27  thunkArgs
     28 ) {
     29  const { sourceMapLoader } = thunkArgs;
     30  const ranges = await sourceMapLoader.getGeneratedRanges(start);
     31 
     32  const resultRanges = ranges.map(mapRange => ({
     33    start: {
     34      line: mapRange.line,
     35      column: mapRange.columnStart,
     36    },
     37    end: {
     38      line: mapRange.line,
     39      // SourceMapConsumer's 'lastColumn' is inclusive, so we add 1 to make
     40      // it exclusive like all other locations.
     41      column: mapRange.columnEnd + 1,
     42    },
     43  }));
     44 
     45  // When searching for imports, we expand the range to up to the next available
     46  // mapping to allow for import declarations that are composed of multiple
     47  // variable statements, where the later ones are entirely unmapped.
     48  // Babel 6 produces imports in this style, e.g.
     49  //
     50  // var _mod = require("mod"); // mapped from import statement
     51  // var _mod2 = interop(_mod); // entirely unmapped
     52  if (bindingType === "import" && locationType !== "ref") {
     53    const endPosition = await getGeneratedLocation(end, thunkArgs);
     54    const startPosition = await getGeneratedLocation(start, thunkArgs);
     55 
     56    for (const range of resultRanges) {
     57      if (
     58        mappingContains(range, { start: startPosition, end: startPosition }) &&
     59        positionCmp(range.end, endPosition) < 0
     60      ) {
     61        range.end = {
     62          line: endPosition.line,
     63          column: endPosition.column,
     64        };
     65        break;
     66      }
     67    }
     68  }
     69 
     70  return filterApplicableBindings(generatedAstBindings, resultRanges);
     71 }
     72 
     73 function filterApplicableBindings(bindings, ranges) {
     74  const result = [];
     75  for (const range of ranges) {
     76    // Any binding overlapping a part of the mapping range.
     77    const filteredBindings = filterSortedArray(bindings, binding => {
     78      if (positionCmp(binding.loc.end, range.start) <= 0) {
     79        return -1;
     80      }
     81      if (positionCmp(binding.loc.start, range.end) >= 0) {
     82        return 1;
     83      }
     84 
     85      return 0;
     86    });
     87 
     88    let firstInRange = true;
     89    let firstOnLine = true;
     90    let line = -1;
     91 
     92    for (const binding of filteredBindings) {
     93      if (binding.loc.start.line === line) {
     94        firstOnLine = false;
     95      } else {
     96        line = binding.loc.start.line;
     97        firstOnLine = true;
     98      }
     99 
    100      result.push({
    101        binding,
    102        range,
    103        firstOnLine,
    104        firstInRange,
    105      });
    106 
    107      firstInRange = false;
    108    }
    109  }
    110 
    111  return result;
    112 }