| | |
| | | * console.log(xSquared); |
| | | * ``` |
| | | */ |
| | | static with(rawSourceMap, sourceMapUrl, f) { |
| | | // Note: The `acorn` version that `webpack` currently depends on doesn't |
| | | // support `async` functions, and the nodes that we support don't all have |
| | | // `.finally`. Therefore, this is written a bit more convolutedly than it |
| | | // should really be. |
| | | |
| | | let consumer = null; |
| | | const promise = new SourceMapConsumer(rawSourceMap, sourceMapUrl); |
| | | return promise |
| | | .then(c => { |
| | | consumer = c; |
| | | return f(c); |
| | | }) |
| | | .then(x => { |
| | | if (consumer) { |
| | | consumer.destroy(); |
| | | } |
| | | return x; |
| | | }, e => { |
| | | if (consumer) { |
| | | consumer.destroy(); |
| | | } |
| | | throw e; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 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). |
| | | */ |
| | | _parseMappings(aStr, aSourceRoot) { |
| | | throw new Error("Subclasses must implement _parseMappings"); |
| | | static async with(rawSourceMap, sourceMapUrl, f) { |
| | | const consumer = await new SourceMapConsumer(rawSourceMap, sourceMapUrl); |
| | | try { |
| | | return await f(consumer); |
| | | } finally { |
| | | consumer.destroy(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | const version = util.getArg(sourceMap, "version"); |
| | | let sources = util.getArg(sourceMap, "sources"); |
| | | const sources = util.getArg(sourceMap, "sources").map(String); |
| | | // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which |
| | | // requires the array) to play nice here. |
| | | const names = util.getArg(sourceMap, "names", []); |
| | | let sourceRoot = util.getArg(sourceMap, "sourceRoot", null); |
| | | const sourceRoot = util.getArg(sourceMap, "sourceRoot", null); |
| | | const sourcesContent = util.getArg(sourceMap, "sourcesContent", null); |
| | | const mappings = util.getArg(sourceMap, "mappings"); |
| | | const file = util.getArg(sourceMap, "file", null); |
| | |
| | | throw new Error("Unsupported version: " + version); |
| | | } |
| | | |
| | | if (sourceRoot) { |
| | | sourceRoot = util.normalize(sourceRoot); |
| | | } |
| | | |
| | | sources = sources |
| | | .map(String) |
| | | // Some source maps produce relative source paths like "./foo.js" instead of |
| | | // "foo.js". Normalize these first so that future comparisons will succeed. |
| | | // See bugzil.la/1090768. |
| | | .map(util.normalize) |
| | | // Always ensure that absolute sources are internally stored relative to |
| | | // the source root, if the source root is absolute. Not doing this would |
| | | // be particularly problematic when the source root is a prefix of the |
| | | // source (valid, but why??). See github issue #199 and bugzil.la/1188982. |
| | | .map(function(source) { |
| | | return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) |
| | | ? util.relative(sourceRoot, source) |
| | | : source; |
| | | }); |
| | | that._sourceLookupCache = new Map(); |
| | | |
| | | // Pass `true` below to allow duplicate names and sources. While source maps |
| | | // are intended to be compressed and deduplicated, the TypeScript compiler |
| | |
| | | that._names = ArraySet.fromArray(names.map(String), true); |
| | | that._sources = ArraySet.fromArray(sources, true); |
| | | |
| | | that._absoluteSources = that._sources.toArray().map(function(s) { |
| | | that._absoluteSources = ArraySet.fromArray(that._sources.toArray().map(function(s) { |
| | | return util.computeSourceURL(sourceRoot, s, aSourceMapURL); |
| | | }); |
| | | }), true); |
| | | |
| | | that.sourceRoot = sourceRoot; |
| | | that.sourcesContent = sourcesContent; |
| | |
| | | * found. |
| | | */ |
| | | _findSourceIndex(aSource) { |
| | | let relativeSource = aSource; |
| | | if (this.sourceRoot != null) { |
| | | relativeSource = util.relative(this.sourceRoot, relativeSource); |
| | | // In the most common usecases, we'll be constantly looking up the index for the same source |
| | | // files, so we cache the index lookup to avoid constantly recomputing the full URLs. |
| | | const cachedIndex = this._sourceLookupCache.get(aSource); |
| | | if (typeof cachedIndex === "number") { |
| | | return cachedIndex; |
| | | } |
| | | |
| | | if (this._sources.has(relativeSource)) { |
| | | return this._sources.indexOf(relativeSource); |
| | | // Treat the source as map-relative overall by default. |
| | | const sourceAsMapRelative = util.computeSourceURL(null, aSource, this._sourceMapURL); |
| | | if (this._absoluteSources.has(sourceAsMapRelative)) { |
| | | const index = this._absoluteSources.indexOf(sourceAsMapRelative); |
| | | this._sourceLookupCache.set(aSource, index); |
| | | return index; |
| | | } |
| | | |
| | | // Maybe aSource is an absolute URL as returned by |sources|. In |
| | | // this case we can't simply undo the transform. |
| | | for (let i = 0; i < this._absoluteSources.length; ++i) { |
| | | if (this._absoluteSources[i] == aSource) { |
| | | return i; |
| | | } |
| | | // Fall back to treating the source as sourceRoot-relative. |
| | | const sourceAsSourceRootRelative = util.computeSourceURL(this.sourceRoot, aSource, this._sourceMapURL); |
| | | if (this._absoluteSources.has(sourceAsSourceRootRelative)) { |
| | | const index = this._absoluteSources.indexOf(sourceAsSourceRootRelative); |
| | | this._sourceLookupCache.set(aSource, index); |
| | | return index; |
| | | } |
| | | |
| | | // To avoid this cache growing forever, we do not cache lookup misses. |
| | | return -1; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | get sources() { |
| | | return this._absoluteSources.slice(); |
| | | return this._absoluteSources.toArray(); |
| | | } |
| | | |
| | | _getMappingsPtr() { |
| | | if (this._mappingsPtr === 0) { |
| | | this._parseMappings(this._mappings, this.sourceRoot); |
| | | this._parseMappings(); |
| | | } |
| | | |
| | | return this._mappingsPtr; |
| | |
| | | * query (the ordered arrays in the `this.__generatedMappings` and |
| | | * `this.__originalMappings` properties). |
| | | */ |
| | | _parseMappings(aStr, aSourceRoot) { |
| | | _parseMappings() { |
| | | const aStr = this._mappings; |
| | | const size = aStr.length; |
| | | |
| | | const mappingsBufPtr = this._wasm.exports.allocate_mappings(size); |
| | |
| | | eachMapping(aCallback, aContext, aOrder) { |
| | | const context = aContext || null; |
| | | const order = aOrder || SourceMapConsumer.GENERATED_ORDER; |
| | | const sourceRoot = this.sourceRoot; |
| | | |
| | | this._wasm.withMappingCallback( |
| | | mapping => { |
| | | if (mapping.source !== null) { |
| | | mapping.source = this._sources.at(mapping.source); |
| | | mapping.source = util.computeSourceURL(sourceRoot, mapping.source, this._sourceMapURL); |
| | | mapping.source = this._absoluteSources.at(mapping.source); |
| | | |
| | | if (mapping.name !== null) { |
| | | mapping.name = this._names.at(mapping.name); |
| | | } |
| | | } |
| | | if (this._computedColumnSpans && mapping.lastGeneratedColumn === null) { |
| | | mapping.lastGeneratedColumn = Infinity; |
| | | } |
| | | |
| | | aCallback.call(context, mapping); |
| | |
| | | if (mapping.generatedLine === needle.generatedLine) { |
| | | let source = util.getArg(mapping, "source", null); |
| | | if (source !== null) { |
| | | source = this._sources.at(source); |
| | | source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL); |
| | | source = this._absoluteSources.at(source); |
| | | } |
| | | |
| | | let name = util.getArg(mapping, "name", null); |
| | |
| | | return this.sourcesContent[index]; |
| | | } |
| | | |
| | | let relativeSource = aSource; |
| | | if (this.sourceRoot != null) { |
| | | relativeSource = util.relative(this.sourceRoot, relativeSource); |
| | | } |
| | | |
| | | let url; |
| | | if (this.sourceRoot != null |
| | | && (url = util.urlParse(this.sourceRoot))) { |
| | | // XXX: file:// URIs and absolute paths lead to unexpected behavior for |
| | | // many users. We can help them out when they expect file:// URIs to |
| | | // behave like it would if they were running a local HTTP server. See |
| | | // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. |
| | | const fileUriAbsPath = relativeSource.replace(/^file:\/\//, ""); |
| | | if (url.scheme == "file" |
| | | && this._sources.has(fileUriAbsPath)) { |
| | | return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]; |
| | | } |
| | | |
| | | if ((!url.path || url.path == "/") |
| | | && this._sources.has("/" + relativeSource)) { |
| | | return this.sourcesContent[this._sources.indexOf("/" + relativeSource)]; |
| | | } |
| | | } |
| | | |
| | | // This function is used recursively from |
| | | // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we |
| | | // don't want to throw if we can't find the source - we just want to |
| | |
| | | return null; |
| | | } |
| | | |
| | | throw new Error('"' + relativeSource + '" is not in the SourceMap.'); |
| | | throw new Error('"' + aSource + '" is not in the SourceMap.'); |
| | | } |
| | | |
| | | /** |
| | |
| | | throw new Error("Unsupported version: " + version); |
| | | } |
| | | |
| | | that._sources = new ArraySet(); |
| | | that._names = new ArraySet(); |
| | | that.__generatedMappings = null; |
| | | that.__originalMappings = null; |
| | | that.__generatedMappingsUnsorted = null; |
| | | that.__originalMappingsUnsorted = null; |
| | | |
| | | let lastOffset = { |
| | | line: -1, |
| | | column: 0 |
| | |
| | | return that; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | // `__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. |
| | | get _generatedMappings() { |
| | | if (!this.__generatedMappings) { |
| | | this._sortGeneratedMappings(); |
| | | } |
| | | |
| | | return this.__generatedMappings; |
| | | } |
| | | |
| | | get _originalMappings() { |
| | | if (!this.__originalMappings) { |
| | | this._sortOriginalMappings(); |
| | | } |
| | | |
| | | return this.__originalMappings; |
| | | } |
| | | |
| | | get _generatedMappingsUnsorted() { |
| | | if (!this.__generatedMappingsUnsorted) { |
| | | this._parseMappings(this._mappings, this.sourceRoot); |
| | | } |
| | | |
| | | return this.__generatedMappingsUnsorted; |
| | | } |
| | | |
| | | get _originalMappingsUnsorted() { |
| | | if (!this.__originalMappingsUnsorted) { |
| | | this._parseMappings(this._mappings, this.sourceRoot); |
| | | } |
| | | |
| | | return this.__originalMappingsUnsorted; |
| | | } |
| | | |
| | | _sortGeneratedMappings() { |
| | | const mappings = this._generatedMappingsUnsorted; |
| | | mappings.sort(util.compareByGeneratedPositionsDeflated); |
| | | this.__generatedMappings = mappings; |
| | | } |
| | | |
| | | _sortOriginalMappings() { |
| | | const mappings = this._originalMappingsUnsorted; |
| | | mappings.sort(util.compareByOriginalPositions); |
| | | this.__originalMappings = mappings; |
| | | } |
| | | |
| | | /** |
| | |
| | | throw new Error('"' + aSource + '" is not in the SourceMap.'); |
| | | } |
| | | |
| | | _findSectionIndex(source) { |
| | | for (let i = 0; i < this._sections.length; i++) { |
| | | const { consumer } = this._sections[i]; |
| | | if (consumer._findSourceIndex(source) !== -1) { |
| | | return i; |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | /** |
| | | * Returns the generated line and column information for the original source, |
| | | * line, and column positions provided. The only argument is an object with |
| | |
| | | * The column number is 0-based. |
| | | */ |
| | | generatedPositionFor(aArgs) { |
| | | for (let i = 0; i < this._sections.length; i++) { |
| | | const section = this._sections[i]; |
| | | const index = this._findSectionIndex(util.getArg(aArgs, "source")); |
| | | const section = index >= 0 ? this._sections[index] : null; |
| | | const nextSection = |
| | | index >= 0 && index + 1 < this._sections.length |
| | | ? this._sections[index + 1] |
| | | : null; |
| | | |
| | | // Only consider this section if the requested source is in the list of |
| | | // sources of the consumer. |
| | | if (section.consumer._findSourceIndex(util.getArg(aArgs, "source")) === -1) { |
| | | continue; |
| | | const generatedPosition = |
| | | section && section.consumer.generatedPositionFor(aArgs); |
| | | if (generatedPosition && generatedPosition.line !== null) { |
| | | const lineShift = section.generatedOffset.generatedLine - 1; |
| | | const columnShift = section.generatedOffset.generatedColumn - 1; |
| | | |
| | | if (generatedPosition.line === 1) { |
| | | generatedPosition.column += columnShift; |
| | | if (typeof generatedPosition.lastColumn === "number") { |
| | | generatedPosition.lastColumn += columnShift; |
| | | } |
| | | } |
| | | const generatedPosition = section.consumer.generatedPositionFor(aArgs); |
| | | if (generatedPosition) { |
| | | const ret = { |
| | | line: generatedPosition.line + |
| | | (section.generatedOffset.generatedLine - 1), |
| | | column: generatedPosition.column + |
| | | (section.generatedOffset.generatedLine === generatedPosition.line |
| | | ? section.generatedOffset.generatedColumn - 1 |
| | | : 0) |
| | | }; |
| | | return ret; |
| | | |
| | | if ( |
| | | generatedPosition.lastColumn === Infinity && |
| | | nextSection && |
| | | generatedPosition.line === nextSection.generatedOffset.generatedLine |
| | | ) { |
| | | generatedPosition.lastColumn = |
| | | nextSection.generatedOffset.generatedColumn - 2; |
| | | } |
| | | generatedPosition.line += lineShift; |
| | | |
| | | return generatedPosition; |
| | | } |
| | | |
| | | return { |
| | | line: null, |
| | | column: null |
| | | column: null, |
| | | lastColumn: null |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * 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). |
| | | */ |
| | | _parseMappings(aStr, aSourceRoot) { |
| | | const generatedMappings = this.__generatedMappingsUnsorted = []; |
| | | const originalMappings = this.__originalMappingsUnsorted = []; |
| | | for (let i = 0; i < this._sections.length; i++) { |
| | | const section = this._sections[i]; |
| | | |
| | | const sectionMappings = []; |
| | | section.consumer.eachMapping(m => sectionMappings.push(m)); |
| | | |
| | | for (let j = 0; j < sectionMappings.length; j++) { |
| | | const mapping = sectionMappings[j]; |
| | | |
| | | // TODO: test if null is correct here. The original code used |
| | | // `source`, which would actually have gotten used as null because |
| | | // var's get hoisted. |
| | | // See: https://github.com/mozilla/source-map/issues/333 |
| | | let source = util.computeSourceURL(section.consumer.sourceRoot, null, this._sourceMapURL); |
| | | this._sources.add(source); |
| | | source = this._sources.indexOf(source); |
| | | |
| | | let name = null; |
| | | if (mapping.name) { |
| | | this._names.add(mapping.name); |
| | | name = this._names.indexOf(mapping.name); |
| | | } |
| | | |
| | | // The mappings coming from the consumer for the section have |
| | | // generated positions relative to the start of the section, so we |
| | | // need to offset them to be relative to the start of the concatenated |
| | | // generated file. |
| | | const adjustedMapping = { |
| | | source, |
| | | generatedLine: mapping.generatedLine + |
| | | (section.generatedOffset.generatedLine - 1), |
| | | generatedColumn: mapping.generatedColumn + |
| | | (section.generatedOffset.generatedLine === mapping.generatedLine |
| | | ? section.generatedOffset.generatedColumn - 1 |
| | | : 0), |
| | | originalLine: mapping.originalLine, |
| | | originalColumn: mapping.originalColumn, |
| | | name |
| | | }; |
| | | |
| | | generatedMappings.push(adjustedMapping); |
| | | if (typeof adjustedMapping.originalLine === "number") { |
| | | originalMappings.push(adjustedMapping); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | eachMapping(aCallback, aContext, aOrder) { |
| | | const context = aContext || null; |
| | | const order = aOrder || SourceMapConsumer.GENERATED_ORDER; |
| | | |
| | | let 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."); |
| | | } |
| | | |
| | | const sourceRoot = this.sourceRoot; |
| | | mappings.map(function(mapping) { |
| | | let source = null; |
| | | if (mapping.source !== null) { |
| | | source = this._sources.at(mapping.source); |
| | | source = util.computeSourceURL(sourceRoot, source, this._sourceMapURL); |
| | | } |
| | | return { |
| | | source, |
| | | generatedLine: mapping.generatedLine, |
| | | generatedColumn: mapping.generatedColumn, |
| | | originalLine: mapping.originalLine, |
| | | originalColumn: mapping.originalColumn, |
| | | name: mapping.name === null ? null : this._names.at(mapping.name) |
| | | }; |
| | | }, this).forEach(aCallback, context); |
| | | } |
| | | |
| | | /** |
| | | * Find the mapping that best matches the hypothetical "needle" mapping that |
| | | * we are searching for in the given "haystack" of mappings. |
| | | */ |
| | | _findMapping(aNeedle, aMappings, aLineName, |
| | | aColumnName, aComparator, aBias) { |
| | | // To return the position we are searching for, we must first find the |
| | | // mapping for the given position and then return the opposite position it |
| | | // points to. Because the mappings are sorted, we can use binary search to |
| | | // find the best mapping. |
| | | |
| | | if (aNeedle[aLineName] <= 0) { |
| | | throw new TypeError("Line must be greater than or equal to 1, got " |
| | | + aNeedle[aLineName]); |
| | | } |
| | | if (aNeedle[aColumnName] < 0) { |
| | | throw new TypeError("Column must be greater than or equal to 0, got " |
| | | + aNeedle[aColumnName]); |
| | | } |
| | | |
| | | return binarySearch.search(aNeedle, aMappings, aComparator, aBias); |
| | | } |
| | | |
| | | allGeneratedPositionsFor(aArgs) { |
| | | const line = util.getArg(aArgs, "line"); |
| | | const index = this._findSectionIndex(util.getArg(aArgs, "source")); |
| | | const section = index >= 0 ? this._sections[index] : null; |
| | | const nextSection = |
| | | index >= 0 && index + 1 < this._sections.length |
| | | ? this._sections[index + 1] |
| | | : null; |
| | | |
| | | // 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 0, we thus find the last mapping for |
| | | // the given line, provided such a mapping exists. |
| | | const needle = { |
| | | source: util.getArg(aArgs, "source"), |
| | | originalLine: line, |
| | | originalColumn: util.getArg(aArgs, "column", 0) |
| | | }; |
| | | if (!section) return []; |
| | | |
| | | needle.source = this._findSourceIndex(needle.source); |
| | | if (needle.source < 0) { |
| | | return []; |
| | | } |
| | | return section.consumer.allGeneratedPositionsFor(aArgs).map( |
| | | generatedPosition => { |
| | | const lineShift = section.generatedOffset.generatedLine - 1; |
| | | const columnShift = section.generatedOffset.generatedColumn - 1; |
| | | |
| | | if (needle.originalLine < 1) { |
| | | throw new Error("Line numbers must be >= 1"); |
| | | } |
| | | |
| | | if (needle.originalColumn < 0) { |
| | | throw new Error("Column numbers must be >= 0"); |
| | | } |
| | | |
| | | const mappings = []; |
| | | |
| | | let index = this._findMapping(needle, |
| | | this._originalMappings, |
| | | "originalLine", |
| | | "originalColumn", |
| | | util.compareByOriginalPositions, |
| | | binarySearch.LEAST_UPPER_BOUND); |
| | | if (index >= 0) { |
| | | let mapping = this._originalMappings[index]; |
| | | |
| | | if (aArgs.column === undefined) { |
| | | const originalLine = mapping.originalLine; |
| | | |
| | | // Iterate until either we run out of mappings, or we run into |
| | | // a mapping for a different line than the one we found. Since |
| | | // mappings are sorted, this is guaranteed to find all mappings for |
| | | // the line we found. |
| | | while (mapping && mapping.originalLine === originalLine) { |
| | | let lastColumn = mapping.lastGeneratedColumn; |
| | | if (this._computedColumnSpans && lastColumn === null) { |
| | | lastColumn = Infinity; |
| | | if (generatedPosition.line === 1) { |
| | | generatedPosition.column += columnShift; |
| | | if (typeof generatedPosition.lastColumn === "number") { |
| | | generatedPosition.lastColumn += columnShift; |
| | | } |
| | | mappings.push({ |
| | | line: util.getArg(mapping, "generatedLine", null), |
| | | column: util.getArg(mapping, "generatedColumn", null), |
| | | lastColumn, |
| | | }); |
| | | |
| | | mapping = this._originalMappings[++index]; |
| | | } |
| | | } else { |
| | | const originalColumn = mapping.originalColumn; |
| | | |
| | | // Iterate until either we run out of mappings, or we run into |
| | | // a mapping for a different line than the one we were searching for. |
| | | // Since mappings are sorted, this is guaranteed to find all mappings for |
| | | // the line we are searching for. |
| | | while (mapping && |
| | | mapping.originalLine === line && |
| | | mapping.originalColumn == originalColumn) { |
| | | let lastColumn = mapping.lastGeneratedColumn; |
| | | if (this._computedColumnSpans && lastColumn === null) { |
| | | lastColumn = Infinity; |
| | | } |
| | | mappings.push({ |
| | | line: util.getArg(mapping, "generatedLine", null), |
| | | column: util.getArg(mapping, "generatedColumn", null), |
| | | lastColumn, |
| | | }); |
| | | |
| | | mapping = this._originalMappings[++index]; |
| | | if ( |
| | | generatedPosition.lastColumn === Infinity && |
| | | nextSection && |
| | | generatedPosition.line === nextSection.generatedOffset.generatedLine |
| | | ) { |
| | | generatedPosition.lastColumn = |
| | | nextSection.generatedOffset.generatedColumn - 2; |
| | | } |
| | | generatedPosition.line += lineShift; |
| | | |
| | | return generatedPosition; |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | |
| | | return mappings; |
| | | eachMapping(aCallback, aContext, aOrder) { |
| | | this._sections.forEach((section, index) => { |
| | | const nextSection = |
| | | index + 1 < this._sections.length |
| | | ? this._sections[index + 1] |
| | | : null; |
| | | const { generatedOffset } = section; |
| | | |
| | | const lineShift = generatedOffset.generatedLine - 1; |
| | | const columnShift = generatedOffset.generatedColumn - 1; |
| | | |
| | | section.consumer.eachMapping(function(mapping) { |
| | | if (mapping.generatedLine === 1) { |
| | | mapping.generatedColumn += columnShift; |
| | | |
| | | if (typeof mapping.lastGeneratedColumn === "number") { |
| | | mapping.lastGeneratedColumn += columnShift; |
| | | } |
| | | } |
| | | |
| | | if ( |
| | | mapping.lastGeneratedColumn === Infinity && |
| | | nextSection && |
| | | mapping.generatedLine === nextSection.generatedOffset.generatedLine |
| | | ) { |
| | | mapping.lastGeneratedColumn = |
| | | nextSection.generatedOffset.generatedColumn - 2; |
| | | } |
| | | mapping.generatedLine += lineShift; |
| | | |
| | | aCallback.call(this, mapping); |
| | | }, aContext, aOrder); |
| | | }); |
| | | } |
| | | |
| | | computeColumnSpans() { |
| | | for (let i = 0; i < this._sections.length; i++) { |
| | | this._sections[i].consumer.computeColumnSpans(); |
| | | } |
| | | } |
| | | |
| | | destroy() { |