react / react-0.13.3 / examples / basic-commonjs / node_modules / browserify / node_modules / umd / node_modules / uglify-js / node_modules / source-map / lib / source-map / source-map-consumer.js
80766 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 ArraySet = require('./array-set').ArraySet;14var base64VLQ = require('./base64-vlq');1516/**17* A SourceMapConsumer instance represents a parsed source map which we can18* query for information about the original file positions by giving it a file19* position in the generated source.20*21* The only parameter is the raw source map (either as a JSON string, or22* already parsed to an object). According to the spec, source maps have the23* following attributes:24*25* - version: Which version of the source map spec this map is following.26* - sources: An array of URLs to the original source files.27* - names: An array of identifiers which can be referrenced by individual mappings.28* - sourceRoot: Optional. The URL root from which all sources are relative.29* - sourcesContent: Optional. An array of contents of the original source files.30* - mappings: A string of base64 VLQs which contain the actual mappings.31* - file: Optional. The generated file this source map is associated with.32*33* Here is an example source map, taken from the source map spec[0]:34*35* {36* version : 3,37* file: "out.js",38* sourceRoot : "",39* sources: ["foo.js", "bar.js"],40* names: ["src", "maps", "are", "fun"],41* mappings: "AA,AB;;ABCDE;"42* }43*44* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#45*/46function SourceMapConsumer(aSourceMap) {47var sourceMap = aSourceMap;48if (typeof aSourceMap === 'string') {49sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));50}5152var version = util.getArg(sourceMap, 'version');53var sources = util.getArg(sourceMap, 'sources');54// Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which55// requires the array) to play nice here.56var names = util.getArg(sourceMap, 'names', []);57var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);58var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);59var mappings = util.getArg(sourceMap, 'mappings');60var file = util.getArg(sourceMap, 'file', null);6162// Once again, Sass deviates from the spec and supplies the version as a63// string rather than a number, so we use loose equality checking here.64if (version != this._version) {65throw new Error('Unsupported version: ' + version);66}6768// Pass `true` below to allow duplicate names and sources. While source maps69// are intended to be compressed and deduplicated, the TypeScript compiler70// sometimes generates source maps with duplicates in them. See Github issue71// #72 and bugzil.la/889492.72this._names = ArraySet.fromArray(names, true);73this._sources = ArraySet.fromArray(sources, true);7475this.sourceRoot = sourceRoot;76this.sourcesContent = sourcesContent;77this._mappings = mappings;78this.file = file;79}8081/**82* Create a SourceMapConsumer from a SourceMapGenerator.83*84* @param SourceMapGenerator aSourceMap85* The source map that will be consumed.86* @returns SourceMapConsumer87*/88SourceMapConsumer.fromSourceMap =89function SourceMapConsumer_fromSourceMap(aSourceMap) {90var smc = Object.create(SourceMapConsumer.prototype);9192smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);93smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);94smc.sourceRoot = aSourceMap._sourceRoot;95smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),96smc.sourceRoot);97smc.file = aSourceMap._file;9899smc.__generatedMappings = aSourceMap._mappings.slice()100.sort(util.compareByGeneratedPositions);101smc.__originalMappings = aSourceMap._mappings.slice()102.sort(util.compareByOriginalPositions);103104return smc;105};106107/**108* The version of the source mapping spec that we are consuming.109*/110SourceMapConsumer.prototype._version = 3;111112/**113* The list of original sources.114*/115Object.defineProperty(SourceMapConsumer.prototype, 'sources', {116get: function () {117return this._sources.toArray().map(function (s) {118return this.sourceRoot ? util.join(this.sourceRoot, s) : s;119}, this);120}121});122123// `__generatedMappings` and `__originalMappings` are arrays that hold the124// parsed mapping coordinates from the source map's "mappings" attribute. They125// are lazily instantiated, accessed via the `_generatedMappings` and126// `_originalMappings` getters respectively, and we only parse the mappings127// and create these arrays once queried for a source location. We jump through128// these hoops because there can be many thousands of mappings, and parsing129// them is expensive, so we only want to do it if we must.130//131// Each object in the arrays is of the form:132//133// {134// generatedLine: The line number in the generated code,135// generatedColumn: The column number in the generated code,136// source: The path to the original source file that generated this137// chunk of code,138// originalLine: The line number in the original source that139// corresponds to this chunk of generated code,140// originalColumn: The column number in the original source that141// corresponds to this chunk of generated code,142// name: The name of the original symbol which generated this chunk of143// code.144// }145//146// All properties except for `generatedLine` and `generatedColumn` can be147// `null`.148//149// `_generatedMappings` is ordered by the generated positions.150//151// `_originalMappings` is ordered by the original positions.152153SourceMapConsumer.prototype.__generatedMappings = null;154Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {155get: function () {156if (!this.__generatedMappings) {157this.__generatedMappings = [];158this.__originalMappings = [];159this._parseMappings(this._mappings, this.sourceRoot);160}161162return this.__generatedMappings;163}164});165166SourceMapConsumer.prototype.__originalMappings = null;167Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {168get: function () {169if (!this.__originalMappings) {170this.__generatedMappings = [];171this.__originalMappings = [];172this._parseMappings(this._mappings, this.sourceRoot);173}174175return this.__originalMappings;176}177});178179/**180* Parse the mappings in a string in to a data structure which we can easily181* query (the ordered arrays in the `this.__generatedMappings` and182* `this.__originalMappings` properties).183*/184SourceMapConsumer.prototype._parseMappings =185function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {186var generatedLine = 1;187var previousGeneratedColumn = 0;188var previousOriginalLine = 0;189var previousOriginalColumn = 0;190var previousSource = 0;191var previousName = 0;192var mappingSeparator = /^[,;]/;193var str = aStr;194var mapping;195var temp;196197while (str.length > 0) {198if (str.charAt(0) === ';') {199generatedLine++;200str = str.slice(1);201previousGeneratedColumn = 0;202}203else if (str.charAt(0) === ',') {204str = str.slice(1);205}206else {207mapping = {};208mapping.generatedLine = generatedLine;209210// Generated column.211temp = base64VLQ.decode(str);212mapping.generatedColumn = previousGeneratedColumn + temp.value;213previousGeneratedColumn = mapping.generatedColumn;214str = temp.rest;215216if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {217// Original source.218temp = base64VLQ.decode(str);219mapping.source = this._sources.at(previousSource + temp.value);220previousSource += temp.value;221str = temp.rest;222if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {223throw new Error('Found a source, but no line and column');224}225226// Original line.227temp = base64VLQ.decode(str);228mapping.originalLine = previousOriginalLine + temp.value;229previousOriginalLine = mapping.originalLine;230// Lines are stored 0-based231mapping.originalLine += 1;232str = temp.rest;233if (str.length === 0 || mappingSeparator.test(str.charAt(0))) {234throw new Error('Found a source and line, but no column');235}236237// Original column.238temp = base64VLQ.decode(str);239mapping.originalColumn = previousOriginalColumn + temp.value;240previousOriginalColumn = mapping.originalColumn;241str = temp.rest;242243if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) {244// Original name.245temp = base64VLQ.decode(str);246mapping.name = this._names.at(previousName + temp.value);247previousName += temp.value;248str = temp.rest;249}250}251252this.__generatedMappings.push(mapping);253if (typeof mapping.originalLine === 'number') {254this.__originalMappings.push(mapping);255}256}257}258259this.__generatedMappings.sort(util.compareByGeneratedPositions);260this.__originalMappings.sort(util.compareByOriginalPositions);261};262263/**264* Find the mapping that best matches the hypothetical "needle" mapping that265* we are searching for in the given "haystack" of mappings.266*/267SourceMapConsumer.prototype._findMapping =268function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,269aColumnName, aComparator) {270// To return the position we are searching for, we must first find the271// mapping for the given position and then return the opposite position it272// points to. Because the mappings are sorted, we can use binary search to273// find the best mapping.274275if (aNeedle[aLineName] <= 0) {276throw new TypeError('Line must be greater than or equal to 1, got '277+ aNeedle[aLineName]);278}279if (aNeedle[aColumnName] < 0) {280throw new TypeError('Column must be greater than or equal to 0, got '281+ aNeedle[aColumnName]);282}283284return binarySearch.search(aNeedle, aMappings, aComparator);285};286287/**288* Returns the original source, line, and column information for the generated289* source's line and column positions provided. The only argument is an object290* with the following properties:291*292* - line: The line number in the generated source.293* - column: The column number in the generated source.294*295* and an object is returned with the following properties:296*297* - source: The original source file, or null.298* - line: The line number in the original source, or null.299* - column: The column number in the original source, or null.300* - name: The original identifier, or null.301*/302SourceMapConsumer.prototype.originalPositionFor =303function SourceMapConsumer_originalPositionFor(aArgs) {304var needle = {305generatedLine: util.getArg(aArgs, 'line'),306generatedColumn: util.getArg(aArgs, 'column')307};308309var mapping = this._findMapping(needle,310this._generatedMappings,311"generatedLine",312"generatedColumn",313util.compareByGeneratedPositions);314315if (mapping && mapping.generatedLine === needle.generatedLine) {316var source = util.getArg(mapping, 'source', null);317if (source && this.sourceRoot) {318source = util.join(this.sourceRoot, source);319}320return {321source: source,322line: util.getArg(mapping, 'originalLine', null),323column: util.getArg(mapping, 'originalColumn', null),324name: util.getArg(mapping, 'name', null)325};326}327328return {329source: null,330line: null,331column: null,332name: null333};334};335336/**337* Returns the original source content. The only argument is the url of the338* original source file. Returns null if no original source content is339* availible.340*/341SourceMapConsumer.prototype.sourceContentFor =342function SourceMapConsumer_sourceContentFor(aSource) {343if (!this.sourcesContent) {344return null;345}346347if (this.sourceRoot) {348aSource = util.relative(this.sourceRoot, aSource);349}350351if (this._sources.has(aSource)) {352return this.sourcesContent[this._sources.indexOf(aSource)];353}354355var url;356if (this.sourceRoot357&& (url = util.urlParse(this.sourceRoot))) {358// XXX: file:// URIs and absolute paths lead to unexpected behavior for359// many users. We can help them out when they expect file:// URIs to360// behave like it would if they were running a local HTTP server. See361// https://bugzilla.mozilla.org/show_bug.cgi?id=885597.362var fileUriAbsPath = aSource.replace(/^file:\/\//, "");363if (url.scheme == "file"364&& this._sources.has(fileUriAbsPath)) {365return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]366}367368if ((!url.path || url.path == "/")369&& this._sources.has("/" + aSource)) {370return this.sourcesContent[this._sources.indexOf("/" + aSource)];371}372}373374throw new Error('"' + aSource + '" is not in the SourceMap.');375};376377/**378* Returns the generated line and column information for the original source,379* line, and column positions provided. The only argument is an object with380* the following properties:381*382* - source: The filename of the original source.383* - line: The line number in the original source.384* - column: The column number in the original source.385*386* and an object is returned with the following properties:387*388* - line: The line number in the generated source, or null.389* - column: The column number in the generated source, or null.390*/391SourceMapConsumer.prototype.generatedPositionFor =392function SourceMapConsumer_generatedPositionFor(aArgs) {393var needle = {394source: util.getArg(aArgs, 'source'),395originalLine: util.getArg(aArgs, 'line'),396originalColumn: util.getArg(aArgs, 'column')397};398399if (this.sourceRoot) {400needle.source = util.relative(this.sourceRoot, needle.source);401}402403var mapping = this._findMapping(needle,404this._originalMappings,405"originalLine",406"originalColumn",407util.compareByOriginalPositions);408409if (mapping) {410return {411line: util.getArg(mapping, 'generatedLine', null),412column: util.getArg(mapping, 'generatedColumn', null)413};414}415416return {417line: null,418column: null419};420};421422SourceMapConsumer.GENERATED_ORDER = 1;423SourceMapConsumer.ORIGINAL_ORDER = 2;424425/**426* Iterate over each mapping between an original source/line/column and a427* generated line/column in this source map.428*429* @param Function aCallback430* The function that is called with each mapping.431* @param Object aContext432* Optional. If specified, this object will be the value of `this` every433* time that `aCallback` is called.434* @param aOrder435* Either `SourceMapConsumer.GENERATED_ORDER` or436* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to437* iterate over the mappings sorted by the generated file's line/column438* order or the original's source/line/column order, respectively. Defaults to439* `SourceMapConsumer.GENERATED_ORDER`.440*/441SourceMapConsumer.prototype.eachMapping =442function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {443var context = aContext || null;444var order = aOrder || SourceMapConsumer.GENERATED_ORDER;445446var mappings;447switch (order) {448case SourceMapConsumer.GENERATED_ORDER:449mappings = this._generatedMappings;450break;451case SourceMapConsumer.ORIGINAL_ORDER:452mappings = this._originalMappings;453break;454default:455throw new Error("Unknown order of iteration.");456}457458var sourceRoot = this.sourceRoot;459mappings.map(function (mapping) {460var source = mapping.source;461if (source && sourceRoot) {462source = util.join(sourceRoot, source);463}464return {465source: source,466generatedLine: mapping.generatedLine,467generatedColumn: mapping.generatedColumn,468originalLine: mapping.originalLine,469originalColumn: mapping.originalColumn,470name: mapping.name471};472}).forEach(aCallback, context);473};474475exports.SourceMapConsumer = SourceMapConsumer;476477});478479480