| /* -*- Mode: js; js-indent-level: 2; -*- */ |
| /* |
| * Copyright 2011 Mozilla Foundation and contributors |
| * Licensed under the New BSD license. See LICENSE or: |
| * http://opensource.org/licenses/BSD-3-Clause |
| */ |
| if (typeof define !== 'function') { |
| var define = require('amdefine')(module, require); |
| } |
| define(function (require, exports, module) { |
| |
| var util = require('./util'); |
| |
| function SourceMapConsumer(aSourceMap) { |
| var sourceMap = aSourceMap; |
| if (typeof aSourceMap === 'string') { |
| sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); |
| } |
| |
| // We do late requires because the subclasses require() this file. |
| if (sourceMap.sections != null) { |
| var indexedSourceMapConsumer = require('./indexed-source-map-consumer'); |
| return new indexedSourceMapConsumer.IndexedSourceMapConsumer(sourceMap); |
| } else { |
| var basicSourceMapConsumer = require('./basic-source-map-consumer'); |
| return new basicSourceMapConsumer.BasicSourceMapConsumer(sourceMap); |
| } |
| } |
| |
| SourceMapConsumer.fromSourceMap = function(aSourceMap) { |
| var basicSourceMapConsumer = require('./basic-source-map-consumer'); |
| return basicSourceMapConsumer.BasicSourceMapConsumer |
| .fromSourceMap(aSourceMap); |
| } |
| |
| /** |
| * The version of the source mapping spec that we are consuming. |
| */ |
| SourceMapConsumer.prototype._version = 3; |
| |
| |
| // `__generatedMappings` and `__originalMappings` are arrays that hold the |
| // parsed mapping coordinates from the source map's "mappings" attribute. They |
| // are lazily instantiated, accessed via the `_generatedMappings` and |
| // `_originalMappings` getters respectively, and we only parse the mappings |
| // and create these arrays once queried for a source location. We jump through |
| // these hoops because there can be many thousands of mappings, and parsing |
| // them is expensive, so we only want to do it if we must. |
| // |
| // Each object in the arrays is of the form: |
| // |
| // { |
| // generatedLine: The line number in the generated code, |
| // generatedColumn: The column number in the generated code, |
| // source: The path to the original source file that generated this |
| // chunk of code, |
| // originalLine: The line number in the original source that |
| // corresponds to this chunk of generated code, |
| // originalColumn: The column number in the original source that |
| // corresponds to this chunk of generated code, |
| // name: The name of the original symbol which generated this chunk of |
| // code. |
| // } |
| // |
| // All properties except for `generatedLine` and `generatedColumn` can be |
| // `null`. |
| // |
| // `_generatedMappings` is ordered by the generated positions. |
| // |
| // `_originalMappings` is ordered by the original positions. |
| |
| SourceMapConsumer.prototype.__generatedMappings = null; |
| Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { |
| get: function () { |
| if (!this.__generatedMappings) { |
| this.__generatedMappings = []; |
| this.__originalMappings = []; |
| this._parseMappings(this._mappings, this.sourceRoot); |
| } |
| |
| return this.__generatedMappings; |
| } |
| }); |
| |
| SourceMapConsumer.prototype.__originalMappings = null; |
| Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { |
| get: function () { |
| if (!this.__originalMappings) { |
| this.__generatedMappings = []; |
| this.__originalMappings = []; |
| this._parseMappings(this._mappings, this.sourceRoot); |
| } |
| |
| return this.__originalMappings; |
| } |
| }); |
| |
| SourceMapConsumer.prototype._nextCharIsMappingSeparator = |
| function SourceMapConsumer_nextCharIsMappingSeparator(aStr) { |
| var c = aStr.charAt(0); |
| return c === ";" || c === ","; |
| }; |
| |
| /** |
| * Parse the mappings in a string in to a data structure which we can easily |
| * query (the ordered arrays in the `this.__generatedMappings` and |
| * `this.__originalMappings` properties). |
| */ |
| SourceMapConsumer.prototype._parseMappings = |
| function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { |
| throw new Error("Subclasses must implement _parseMappings"); |
| }; |
| |
| SourceMapConsumer.GENERATED_ORDER = 1; |
| SourceMapConsumer.ORIGINAL_ORDER = 2; |
| |
| /** |
| * Iterate over each mapping between an original source/line/column and a |
| * generated line/column in this source map. |
| * |
| * @param Function aCallback |
| * The function that is called with each mapping. |
| * @param Object aContext |
| * Optional. If specified, this object will be the value of `this` every |
| * time that `aCallback` is called. |
| * @param aOrder |
| * Either `SourceMapConsumer.GENERATED_ORDER` or |
| * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to |
| * iterate over the mappings sorted by the generated file's line/column |
| * order or the original's source/line/column order, respectively. Defaults to |
| * `SourceMapConsumer.GENERATED_ORDER`. |
| */ |
| SourceMapConsumer.prototype.eachMapping = |
| function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { |
| var context = aContext || null; |
| var order = aOrder || SourceMapConsumer.GENERATED_ORDER; |
| |
| var mappings; |
| switch (order) { |
| case SourceMapConsumer.GENERATED_ORDER: |
| mappings = this._generatedMappings; |
| break; |
| case SourceMapConsumer.ORIGINAL_ORDER: |
| mappings = this._originalMappings; |
| break; |
| default: |
| throw new Error("Unknown order of iteration."); |
| } |
| |
| var sourceRoot = this.sourceRoot; |
| mappings.map(function (mapping) { |
| var source = mapping.source; |
| if (source != null && sourceRoot != null) { |
| source = util.join(sourceRoot, source); |
| } |
| return { |
| source: source, |
| generatedLine: mapping.generatedLine, |
| generatedColumn: mapping.generatedColumn, |
| originalLine: mapping.originalLine, |
| originalColumn: mapping.originalColumn, |
| name: mapping.name |
| }; |
| }).forEach(aCallback, context); |
| }; |
| |
| /** |
| * Returns all generated line and column information for the original source |
| * and line provided. The only argument is an object with the following |
| * properties: |
| * |
| * - source: The filename of the original source. |
| * - line: The line number in the original source. |
| * |
| * and an array of objects is returned, each with the following properties: |
| * |
| * - line: The line number in the generated source, or null. |
| * - column: The column number in the generated source, or null. |
| */ |
| SourceMapConsumer.prototype.allGeneratedPositionsFor = |
| function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { |
| // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping |
| // returns the index of the closest mapping less than the needle. By |
| // setting needle.originalColumn to Infinity, we thus find the last |
| // mapping for the given line, provided such a mapping exists. |
| var needle = { |
| source: util.getArg(aArgs, 'source'), |
| originalLine: util.getArg(aArgs, 'line'), |
| originalColumn: Infinity |
| }; |
| |
| if (this.sourceRoot != null) { |
| needle.source = util.relative(this.sourceRoot, needle.source); |
| } |
| |
| var mappings = []; |
| |
| var index = this._findMapping(needle, |
| this._originalMappings, |
| "originalLine", |
| "originalColumn", |
| util.compareByOriginalPositions); |
| if (index >= 0) { |
| var mapping = this._originalMappings[index]; |
| |
| while (mapping && mapping.originalLine === needle.originalLine) { |
| mappings.push({ |
| line: util.getArg(mapping, 'generatedLine', null), |
| column: util.getArg(mapping, 'generatedColumn', null), |
| lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) |
| }); |
| |
| mapping = this._originalMappings[--index]; |
| } |
| } |
| |
| return mappings.reverse(); |
| }; |
| |
| exports.SourceMapConsumer = SourceMapConsumer; |
| |
| }); |