.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / postcss-less / node_modules / source-map / lib / source-map-generator.js
1 /* -*- Mode: js; js-indent-level: 2; -*- */
2 /*
3  * Copyright 2011 Mozilla Foundation and contributors
4  * Licensed under the New BSD license. See LICENSE or:
5  * http://opensource.org/licenses/BSD-3-Clause
6  */
7
8 var base64VLQ = require('./base64-vlq');
9 var util = require('./util');
10 var ArraySet = require('./array-set').ArraySet;
11 var MappingList = require('./mapping-list').MappingList;
12
13 /**
14  * An instance of the SourceMapGenerator represents a source map which is
15  * being built incrementally. You may pass an object with the following
16  * properties:
17  *
18  *   - file: The filename of the generated source.
19  *   - sourceRoot: A root for all relative URLs in this source map.
20  */
21 function SourceMapGenerator(aArgs) {
22   if (!aArgs) {
23     aArgs = {};
24   }
25   this._file = util.getArg(aArgs, 'file', null);
26   this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
27   this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
28   this._sources = new ArraySet();
29   this._names = new ArraySet();
30   this._mappings = new MappingList();
31   this._sourcesContents = null;
32 }
33
34 SourceMapGenerator.prototype._version = 3;
35
36 /**
37  * Creates a new SourceMapGenerator based on a SourceMapConsumer
38  *
39  * @param aSourceMapConsumer The SourceMap.
40  */
41 SourceMapGenerator.fromSourceMap =
42   function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
43     var sourceRoot = aSourceMapConsumer.sourceRoot;
44     var generator = new SourceMapGenerator({
45       file: aSourceMapConsumer.file,
46       sourceRoot: sourceRoot
47     });
48     aSourceMapConsumer.eachMapping(function (mapping) {
49       var newMapping = {
50         generated: {
51           line: mapping.generatedLine,
52           column: mapping.generatedColumn
53         }
54       };
55
56       if (mapping.source != null) {
57         newMapping.source = mapping.source;
58         if (sourceRoot != null) {
59           newMapping.source = util.relative(sourceRoot, newMapping.source);
60         }
61
62         newMapping.original = {
63           line: mapping.originalLine,
64           column: mapping.originalColumn
65         };
66
67         if (mapping.name != null) {
68           newMapping.name = mapping.name;
69         }
70       }
71
72       generator.addMapping(newMapping);
73     });
74     aSourceMapConsumer.sources.forEach(function (sourceFile) {
75       var content = aSourceMapConsumer.sourceContentFor(sourceFile);
76       if (content != null) {
77         generator.setSourceContent(sourceFile, content);
78       }
79     });
80     return generator;
81   };
82
83 /**
84  * Add a single mapping from original source line and column to the generated
85  * source's line and column for this source map being created. The mapping
86  * object should have the following properties:
87  *
88  *   - generated: An object with the generated line and column positions.
89  *   - original: An object with the original line and column positions.
90  *   - source: The original source file (relative to the sourceRoot).
91  *   - name: An optional original token name for this mapping.
92  */
93 SourceMapGenerator.prototype.addMapping =
94   function SourceMapGenerator_addMapping(aArgs) {
95     var generated = util.getArg(aArgs, 'generated');
96     var original = util.getArg(aArgs, 'original', null);
97     var source = util.getArg(aArgs, 'source', null);
98     var name = util.getArg(aArgs, 'name', null);
99
100     if (!this._skipValidation) {
101       this._validateMapping(generated, original, source, name);
102     }
103
104     if (source != null) {
105       source = String(source);
106       if (!this._sources.has(source)) {
107         this._sources.add(source);
108       }
109     }
110
111     if (name != null) {
112       name = String(name);
113       if (!this._names.has(name)) {
114         this._names.add(name);
115       }
116     }
117
118     this._mappings.add({
119       generatedLine: generated.line,
120       generatedColumn: generated.column,
121       originalLine: original != null && original.line,
122       originalColumn: original != null && original.column,
123       source: source,
124       name: name
125     });
126   };
127
128 /**
129  * Set the source content for a source file.
130  */
131 SourceMapGenerator.prototype.setSourceContent =
132   function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
133     var source = aSourceFile;
134     if (this._sourceRoot != null) {
135       source = util.relative(this._sourceRoot, source);
136     }
137
138     if (aSourceContent != null) {
139       // Add the source content to the _sourcesContents map.
140       // Create a new _sourcesContents map if the property is null.
141       if (!this._sourcesContents) {
142         this._sourcesContents = Object.create(null);
143       }
144       this._sourcesContents[util.toSetString(source)] = aSourceContent;
145     } else if (this._sourcesContents) {
146       // Remove the source file from the _sourcesContents map.
147       // If the _sourcesContents map is empty, set the property to null.
148       delete this._sourcesContents[util.toSetString(source)];
149       if (Object.keys(this._sourcesContents).length === 0) {
150         this._sourcesContents = null;
151       }
152     }
153   };
154
155 /**
156  * Applies the mappings of a sub-source-map for a specific source file to the
157  * source map being generated. Each mapping to the supplied source file is
158  * rewritten using the supplied source map. Note: The resolution for the
159  * resulting mappings is the minimium of this map and the supplied map.
160  *
161  * @param aSourceMapConsumer The source map to be applied.
162  * @param aSourceFile Optional. The filename of the source file.
163  *        If omitted, SourceMapConsumer's file property will be used.
164  * @param aSourceMapPath Optional. The dirname of the path to the source map
165  *        to be applied. If relative, it is relative to the SourceMapConsumer.
166  *        This parameter is needed when the two source maps aren't in the same
167  *        directory, and the source map to be applied contains relative source
168  *        paths. If so, those relative source paths need to be rewritten
169  *        relative to the SourceMapGenerator.
170  */
171 SourceMapGenerator.prototype.applySourceMap =
172   function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
173     var sourceFile = aSourceFile;
174     // If aSourceFile is omitted, we will use the file property of the SourceMap
175     if (aSourceFile == null) {
176       if (aSourceMapConsumer.file == null) {
177         throw new Error(
178           'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
179           'or the source map\'s "file" property. Both were omitted.'
180         );
181       }
182       sourceFile = aSourceMapConsumer.file;
183     }
184     var sourceRoot = this._sourceRoot;
185     // Make "sourceFile" relative if an absolute Url is passed.
186     if (sourceRoot != null) {
187       sourceFile = util.relative(sourceRoot, sourceFile);
188     }
189     // Applying the SourceMap can add and remove items from the sources and
190     // the names array.
191     var newSources = new ArraySet();
192     var newNames = new ArraySet();
193
194     // Find mappings for the "sourceFile"
195     this._mappings.unsortedForEach(function (mapping) {
196       if (mapping.source === sourceFile && mapping.originalLine != null) {
197         // Check if it can be mapped by the source map, then update the mapping.
198         var original = aSourceMapConsumer.originalPositionFor({
199           line: mapping.originalLine,
200           column: mapping.originalColumn
201         });
202         if (original.source != null) {
203           // Copy mapping
204           mapping.source = original.source;
205           if (aSourceMapPath != null) {
206             mapping.source = util.join(aSourceMapPath, mapping.source)
207           }
208           if (sourceRoot != null) {
209             mapping.source = util.relative(sourceRoot, mapping.source);
210           }
211           mapping.originalLine = original.line;
212           mapping.originalColumn = original.column;
213           if (original.name != null) {
214             mapping.name = original.name;
215           }
216         }
217       }
218
219       var source = mapping.source;
220       if (source != null && !newSources.has(source)) {
221         newSources.add(source);
222       }
223
224       var name = mapping.name;
225       if (name != null && !newNames.has(name)) {
226         newNames.add(name);
227       }
228
229     }, this);
230     this._sources = newSources;
231     this._names = newNames;
232
233     // Copy sourcesContents of applied map.
234     aSourceMapConsumer.sources.forEach(function (sourceFile) {
235       var content = aSourceMapConsumer.sourceContentFor(sourceFile);
236       if (content != null) {
237         if (aSourceMapPath != null) {
238           sourceFile = util.join(aSourceMapPath, sourceFile);
239         }
240         if (sourceRoot != null) {
241           sourceFile = util.relative(sourceRoot, sourceFile);
242         }
243         this.setSourceContent(sourceFile, content);
244       }
245     }, this);
246   };
247
248 /**
249  * A mapping can have one of the three levels of data:
250  *
251  *   1. Just the generated position.
252  *   2. The Generated position, original position, and original source.
253  *   3. Generated and original position, original source, as well as a name
254  *      token.
255  *
256  * To maintain consistency, we validate that any new mapping being added falls
257  * in to one of these categories.
258  */
259 SourceMapGenerator.prototype._validateMapping =
260   function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
261                                               aName) {
262     // When aOriginal is truthy but has empty values for .line and .column,
263     // it is most likely a programmer error. In this case we throw a very
264     // specific error message to try to guide them the right way.
265     // For example: https://github.com/Polymer/polymer-bundler/pull/519
266     if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
267         throw new Error(
268             'original.line and original.column are not numbers -- you probably meant to omit ' +
269             'the original mapping entirely and only map the generated position. If so, pass ' +
270             'null for the original mapping instead of an object with empty or null values.'
271         );
272     }
273
274     if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
275         && aGenerated.line > 0 && aGenerated.column >= 0
276         && !aOriginal && !aSource && !aName) {
277       // Case 1.
278       return;
279     }
280     else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
281              && aOriginal && 'line' in aOriginal && 'column' in aOriginal
282              && aGenerated.line > 0 && aGenerated.column >= 0
283              && aOriginal.line > 0 && aOriginal.column >= 0
284              && aSource) {
285       // Cases 2 and 3.
286       return;
287     }
288     else {
289       throw new Error('Invalid mapping: ' + JSON.stringify({
290         generated: aGenerated,
291         source: aSource,
292         original: aOriginal,
293         name: aName
294       }));
295     }
296   };
297
298 /**
299  * Serialize the accumulated mappings in to the stream of base 64 VLQs
300  * specified by the source map format.
301  */
302 SourceMapGenerator.prototype._serializeMappings =
303   function SourceMapGenerator_serializeMappings() {
304     var previousGeneratedColumn = 0;
305     var previousGeneratedLine = 1;
306     var previousOriginalColumn = 0;
307     var previousOriginalLine = 0;
308     var previousName = 0;
309     var previousSource = 0;
310     var result = '';
311     var next;
312     var mapping;
313     var nameIdx;
314     var sourceIdx;
315
316     var mappings = this._mappings.toArray();
317     for (var i = 0, len = mappings.length; i < len; i++) {
318       mapping = mappings[i];
319       next = ''
320
321       if (mapping.generatedLine !== previousGeneratedLine) {
322         previousGeneratedColumn = 0;
323         while (mapping.generatedLine !== previousGeneratedLine) {
324           next += ';';
325           previousGeneratedLine++;
326         }
327       }
328       else {
329         if (i > 0) {
330           if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
331             continue;
332           }
333           next += ',';
334         }
335       }
336
337       next += base64VLQ.encode(mapping.generatedColumn
338                                  - previousGeneratedColumn);
339       previousGeneratedColumn = mapping.generatedColumn;
340
341       if (mapping.source != null) {
342         sourceIdx = this._sources.indexOf(mapping.source);
343         next += base64VLQ.encode(sourceIdx - previousSource);
344         previousSource = sourceIdx;
345
346         // lines are stored 0-based in SourceMap spec version 3
347         next += base64VLQ.encode(mapping.originalLine - 1
348                                    - previousOriginalLine);
349         previousOriginalLine = mapping.originalLine - 1;
350
351         next += base64VLQ.encode(mapping.originalColumn
352                                    - previousOriginalColumn);
353         previousOriginalColumn = mapping.originalColumn;
354
355         if (mapping.name != null) {
356           nameIdx = this._names.indexOf(mapping.name);
357           next += base64VLQ.encode(nameIdx - previousName);
358           previousName = nameIdx;
359         }
360       }
361
362       result += next;
363     }
364
365     return result;
366   };
367
368 SourceMapGenerator.prototype._generateSourcesContent =
369   function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
370     return aSources.map(function (source) {
371       if (!this._sourcesContents) {
372         return null;
373       }
374       if (aSourceRoot != null) {
375         source = util.relative(aSourceRoot, source);
376       }
377       var key = util.toSetString(source);
378       return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
379         ? this._sourcesContents[key]
380         : null;
381     }, this);
382   };
383
384 /**
385  * Externalize the source map.
386  */
387 SourceMapGenerator.prototype.toJSON =
388   function SourceMapGenerator_toJSON() {
389     var map = {
390       version: this._version,
391       sources: this._sources.toArray(),
392       names: this._names.toArray(),
393       mappings: this._serializeMappings()
394     };
395     if (this._file != null) {
396       map.file = this._file;
397     }
398     if (this._sourceRoot != null) {
399       map.sourceRoot = this._sourceRoot;
400     }
401     if (this._sourcesContents) {
402       map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
403     }
404
405     return map;
406   };
407
408 /**
409  * Render the source map being generated to a string.
410  */
411 SourceMapGenerator.prototype.toString =
412   function SourceMapGenerator_toString() {
413     return JSON.stringify(this.toJSON());
414   };
415
416 exports.SourceMapGenerator = SourceMapGenerator;