react / wstein / node_modules / browserify / node_modules / insert-module-globals / node_modules / combine-source-map / node_modules / inline-source-map / node_modules / source-map / lib / source-map / indexed-source-map-consumer.js
80620 views/* -*- Mode: js; js-indent-level: 2; -*- */1/*2* Copyright 2011 Mozilla Foundation and contributors3* Licensed under the New BSD license. See LICENSE or:4* http://opensource.org/licenses/BSD-3-Clause5*/6if (typeof define !== 'function') {7var define = require('amdefine')(module, require);8}9define(function (require, exports, module) {1011var util = require('./util');12var binarySearch = require('./binary-search');13var SourceMapConsumer = require('./source-map-consumer').SourceMapConsumer;14var BasicSourceMapConsumer = require('./basic-source-map-consumer').BasicSourceMapConsumer;1516/**17* An IndexedSourceMapConsumer instance represents a parsed source map which18* we can query for information. It differs from BasicSourceMapConsumer in19* that it takes "indexed" source maps (i.e. ones with a "sections" field) as20* input.21*22* The only parameter is a raw source map (either as a JSON string, or already23* parsed to an object). According to the spec for indexed source maps, they24* have the following attributes:25*26* - version: Which version of the source map spec this map is following.27* - file: Optional. The generated file this source map is associated with.28* - sections: A list of section definitions.29*30* Each value under the "sections" field has two fields:31* - offset: The offset into the original specified at which this section32* begins to apply, defined as an object with a "line" and "column"33* field.34* - map: A source map definition. This source map could also be indexed,35* but doesn't have to be.36*37* Instead of the "map" field, it's also possible to have a "url" field38* specifying a URL to retrieve a source map from, but that's currently39* unsupported.40*41* Here's an example source map, taken from the source map spec[0], but42* modified to omit a section which uses the "url" field.43*44* {45* version : 3,46* file: "app.js",47* sections: [{48* offset: {line:100, column:10},49* map: {50* version : 3,51* file: "section.js",52* sources: ["foo.js", "bar.js"],53* names: ["src", "maps", "are", "fun"],54* mappings: "AAAA,E;;ABCDE;"55* }56* }],57* }58*59* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt60*/61function IndexedSourceMapConsumer(aSourceMap) {62var sourceMap = aSourceMap;63if (typeof aSourceMap === 'string') {64sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));65}6667var version = util.getArg(sourceMap, 'version');68var sections = util.getArg(sourceMap, 'sections');6970if (version != this._version) {71throw new Error('Unsupported version: ' + version);72}7374var lastOffset = {75line: -1,76column: 077};78this._sections = sections.map(function (s) {79if (s.url) {80// The url field will require support for asynchronicity.81// See https://github.com/mozilla/source-map/issues/1682throw new Error('Support for url field in sections not implemented.');83}84var offset = util.getArg(s, 'offset');85var offsetLine = util.getArg(offset, 'line');86var offsetColumn = util.getArg(offset, 'column');8788if (offsetLine < lastOffset.line ||89(offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {90throw new Error('Section offsets must be ordered and non-overlapping.');91}92lastOffset = offset;9394return {95generatedOffset: {96// The offset fields are 0-based, but we use 1-based indices when97// encoding/decoding from VLQ.98generatedLine: offsetLine + 1,99generatedColumn: offsetColumn + 1100},101consumer: new SourceMapConsumer(util.getArg(s, 'map'))102}103});104}105106IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);107IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;108109/**110* The version of the source mapping spec that we are consuming.111*/112IndexedSourceMapConsumer.prototype._version = 3;113114/**115* The list of original sources.116*/117Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {118get: function () {119var sources = [];120for (var i = 0; i < this._sections.length; i++) {121for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {122sources.push(this._sections[i].consumer.sources[j]);123}124};125return sources;126}127});128129/**130* Returns the original source, line, and column information for the generated131* source's line and column positions provided. The only argument is an object132* with the following properties:133*134* - line: The line number in the generated source.135* - column: The column number in the generated source.136*137* and an object is returned with the following properties:138*139* - source: The original source file, or null.140* - line: The line number in the original source, or null.141* - column: The column number in the original source, or null.142* - name: The original identifier, or null.143*/144IndexedSourceMapConsumer.prototype.originalPositionFor =145function IndexedSourceMapConsumer_originalPositionFor(aArgs) {146var needle = {147generatedLine: util.getArg(aArgs, 'line'),148generatedColumn: util.getArg(aArgs, 'column')149};150151// Find the section containing the generated position we're trying to map152// to an original position.153var sectionIndex = binarySearch.search(needle, this._sections,154function(needle, section) {155var cmp = needle.generatedLine - section.generatedOffset.generatedLine;156if (cmp) {157return cmp;158}159160return (needle.generatedColumn -161section.generatedOffset.generatedColumn);162}, binarySearch.GREATEST_LOWER_BOUND);163var section = this._sections[sectionIndex];164165if (!section) {166return {167source: null,168line: null,169column: null,170name: null171};172}173174return section.consumer.originalPositionFor({175line: needle.generatedLine -176(section.generatedOffset.generatedLine - 1),177column: needle.generatedColumn -178(section.generatedOffset.generatedLine === needle.generatedLine179? section.generatedOffset.generatedColumn - 1180: 0)181});182};183184/**185* Returns the original source content. The only argument is the url of the186* original source file. Returns null if no original source content is187* available.188*/189IndexedSourceMapConsumer.prototype.sourceContentFor =190function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {191for (var i = 0; i < this._sections.length; i++) {192var section = this._sections[i];193194var content = section.consumer.sourceContentFor(aSource, true);195if (content) {196return content;197}198}199if (nullOnMissing) {200return null;201}202else {203throw new Error('"' + aSource + '" is not in the SourceMap.');204}205};206207/**208* Returns the generated line and column information for the original source,209* line, and column positions provided. The only argument is an object with210* the following properties:211*212* - source: The filename of the original source.213* - line: The line number in the original source.214* - column: The column number in the original source.215*216* and an object is returned with the following properties:217*218* - line: The line number in the generated source, or null.219* - column: The column number in the generated source, or null.220*/221IndexedSourceMapConsumer.prototype.generatedPositionFor =222function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {223for (var i = 0; i < this._sections.length; i++) {224var section = this._sections[i];225226// Only consider this section if the requested source is in the list of227// sources of the consumer.228if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {229continue;230}231var generatedPosition = section.consumer.generatedPositionFor(aArgs);232if (generatedPosition) {233var ret = {234line: generatedPosition.line +235(section.generatedOffset.generatedLine - 1),236column: generatedPosition.column +237(section.generatedOffset.generatedLine === generatedPosition.line238? section.generatedOffset.generatedColumn - 1239: 0)240};241return ret;242}243}244245return {246line: null,247column: null248};249};250251/**252* Parse the mappings in a string in to a data structure which we can easily253* query (the ordered arrays in the `this.__generatedMappings` and254* `this.__originalMappings` properties).255*/256IndexedSourceMapConsumer.prototype._parseMappings =257function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {258this.__generatedMappings = [];259this.__originalMappings = [];260for (var i = 0; i < this._sections.length; i++) {261var section = this._sections[i];262var sectionMappings = section.consumer._generatedMappings;263for (var j = 0; j < sectionMappings.length; j++) {264var mapping = sectionMappings[i];265266var source = mapping.source;267var sourceRoot = section.consumer.sourceRoot;268269if (source != null && sourceRoot != null) {270source = util.join(sourceRoot, source);271}272273// The mappings coming from the consumer for the section have274// generated positions relative to the start of the section, so we275// need to offset them to be relative to the start of the concatenated276// generated file.277var adjustedMapping = {278source: source,279generatedLine: mapping.generatedLine +280(section.generatedOffset.generatedLine - 1),281generatedColumn: mapping.column +282(section.generatedOffset.generatedLine === mapping.generatedLine)283? section.generatedOffset.generatedColumn - 1284: 0,285originalLine: mapping.originalLine,286originalColumn: mapping.originalColumn,287name: mapping.name288};289290this.__generatedMappings.push(adjustedMapping);291if (typeof adjustedMapping.originalLine === 'number') {292this.__originalMappings.push(adjustedMapping);293}294};295};296297this.__generatedMappings.sort(util.compareByGeneratedPositions);298this.__originalMappings.sort(util.compareByOriginalPositions);299};300301exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;302});303304305