CoolFace
Apppublic

Pinsave/counterstrike

sourceHugging Faceupdated 3mo agoView on Hugging Face
1likes
source-map-consumer.js1189 linesDownload Raw Back to lib
1/* -*- Mode: js; js-indent-level: 2; -*- */2/*3 * Copyright 2011 Mozilla Foundation and contributors4 * Licensed under the New BSD license. See LICENSE or:5 * http://opensource.org/licenses/BSD-3-Clause6 */7 8var util = require('./util');9var binarySearch = require('./binary-search');10var ArraySet = require('./array-set').ArraySet;11var base64VLQ = require('./base64-vlq');12var quickSort = require('./quick-sort').quickSort;13 14function SourceMapConsumer(aSourceMap, aSourceMapURL) {15  var sourceMap = aSourceMap;16  if (typeof aSourceMap === 'string') {17    sourceMap = util.parseSourceMapInput(aSourceMap);18  }19 20  return sourceMap.sections != null21    ? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL)22    : new BasicSourceMapConsumer(sourceMap, aSourceMapURL);23}24 25SourceMapConsumer.fromSourceMap = function(aSourceMap, aSourceMapURL) {26  return BasicSourceMapConsumer.fromSourceMap(aSourceMap, aSourceMapURL);27}28 29/**30 * The version of the source mapping spec that we are consuming.31 */32SourceMapConsumer.prototype._version = 3;33 34// `__generatedMappings` and `__originalMappings` are arrays that hold the35// parsed mapping coordinates from the source map's "mappings" attribute. They36// are lazily instantiated, accessed via the `_generatedMappings` and37// `_originalMappings` getters respectively, and we only parse the mappings38// and create these arrays once queried for a source location. We jump through39// these hoops because there can be many thousands of mappings, and parsing40// them is expensive, so we only want to do it if we must.41//42// Each object in the arrays is of the form:43//44//     {45//       generatedLine: The line number in the generated code,46//       generatedColumn: The column number in the generated code,47//       source: The path to the original source file that generated this48//               chunk of code,49//       originalLine: The line number in the original source that50//                     corresponds to this chunk of generated code,51//       originalColumn: The column number in the original source that52//                       corresponds to this chunk of generated code,53//       name: The name of the original symbol which generated this chunk of54//             code.55//     }56//57// All properties except for `generatedLine` and `generatedColumn` can be58// `null`.59//60// `_generatedMappings` is ordered by the generated positions.61//62// `_originalMappings` is ordered by the original positions.63 64SourceMapConsumer.prototype.__generatedMappings = null;65Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {66  configurable: true,67  enumerable: true,68  get: function () {69    if (!this.__generatedMappings) {70      this._parseMappings(this._mappings, this.sourceRoot);71    }72 73    return this.__generatedMappings;74  }75});76 77SourceMapConsumer.prototype.__originalMappings = null;78Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {79  configurable: true,80  enumerable: true,81  get: function () {82    if (!this.__originalMappings) {83      this._parseMappings(this._mappings, this.sourceRoot);84    }85 86    return this.__originalMappings;87  }88});89 90SourceMapConsumer.prototype._charIsMappingSeparator =91  function SourceMapConsumer_charIsMappingSeparator(aStr, index) {92    var c = aStr.charAt(index);93    return c === ";" || c === ",";94  };95 96/**97 * Parse the mappings in a string in to a data structure which we can easily98 * query (the ordered arrays in the `this.__generatedMappings` and99 * `this.__originalMappings` properties).100 */101SourceMapConsumer.prototype._parseMappings =102  function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {103    throw new Error("Subclasses must implement _parseMappings");104  };105 106SourceMapConsumer.GENERATED_ORDER = 1;107SourceMapConsumer.ORIGINAL_ORDER = 2;108 109SourceMapConsumer.GREATEST_LOWER_BOUND = 1;110SourceMapConsumer.LEAST_UPPER_BOUND = 2;111 112/**113 * Iterate over each mapping between an original source/line/column and a114 * generated line/column in this source map.115 *116 * @param Function aCallback117 *        The function that is called with each mapping.118 * @param Object aContext119 *        Optional. If specified, this object will be the value of `this` every120 *        time that `aCallback` is called.121 * @param aOrder122 *        Either `SourceMapConsumer.GENERATED_ORDER` or123 *        `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to124 *        iterate over the mappings sorted by the generated file's line/column125 *        order or the original's source/line/column order, respectively. Defaults to126 *        `SourceMapConsumer.GENERATED_ORDER`.127 */128SourceMapConsumer.prototype.eachMapping =129  function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {130    var context = aContext || null;131    var order = aOrder || SourceMapConsumer.GENERATED_ORDER;132 133    var mappings;134    switch (order) {135    case SourceMapConsumer.GENERATED_ORDER:136      mappings = this._generatedMappings;137      break;138    case SourceMapConsumer.ORIGINAL_ORDER:139      mappings = this._originalMappings;140      break;141    default:142      throw new Error("Unknown order of iteration.");143    }144 145    var sourceRoot = this.sourceRoot;146    var boundCallback = aCallback.bind(context);147    var names = this._names;148    var sources = this._sources;149    var sourceMapURL = this._sourceMapURL;150 151    for (var i = 0, n = mappings.length; i < n; i++) {152      var mapping = mappings[i];153      var source = mapping.source === null ? null : sources.at(mapping.source);154      if(source !== null) {155        source = util.computeSourceURL(sourceRoot, source, sourceMapURL);156      }157      boundCallback({158        source: source,159        generatedLine: mapping.generatedLine,160        generatedColumn: mapping.generatedColumn,161        originalLine: mapping.originalLine,162        originalColumn: mapping.originalColumn,163        name: mapping.name === null ? null : names.at(mapping.name)164      });165    }166  };167 168/**169 * Returns all generated line and column information for the original source,170 * line, and column provided. If no column is provided, returns all mappings171 * corresponding to a either the line we are searching for or the next172 * closest line that has any mappings. Otherwise, returns all mappings173 * corresponding to the given line and either the column we are searching for174 * or the next closest column that has any offsets.175 *176 * The only argument is an object with the following properties:177 *178 *   - source: The filename of the original source.179 *   - line: The line number in the original source.  The line number is 1-based.180 *   - column: Optional. the column number in the original source.181 *    The column number is 0-based.182 *183 * and an array of objects is returned, each with the following properties:184 *185 *   - line: The line number in the generated source, or null.  The186 *    line number is 1-based.187 *   - column: The column number in the generated source, or null.188 *    The column number is 0-based.189 */190SourceMapConsumer.prototype.allGeneratedPositionsFor =191  function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {192    var line = util.getArg(aArgs, 'line');193 194    // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping195    // returns the index of the closest mapping less than the needle. By196    // setting needle.originalColumn to 0, we thus find the last mapping for197    // the given line, provided such a mapping exists.198    var needle = {199      source: util.getArg(aArgs, 'source'),200      originalLine: line,201      originalColumn: util.getArg(aArgs, 'column', 0)202    };203 204    needle.source = this._findSourceIndex(needle.source);205    if (needle.source < 0) {206      return [];207    }208 209    var mappings = [];210 211    var index = this._findMapping(needle,212                                  this._originalMappings,213                                  "originalLine",214                                  "originalColumn",215                                  util.compareByOriginalPositions,216                                  binarySearch.LEAST_UPPER_BOUND);217    if (index >= 0) {218      var mapping = this._originalMappings[index];219 220      if (aArgs.column === undefined) {221        var originalLine = mapping.originalLine;222 223        // Iterate until either we run out of mappings, or we run into224        // a mapping for a different line than the one we found. Since225        // mappings are sorted, this is guaranteed to find all mappings for226        // the line we found.227        while (mapping && mapping.originalLine === originalLine) {228          mappings.push({229            line: util.getArg(mapping, 'generatedLine', null),230            column: util.getArg(mapping, 'generatedColumn', null),231            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)232          });233 234          mapping = this._originalMappings[++index];235        }236      } else {237        var originalColumn = mapping.originalColumn;238 239        // Iterate until either we run out of mappings, or we run into240        // a mapping for a different line than the one we were searching for.241        // Since mappings are sorted, this is guaranteed to find all mappings for242        // the line we are searching for.243        while (mapping &&244               mapping.originalLine === line &&245               mapping.originalColumn == originalColumn) {246          mappings.push({247            line: util.getArg(mapping, 'generatedLine', null),248            column: util.getArg(mapping, 'generatedColumn', null),249            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)250          });251 252          mapping = this._originalMappings[++index];253        }254      }255    }256 257    return mappings;258  };259 260exports.SourceMapConsumer = SourceMapConsumer;261 262/**263 * A BasicSourceMapConsumer instance represents a parsed source map which we can264 * query for information about the original file positions by giving it a file265 * position in the generated source.266 *267 * The first parameter is the raw source map (either as a JSON string, or268 * already parsed to an object). According to the spec, source maps have the269 * following attributes:270 *271 *   - version: Which version of the source map spec this map is following.272 *   - sources: An array of URLs to the original source files.273 *   - names: An array of identifiers which can be referrenced by individual mappings.274 *   - sourceRoot: Optional. The URL root from which all sources are relative.275 *   - sourcesContent: Optional. An array of contents of the original source files.276 *   - mappings: A string of base64 VLQs which contain the actual mappings.277 *   - file: Optional. The generated file this source map is associated with.278 *279 * Here is an example source map, taken from the source map spec[0]:280 *281 *     {282 *       version : 3,283 *       file: "out.js",284 *       sourceRoot : "",285 *       sources: ["foo.js", "bar.js"],286 *       names: ["src", "maps", "are", "fun"],287 *       mappings: "AA,AB;;ABCDE;"288 *     }289 *290 * The second parameter, if given, is a string whose value is the URL291 * at which the source map was found.  This URL is used to compute the292 * sources array.293 *294 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#295 */296function BasicSourceMapConsumer(aSourceMap, aSourceMapURL) {297  var sourceMap = aSourceMap;298  if (typeof aSourceMap === 'string') {299    sourceMap = util.parseSourceMapInput(aSourceMap);300  }301 302  var version = util.getArg(sourceMap, 'version');303  var sources = util.getArg(sourceMap, 'sources');304  // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which305  // requires the array) to play nice here.306  var names = util.getArg(sourceMap, 'names', []);307  var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);308  var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);309  var mappings = util.getArg(sourceMap, 'mappings');310  var file = util.getArg(sourceMap, 'file', null);311 312  // Once again, Sass deviates from the spec and supplies the version as a313  // string rather than a number, so we use loose equality checking here.314  if (version != this._version) {315    throw new Error('Unsupported version: ' + version);316  }317 318  if (sourceRoot) {319    sourceRoot = util.normalize(sourceRoot);320  }321 322  sources = sources323    .map(String)324    // Some source maps produce relative source paths like "./foo.js" instead of325    // "foo.js".  Normalize these first so that future comparisons will succeed.326    // See bugzil.la/1090768.327    .map(util.normalize)328    // Always ensure that absolute sources are internally stored relative to329    // the source root, if the source root is absolute. Not doing this would330    // be particularly problematic when the source root is a prefix of the331    // source (valid, but why??). See github issue #199 and bugzil.la/1188982.332    .map(function (source) {333      return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source)334        ? util.relative(sourceRoot, source)335        : source;336    });337 338  // Pass `true` below to allow duplicate names and sources. While source maps339  // are intended to be compressed and deduplicated, the TypeScript compiler340  // sometimes generates source maps with duplicates in them. See Github issue341  // #72 and bugzil.la/889492.342  this._names = ArraySet.fromArray(names.map(String), true);343  this._sources = ArraySet.fromArray(sources, true);344 345  this._absoluteSources = this._sources.toArray().map(function (s) {346    return util.computeSourceURL(sourceRoot, s, aSourceMapURL);347  });348 349  this.sourceRoot = sourceRoot;350  this.sourcesContent = sourcesContent;351  this._mappings = mappings;352  this._sourceMapURL = aSourceMapURL;353  this.file = file;354}355 356BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);357BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;358 359/**360 * Utility function to find the index of a source.  Returns -1 if not361 * found.362 */363BasicSourceMapConsumer.prototype._findSourceIndex = function(aSource) {364  var relativeSource = aSource;365  if (this.sourceRoot != null) {366    relativeSource = util.relative(this.sourceRoot, relativeSource);367  }368 369  if (this._sources.has(relativeSource)) {370    return this._sources.indexOf(relativeSource);371  }372 373  // Maybe aSource is an absolute URL as returned by |sources|.  In374  // this case we can't simply undo the transform.375  var i;376  for (i = 0; i < this._absoluteSources.length; ++i) {377    if (this._absoluteSources[i] == aSource) {378      return i;379    }380  }381 382  return -1;383};384 385/**386 * Create a BasicSourceMapConsumer from a SourceMapGenerator.387 *388 * @param SourceMapGenerator aSourceMap389 *        The source map that will be consumed.390 * @param String aSourceMapURL391 *        The URL at which the source map can be found (optional)392 * @returns BasicSourceMapConsumer393 */394BasicSourceMapConsumer.fromSourceMap =395  function SourceMapConsumer_fromSourceMap(aSourceMap, aSourceMapURL) {396    var smc = Object.create(BasicSourceMapConsumer.prototype);397 398    var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);399    var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);400    smc.sourceRoot = aSourceMap._sourceRoot;401    smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),402                                                            smc.sourceRoot);403    smc.file = aSourceMap._file;404    smc._sourceMapURL = aSourceMapURL;405    smc._absoluteSources = smc._sources.toArray().map(function (s) {406      return util.computeSourceURL(smc.sourceRoot, s, aSourceMapURL);407    });408 409    // Because we are modifying the entries (by converting string sources and410    // names to indices into the sources and names ArraySets), we have to make411    // a copy of the entry or else bad things happen. Shared mutable state412    // strikes again! See github issue #191.413 414    var generatedMappings = aSourceMap._mappings.toArray().slice();415    var destGeneratedMappings = smc.__generatedMappings = [];416    var destOriginalMappings = smc.__originalMappings = [];417 418    for (var i = 0, length = generatedMappings.length; i < length; i++) {419      var srcMapping = generatedMappings[i];420      var destMapping = new Mapping;421      destMapping.generatedLine = srcMapping.generatedLine;422      destMapping.generatedColumn = srcMapping.generatedColumn;423 424      if (srcMapping.source) {425        destMapping.source = sources.indexOf(srcMapping.source);426        destMapping.originalLine = srcMapping.originalLine;427        destMapping.originalColumn = srcMapping.originalColumn;428 429        if (srcMapping.name) {430          destMapping.name = names.indexOf(srcMapping.name);431        }432 433        destOriginalMappings.push(destMapping);434      }435 436      destGeneratedMappings.push(destMapping);437    }438 439    quickSort(smc.__originalMappings, util.compareByOriginalPositions);440 441    return smc;442  };443 444/**445 * The version of the source mapping spec that we are consuming.446 */447BasicSourceMapConsumer.prototype._version = 3;448 449/**450 * The list of original sources.451 */452Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {453  get: function () {454    return this._absoluteSources.slice();455  }456});457 458/**459 * Provide the JIT with a nice shape / hidden class.460 */461function Mapping() {462  this.generatedLine = 0;463  this.generatedColumn = 0;464  this.source = null;465  this.originalLine = null;466  this.originalColumn = null;467  this.name = null;468}469 470/**471 * Parse the mappings in a string in to a data structure which we can easily472 * query (the ordered arrays in the `this.__generatedMappings` and473 * `this.__originalMappings` properties).474 */475 476const compareGenerated = util.compareByGeneratedPositionsDeflatedNoLine;477function sortGenerated(array, start) {478  let l = array.length;479  let n = array.length - start;480  if (n <= 1) {481    return;482  } else if (n == 2) {483    let a = array[start];484    let b = array[start + 1];485    if (compareGenerated(a, b) > 0) {486      array[start] = b;487      array[start + 1] = a;488    }489  } else if (n < 20) {490    for (let i = start; i < l; i++) {491      for (let j = i; j > start; j--) {492        let a = array[j - 1];493        let b = array[j];494        if (compareGenerated(a, b) <= 0) {495          break;496        }497        array[j - 1] = b;498        array[j] = a;499      }500    }501  } else {502    quickSort(array, compareGenerated, start);503  }504}505BasicSourceMapConsumer.prototype._parseMappings =506  function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {507    var generatedLine = 1;508    var previousGeneratedColumn = 0;509    var previousOriginalLine = 0;510    var previousOriginalColumn = 0;511    var previousSource = 0;512    var previousName = 0;513    var length = aStr.length;514    var index = 0;515    var cachedSegments = {};516    var temp = {};517    var originalMappings = [];518    var generatedMappings = [];519    var mapping, str, segment, end, value;520 521    let subarrayStart = 0;522    while (index < length) {523      if (aStr.charAt(index) === ';') {524        generatedLine++;525        index++;526        previousGeneratedColumn = 0;527 528        sortGenerated(generatedMappings, subarrayStart);529        subarrayStart = generatedMappings.length;530      }531      else if (aStr.charAt(index) === ',') {532        index++;533      }534      else {535        mapping = new Mapping();536        mapping.generatedLine = generatedLine;537 538        for (end = index; end < length; end++) {539          if (this._charIsMappingSeparator(aStr, end)) {540            break;541          }542        }543        str = aStr.slice(index, end);544 545        segment = [];546        while (index < end) {547          base64VLQ.decode(aStr, index, temp);548          value = temp.value;549          index = temp.rest;550          segment.push(value);551        }552 553        if (segment.length === 2) {554          throw new Error('Found a source, but no line and column');555        }556 557        if (segment.length === 3) {558          throw new Error('Found a source and line, but no column');559        }560 561        // Generated column.562        mapping.generatedColumn = previousGeneratedColumn + segment[0];563        previousGeneratedColumn = mapping.generatedColumn;564 565        if (segment.length > 1) {566          // Original source.567          mapping.source = previousSource + segment[1];568          previousSource += segment[1];569 570          // Original line.571          mapping.originalLine = previousOriginalLine + segment[2];572          previousOriginalLine = mapping.originalLine;573          // Lines are stored 0-based574          mapping.originalLine += 1;575 576          // Original column.577          mapping.originalColumn = previousOriginalColumn + segment[3];578          previousOriginalColumn = mapping.originalColumn;579 580          if (segment.length > 4) {581            // Original name.582            mapping.name = previousName + segment[4];583            previousName += segment[4];584          }585        }586 587        generatedMappings.push(mapping);588        if (typeof mapping.originalLine === 'number') {589          let currentSource = mapping.source;590          while (originalMappings.length <= currentSource) {591            originalMappings.push(null);592          }593          if (originalMappings[currentSource] === null) {594            originalMappings[currentSource] = [];595          }596          originalMappings[currentSource].push(mapping);597        }598      }599    }600 601    sortGenerated(generatedMappings, subarrayStart);602    this.__generatedMappings = generatedMappings;603 604    for (var i = 0; i < originalMappings.length; i++) {605      if (originalMappings[i] != null) {606        quickSort(originalMappings[i], util.compareByOriginalPositionsNoSource);607      }608    }609    this.__originalMappings = [].concat(...originalMappings);610  };611 612/**613 * Find the mapping that best matches the hypothetical "needle" mapping that614 * we are searching for in the given "haystack" of mappings.615 */616BasicSourceMapConsumer.prototype._findMapping =617  function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,618                                         aColumnName, aComparator, aBias) {619    // To return the position we are searching for, we must first find the620    // mapping for the given position and then return the opposite position it621    // points to. Because the mappings are sorted, we can use binary search to622    // find the best mapping.623 624    if (aNeedle[aLineName] <= 0) {625      throw new TypeError('Line must be greater than or equal to 1, got '626                          + aNeedle[aLineName]);627    }628    if (aNeedle[aColumnName] < 0) {629      throw new TypeError('Column must be greater than or equal to 0, got '630                          + aNeedle[aColumnName]);631    }632 633    return binarySearch.search(aNeedle, aMappings, aComparator, aBias);634  };635 636/**637 * Compute the last column for each generated mapping. The last column is638 * inclusive.639 */640BasicSourceMapConsumer.prototype.computeColumnSpans =641  function SourceMapConsumer_computeColumnSpans() {642    for (var index = 0; index < this._generatedMappings.length; ++index) {643      var mapping = this._generatedMappings[index];644 645      // Mappings do not contain a field for the last generated columnt. We646      // can come up with an optimistic estimate, however, by assuming that647      // mappings are contiguous (i.e. given two consecutive mappings, the648      // first mapping ends where the second one starts).649      if (index + 1 < this._generatedMappings.length) {650        var nextMapping = this._generatedMappings[index + 1];651 652        if (mapping.generatedLine === nextMapping.generatedLine) {653          mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;654          continue;655        }656      }657 658      // The last mapping for each line spans the entire line.659      mapping.lastGeneratedColumn = Infinity;660    }661  };662 663/**664 * Returns the original source, line, and column information for the generated665 * source's line and column positions provided. The only argument is an object666 * with the following properties:667 *668 *   - line: The line number in the generated source.  The line number669 *     is 1-based.670 *   - column: The column number in the generated source.  The column671 *     number is 0-based.672 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or673 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the674 *     closest element that is smaller than or greater than the one we are675 *     searching for, respectively, if the exact element cannot be found.676 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.677 *678 * and an object is returned with the following properties:679 *680 *   - source: The original source file, or null.681 *   - line: The line number in the original source, or null.  The682 *     line number is 1-based.683 *   - column: The column number in the original source, or null.  The684 *     column number is 0-based.685 *   - name: The original identifier, or null.686 */687BasicSourceMapConsumer.prototype.originalPositionFor =688  function SourceMapConsumer_originalPositionFor(aArgs) {689    var needle = {690      generatedLine: util.getArg(aArgs, 'line'),691      generatedColumn: util.getArg(aArgs, 'column')692    };693 694    var index = this._findMapping(695      needle,696      this._generatedMappings,697      "generatedLine",698      "generatedColumn",699      util.compareByGeneratedPositionsDeflated,700      util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)701    );702 703    if (index >= 0) {704      var mapping = this._generatedMappings[index];705 706      if (mapping.generatedLine === needle.generatedLine) {707        var source = util.getArg(mapping, 'source', null);708        if (source !== null) {709          source = this._sources.at(source);710          source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL);711        }712        var name = util.getArg(mapping, 'name', null);713        if (name !== null) {714          name = this._names.at(name);715        }716        return {717          source: source,718          line: util.getArg(mapping, 'originalLine', null),719          column: util.getArg(mapping, 'originalColumn', null),720          name: name721        };722      }723    }724 725    return {726      source: null,727      line: null,728      column: null,729      name: null730    };731  };732 733/**734 * Return true if we have the source content for every source in the source735 * map, false otherwise.736 */737BasicSourceMapConsumer.prototype.hasContentsOfAllSources =738  function BasicSourceMapConsumer_hasContentsOfAllSources() {739    if (!this.sourcesContent) {740      return false;741    }742    return this.sourcesContent.length >= this._sources.size() &&743      !this.sourcesContent.some(function (sc) { return sc == null; });744  };745 746/**747 * Returns the original source content. The only argument is the url of the748 * original source file. Returns null if no original source content is749 * available.750 */751BasicSourceMapConsumer.prototype.sourceContentFor =752  function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {753    if (!this.sourcesContent) {754      return null;755    }756 757    var index = this._findSourceIndex(aSource);758    if (index >= 0) {759      return this.sourcesContent[index];760    }761 762    var relativeSource = aSource;763    if (this.sourceRoot != null) {764      relativeSource = util.relative(this.sourceRoot, relativeSource);765    }766 767    var url;768    if (this.sourceRoot != null769        && (url = util.urlParse(this.sourceRoot))) {770      // XXX: file:// URIs and absolute paths lead to unexpected behavior for771      // many users. We can help them out when they expect file:// URIs to772      // behave like it would if they were running a local HTTP server. See773      // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.774      var fileUriAbsPath = relativeSource.replace(/^file:\/\//, "");775      if (url.scheme == "file"776          && this._sources.has(fileUriAbsPath)) {777        return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]778      }779 780      if ((!url.path || url.path == "/")781          && this._sources.has("/" + relativeSource)) {782        return this.sourcesContent[this._sources.indexOf("/" + relativeSource)];783      }784    }785 786    // This function is used recursively from787    // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we788    // don't want to throw if we can't find the source - we just want to789    // return null, so we provide a flag to exit gracefully.790    if (nullOnMissing) {791      return null;792    }793    else {794      throw new Error('"' + relativeSource + '" is not in the SourceMap.');795    }796  };797 798/**799 * Returns the generated line and column information for the original source,800 * line, and column positions provided. The only argument is an object with801 * the following properties:802 *803 *   - source: The filename of the original source.804 *   - line: The line number in the original source.  The line number805 *     is 1-based.806 *   - column: The column number in the original source.  The column807 *     number is 0-based.808 *   - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or809 *     'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the810 *     closest element that is smaller than or greater than the one we are811 *     searching for, respectively, if the exact element cannot be found.812 *     Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.813 *814 * and an object is returned with the following properties:815 *816 *   - line: The line number in the generated source, or null.  The817 *     line number is 1-based.818 *   - column: The column number in the generated source, or null.819 *     The column number is 0-based.820 */821BasicSourceMapConsumer.prototype.generatedPositionFor =822  function SourceMapConsumer_generatedPositionFor(aArgs) {823    var source = util.getArg(aArgs, 'source');824    source = this._findSourceIndex(source);825    if (source < 0) {826      return {827        line: null,828        column: null,829        lastColumn: null830      };831    }832 833    var needle = {834      source: source,835      originalLine: util.getArg(aArgs, 'line'),836      originalColumn: util.getArg(aArgs, 'column')837    };838 839    var index = this._findMapping(840      needle,841      this._originalMappings,842      "originalLine",843      "originalColumn",844      util.compareByOriginalPositions,845      util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)846    );847 848    if (index >= 0) {849      var mapping = this._originalMappings[index];850 851      if (mapping.source === needle.source) {852        return {853          line: util.getArg(mapping, 'generatedLine', null),854          column: util.getArg(mapping, 'generatedColumn', null),855          lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)856        };857      }858    }859 860    return {861      line: null,862      column: null,863      lastColumn: null864    };865  };866 867exports.BasicSourceMapConsumer = BasicSourceMapConsumer;868 869/**870 * An IndexedSourceMapConsumer instance represents a parsed source map which871 * we can query for information. It differs from BasicSourceMapConsumer in872 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as873 * input.874 *875 * The first parameter is a raw source map (either as a JSON string, or already876 * parsed to an object). According to the spec for indexed source maps, they877 * have the following attributes:878 *879 *   - version: Which version of the source map spec this map is following.880 *   - file: Optional. The generated file this source map is associated with.881 *   - sections: A list of section definitions.882 *883 * Each value under the "sections" field has two fields:884 *   - offset: The offset into the original specified at which this section885 *       begins to apply, defined as an object with a "line" and "column"886 *       field.887 *   - map: A source map definition. This source map could also be indexed,888 *       but doesn't have to be.889 *890 * Instead of the "map" field, it's also possible to have a "url" field891 * specifying a URL to retrieve a source map from, but that's currently892 * unsupported.893 *894 * Here's an example source map, taken from the source map spec[0], but895 * modified to omit a section which uses the "url" field.896 *897 *  {898 *    version : 3,899 *    file: "app.js",900 *    sections: [{901 *      offset: {line:100, column:10},902 *      map: {903 *        version : 3,904 *        file: "section.js",905 *        sources: ["foo.js", "bar.js"],906 *        names: ["src", "maps", "are", "fun"],907 *        mappings: "AAAA,E;;ABCDE;"908 *      }909 *    }],910 *  }911 *912 * The second parameter, if given, is a string whose value is the URL913 * at which the source map was found.  This URL is used to compute the914 * sources array.915 *916 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt917 */918function IndexedSourceMapConsumer(aSourceMap, aSourceMapURL) {919  var sourceMap = aSourceMap;920  if (typeof aSourceMap === 'string') {921    sourceMap = util.parseSourceMapInput(aSourceMap);922  }923 924  var version = util.getArg(sourceMap, 'version');925  var sections = util.getArg(sourceMap, 'sections');926 927  if (version != this._version) {928    throw new Error('Unsupported version: ' + version);929  }930 931  this._sources = new ArraySet();932  this._names = new ArraySet();933 934  var lastOffset = {935    line: -1,936    column: 0937  };938  this._sections = sections.map(function (s) {939    if (s.url) {940      // The url field will require support for asynchronicity.941      // See https://github.com/mozilla/source-map/issues/16942      throw new Error('Support for url field in sections not implemented.');943    }944    var offset = util.getArg(s, 'offset');945    var offsetLine = util.getArg(offset, 'line');946    var offsetColumn = util.getArg(offset, 'column');947 948    if (offsetLine < lastOffset.line ||949        (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {950      throw new Error('Section offsets must be ordered and non-overlapping.');951    }952    lastOffset = offset;953 954    return {955      generatedOffset: {956        // The offset fields are 0-based, but we use 1-based indices when957        // encoding/decoding from VLQ.958        generatedLine: offsetLine + 1,959        generatedColumn: offsetColumn + 1960      },961      consumer: new SourceMapConsumer(util.getArg(s, 'map'), aSourceMapURL)962    }963  });964}965 966IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);967IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;968 969/**970 * The version of the source mapping spec that we are consuming.971 */972IndexedSourceMapConsumer.prototype._version = 3;973 974/**975 * The list of original sources.976 */977Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {978  get: function () {979    var sources = [];980    for (var i = 0; i < this._sections.length; i++) {981      for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {982        sources.push(this._sections[i].consumer.sources[j]);983      }984    }985    return sources;986  }987});988 989/**990 * Returns the original source, line, and column information for the generated991 * source's line and column positions provided. The only argument is an object992 * with the following properties:993 *994 *   - line: The line number in the generated source.  The line number995 *     is 1-based.996 *   - column: The column number in the generated source.  The column997 *     number is 0-based.998 *999 * and an object is returned with the following properties:1000 *1001 *   - source: The original source file, or null.1002 *   - line: The line number in the original source, or null.  The1003 *     line number is 1-based.1004 *   - column: The column number in the original source, or null.  The1005 *     column number is 0-based.1006 *   - name: The original identifier, or null.1007 */1008IndexedSourceMapConsumer.prototype.originalPositionFor =1009  function IndexedSourceMapConsumer_originalPositionFor(aArgs) {1010    var needle = {1011      generatedLine: util.getArg(aArgs, 'line'),1012      generatedColumn: util.getArg(aArgs, 'column')1013    };1014 1015    // Find the section containing the generated position we're trying to map1016    // to an original position.1017    var sectionIndex = binarySearch.search(needle, this._sections,1018      function(needle, section) {1019        var cmp = needle.generatedLine - section.generatedOffset.generatedLine;1020        if (cmp) {1021          return cmp;1022        }1023 1024        return (needle.generatedColumn -1025                section.generatedOffset.generatedColumn);1026      });1027    var section = this._sections[sectionIndex];1028 1029    if (!section) {1030      return {1031        source: null,1032        line: null,1033        column: null,1034        name: null1035      };1036    }1037 1038    return section.consumer.originalPositionFor({1039      line: needle.generatedLine -1040        (section.generatedOffset.generatedLine - 1),1041      column: needle.generatedColumn -1042        (section.generatedOffset.generatedLine === needle.generatedLine1043         ? section.generatedOffset.generatedColumn - 11044         : 0),1045      bias: aArgs.bias1046    });1047  };1048 1049/**1050 * Return true if we have the source content for every source in the source1051 * map, false otherwise.1052 */1053IndexedSourceMapConsumer.prototype.hasContentsOfAllSources =1054  function IndexedSourceMapConsumer_hasContentsOfAllSources() {1055    return this._sections.every(function (s) {1056      return s.consumer.hasContentsOfAllSources();1057    });1058  };1059 1060/**1061 * Returns the original source content. The only argument is the url of the1062 * original source file. Returns null if no original source content is1063 * available.1064 */1065IndexedSourceMapConsumer.prototype.sourceContentFor =1066  function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {1067    for (var i = 0; i < this._sections.length; i++) {1068      var section = this._sections[i];1069 1070      var content = section.consumer.sourceContentFor(aSource, true);1071      if (content || content === '') {1072        return content;1073      }1074    }1075    if (nullOnMissing) {1076      return null;1077    }1078    else {1079      throw new Error('"' + aSource + '" is not in the SourceMap.');1080    }1081  };1082 1083/**1084 * Returns the generated line and column information for the original source,1085 * line, and column positions provided. The only argument is an object with1086 * the following properties:1087 *1088 *   - source: The filename of the original source.1089 *   - line: The line number in the original source.  The line number1090 *     is 1-based.1091 *   - column: The column number in the original source.  The column1092 *     number is 0-based.1093 *1094 * and an object is returned with the following properties:1095 *1096 *   - line: The line number in the generated source, or null.  The1097 *     line number is 1-based. 1098 *   - column: The column number in the generated source, or null.1099 *     The column number is 0-based.1100 */1101IndexedSourceMapConsumer.prototype.generatedPositionFor =1102  function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {1103    for (var i = 0; i < this._sections.length; i++) {1104      var section = this._sections[i];1105 1106      // Only consider this section if the requested source is in the list of1107      // sources of the consumer.1108      if (section.consumer._findSourceIndex(util.getArg(aArgs, 'source')) === -1) {1109        continue;1110      }1111      var generatedPosition = section.consumer.generatedPositionFor(aArgs);1112      if (generatedPosition) {1113        var ret = {1114          line: generatedPosition.line +1115            (section.generatedOffset.generatedLine - 1),1116          column: generatedPosition.column +1117            (section.generatedOffset.generatedLine === generatedPosition.line1118             ? section.generatedOffset.generatedColumn - 11119             : 0)1120        };1121        return ret;1122      }1123    }1124 1125    return {1126      line: null,1127      column: null1128    };1129  };1130 1131/**1132 * Parse the mappings in a string in to a data structure which we can easily1133 * query (the ordered arrays in the `this.__generatedMappings` and1134 * `this.__originalMappings` properties).1135 */1136IndexedSourceMapConsumer.prototype._parseMappings =1137  function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {1138    this.__generatedMappings = [];1139    this.__originalMappings = [];1140    for (var i = 0; i < this._sections.length; i++) {1141      var section = this._sections[i];1142      var sectionMappings = section.consumer._generatedMappings;1143      for (var j = 0; j < sectionMappings.length; j++) {1144        var mapping = sectionMappings[j];1145 1146        var source = section.consumer._sources.at(mapping.source);1147        if(source !== null) {1148          source = util.computeSourceURL(section.consumer.sourceRoot, source, this._sourceMapURL);1149        }1150        this._sources.add(source);1151        source = this._sources.indexOf(source);1152 1153        var name = null;1154        if (mapping.name) {1155          name = section.consumer._names.at(mapping.name);1156          this._names.add(name);1157          name = this._names.indexOf(name);1158        }1159 1160        // The mappings coming from the consumer for the section have1161        // generated positions relative to the start of the section, so we1162        // need to offset them to be relative to the start of the concatenated1163        // generated file.1164        var adjustedMapping = {1165          source: source,1166          generatedLine: mapping.generatedLine +1167            (section.generatedOffset.generatedLine - 1),1168          generatedColumn: mapping.generatedColumn +1169            (section.generatedOffset.generatedLine === mapping.generatedLine1170            ? section.generatedOffset.generatedColumn - 11171            : 0),1172          originalLine: mapping.originalLine,1173          originalColumn: mapping.originalColumn,1174          name: name1175        };1176 1177        this.__generatedMappings.push(adjustedMapping);1178        if (typeof adjustedMapping.originalLine === 'number') {1179          this.__originalMappings.push(adjustedMapping);1180        }1181      }1182    }1183 1184    quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);1185    quickSort(this.__originalMappings, util.compareByOriginalPositions);1186  };1187 1188exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;1189