Show More
Commit Description:
fix wrong merge
Commit Description:
fix wrong merge
References:
File last commit:
Show/Diff file:
Action:
node_modules/source-map/lib/source-map-generator.js
| 425 lines
| 14.0 KiB
| application/javascript
| JavascriptLexer
|
r789 | /* -*- 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 | ||||
*/ | ||||
var base64VLQ = require('./base64-vlq'); | ||||
var util = require('./util'); | ||||
var ArraySet = require('./array-set').ArraySet; | ||||
var MappingList = require('./mapping-list').MappingList; | ||||
/** | ||||
* An instance of the SourceMapGenerator represents a source map which is | ||||
* being built incrementally. You may pass an object with the following | ||||
* properties: | ||||
* | ||||
* - file: The filename of the generated source. | ||||
* - sourceRoot: A root for all relative URLs in this source map. | ||||
*/ | ||||
function SourceMapGenerator(aArgs) { | ||||
if (!aArgs) { | ||||
aArgs = {}; | ||||
} | ||||
this._file = util.getArg(aArgs, 'file', null); | ||||
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); | ||||
this._skipValidation = util.getArg(aArgs, 'skipValidation', false); | ||||
this._sources = new ArraySet(); | ||||
this._names = new ArraySet(); | ||||
this._mappings = new MappingList(); | ||||
this._sourcesContents = null; | ||||
} | ||||
SourceMapGenerator.prototype._version = 3; | ||||
/** | ||||
* Creates a new SourceMapGenerator based on a SourceMapConsumer | ||||
* | ||||
* @param aSourceMapConsumer The SourceMap. | ||||
*/ | ||||
SourceMapGenerator.fromSourceMap = | ||||
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { | ||||
var sourceRoot = aSourceMapConsumer.sourceRoot; | ||||
var generator = new SourceMapGenerator({ | ||||
file: aSourceMapConsumer.file, | ||||
sourceRoot: sourceRoot | ||||
}); | ||||
aSourceMapConsumer.eachMapping(function (mapping) { | ||||
var newMapping = { | ||||
generated: { | ||||
line: mapping.generatedLine, | ||||
column: mapping.generatedColumn | ||||
} | ||||
}; | ||||
if (mapping.source != null) { | ||||
newMapping.source = mapping.source; | ||||
if (sourceRoot != null) { | ||||
newMapping.source = util.relative(sourceRoot, newMapping.source); | ||||
} | ||||
newMapping.original = { | ||||
line: mapping.originalLine, | ||||
column: mapping.originalColumn | ||||
}; | ||||
if (mapping.name != null) { | ||||
newMapping.name = mapping.name; | ||||
} | ||||
} | ||||
generator.addMapping(newMapping); | ||||
}); | ||||
aSourceMapConsumer.sources.forEach(function (sourceFile) { | ||||
var sourceRelative = sourceFile; | ||||
if (sourceRoot !== null) { | ||||
sourceRelative = util.relative(sourceRoot, sourceFile); | ||||
} | ||||
if (!generator._sources.has(sourceRelative)) { | ||||
generator._sources.add(sourceRelative); | ||||
} | ||||
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | ||||
if (content != null) { | ||||
generator.setSourceContent(sourceFile, content); | ||||
} | ||||
}); | ||||
return generator; | ||||
}; | ||||
/** | ||||
* Add a single mapping from original source line and column to the generated | ||||
* source's line and column for this source map being created. The mapping | ||||
* object should have the following properties: | ||||
* | ||||
* - generated: An object with the generated line and column positions. | ||||
* - original: An object with the original line and column positions. | ||||
* - source: The original source file (relative to the sourceRoot). | ||||
* - name: An optional original token name for this mapping. | ||||
*/ | ||||
SourceMapGenerator.prototype.addMapping = | ||||
function SourceMapGenerator_addMapping(aArgs) { | ||||
var generated = util.getArg(aArgs, 'generated'); | ||||
var original = util.getArg(aArgs, 'original', null); | ||||
var source = util.getArg(aArgs, 'source', null); | ||||
var name = util.getArg(aArgs, 'name', null); | ||||
if (!this._skipValidation) { | ||||
this._validateMapping(generated, original, source, name); | ||||
} | ||||
if (source != null) { | ||||
source = String(source); | ||||
if (!this._sources.has(source)) { | ||||
this._sources.add(source); | ||||
} | ||||
} | ||||
if (name != null) { | ||||
name = String(name); | ||||
if (!this._names.has(name)) { | ||||
this._names.add(name); | ||||
} | ||||
} | ||||
this._mappings.add({ | ||||
generatedLine: generated.line, | ||||
generatedColumn: generated.column, | ||||
originalLine: original != null && original.line, | ||||
originalColumn: original != null && original.column, | ||||
source: source, | ||||
name: name | ||||
}); | ||||
}; | ||||
/** | ||||
* Set the source content for a source file. | ||||
*/ | ||||
SourceMapGenerator.prototype.setSourceContent = | ||||
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { | ||||
var source = aSourceFile; | ||||
if (this._sourceRoot != null) { | ||||
source = util.relative(this._sourceRoot, source); | ||||
} | ||||
if (aSourceContent != null) { | ||||
// Add the source content to the _sourcesContents map. | ||||
// Create a new _sourcesContents map if the property is null. | ||||
if (!this._sourcesContents) { | ||||
this._sourcesContents = Object.create(null); | ||||
} | ||||
this._sourcesContents[util.toSetString(source)] = aSourceContent; | ||||
} else if (this._sourcesContents) { | ||||
// Remove the source file from the _sourcesContents map. | ||||
// If the _sourcesContents map is empty, set the property to null. | ||||
delete this._sourcesContents[util.toSetString(source)]; | ||||
if (Object.keys(this._sourcesContents).length === 0) { | ||||
this._sourcesContents = null; | ||||
} | ||||
} | ||||
}; | ||||
/** | ||||
* Applies the mappings of a sub-source-map for a specific source file to the | ||||
* source map being generated. Each mapping to the supplied source file is | ||||
* rewritten using the supplied source map. Note: The resolution for the | ||||
* resulting mappings is the minimium of this map and the supplied map. | ||||
* | ||||
* @param aSourceMapConsumer The source map to be applied. | ||||
* @param aSourceFile Optional. The filename of the source file. | ||||
* If omitted, SourceMapConsumer's file property will be used. | ||||
* @param aSourceMapPath Optional. The dirname of the path to the source map | ||||
* to be applied. If relative, it is relative to the SourceMapConsumer. | ||||
* This parameter is needed when the two source maps aren't in the same | ||||
* directory, and the source map to be applied contains relative source | ||||
* paths. If so, those relative source paths need to be rewritten | ||||
* relative to the SourceMapGenerator. | ||||
*/ | ||||
SourceMapGenerator.prototype.applySourceMap = | ||||
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { | ||||
var sourceFile = aSourceFile; | ||||
// If aSourceFile is omitted, we will use the file property of the SourceMap | ||||
if (aSourceFile == null) { | ||||
if (aSourceMapConsumer.file == null) { | ||||
throw new Error( | ||||
'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + | ||||
'or the source map\'s "file" property. Both were omitted.' | ||||
); | ||||
} | ||||
sourceFile = aSourceMapConsumer.file; | ||||
} | ||||
var sourceRoot = this._sourceRoot; | ||||
// Make "sourceFile" relative if an absolute Url is passed. | ||||
if (sourceRoot != null) { | ||||
sourceFile = util.relative(sourceRoot, sourceFile); | ||||
} | ||||
// Applying the SourceMap can add and remove items from the sources and | ||||
// the names array. | ||||
var newSources = new ArraySet(); | ||||
var newNames = new ArraySet(); | ||||
// Find mappings for the "sourceFile" | ||||
this._mappings.unsortedForEach(function (mapping) { | ||||
if (mapping.source === sourceFile && mapping.originalLine != null) { | ||||
// Check if it can be mapped by the source map, then update the mapping. | ||||
var original = aSourceMapConsumer.originalPositionFor({ | ||||
line: mapping.originalLine, | ||||
column: mapping.originalColumn | ||||
}); | ||||
if (original.source != null) { | ||||
// Copy mapping | ||||
mapping.source = original.source; | ||||
if (aSourceMapPath != null) { | ||||
mapping.source = util.join(aSourceMapPath, mapping.source) | ||||
} | ||||
if (sourceRoot != null) { | ||||
mapping.source = util.relative(sourceRoot, mapping.source); | ||||
} | ||||
mapping.originalLine = original.line; | ||||
mapping.originalColumn = original.column; | ||||
if (original.name != null) { | ||||
mapping.name = original.name; | ||||
} | ||||
} | ||||
} | ||||
var source = mapping.source; | ||||
if (source != null && !newSources.has(source)) { | ||||
newSources.add(source); | ||||
} | ||||
var name = mapping.name; | ||||
if (name != null && !newNames.has(name)) { | ||||
newNames.add(name); | ||||
} | ||||
}, this); | ||||
this._sources = newSources; | ||||
this._names = newNames; | ||||
// Copy sourcesContents of applied map. | ||||
aSourceMapConsumer.sources.forEach(function (sourceFile) { | ||||
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | ||||
if (content != null) { | ||||
if (aSourceMapPath != null) { | ||||
sourceFile = util.join(aSourceMapPath, sourceFile); | ||||
} | ||||
if (sourceRoot != null) { | ||||
sourceFile = util.relative(sourceRoot, sourceFile); | ||||
} | ||||
this.setSourceContent(sourceFile, content); | ||||
} | ||||
}, this); | ||||
}; | ||||
/** | ||||
* A mapping can have one of the three levels of data: | ||||
* | ||||
* 1. Just the generated position. | ||||
* 2. The Generated position, original position, and original source. | ||||
* 3. Generated and original position, original source, as well as a name | ||||
* token. | ||||
* | ||||
* To maintain consistency, we validate that any new mapping being added falls | ||||
* in to one of these categories. | ||||
*/ | ||||
SourceMapGenerator.prototype._validateMapping = | ||||
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, | ||||
aName) { | ||||
// When aOriginal is truthy but has empty values for .line and .column, | ||||
// it is most likely a programmer error. In this case we throw a very | ||||
// specific error message to try to guide them the right way. | ||||
// For example: https://github.com/Polymer/polymer-bundler/pull/519 | ||||
if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { | ||||
throw new Error( | ||||
'original.line and original.column are not numbers -- you probably meant to omit ' + | ||||
'the original mapping entirely and only map the generated position. If so, pass ' + | ||||
'null for the original mapping instead of an object with empty or null values.' | ||||
); | ||||
} | ||||
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | ||||
&& aGenerated.line > 0 && aGenerated.column >= 0 | ||||
&& !aOriginal && !aSource && !aName) { | ||||
// Case 1. | ||||
return; | ||||
} | ||||
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | ||||
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal | ||||
&& aGenerated.line > 0 && aGenerated.column >= 0 | ||||
&& aOriginal.line > 0 && aOriginal.column >= 0 | ||||
&& aSource) { | ||||
// Cases 2 and 3. | ||||
return; | ||||
} | ||||
else { | ||||
throw new Error('Invalid mapping: ' + JSON.stringify({ | ||||
generated: aGenerated, | ||||
source: aSource, | ||||
original: aOriginal, | ||||
name: aName | ||||
})); | ||||
} | ||||
}; | ||||
/** | ||||
* Serialize the accumulated mappings in to the stream of base 64 VLQs | ||||
* specified by the source map format. | ||||
*/ | ||||
SourceMapGenerator.prototype._serializeMappings = | ||||
function SourceMapGenerator_serializeMappings() { | ||||
var previousGeneratedColumn = 0; | ||||
var previousGeneratedLine = 1; | ||||
var previousOriginalColumn = 0; | ||||
var previousOriginalLine = 0; | ||||
var previousName = 0; | ||||
var previousSource = 0; | ||||
var result = ''; | ||||
var next; | ||||
var mapping; | ||||
var nameIdx; | ||||
var sourceIdx; | ||||
var mappings = this._mappings.toArray(); | ||||
for (var i = 0, len = mappings.length; i < len; i++) { | ||||
mapping = mappings[i]; | ||||
next = '' | ||||
if (mapping.generatedLine !== previousGeneratedLine) { | ||||
previousGeneratedColumn = 0; | ||||
while (mapping.generatedLine !== previousGeneratedLine) { | ||||
next += ';'; | ||||
previousGeneratedLine++; | ||||
} | ||||
} | ||||
else { | ||||
if (i > 0) { | ||||
if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { | ||||
continue; | ||||
} | ||||
next += ','; | ||||
} | ||||
} | ||||
next += base64VLQ.encode(mapping.generatedColumn | ||||
- previousGeneratedColumn); | ||||
previousGeneratedColumn = mapping.generatedColumn; | ||||
if (mapping.source != null) { | ||||
sourceIdx = this._sources.indexOf(mapping.source); | ||||
next += base64VLQ.encode(sourceIdx - previousSource); | ||||
previousSource = sourceIdx; | ||||
// lines are stored 0-based in SourceMap spec version 3 | ||||
next += base64VLQ.encode(mapping.originalLine - 1 | ||||
- previousOriginalLine); | ||||
previousOriginalLine = mapping.originalLine - 1; | ||||
next += base64VLQ.encode(mapping.originalColumn | ||||
- previousOriginalColumn); | ||||
previousOriginalColumn = mapping.originalColumn; | ||||
if (mapping.name != null) { | ||||
nameIdx = this._names.indexOf(mapping.name); | ||||
next += base64VLQ.encode(nameIdx - previousName); | ||||
previousName = nameIdx; | ||||
} | ||||
} | ||||
result += next; | ||||
} | ||||
return result; | ||||
}; | ||||
SourceMapGenerator.prototype._generateSourcesContent = | ||||
function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { | ||||
return aSources.map(function (source) { | ||||
if (!this._sourcesContents) { | ||||
return null; | ||||
} | ||||
if (aSourceRoot != null) { | ||||
source = util.relative(aSourceRoot, source); | ||||
} | ||||
var key = util.toSetString(source); | ||||
return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) | ||||
? this._sourcesContents[key] | ||||
: null; | ||||
}, this); | ||||
}; | ||||
/** | ||||
* Externalize the source map. | ||||
*/ | ||||
SourceMapGenerator.prototype.toJSON = | ||||
function SourceMapGenerator_toJSON() { | ||||
var map = { | ||||
version: this._version, | ||||
sources: this._sources.toArray(), | ||||
names: this._names.toArray(), | ||||
mappings: this._serializeMappings() | ||||
}; | ||||
if (this._file != null) { | ||||
map.file = this._file; | ||||
} | ||||
if (this._sourceRoot != null) { | ||||
map.sourceRoot = this._sourceRoot; | ||||
} | ||||
if (this._sourcesContents) { | ||||
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); | ||||
} | ||||
return map; | ||||
}; | ||||
/** | ||||
* Render the source map being generated to a string. | ||||
*/ | ||||
SourceMapGenerator.prototype.toString = | ||||
function SourceMapGenerator_toString() { | ||||
return JSON.stringify(this.toJSON()); | ||||
}; | ||||
exports.SourceMapGenerator = SourceMapGenerator; | ||||